/** Makes sure that the input properties are set correctly * @param inputWorkspace The input workspace * @throw std::runtime_error If the properties are invalid */ void NormaliseToMonitor::checkProperties(API::MatrixWorkspace_sptr inputWorkspace) { // Check where the monitor spectrum should come from Property* monSpec = getProperty("MonitorSpectrum"); Property* monWS = getProperty("MonitorWorkspace"); Property* monID = getProperty("MonitorID"); // Is the monitor spectrum within the main input workspace const bool inWS = !monSpec->isDefault(); // Or is it in a separate workspace bool sepWS = !monWS->isDefault(); // or monitor ID bool monIDs = !monID->isDefault(); // something has to be set if ( !inWS && !sepWS && !monIDs) { const std::string mess("Neither the MonitorSpectrum, nor the MonitorID or the MonitorWorkspace property has been set"); g_log.error()<<mess<<std::endl; throw std::runtime_error(mess); } // One and only one of these properties should have been set // input from separate workspace is owerwritten by monitor spectrum if ( inWS && sepWS ){ g_log.information("Both input workspace MonitorSpectrum number and monitor workspace are specified. Ignoring Monitor Workspace"); sepWS = false; } // input from detector ID is rejected in favour of monitor sp if ( inWS && monIDs ){ g_log.information("Both input workspace MonitorSpectrum number and detector ID are specified. Ignoring Detector ID"); monIDs = false; } // separate ws takes over detectorID (this logic is dublicated within getInWSMonitorSpectrum) if ( sepWS && monIDs ){ g_log.information("Both input MonitorWorkspace and detector ID are specified. Ignoring Detector ID"); } // Do a check for common binning and store m_commonBins = API::WorkspaceHelpers::commonBoundaries(inputWorkspace); int spec_num(-1); // Check the monitor spectrum or workspace and extract into new workspace m_monitor = sepWS ? this->getMonitorWorkspace(inputWorkspace,spec_num) : this->getInWSMonitorSpectrum(inputWorkspace,spec_num) ; // Check that the 'monitor' spectrum actually relates to a monitor - warn if not try { Geometry::IDetector_const_sptr mon = m_monitor->getDetector(0); if ( !mon->isMonitor() ) { g_log.warning()<<"The spectrum N: "<<spec_num<<" in MonitorWorkspace does not refer to a monitor.\n" <<"Continuing with normalisation regardless."; } } catch (Kernel::Exception::NotFoundError &) { g_log.warning("Unable to check if the spectrum provided relates to a monitor - " "the instrument is not fully specified.\n" "Continuing with normalisation regardless."); } }
void CalculateDIFC::calculate(API::Progress &progress, API::MatrixWorkspace_sptr &outputWs, DataObjects::OffsetsWorkspace_sptr &offsetsWS, double l1, double beamlineNorm, Kernel::V3D &beamline, Kernel::V3D &samplePos, detid2det_map &allDetectors) { SpecialWorkspace2D_sptr localWS = boost::dynamic_pointer_cast<SpecialWorkspace2D>(outputWs); // Now go through all detid2det_map::const_iterator it = allDetectors.begin(); for (; it != allDetectors.end(); ++it) { Geometry::IDetector_const_sptr det = it->second; if ((!det->isMasked()) && (!det->isMonitor())) { const detid_t detID = it->first; double offset = 0.; if (offsetsWS) offset = offsetsWS->getValue(detID, 0.); double difc = Geometry::Instrument::calcConversion( l1, beamline, beamlineNorm, samplePos, det, offset); difc = 1. / difc; // calcConversion gives 1/DIFC localWS->setValue(detID, difc); } progress.report("Calculate DIFC"); } }
void FindDetectorsPar::populate_values_from_file( const API::MatrixWorkspace_sptr &inputWS) { size_t nHist = inputWS->getNumberHistograms(); if (this->current_ASCII_file.Type == PAR_type) { // in this case data in azimuthal width and polar width are in fact real // sizes in meters; have to transform it in into angular values for (size_t i = 0; i < nHist; i++) { azimuthalWidth[i] = atan2(azimuthalWidth[i], secondaryFlightpath[i]) * rad2deg; polarWidth[i] = atan2(polarWidth[i], secondaryFlightpath[i]) * rad2deg; } m_SizesAreLinear = false; } else { Geometry::IComponent_const_sptr sample = inputWS->getInstrument()->getSample(); secondaryFlightpath.resize(nHist); // Loop over the spectra for (size_t i = 0; i < nHist; i++) { Geometry::IDetector_const_sptr spDet; try { spDet = inputWS->getDetector(i); } catch (Kernel::Exception::NotFoundError &) { continue; } // Check that we aren't writing a monitor... if (spDet->isMonitor()) continue; /// this is the only value, which is not defined in phx file, so we /// calculate it secondaryFlightpath[i] = spDet->getDistance(*sample); } } }
/** Retrieves the detector postion for a given spectrum * @param index :: The workspace index of the spectrum * @param l1 :: Returns the source-sample distance * @param l2 :: Returns the sample-detector distance * @param twoTheta :: Returns the detector's scattering angle */ void RemoveBins::calculateDetectorPosition(const int& index, double& l1, double& l2, double& twoTheta) { // Get a pointer to the instrument contained in the workspace Geometry::Instrument_const_sptr instrument = m_inputWorkspace->getInstrument(); // Get the distance between the source and the sample (assume in metres) Geometry::IObjComponent_const_sptr sample = instrument->getSample(); // Check for valid instrument if (sample == NULL) { throw Exception::InstrumentDefinitionError("Instrument not sufficiently defined: failed to get sample"); } l1 = instrument->getSource()->getDistance(*sample); Geometry::IDetector_const_sptr det = m_inputWorkspace->getDetector(index); // Get the sample-detector distance for this detector (in metres) if ( ! det->isMonitor() ) { l2 = det->getDistance(*sample); // The scattering angle for this detector (in radians). twoTheta = m_inputWorkspace->detectorTwoTheta(det); } else // If this is a monitor then make l1+l2 = source-detector distance and twoTheta=0 { l2 = det->getDistance(*(instrument->getSource())); l2 = l2 - l1; twoTheta = 0.0; } g_log.debug() << "Detector for index " << index << " has L1+L2=" << l1+l2 << " & 2theta= " << twoTheta << std::endl; return; }
void CalculateDIFC::calculate() { Instrument_const_sptr instrument = m_inputWS->getInstrument(); SpecialWorkspace2D_sptr localWS = boost::dynamic_pointer_cast<SpecialWorkspace2D>(m_outputWS); double l1; Kernel::V3D beamline, samplePos; double beamline_norm; instrument->getInstrumentParameters(l1, beamline, beamline_norm, samplePos); // To get all the detector ID's detid2det_map allDetectors; instrument->getDetectors(allDetectors); // Now go through all detid2det_map::const_iterator it = allDetectors.begin(); for (; it != allDetectors.end(); ++it) { Geometry::IDetector_const_sptr det = it->second; if ((!det->isMasked()) && (!det->isMonitor())) { const detid_t detID = it->first; double offset = 0.; if (m_offsetsWS) offset = m_offsetsWS->getValue(detID, 0.); double difc = Geometry::Instrument::calcConversion( l1, beamline, beamline_norm, samplePos, det, offset); difc = 1. / difc; // calcConversion gives 1/DIFC localWS->setValue(detID, difc); } } }
/** Calculates the total flightpath for the given detector. * This is L1+L2 normally, but is the source-detector distance for a monitor. * @param spectrum :: The workspace index * @param L1 :: The primary flightpath * @param isMonitor :: Output: true is this detector is a monitor * @return The flightpath (Ld) for the detector linked to spectrum * @throw Kernel::Exception::InstrumentDefinitionError if the detector position * can't be obtained */ double UnwrapMonitor::calculateFlightpath(const int &spectrum, const double &L1, bool &isMonitor) const { double Ld = -1.0; try { // Get the detector object for this histogram Geometry::IDetector_const_sptr det = m_inputWS->getDetector(spectrum); // Get the sample-detector distance for this detector (or source-detector if // a monitor) // This is the total flightpath isMonitor = det->isMonitor(); // Get the L2 distance if this detector is not a monitor if (!isMonitor) { double L2 = det->getDistance(*(m_inputWS->getInstrument()->getSample())); Ld = L1 + L2; } // If it is a monitor, then the flightpath is the distance to the source else { Ld = det->getDistance(*(m_inputWS->getInstrument()->getSource())); } } catch (Exception::NotFoundError &) { // If the detector information is missing, return a negative number } return Ld; }
/** * Corrects a spectra for the detector efficiency calculated from detector * information. Gets the detector information and uses this to calculate its * efficiency * @param spectraIndex :: index of the spectrum to get the efficiency for * @throw invalid_argument if the shape of a detector is isn't a cylinder * aligned along one axis * @throw runtime_error if the SpectraDetectorMap has not been filled * @throw NotFoundError if the detector or its gas pressure or wall thickness * were not found */ void He3TubeEfficiency::correctForEfficiency(std::size_t spectraIndex) { Geometry::IDetector_const_sptr det = this->inputWS->getDetector(spectraIndex); if( det->isMonitor() || det->isMasked() ) { return; } const double exp_constant = this->calculateExponential(spectraIndex, det); const double scale = this->getProperty("ScaleFactor"); Mantid::MantidVec &yout = this->outputWS->dataY(spectraIndex); Mantid::MantidVec &eout = this->outputWS->dataE(spectraIndex); // Need the original values so this is not a reference const Mantid::MantidVec yValues = this->inputWS->readY(spectraIndex); const Mantid::MantidVec eValues = this->inputWS->readE(spectraIndex); std::vector<double>::const_iterator yinItr = yValues.begin(); std::vector<double>::const_iterator einItr = eValues.begin(); Mantid::MantidVec::const_iterator xItr = this->inputWS->readX(spectraIndex).begin(); Mantid::MantidVec::iterator youtItr = yout.begin(); Mantid::MantidVec::iterator eoutItr = eout.begin(); for( ; youtItr != yout.end(); ++youtItr, ++eoutItr) { const double wavelength = (*xItr + *(xItr + 1)) / 2.0; const double effcorr = this->detectorEfficiency(exp_constant * wavelength, scale); *youtItr = (*yinItr) * effcorr; *eoutItr = (*einItr) * effcorr; ++yinItr; ++einItr; ++xItr; } return; }
/// helper function to preprocess the detectors directions void ConvertToQ3DdE::process_detectors_positions(const DataObjects::Workspace2D_const_sptr inputWS) { const size_t nHist = inputWS->getNumberHistograms(); det_loc.det_dir.resize(nHist); det_loc.det_id.resize(nHist); // Loop over the spectra size_t ic(0); for (size_t i = 0; i < nHist; i++){ Geometry::IDetector_const_sptr spDet; try{ spDet= inputWS->getDetector(i); }catch(Kernel::Exception::NotFoundError &){ continue; } // Check that we aren't dealing with monitor... if (spDet->isMonitor())continue; det_loc.det_id[ic] = spDet->getID(); // dist = spDet->getDistance(*sample); double polar = inputWS->detectorTwoTheta(spDet); double azim = spDet->getPhi(); double sPhi=sin(polar); double ez = cos(polar); double ex = sPhi*cos(azim); double ey = sPhi*sin(azim); det_loc.det_dir[ic].setX(ex); det_loc.det_dir[ic].setY(ey); det_loc.det_dir[ic].setZ(ez); ic++; } // if(ic<nHist){ det_loc.det_dir.resize(ic); det_loc.det_id.resize(ic); } }
/** * Set the new detector position given the r,theta and phi. * @param det :: A pointer to the detector * @param l2 :: A single l2 * @param theta :: A single theta * @param phi :: A single phi */ void UpdateInstrumentFromFile::setDetectorPosition(const Geometry::IDetector_const_sptr & det, const float l2, const float theta, const float phi) { if( m_ignoreMonitors && det->isMonitor() ) return; Geometry::ParameterMap & pmap = m_workspace->instrumentParameters(); Kernel::V3D pos; if (!m_ignorePhi) { pos.spherical(l2, theta, phi); } else { double r,t,p; det->getPos().getSpherical(r,t,p); pos.spherical(l2, theta, p); } Geometry::ComponentHelper::moveComponent(*det, pmap, pos, Geometry::ComponentHelper::Absolute); }
std::pair<double, double> LoadILLSANS::calculateQMaxQMin() { double min = std::numeric_limits<double>::max(), max = std::numeric_limits<double>::min(); g_log.debug("Calculating Qmin Qmax..."); std::size_t nHist = m_localWorkspace->getNumberHistograms(); for (std::size_t i = 0; i < nHist; ++i) { Geometry::IDetector_const_sptr det = m_localWorkspace->getDetector(i); if (!det->isMonitor()) { const MantidVec &lambdaBinning = m_localWorkspace->readX(i); Kernel::V3D detPos = det->getPos(); double r, theta, phi; detPos.getSpherical(r, theta, phi); double v1 = calculateQ(*(lambdaBinning.begin()), theta); double v2 = calculateQ(*(lambdaBinning.end() - 1), theta); // std::cout << "i=" << i << " theta="<<theta << " lambda_i=" << // *(lambdaBinning.begin()) << " lambda_f=" << *(lambdaBinning.end()-1) << // " v1=" << v1 << " v2=" << v2 << '\n'; if (i == 0) { min = v1; max = v1; } if (v1 < min) { min = v1; } if (v2 < min) { min = v2; } if (v1 > max) { max = v1; } if (v2 > max) { max = v2; } } else g_log.debug() << "Detector " << i << " is a Monitor : " << det->getID() << '\n'; } g_log.debug() << "Calculating Qmin Qmax. Done : [" << min << "," << max << "]\n"; return std::pair<double, double>(min, max); }
/** Method updates the column, which describes if current detector/spectra is masked It is used if one tries to process multiple workspaces obtained from a series of experiments where the masked detectors can change */ void PreprocessDetectorsToMD::updateMasksState( const API::MatrixWorkspace_const_sptr &inputWS, DataObjects::TableWorkspace_sptr &targWS) { int *pMasksArray = targWS->getColDataArray<int>("detMask"); if (!pMasksArray) throw std::invalid_argument( "target workspace " + targWS->getName() + " does not have defined masks column to update"); size_t nHist = targWS->rowCount(); const size_t nRows = inputWS->getNumberHistograms(); if (nHist != nRows) throw std::invalid_argument( " source workspace " + inputWS->getName() + " and target workspace " + targWS->getName() + " are inconsistent as have different numner of detectors"); uint32_t liveDetectorsCount(0); for (size_t i = 0; i < nHist; i++) { // get detector or detector group which corresponds to the spectra i Geometry::IDetector_const_sptr spDet; try { spDet = inputWS->getDetector(i); } catch (Kernel::Exception::NotFoundError &) { continue; } // Check that we aren't dealing with monitor... if (spDet->isMonitor()) continue; // if masked detectors state is not used, masked detectors just ignored; bool maskDetector = spDet->isMasked(); *(pMasksArray + liveDetectorsCount) = maskDetector ? 1 : 0; liveDetectorsCount++; } }
/** Executes the algorithm *@param localworkspace :: the input workspace *@param indices :: set of indices to sum up */ void SumSpectra::execEvent(EventWorkspace_const_sptr localworkspace, std::set<int> &indices) { // Make a brand new EventWorkspace EventWorkspace_sptr outputWorkspace = boost::dynamic_pointer_cast<EventWorkspace>( API::WorkspaceFactory::Instance().create("EventWorkspace", 1, 2, 1)); // Copy geometry over. API::WorkspaceFactory::Instance().initializeFromParent(localworkspace, outputWorkspace, true); Progress progress(this, 0, 1, indices.size()); // Get the pointer to the output event list EventList &outEL = outputWorkspace->getEventList(0); outEL.setSpectrumNo(m_outSpecId); outEL.clearDetectorIDs(); // Loop over spectra std::set<int>::iterator it; size_t numSpectra(0); size_t numMasked(0); size_t numZeros(0); // for (int i = m_minSpec; i <= m_maxSpec; ++i) for (it = indices.begin(); it != indices.end(); ++it) { int i = *it; // Don't go outside the range. if ((i >= m_numberOfSpectra) || (i < 0)) { g_log.error() << "Invalid index " << i << " was specified. Sum was aborted.\n"; break; } try { // Get the detector object for this spectrum Geometry::IDetector_const_sptr det = localworkspace->getDetector(i); // Skip monitors, if the property is set to do so if (!m_keepMonitors && det->isMonitor()) continue; // Skip masked detectors if (det->isMasked()) { numMasked++; continue; } } catch (...) { // if the detector not found just carry on } numSpectra++; // Add the event lists with the operator const EventList &tOutEL = localworkspace->getEventList(i); if (tOutEL.empty()) { ++numZeros; } outEL += tOutEL; progress.report(); } // Set all X bins on the output cow_ptr<MantidVec> XValues; XValues.access() = localworkspace->readX(0); outputWorkspace->setAllX(XValues); outputWorkspace->mutableRun().addProperty("NumAllSpectra", int(numSpectra), "", true); outputWorkspace->mutableRun().addProperty("NumMaskSpectra", int(numMasked), "", true); outputWorkspace->mutableRun().addProperty("NumZeroSpectra", int(numZeros), "", true); // Assign it to the output workspace property setProperty("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(outputWorkspace)); }
/** * This function handles the logic for summing RebinnedOutput workspaces. * @param outputWorkspace the workspace to hold the summed input * @param progress the progress indicator * @param numSpectra * @param numMasked * @param numZeros */ void SumSpectra::doRebinnedOutput(MatrixWorkspace_sptr outputWorkspace, Progress &progress, size_t &numSpectra, size_t &numMasked, size_t &numZeros) { // Get a copy of the input workspace MatrixWorkspace_sptr temp = getProperty("InputWorkspace"); // First, we need to clean the input workspace for nan's and inf's in order // to treat the data correctly later. This will create a new private // workspace that will be retrieved as mutable. IAlgorithm_sptr alg = this->createChildAlgorithm("ReplaceSpecialValues"); alg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", temp); std::string outName = "_" + temp->getName() + "_clean"; alg->setProperty("OutputWorkspace", outName); alg->setProperty("NaNValue", 0.0); alg->setProperty("NaNError", 0.0); alg->setProperty("InfinityValue", 0.0); alg->setProperty("InfinityError", 0.0); alg->executeAsChildAlg(); MatrixWorkspace_sptr localworkspace = alg->getProperty("OutputWorkspace"); // Transform to real workspace types RebinnedOutput_sptr inWS = boost::dynamic_pointer_cast<RebinnedOutput>(localworkspace); RebinnedOutput_sptr outWS = boost::dynamic_pointer_cast<RebinnedOutput>(outputWorkspace); // Get references to the output workspaces's data vectors ISpectrum *outSpec = outputWorkspace->getSpectrum(0); MantidVec &YSum = outSpec->dataY(); MantidVec &YError = outSpec->dataE(); MantidVec &FracSum = outWS->dataF(0); MantidVec Weight; std::vector<size_t> nZeros; if (m_calculateWeightedSum) { Weight.assign(YSum.size(), 0); nZeros.assign(YSum.size(), 0); } numSpectra = 0; numMasked = 0; numZeros = 0; // Loop over spectra std::set<int>::iterator it; // for (int i = m_minSpec; i <= m_maxSpec; ++i) for (it = m_indices.begin(); it != m_indices.end(); ++it) { int i = *it; // Don't go outside the range. if ((i >= m_numberOfSpectra) || (i < 0)) { g_log.error() << "Invalid index " << i << " was specified. Sum was aborted.\n"; break; } try { // Get the detector object for this spectrum Geometry::IDetector_const_sptr det = localworkspace->getDetector(i); // Skip monitors, if the property is set to do so if (!m_keepMonitors && det->isMonitor()) continue; // Skip masked detectors if (det->isMasked()) { numMasked++; continue; } } catch (...) { // if the detector not found just carry on } numSpectra++; // Retrieve the spectrum into a vector const MantidVec &YValues = localworkspace->readY(i); const MantidVec &YErrors = localworkspace->readE(i); const MantidVec &FracArea = inWS->readF(i); if (m_calculateWeightedSum) { for (int k = 0; k < this->m_yLength; ++k) { if (YErrors[k] != 0) { double errsq = YErrors[k] * YErrors[k] * FracArea[k] * FracArea[k]; YError[k] += errsq; Weight[k] += 1. / errsq; YSum[k] += YValues[k] * FracArea[k] / errsq; FracSum[k] += FracArea[k]; } else { nZeros[k]++; FracSum[k] += FracArea[k]; } } } else { for (int k = 0; k < this->m_yLength; ++k) { YSum[k] += YValues[k] * FracArea[k]; YError[k] += YErrors[k] * YErrors[k] * FracArea[k] * FracArea[k]; FracSum[k] += FracArea[k]; } } // Map all the detectors onto the spectrum of the output outSpec->addDetectorIDs(localworkspace->getSpectrum(i)->getDetectorIDs()); progress.report(); } if (m_calculateWeightedSum) { numZeros = 0; for (size_t i = 0; i < Weight.size(); i++) { if (nZeros[i] == 0) YSum[i] *= double(numSpectra) / Weight[i]; else numZeros += nZeros[i]; } } // Create the correct representation outWS->finalize(); }
/** * This function deals with the logic necessary for summing a Workspace2D. * @param localworkspace The input workspace for summing. * @param outSpec The spectrum for the summed output. * @param progress The progress indicator. * @param numSpectra The number of spectra contributed to the sum. * @param numMasked The spectra dropped from the summations because they are * masked. * @param numZeros The number of zero bins in histogram workspace or empty * spectra for event workspace. */ void SumSpectra::doWorkspace2D(MatrixWorkspace_const_sptr localworkspace, ISpectrum *outSpec, Progress &progress, size_t &numSpectra, size_t &numMasked, size_t &numZeros) { // Get references to the output workspaces's data vectors MantidVec &YSum = outSpec->dataY(); MantidVec &YError = outSpec->dataE(); MantidVec Weight; std::vector<size_t> nZeros; if (m_calculateWeightedSum) { Weight.assign(YSum.size(), 0); nZeros.assign(YSum.size(), 0); } numSpectra = 0; numMasked = 0; numZeros = 0; // Loop over spectra std::set<int>::iterator it; // for (int i = m_minSpec; i <= m_maxSpec; ++i) for (it = this->m_indices.begin(); it != this->m_indices.end(); ++it) { int i = *it; // Don't go outside the range. if ((i >= this->m_numberOfSpectra) || (i < 0)) { g_log.error() << "Invalid index " << i << " was specified. Sum was aborted.\n"; break; } try { // Get the detector object for this spectrum Geometry::IDetector_const_sptr det = localworkspace->getDetector(i); // Skip monitors, if the property is set to do so if (!m_keepMonitors && det->isMonitor()) continue; // Skip masked detectors if (det->isMasked()) { numMasked++; continue; } } catch (...) { // if the detector not found just carry on } numSpectra++; // Retrieve the spectrum into a vector const MantidVec &YValues = localworkspace->readY(i); const MantidVec &YErrors = localworkspace->readE(i); if (m_calculateWeightedSum) { for (int k = 0; k < this->m_yLength; ++k) { if (YErrors[k] != 0) { double errsq = YErrors[k] * YErrors[k]; YError[k] += errsq; Weight[k] += 1. / errsq; YSum[k] += YValues[k] / errsq; } else { nZeros[k]++; } } } else { for (int k = 0; k < this->m_yLength; ++k) { YSum[k] += YValues[k]; YError[k] += YErrors[k] * YErrors[k]; } } // Map all the detectors onto the spectrum of the output outSpec->addDetectorIDs(localworkspace->getSpectrum(i)->getDetectorIDs()); progress.report(); } if (m_calculateWeightedSum) { numZeros = 0; for (size_t i = 0; i < Weight.size(); i++) { if (nZeros[i] == 0) YSum[i] *= double(numSpectra) / Weight[i]; else numZeros += nZeros[i]; } } }
/** method does preliminary calculations of the detectors positions to convert results into k-dE space ; and places the results into static cash to be used in subsequent calls to this algorithm */ void PreprocessDetectorsToMD::processDetectorsPositions( const API::MatrixWorkspace_const_sptr &inputWS, DataObjects::TableWorkspace_sptr &targWS) { g_log.information() << "Preprocessing detector locations in a target reciprocal space\n"; // Geometry::Instrument_const_sptr instrument = inputWS->getInstrument(); // this->pBaseInstr = instrument->baseInstrument(); // Geometry::IComponent_const_sptr source = instrument->getSource(); Geometry::IComponent_const_sptr sample = instrument->getSample(); if ((!source) || (!sample)) { g_log.error() << " Instrument is not fully defined. Can not identify " "source or sample\n"; throw Kernel::Exception::InstrumentDefinitionError( "Instrument not sufficiently defined: failed to get source and/or " "sample"); } // L1 try { double L1 = source->getDistance(*sample); targWS->logs()->addProperty<double>("L1", L1, true); g_log.debug() << "Source-sample distance: " << L1 << std::endl; } catch (Kernel::Exception::NotFoundError &) { throw Kernel::Exception::InstrumentDefinitionError( "Unable to calculate source-sample distance for workspace", inputWS->getTitle()); } // Instrument name std::string InstrName = instrument->getName(); targWS->logs()->addProperty<std::string>( "InstrumentName", InstrName, true); // "The name which should unique identify current instrument"); targWS->logs()->addProperty<bool>("FakeDetectors", false, true); // get access to the workspace memory auto &sp2detMap = targWS->getColVector<size_t>("spec2detMap"); auto &detId = targWS->getColVector<int32_t>("DetectorID"); auto &detIDMap = targWS->getColVector<size_t>("detIDMap"); auto &L2 = targWS->getColVector<double>("L2"); auto &TwoTheta = targWS->getColVector<double>("TwoTheta"); auto &Azimuthal = targWS->getColVector<double>("Azimuthal"); auto &detDir = targWS->getColVector<Kernel::V3D>("DetDirections"); // Efixed; do we need one and does one exist? double Efi = targWS->getLogs()->getPropertyValueAsType<double>("Ei"); float *pEfixedArray(nullptr); const Geometry::ParameterMap &pmap = inputWS->constInstrumentParameters(); if (m_getEFixed) pEfixedArray = targWS->getColDataArray<float>("eFixed"); // check if one needs to generate masked detectors column. int *pMasksArray(nullptr); if (m_getIsMasked) pMasksArray = targWS->getColDataArray<int>("detMask"); //// progress message appearance size_t div = 100; size_t nHist = targWS->rowCount(); Mantid::API::Progress theProgress(this, 0, 1, nHist); //// Loop over the spectra uint32_t liveDetectorsCount(0); for (size_t i = 0; i < nHist; i++) { sp2detMap[i] = std::numeric_limits<uint64_t>::quiet_NaN(); detId[i] = std::numeric_limits<int32_t>::quiet_NaN(); detIDMap[i] = std::numeric_limits<uint64_t>::quiet_NaN(); L2[i] = std::numeric_limits<double>::quiet_NaN(); TwoTheta[i] = std::numeric_limits<double>::quiet_NaN(); Azimuthal[i] = std::numeric_limits<double>::quiet_NaN(); // detMask[i] = true; // get detector or detector group which corresponds to the spectra i Geometry::IDetector_const_sptr spDet; try { spDet = inputWS->getDetector(i); } catch (Kernel::Exception::NotFoundError &) { continue; } // Check that we aren't dealing with monitor... if (spDet->isMonitor()) continue; // if masked detectors state is not used, masked detectors just ignored; bool maskDetector = spDet->isMasked(); if (m_getIsMasked) *(pMasksArray + liveDetectorsCount) = maskDetector ? 1 : 0; else if (maskDetector) continue; // calculate the requested values; sp2detMap[i] = liveDetectorsCount; detId[liveDetectorsCount] = int32_t(spDet->getID()); detIDMap[liveDetectorsCount] = i; L2[liveDetectorsCount] = spDet->getDistance(*sample); double polar = inputWS->detectorTwoTheta(spDet); double azim = spDet->getPhi(); TwoTheta[liveDetectorsCount] = polar; Azimuthal[liveDetectorsCount] = azim; double sPhi = sin(polar); double ez = cos(polar); double ex = sPhi * cos(azim); double ey = sPhi * sin(azim); detDir[liveDetectorsCount].setX(ex); detDir[liveDetectorsCount].setY(ey); detDir[liveDetectorsCount].setZ(ez); // double sinTheta=sin(0.5*polar); // this->SinThetaSq[liveDetectorsCount] = sinTheta*sinTheta; // specific code which should work and makes sense // for indirect instrument but may be deployed on any code with Ei property // defined; if (pEfixedArray) { try { Geometry::Parameter_sptr par = pmap.getRecursive(spDet.get(), "eFixed"); if (par) Efi = par->value<double>(); } catch (std::runtime_error &) { } // set efixed for each existing detector *(pEfixedArray + liveDetectorsCount) = static_cast<float>(Efi); } liveDetectorsCount++; if (i % div == 0) theProgress.report(i, "Preprocessing detectors"); } targWS->logs()->addProperty<uint32_t>("ActualDetectorsNum", liveDetectorsCount, true); theProgress.report(); g_log.information() << "Finished preprocessing detector locations. Found: " << liveDetectorsCount << " detectors out of: " << nHist << " histograms\n"; }
/** Read the scaling information from a file (e.g. merlin_detector.sca) or from * the RAW file (.raw) * @param scalingFile :: Name of scaling file .sca * @param truepos :: V3D vector of actual positions as read from the file * @return False if unable to open file, True otherwise */ bool SetScalingPSD::processScalingFile(const std::string &scalingFile, std::vector<Kernel::V3D> &truepos) { // Read the scaling information from a text file (.sca extension) or from a // raw file (.raw) // This is really corrected positions as (r,theta,phi) for each detector // Compare these with the instrument values to determine the change in // position and the scaling // which may be necessary for each pixel if in a tube. // movePos is used to updated positions std::map<int, Kernel::V3D> posMap; std::map<int, double> scaleMap; std::map<int, double>::iterator its; Instrument_const_sptr instrument = m_workspace->getInstrument(); if (scalingFile.find(".sca") != std::string::npos || scalingFile.find(".SCA") != std::string::npos) { // read a .sca text format file // format consists of a short header followed by one line per detector std::ifstream sFile(scalingFile.c_str()); if (!sFile) { g_log.error() << "Unable to open scaling file " << scalingFile << std::endl; return false; } std::string str; getline(sFile, str); // skip header line should be <filename> generated by <prog> int detectorCount; getline(sFile, str); // get detector count line std::istringstream istr(str); istr >> detectorCount; if (detectorCount < 1) { g_log.error("Bad detector count in scaling file"); throw std::runtime_error("Bad detector count in scaling file"); } truepos.reserve(detectorCount); getline(sFile, str); // skip title line int detIdLast = -10; Kernel::V3D truPosLast, detPosLast; Progress prog(this, 0.0, 0.5, detectorCount); // Now loop through lines, one for each detector/monitor. The latter are // ignored. while (getline(sFile, str)) { if (str.empty() || str[0] == '#') continue; std::istringstream istr(str); // read 6 values from the line to get the 3 (l2,theta,phi) of interest int detIndex, code; double l2, theta, phi, offset; istr >> detIndex >> offset >> l2 >> code >> theta >> phi; // sanity check on angles - l2 should be +ve but sample file has a few -ve // values // on monitors if (theta > 181.0 || theta < -1 || phi < -181 || phi > 181) { g_log.error("Position angle data out of range in .sca file"); throw std::runtime_error( "Position angle data out of range in .sca file"); } Kernel::V3D truPos; // use abs as correction file has -ve l2 for first few detectors truPos.spherical(fabs(l2), theta, phi); truepos.push_back(truPos); // Geometry::IDetector_const_sptr det; try { det = instrument->getDetector(detIndex); } catch (Kernel::Exception::NotFoundError &) { continue; } Kernel::V3D detPos = det->getPos(); Kernel::V3D shift = truPos - detPos; // scaling applied to dets that are not monitors and have sequential IDs if (detIdLast == detIndex - 1 && !det->isMonitor()) { Kernel::V3D diffI = detPos - detPosLast; Kernel::V3D diffT = truPos - truPosLast; double scale = diffT.norm() / diffI.norm(); Kernel::V3D scaleDir = diffT / diffT.norm(); // Wish to store the scaling in a map, if we already have a scaling // for this detector (i.e. from the other side) we average the two // values. End of tube detectors only have one scaling estimate. scaleMap[detIndex] = scale; its = scaleMap.find(detIndex - 1); if (its == scaleMap.end()) scaleMap[detIndex - 1] = scale; else its->second = 0.5 * (its->second + scale); // std::cout << detIndex << scale << scaleDir << std::endl; } detIdLast = detIndex; detPosLast = detPos; truPosLast = truPos; posMap[detIndex] = shift; // prog.report(); } } else if (scalingFile.find(".raw") != std::string::npos ||