/** * Calculate detector efficiency given a formula, the efficiency at the elastic line, * and a vector with energies. * Efficiency = f(Ei-DeltaE) / f(Ei) * Hope all compilers supports the NRVO (otherwise will copy the output vector) * @param eff0 :: calculated eff0 * @param formula :: formula to calculate efficiency (parsed from IDF) * @param xIn :: Energy bins vector (X axis) * @return a vector with the efficiencies */ MantidVec DetectorEfficiencyCorUser::calculateEfficiency(double eff0, const std::string& formula, const MantidVec& xIn) { MantidVec effOut(xIn.size() - 1); // x are bins and have more one value than y try { double e; mu::Parser p; p.DefineVar("e", &e); p.SetExpr(formula); // copied from Jaques Ollivier Code bool conditionForEnergy = std::min( std::abs( *std::min_element(xIn.begin(), xIn.end()) ) , m_Ei) < m_Ei; MantidVec::const_iterator xIn_it = xIn.begin(); // DeltaE MantidVec::iterator effOut_it = effOut.begin(); for (; effOut_it != effOut.end(); ++xIn_it, ++effOut_it) { if (conditionForEnergy ) { // cppcheck cannot see that this is used by reference by muparser e = std::fabs(m_Ei + *xIn_it); } else { // cppcheck cannot see that this is used by reference by muparser // cppcheck-suppress unreadVariable e = std::fabs(m_Ei - *xIn_it); } double eff = p.Eval(); *effOut_it = eff / eff0; } return effOut; } catch (mu::Parser::exception_type &e) { throw Kernel::Exception::InstrumentDefinitionError( "Error calculating formula from string. Muparser error message is: " + e.GetMsg()); } }
/** Calculates Sn as estimator of scale for given vector * * This method implements a naive calculation of Sn, as defined by Rousseeuw and Croux (http://dx.doi.org/10.2307%2F2291267). * In contrast to standard deviation, this is more robust towards outliers. * * @param begin :: Beginning of vector. * @param end :: End of vector. * @return Sn of supplied data. */ double PoldiPeakSearch::getSn(MantidVec::const_iterator begin, MantidVec::const_iterator end) const { size_t numberOfPoints = std::distance(begin, end); MantidVec absoluteDifferenceMedians(numberOfPoints); PARALLEL_FOR_NO_WSP_CHECK() for(int i = 0; i < static_cast<int>(numberOfPoints); ++i) { double currentValue = *(begin + i); MantidVec temp; temp.reserve(numberOfPoints - 1); for(int j = 0; j < static_cast<int>(numberOfPoints); ++j) { if(j != i) { temp.push_back(fabs(*(begin + j) - currentValue)); } } std::sort(temp.begin(), temp.end()); absoluteDifferenceMedians[i] = getMedianFromSortedVector(temp.begin(), temp.end()); } std::sort(absoluteDifferenceMedians.begin(), absoluteDifferenceMedians.end()); return 1.1926 * getMedianFromSortedVector(absoluteDifferenceMedians.begin(), absoluteDifferenceMedians.end()); }
/** Retrieves a vector with all counts that belong to the background * * In this method, a vector is assembled which contains all count data that is *considered to be background. * Whether a point is considered background depends on its distance to the *given peak positions. * * @param peakPositions :: Peak positions. * @param correlationCounts :: Vector with the complete correlation spectrum. * @return Vector only with counts that belong to the background. */ MantidVec PoldiPeakSearch::getBackground( std::list<MantidVec::const_iterator> peakPositions, const MantidVec &correlationCounts) const { size_t backgroundPoints = getNumberOfBackgroundPoints(peakPositions, correlationCounts); MantidVec background; background.reserve(backgroundPoints); for (MantidVec::const_iterator point = correlationCounts.begin() + 1; point != correlationCounts.end() - 1; ++point) { if (distanceToPeaksGreaterThanMinimum(peakPositions, point)) { background.push_back(*point); } } return background; }
/** Write data in SLOG format */ void SaveGSS::writeSLOGdata(const int bank, const bool MultiplyByBinWidth, std::stringstream &out, const MantidVec &X, const MantidVec &Y, const MantidVec &E) const { const size_t datasize = Y.size(); double bc1 = X.front(); // minimum TOF in microseconds if (bc1 <= 0.) { throw std::runtime_error( "Cannot write out logarithmic data starting at zero"); } double bc2 = 0.5 * (*(X.rbegin()) + *(X.rbegin() + 1)); // maximum TOF (in microseconds?) double bc3 = (*(X.begin() + 1) - bc1) / bc1; // deltaT/T g_log.debug() << "SaveGSS(): Min TOF = " << bc1 << std::endl; writeBankLine(out, "SLOG", bank, datasize); out << std::fixed << " " << std::setprecision(0) << std::setw(10) << bc1 << std::fixed << " " << std::setprecision(0) << std::setw(10) << bc2 << std::fixed << " " << std::setprecision(7) << std::setw(10) << bc3 << std::fixed << " 0 FXYE" << std::endl; for (size_t i = 0; i < datasize; i++) { double y = Y[i]; double e = E[i]; if (MultiplyByBinWidth) { // Multiple by bin width as double delta = X[i + 1] - X[i]; y *= delta; e *= delta; } e = fixErrorValue(e); out << " " << std::fixed << std::setprecision(9) << std::setw(20) << 0.5 * (X[i] + X[i + 1]) << " " << std::fixed << std::setprecision(9) << std::setw(20) << y << " " << std::fixed << std::setprecision(9) << std::setw(20) << e << std::setw(12) << " " << "\n"; // let it flush its own buffer } out << std::flush; return; }
/** * Copy over the metadata from the input matrix workspace to output MDEventWorkspace * @param mdEventWS :: The output MDEventWorkspace where metadata are copied to. The source of the metadata is the input matrix workspace * */ void ConvertToMD::copyMetaData(API::IMDEventWorkspace_sptr &mdEventWS) const { // found detector which is not a monitor to get proper bin boundaries. size_t spectra_index(0); bool dector_found(false); for(size_t i=0;i<m_InWS2D->getNumberHistograms(); ++i) { try { auto det=m_InWS2D->getDetector(i); if (!det->isMonitor()) { spectra_index=i; dector_found = true; g_log.debug()<<"Using spectra N "<<i<< " as the source of the bin boundaries for the resolution corrections \n"; break; } } catch(...) {} } if (!dector_found) g_log.warning()<<"No detectors in the workspace are associated with spectra. Using spectrum 0 trying to retrieve the bin boundaries \n"; // retrieve representative bin boundaries MantidVec binBoundaries = m_InWS2D->readX(spectra_index); // check if the boundaries transformation is necessary if (m_Convertor->getUnitConversionHelper().isUnitConverted()) { if( !dynamic_cast<DataObjects::EventWorkspace *>(m_InWS2D.get())) { g_log.information()<<" ConvertToMD converts input workspace units, but the bin boundaries are copied from the first workspace spectra. The resolution estimates can be incorrect if unit conversion depends on spectra number.\n"; UnitsConversionHelper &unitConv = m_Convertor->getUnitConversionHelper(); unitConv.updateConversion(spectra_index); for(size_t i=0;i<binBoundaries.size();i++) { binBoundaries[i] =unitConv.convertUnits(binBoundaries[i]); } } // sort bin boundaries in case if unit transformation have swapped them. if (binBoundaries[0]>binBoundaries[binBoundaries.size()-1]) { g_log.information()<<"Bin boundaries are not arranged monotonously. Sorting performed\n"; std::sort(binBoundaries.begin(),binBoundaries.end()); } } // Replacement for SpectraDetectorMap::createIDGroupsMap using the ISpectrum objects instead auto mapping = boost::make_shared<det2group_map>(); for ( size_t i = 0; i < m_InWS2D->getNumberHistograms(); ++i ) { const auto& dets = m_InWS2D->getSpectrum(i)->getDetectorIDs(); if(!dets.empty()) { std::vector<detid_t> id_vector; std::copy(dets.begin(), dets.end(), std::back_inserter(id_vector)); mapping->insert(std::make_pair(id_vector.front(), id_vector)); } } uint16_t nexpts = mdEventWS->getNumExperimentInfo(); for(uint16_t i = 0; i < nexpts; ++i) { ExperimentInfo_sptr expt = mdEventWS->getExperimentInfo(i); expt->mutableRun().storeHistogramBinBoundaries(binBoundaries); expt->cacheDetectorGroupings(*mapping); } }
/** Corrects a spectra for the detector efficiency calculated from detector information Gets the detector information and uses this to calculate its efficiency * @param spectraIn :: 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 DetectorEfficiencyCor::correctForEfficiency(int64_t spectraIn) { IDetector_const_sptr det = m_inputWS->getDetector(spectraIn); if( det->isMonitor() || det->isMasked() ) { return; } MantidVec & yout = m_outputWS->dataY(spectraIn); MantidVec & eout = m_outputWS->dataE(spectraIn); // Need the original values so this is not a reference const MantidVec yValues = m_inputWS->readY(spectraIn); const MantidVec eValues = m_inputWS->readE(spectraIn); // get a pointer to the detectors that created the spectrum const std::set<detid_t> dets = m_inputWS->getSpectrum(spectraIn)->getDetectorIDs(); std::set<detid_t>::const_iterator it = dets.begin(); std::set<detid_t>::const_iterator iend = dets.end(); if ( it == iend ) { throw Exception::NotFoundError("No detectors found", spectraIn); } // Storage for the reciprocal wave vectors that are calculated as the //correction proceeds std::vector<double> oneOverWaveVectors(yValues.size()); for( ; it != iend ; ++it ) { IDetector_const_sptr det_member = m_inputWS->getInstrument()->getDetector(*it); Parameter_sptr par = m_paraMap->get(det_member.get(),"3He(atm)"); if ( !par ) { throw Exception::NotFoundError("3He(atm)", spectraIn); } const double atms = par->value<double>(); par = m_paraMap->get(det_member.get(),"wallT(m)"); if ( !par ) { throw Exception::NotFoundError("wallT(m)", spectraIn); } const double wallThickness = par->value<double>(); double detRadius(0.0); V3D detAxis; getDetectorGeometry(det_member, detRadius, detAxis); // now get the sin of the angle, it's the magnitude of the cross product of unit vector along the detector tube axis and a unit vector directed from the sample to the detector centre V3D vectorFromSample = det_member->getPos() - m_samplePos; vectorFromSample.normalize(); Quat rot = det_member->getRotation(); // rotate the original cylinder object axis to get the detector axis in the actual instrument rot.rotate(detAxis); detAxis.normalize(); // Scalar product is quicker than cross product double cosTheta = detAxis.scalar_prod(vectorFromSample); double sinTheta = std::sqrt(1.0 - cosTheta*cosTheta); // Detector constant const double det_const = g_helium_prefactor*(detRadius - wallThickness)*atms/sinTheta; MantidVec::const_iterator yinItr = yValues.begin(); MantidVec::const_iterator einItr = eValues.begin(); MantidVec::iterator youtItr = yout.begin(); MantidVec::iterator eoutItr = eout.begin(); MantidVec::const_iterator xItr = m_inputWS->readX(spectraIn).begin(); std::vector<double>::iterator wavItr = oneOverWaveVectors.begin(); for( ; youtItr != yout.end(); ++youtItr, ++eoutItr) { if( it == dets.begin() ) { *youtItr = 0.0; *eoutItr = 0.0; *wavItr = calculateOneOverK(*xItr, *(xItr + 1 )); } const double oneOverWave = *wavItr; const double factor = 1.0/detectorEfficiency(det_const*oneOverWave); *youtItr += (*yinItr)*factor; *eoutItr += (*einItr)*factor; ++yinItr; ++einItr; ++xItr; ++wavItr; } } }
/** Subtracts a constant from the data values in the given workspace * @param Y :: The vector from which to subtract * @param value :: The value to subtract from each data point */ void IQTransform::subtractBackgroundValue(MantidVec& Y, const double value) { g_log.debug() << "Subtracting the background value " << value << " from the input workspace.\n"; std::transform(Y.begin(),Y.end(),Y.begin(),std::bind2nd(std::minus<double>(),value)); }
void PoldiPeakSearch::exec() { g_log.information() << "PoldiPeakSearch:" << std::endl; Workspace2D_sptr correlationWorkspace = getProperty("InputWorkspace"); MantidVec correlationQValues = correlationWorkspace->readX(0); MantidVec correlatedCounts = correlationWorkspace->readY(0); g_log.information() << " Auto-correlation data read." << std::endl; Unit_sptr xUnit = correlationWorkspace->getAxis(0)->unit(); if (xUnit->caption() == "") { g_log.information() << " Workspace does not have unit, defaulting to MomentumTransfer." << std::endl; xUnit = UnitFactory::Instance().create("MomentumTransfer"); } else { g_log.information() << " Unit of workspace is " << xUnit->caption() << "." << std::endl; } setMinimumDistance(getProperty("MinimumPeakSeparation")); setMinimumPeakHeight(getProperty("MinimumPeakHeight")); setMaximumPeakNumber(getProperty("MaximumPeakNumber")); if (m_doubleMinimumDistance > static_cast<int>(correlatedCounts.size())) { throw(std::runtime_error("MinimumPeakSeparation is smaller than number of " "spectrum points - no peaks possible.")); } g_log.information() << " Parameters set." << std::endl; MantidVec summedNeighborCounts = getNeighborSums(correlatedCounts); g_log.information() << " Neighboring counts summed, contains " << summedNeighborCounts.size() << " data points." << std::endl; std::list<MantidVec::const_iterator> peakPositionsSummed = findPeaks(summedNeighborCounts.begin(), summedNeighborCounts.end()); g_log.information() << " Peaks detected in summed spectrum: " << peakPositionsSummed.size() << std::endl; /* This step is required because peaks are actually searched in the * "sum-of-neighbors"-spectrum. * The mapping removes the offset from the peak position which results from * different beginning * of this vector compared to the original correlation counts. */ std::list<MantidVec::const_iterator> peakPositionsCorrelation = mapPeakPositionsToCorrelationData(peakPositionsSummed, summedNeighborCounts.begin(), correlatedCounts.begin()); g_log.information() << " Peak positions transformed to original spectrum." << std::endl; /* Since intensities are required for filtering, they are extracted from the * original count data, * along with the Q-values. */ std::vector<PoldiPeak_sptr> peakCoordinates = getPeaks(correlatedCounts.begin(), correlatedCounts.end(), peakPositionsCorrelation, correlationQValues, xUnit); g_log.information() << " Extracted peak positions in Q and intensity guesses." << std::endl; UncertainValue backgroundWithSigma = getBackgroundWithSigma(peakPositionsCorrelation, correlatedCounts); g_log.information() << " Calculated average background and deviation: " << UncertainValueIO::toString(backgroundWithSigma) << std::endl; if ((*getProperty("MinimumPeakHeight")).isDefault()) { setMinimumPeakHeight(minimumPeakHeightFromBackground(backgroundWithSigma)); } std::vector<PoldiPeak_sptr> intensityFilteredPeaks(peakCoordinates.size()); auto newEnd = std::remove_copy_if( peakCoordinates.begin(), peakCoordinates.end(), intensityFilteredPeaks.begin(), boost::bind(&PoldiPeakSearch::isLessThanMinimum, this, _1)); intensityFilteredPeaks.resize( std::distance(intensityFilteredPeaks.begin(), newEnd)); g_log.information() << " Peaks above minimum intensity (" << m_minimumPeakHeight << "): " << intensityFilteredPeaks.size() << std::endl; std::sort(intensityFilteredPeaks.begin(), intensityFilteredPeaks.end(), boost::bind<bool>(&PoldiPeak::greaterThan, _1, _2, &PoldiPeak::intensity)); for (std::vector<PoldiPeak_sptr>::const_iterator peak = intensityFilteredPeaks.begin(); peak != intensityFilteredPeaks.end(); ++peak) { m_peaks->addPeak(*peak); } /* The derived background error is set as error in the workspace containing * correlation data, so it may be used as weights for peak fitting later on. */ setErrorsOnWorkspace(correlationWorkspace, backgroundWithSigma.error()); setProperty("OutputWorkspace", m_peaks->asTableWorkspace()); }
void LoadDaveGrp::exec() { const std::string filename = this->getProperty("Filename"); int yLength = 0; MantidVec *xAxis = new MantidVec(); MantidVec *yAxis = new MantidVec(); std::vector<MantidVec *> data; std::vector<MantidVec *> errors; this->ifile.open(filename.c_str()); if (this->ifile.is_open()) { // Size of x axis this->getAxisLength(this->xLength); // Size of y axis this->getAxisLength(yLength); // This is also the number of groups (spectra) this->nGroups = yLength; // Read in the x axis values this->getAxisValues(xAxis, static_cast<std::size_t>(this->xLength)); // Read in the y axis values this->getAxisValues(yAxis, static_cast<std::size_t>(yLength)); // Read in the data this->getData(data, errors); } this->ifile.close(); // Scale the x-axis if it is in micro-eV to get it to meV const bool isUeV = this->getProperty("IsMicroEV"); if (isUeV) { MantidVec::iterator iter; for (iter = xAxis->begin(); iter != xAxis->end(); ++iter) { *iter /= 1000.0; } } // Create workspace API::MatrixWorkspace_sptr outputWorkspace = \ boost::dynamic_pointer_cast<API::MatrixWorkspace>\ (API::WorkspaceFactory::Instance().create("Workspace2D", this->nGroups, this->xLength, yLength)); // Force the workspace to be a distribution outputWorkspace->isDistribution(true); // Set the x-axis units outputWorkspace->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create(this->getProperty("XAxisUnits")); API::Axis* const verticalAxis = new API::NumericAxis(yLength); // Set the y-axis units verticalAxis->unit() = Kernel::UnitFactory::Instance().create(this->getProperty("YAxisUnits")); outputWorkspace->replaceAxis(1, verticalAxis); for(int i = 0; i < this->nGroups; i++) { outputWorkspace->dataX(i) = *xAxis; outputWorkspace->dataY(i) = *data[i]; outputWorkspace->dataE(i) = *errors[i]; verticalAxis->setValue(i, yAxis->at(i)); delete data[i]; delete errors[i]; } delete xAxis; delete yAxis; outputWorkspace->mutableRun().addProperty("Filename",filename); this->setProperty("OutputWorkspace", outputWorkspace); }
/** Finds the index in an ordered vector which follows the given value * @param value :: The value to search for * @param vec :: The vector to search * @return The index (will give vec.size()+1 if the value is past the end of the vector) */ int RemoveBins::findIndex(const double& value, const MantidVec& vec) { MantidVec::const_iterator pos = std::lower_bound(vec.begin(),vec.end(),value); return static_cast<int>(pos-vec.begin()); }
/** * Loads data from a selection of the FITS files into the workspace * @param workspace The workspace to insert data into * @param yVals Reference to a pre-allocated vector to hold data values for the workspace * @param eVals Reference to a pre-allocated vector to hold error values for the workspace * @param bufferAny Pointer to an allocated memory region which will hold a files worth of data * @param x Vector holding the X bin values * @param spectraCount Number of data points in each file * @param bitsPerPixel Number of bits used to represent one data point * @param binChunkStartIndex Index for the first file to be processed in this chunk */ void LoadFITS::loadChunkOfBinsFromFile(MatrixWorkspace_sptr &workspace, vector<vector<double> > &yVals, vector<vector<double> > &eVals, void *&bufferAny, MantidVecPtr &x, size_t spectraCount, int bitsPerPixel, size_t binChunkStartIndex) { size_t binsThisChunk = m_binChunkSize; if((binChunkStartIndex + m_binChunkSize) > m_allHeaderInfo.size()) { // No need to do extra processing if number of bins to process is lower than m_binChunkSize // Also used to prevent out of bounds error where a greater number of elements have been reserved. binsThisChunk = static_cast<size_t>(m_allHeaderInfo.size() - binChunkStartIndex); } uint8_t *buffer8 = NULL; uint16_t *buffer16 = NULL; uint32_t *buffer32 = NULL; // create pointer of correct data type to void pointer of the buffer: buffer8 = static_cast<uint8_t*>(bufferAny); buffer16 = static_cast<uint16_t*>(bufferAny); buffer32 = static_cast<uint32_t*>(bufferAny); for(size_t i=binChunkStartIndex; i < binChunkStartIndex+binsThisChunk ; ++i) { // Read Data bool fileErr = false; FILE * currFile = fopen ( m_allHeaderInfo[i].filePath.c_str(), "rb" ); if (currFile==NULL) fileErr = true; size_t result = 0; if(!fileErr) { fseek (currFile , FIXED_HEADER_SIZE , SEEK_CUR); result = fread(bufferAny, bitsPerPixel/8, spectraCount, currFile); } if (result != spectraCount) fileErr = true; if(fileErr) { throw std::runtime_error("Error reading file; possibly invalid data."); } for(size_t j=0; j<spectraCount;++j) { double val = 0; if(bitsPerPixel == 8) val = static_cast<double>(buffer8[j]); if(bitsPerPixel == 16) val = static_cast<double>(buffer16[j]); if(bitsPerPixel == 32) val = static_cast<double>(buffer32[j]); yVals[j][i-binChunkStartIndex] = val; eVals[j][i-binChunkStartIndex] = sqrt(val); } // Clear memory associated with the file load fclose (currFile); } // Now load chunk into workspace PARALLEL_FOR1(workspace) for (int64_t wi = 0; wi < static_cast<int64_t>(spectraCount); ++wi) { workspace->setX(wi, x); MantidVec *currY = &workspace->dataY(wi); MantidVec *currE = &workspace->dataE(wi); std::copy(yVals[wi].begin(), yVals[wi].end()-(m_binChunkSize-binsThisChunk), currY->begin()+binChunkStartIndex ); std::copy(eVals[wi].begin(), eVals[wi].end()-(m_binChunkSize-binsThisChunk), currE->begin()+binChunkStartIndex ); // I expect this will be wanted once IDF is in a more useful state. //workspace->getSpectrum(wi)->setDetectorID(detid_t(wi)); //workspace->getSpectrum(wi)->setSpectrumNo(specid_t(wi+1)); } }