/** Populates the output workspaces * @param inWS :: [input] The input workspace * @param spec :: [input] The current spectrum being analyzed * @param nspec :: [input] The total number of histograms in the input workspace * @param result :: [input] The result to be written in the output workspace * @param outWS :: [input] The output workspace to populate */ void MaxEnt::populateDataWS(const MatrixWorkspace_sptr &inWS, size_t spec, size_t nspec, const std::vector<double> &result, MatrixWorkspace_sptr &outWS) { if (result.size() % 2) throw std::invalid_argument("Cannot write results to output workspaces"); int npoints = static_cast<int>(result.size() / 2); int npointsX = inWS->isHistogramData() ? npoints + 1 : npoints; MantidVec X(npointsX); MantidVec YR(npoints); MantidVec YI(npoints); MantidVec E(npoints, 0.); double x0 = inWS->readX(spec)[0]; double dx = inWS->readX(spec)[1] - x0; for (int i = 0; i < npoints; i++) { X[i] = x0 + i * dx; YR[i] = result[2 * i]; YI[i] = result[2 * i + 1]; } if (npointsX == npoints + 1) X[npoints] = x0 + npoints * dx; outWS->dataX(spec).assign(X.begin(), X.end()); outWS->dataY(spec).assign(YR.begin(), YR.end()); outWS->dataE(spec).assign(E.begin(), E.end()); outWS->dataX(nspec + spec).assign(X.begin(), X.end()); outWS->dataY(nspec + spec).assign(YI.begin(), YI.end()); outWS->dataE(nspec + spec).assign(E.begin(), E.end()); }
/** * Disable points in the workpsace in the way that points which are not included in any of specified * sections are not used when fitting given workspace * @param ws :: Workspace to disable points in * @param sections :: Section we want to use for fitting */ void ALCBaselineModellingModel::disableUnwantedPoints(MatrixWorkspace_sptr ws, const std::vector<IALCBaselineModellingModel::Section>& sections) { // Whether point with particular index should be disabled std::vector<bool> toDisable(ws->blocksize(), true); // Find points which are in at least one section, and exclude them from disable list for (size_t i = 0; i < ws->blocksize(); ++i) { for (auto it = sections.begin(); it != sections.end(); ++it) { if ( ws->dataX(0)[i] >= it->first && ws->dataX(0)[i] <= it->second ) { toDisable[i] = false; break; // No need to check other sections } } } // XXX: Points are disabled by settings their errors to very high value. This makes those // points to have very low weights during the fitting, effectively disabling them. const double DISABLED_ERR = std::numeric_limits<double>::max(); // Disable chosen points for (size_t i = 0; i < ws->blocksize(); ++i) { if (toDisable[i]) { ws->dataE(0)[i] = DISABLED_ERR; } } }
void EQSANSSensitivityCorrection::exec() { MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); MatrixWorkspace_sptr effWS = getProperty("EfficiencyWorkspace"); const double factor = getProperty("Factor"); const double error = getProperty("Error"); Progress progress(this,0.0,1.0,5); // Now create a workspace to put in the wavelength-dependence MatrixWorkspace_sptr lambdaWS = WorkspaceFactory::Instance().create(inputWS); // Number of X bins const int xLength = static_cast<int>(inputWS->readY(0).size()); // Number of detector pixels const int numHists = static_cast<int>(inputWS->getNumberHistograms()); const MantidVec& XIn = inputWS->dataX(0); MantidVec& YOut = lambdaWS->dataY(0); MantidVec& EOut = lambdaWS->dataE(0); progress.report("Computing detector efficiency"); for (int i = 0; i < xLength; i++) { double wl = (XIn[i]+XIn[i+1])/2.0; YOut[i] = 1.0-std::exp(-factor*wl); EOut[i] = std::fabs(factor)*std::exp(-factor*wl)*error; } progress.report("Computing detector efficiency"); for (int i = 0; i < numHists; i++) { MantidVec& YOut_i = lambdaWS->dataY(i); MantidVec& EOut_i = lambdaWS->dataE(i); MantidVec& XOut_i = lambdaWS->dataX(i); YOut_i = YOut; EOut_i = EOut; XOut_i = XIn; } lambdaWS = lambdaWS * effWS; MatrixWorkspace_sptr outputWS = inputWS / lambdaWS; setProperty("OutputWorkspace", outputWS); setProperty("OutputEfficiencyWorkspace", lambdaWS); setProperty("OutputMessage", "Applied wavelength-dependent sensitivity correction"); }
void SumRowColumn::exec() { // First task is to integrate the input workspace MatrixWorkspace_const_sptr integratedWS = integrateWorkspace(); const size_t numSpec = integratedWS->getNumberHistograms(); // Check number of spectra is 128*128 or 192*192. Print warning if not. if (numSpec != 16384 && numSpec != 36864) { g_log.warning() << "The input workspace has " << numSpec << " spectra." << "This is not 128*128 or 192*192 - did you make a mistake?\n"; } // This is the dimension if all rows/columns are included const int dim = static_cast<int>( std::sqrt(static_cast<double>(numSpec)) ); // Check the column range properties int start = getProperty("HOverVMin"); int end = getProperty("HOverVMax"); if ( isEmpty(start) ) start = 0; if ( isEmpty(end) || end > dim-1 ) end = dim-1; if ( start > end ) { g_log.error("H/V_Min must be less than H/V_Max"); throw std::out_of_range("H/V_Min must be less than H/V_Max"); } MatrixWorkspace_sptr outputWS = WorkspaceFactory::Instance().create(integratedWS,1,dim,dim); // Remove the unit outputWS->getAxis(0)->unit().reset(); // Get references to the vectors for the results MantidVec& X = outputWS->dataX(0); MantidVec& Y = outputWS->dataY(0); // Get the orientation const std::string orientation = getProperty("Orientation"); const bool horizontal = ( orientation=="D_H" ? 1 : 0 ); Progress progress(this,0,1,dim); for (int i = 0; i < dim; ++i) { // Copy X values X[i] = i; // Now loop over calculating Y's for (int j = start; j <= end; ++j) { const int index = ( horizontal ? ( i + j*dim) : ( i*dim + j) ); Y[i] += integratedWS->readY(index)[0]; } } setProperty("OutputWorkspace",outputWS); }
/** Populate output workspace with results * @param outWS :: [input/output] Output workspace to populate * @param nplots :: [input] Number of histograms */ void PlotAsymmetryByLogValue::populateOutputWorkspace( MatrixWorkspace_sptr &outWS, int nplots) { auto tAxis = new TextAxis(nplots); if (nplots == 1) { size_t i = 0; for (auto &value : m_logValue) { outWS->dataX(0)[i] = value.second; outWS->dataY(0)[i] = m_redY[value.first]; outWS->dataE(0)[i] = m_redE[value.first]; i++; } tAxis->setLabel(0, "Asymmetry"); } else { size_t i = 0; for (auto &value : m_logValue) { outWS->dataX(0)[i] = value.second; outWS->dataY(0)[i] = m_diffY[value.first]; outWS->dataE(0)[i] = m_diffE[value.first]; outWS->dataX(1)[i] = value.second; outWS->dataY(1)[i] = m_redY[value.first]; outWS->dataE(1)[i] = m_redE[value.first]; outWS->dataX(2)[i] = value.second; outWS->dataY(2)[i] = m_greenY[value.first]; outWS->dataE(2)[i] = m_greenE[value.first]; outWS->dataX(3)[i] = value.second; outWS->dataY(3)[i] = m_sumY[value.first]; outWS->dataE(3)[i] = m_sumE[value.first]; i++; } tAxis->setLabel(0, "Red-Green"); tAxis->setLabel(1, "Red"); tAxis->setLabel(2, "Green"); tAxis->setLabel(3, "Red+Green"); } outWS->replaceAxis(1, tAxis); outWS->getAxis(0)->title() = m_logName; outWS->setYUnitLabel("Asymmetry"); }
/** Populate output workspace with results * @param outWS :: [input/output] Output workspace to populate * @param nplots :: [input] Number of histograms */ void PlotAsymmetryByLogValue::saveResultsToADS(MatrixWorkspace_sptr &outWS, int nplots) { if (nplots == 2) { size_t i = 0; for (auto &value : m_logValue) { size_t run = value.first; outWS->dataX(0)[i] = static_cast<double>(run); // run number outWS->dataY(0)[i] = value.second; // log value outWS->dataY(1)[i] = m_redY[run]; // redY outWS->dataE(1)[i] = m_redE[run]; // redE i++; } } else { size_t i = 0; for (auto &value : m_logValue) { size_t run = value.first; outWS->dataX(0)[i] = static_cast<double>(run); // run number outWS->dataY(0)[i] = value.second; // log value outWS->dataY(1)[i] = m_diffY[run]; // diffY outWS->dataE(1)[i] = m_diffE[run]; // diffE outWS->dataY(2)[i] = m_redY[run]; // redY outWS->dataE(2)[i] = m_redE[run]; // redE outWS->dataY(3)[i] = m_greenY[run]; // greenY outWS->dataE(3)[i] = m_greenE[run]; // greenE outWS->dataY(4)[i] = m_sumY[run]; // sumY outWS->dataE(4)[i] = m_sumE[run]; // sumE i++; } } // Set the title! outWS->setTitle(m_allProperties); // Save results to ADS // We can't set an output property to store the results as this algorithm // is executed as a child algorithm in the Muon ALC interface // If current results were saved as a property we couln't used // the functionality to re-use previous results in ALC AnalysisDataService::Instance().addOrReplace(m_currResName, outWS); }
/** * Share the given input counts into the output array bins proportionally * according to how much the bins overlap the given lambda range. * outputX.size() must equal outputY.size() + 1 * * @param inputCounts [in] :: the input counts to share out * @param inputErr [in] :: the input errors to share out * @param bLambda [in] :: the bin width in lambda * @param lambdaMin [in] :: the start of the range to share counts to * @param lambdaMax [in] :: the end of the range to share counts to * @param outSpecIdx [in] :: the spectrum index to be updated in the output * workspace * @param IvsLam [in,out] :: the output workspace * @param outputE [in,out] :: the projected E values */ void ReflectometryReductionOne2::sumInQShareCounts( const double inputCounts, const double inputErr, const double bLambda, const double lambdaMin, const double lambdaMax, const size_t outSpecIdx, MatrixWorkspace_sptr IvsLam, std::vector<double> &outputE) { // Check that we have histogram data const auto &outputX = IvsLam->dataX(outSpecIdx); auto &outputY = IvsLam->dataY(outSpecIdx); if (outputX.size() != outputY.size() + 1) { throw std::runtime_error( "Expected output array to be histogram data (got X len=" + std::to_string(outputX.size()) + ", Y len=" + std::to_string(outputY.size()) + ")"); } const double totalWidth = lambdaMax - lambdaMin; // Get the first bin edge in the output X array that is within range. // There will probably be some overlap, so start from the bin edge before // this (unless we're already at the first bin edge). auto startIter = std::lower_bound(outputX.begin(), outputX.end(), lambdaMin); if (startIter != outputX.begin()) { --startIter; } // Loop through all overlapping output bins. Convert the iterator to an // index because we need to index both the X and Y arrays. const int xSize = static_cast<int>(outputX.size()); for (auto outIdx = startIter - outputX.begin(); outIdx < xSize - 1; ++outIdx) { const double binStart = outputX[outIdx]; const double binEnd = outputX[outIdx + 1]; if (binStart > lambdaMax) { // No longer in the overlap region so we're finished break; } // Add a share of the input counts to this bin based on the proportion of // overlap. if (totalWidth > Tolerance) { // Share counts out proportionally based on the overlap of this range const double overlapWidth = std::min({bLambda, lambdaMax - binStart, binEnd - lambdaMin}); const double fraction = overlapWidth / totalWidth; outputY[outIdx] += inputCounts * fraction; outputE[outIdx] += inputErr * fraction; } else { // Projection to a single value. Put all counts in the overlapping output // bin. outputY[outIdx] += inputCounts; outputE[outIdx] += inputCounts; } } }
/** Execute the algorithm. */ void WeightedMeanOfWorkspace::exec() { MatrixWorkspace_sptr inputWS = this->getProperty("InputWorkspace"); // Check if it is an event workspace EventWorkspace_const_sptr eventW = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS); if (eventW != NULL) { throw std::runtime_error("WeightedMeanOfWorkspace cannot handle EventWorkspaces!"); } // Create the output workspace MatrixWorkspace_sptr singleValued = WorkspaceFactory::Instance().create("WorkspaceSingleValue", 1, 1, 1); // Calculate weighted mean std::size_t numHists = inputWS->getNumberHistograms(); double averageValue = 0.0; double weightSum = 0.0; for (std::size_t i = 0; i < numHists; ++i) { try { IDetector_const_sptr det = inputWS->getDetector(i); if( det->isMonitor() || det->isMasked() ) { continue; } } catch (...) { // Swallow these if no instrument is found ; } MantidVec y = inputWS->dataY(i); MantidVec e = inputWS->dataE(i); double weight = 0.0; for (std::size_t j = 0; j < y.size(); ++j) { if (!boost::math::isnan(y[j]) && !boost::math::isinf(y[j]) && !boost::math::isnan(e[j]) && !boost::math::isinf(e[j])) { weight = 1.0 / (e[j] * e[j]); averageValue += (y[j] * weight); weightSum += weight; } } } singleValued->dataX(0)[0] = 0.0; singleValued->dataY(0)[0] = averageValue / weightSum; singleValued->dataE(0)[0] = std::sqrt(weightSum); this->setProperty("OutputWorkspace", singleValued); }
void IQTransform::exec() { MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); // Print a warning if the input workspace has more than one spectrum if ( inputWS->getNumberHistograms() > 1 ) { g_log.warning("This algorithm is intended for use on single-spectrum workspaces.\n" "Only the first spectrum will be transformed."); } // Do background subtraction from a workspace first because it doesn't like // potential conversion to point data that follows. Requires a temporary workspace. MatrixWorkspace_sptr tmpWS; MatrixWorkspace_sptr backgroundWS = getProperty("BackgroundWorkspace"); if ( backgroundWS ) tmpWS = subtractBackgroundWS(inputWS,backgroundWS); else tmpWS = inputWS; // Create the output workspace const size_t length = tmpWS->blocksize(); MatrixWorkspace_sptr outputWS = WorkspaceFactory::Instance().create(inputWS,1,length,length); m_label->setLabel(""); outputWS->setYUnit(""); // Copy the data over. Assume single spectrum input (output will be). // Take the mid-point of histogram bins if ( tmpWS->isHistogramData() ) { VectorHelper::convertToBinCentre(tmpWS->readX(0),outputWS->dataX(0)); } else { outputWS->setX(0,tmpWS->refX(0)); } MantidVec& Y = outputWS->dataY(0) = tmpWS->dataY(0); outputWS->dataE(0) = tmpWS->dataE(0); // Subtract a constant background if requested const double background = getProperty("BackgroundValue"); if ( background > 0.0 ) subtractBackgroundValue(Y,background); // Select the desired transformation function and call it TransformFunc f = m_transforms.find(getProperty("TransformType"))->second; (this->*f)(outputWS); // Need the generic label unit on this (unless the unit on the X axis hasn't changed) if ( ! m_label->caption().empty() ) outputWS->getAxis(0)->unit() = m_label; setProperty("OutputWorkspace",outputWS); }
void ExtractFFTSpectrum::exec() { MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); MatrixWorkspace_sptr inputImagWS = getProperty("InputImagWorkspace"); const int fftPart = getProperty("FFTPart"); const int numHists = static_cast<int>(inputWS->getNumberHistograms()); MatrixWorkspace_sptr outputWS = WorkspaceFactory::Instance().create(inputWS); Progress prog(this, 0.0, 1.0, numHists); PARALLEL_FOR1(outputWS) for ( int i = 0; i < numHists; i++ ) { PARALLEL_START_INTERUPT_REGION IAlgorithm_sptr childFFT = createChildAlgorithm("FFT"); childFFT->setProperty<MatrixWorkspace_sptr>("InputWorkspace", inputWS); childFFT->setProperty<int>("Real", i); if( inputImagWS ) { childFFT->setProperty<MatrixWorkspace_sptr>("InputImagWorkspace", inputImagWS); childFFT->setProperty<int>("Imaginary", i); } childFFT->execute(); MatrixWorkspace_const_sptr fftTemp = childFFT->getProperty("OutputWorkspace"); outputWS->dataE(i) = fftTemp->readE(fftPart); outputWS->dataY(i) = fftTemp->readY(fftPart); outputWS->dataX(i) = fftTemp->readX(fftPart); prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION boost::shared_ptr<Kernel::Units::Label> lblUnit = boost::dynamic_pointer_cast<Kernel::Units::Label>(UnitFactory::Instance().create("Label")); lblUnit->setLabel("Time", "ns"); outputWS->getAxis(0)->unit() = lblUnit; setProperty("OutputWorkspace", outputWS); }
void ConvertTableToMatrixWorkspace::exec() { ITableWorkspace_sptr inputWorkspace = getProperty("InputWorkspace"); std::string columnX = getProperty("ColumnX"); std::string columnY = getProperty("ColumnY"); std::string columnE = getProperty("ColumnE"); size_t nrows = inputWorkspace->rowCount(); std::vector<double> X(nrows); std::vector<double> Y(nrows); std::vector<double> E(nrows); inputWorkspace->getColumn(columnX)->numeric_fill(X); inputWorkspace->getColumn(columnY)->numeric_fill(Y); if (!columnE.empty()) { inputWorkspace->getColumn(columnE)->numeric_fill(E); } else { E.assign(X.size(),1.0); } MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create("Workspace2D",1,X.size(),X.size()); outputWorkspace->dataX(0).assign(X.begin(),X.end()); outputWorkspace->dataY(0).assign(Y.begin(),Y.end()); outputWorkspace->dataE(0).assign(E.begin(),E.end()); outputWorkspace->generateSpectraMap(); boost::shared_ptr<Kernel::Units::Label> labelX = boost::dynamic_pointer_cast<Kernel::Units::Label>( Kernel::UnitFactory::Instance().create("Label") ); labelX->setLabel(columnX); outputWorkspace->getAxis(0)->unit() = labelX; outputWorkspace->setYUnitLabel(columnY); setProperty("OutputWorkspace", outputWorkspace); }
/** Create output workspace * @brief GetSpiceDataRawCountsFromMD::createOutputWorkspace * @param vecX * @param vecY * @param xlabel :: only 'Degrees' can be applied to x-axis * @param ylabel * @return */ MatrixWorkspace_sptr GetSpiceDataRawCountsFromMD::createOutputWorkspace( const std::vector<double> &vecX, const std::vector<double> &vecY, const std::string &xlabel, const std::string &ylabel) { // Create MatrixWorkspace size_t sizex = vecX.size(); size_t sizey = vecY.size(); if (sizex != sizey || sizex == 0) throw std::runtime_error("Unable to create output matrix workspace."); MatrixWorkspace_sptr outws = boost::dynamic_pointer_cast<MatrixWorkspace>( WorkspaceFactory::Instance().create("Workspace2D", 1, sizex, sizey)); if (!outws) throw std::runtime_error("Failed to create output matrix workspace."); // Set data MantidVec &dataX = outws->dataX(0); MantidVec &dataY = outws->dataY(0); MantidVec &dataE = outws->dataE(0); for (size_t i = 0; i < sizex; ++i) { dataX[i] = vecX[i]; dataY[i] = vecY[i]; if (dataY[i] > 1.) dataE[i] = sqrt(dataY[i]); else dataE[i] = 1.; } // Set label outws->setYUnitLabel(ylabel); if (xlabel.size() != 0) { try { outws->getAxis(0)->setUnit(xlabel); } catch (...) { g_log.information() << "Label " << xlabel << " for X-axis is not a unit " "registered." << "\n"; } } return outws; }
void FlatBackground::exec() { // Retrieve the input workspace MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace"); // Copy over all the data const int numHists = static_cast<int>(inputWS->getNumberHistograms()); const int blocksize = static_cast<int>(inputWS->blocksize()); // Get the required X range double startX,endX; this->checkRange(startX,endX); std::vector<int> specInds = getProperty("WorkspaceIndexList"); // check if the user passed an empty list, if so all of spec will be processed this->getSpecInds(specInds, numHists); // Are we removing the background? const bool removeBackground = std::string(getProperty("outputMode")) == "Subtract Background"; // Initialise the progress reporting object m_progress = new Progress(this,0.0,0.2,numHists); MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); // If input and output workspaces are not the same, create a new workspace for the output if (outputWS != inputWS ) { outputWS = WorkspaceFactory::Instance().create(inputWS); PARALLEL_FOR2(inputWS,outputWS) for (int i = 0; i < numHists; ++i) { PARALLEL_START_INTERUPT_REGION outputWS->dataX(i) = inputWS->readX(i); outputWS->dataY(i) = inputWS->readY(i); outputWS->dataE(i) = inputWS->readE(i); m_progress->report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION }
/** * Groups the workspace according to grouping provided. * * @param ws :: Workspace to group * @param g :: The grouping information * @return Sptr to created grouped workspace */ MatrixWorkspace_sptr groupWorkspace(MatrixWorkspace_const_sptr ws, const Grouping& g) { // As I couldn't specify multiple groups for GroupDetectors, I am going down quite a complicated // route - for every group distinct grouped workspace is created using GroupDetectors. These // workspaces are then merged into the output workspace. // Create output workspace MatrixWorkspace_sptr outWs = WorkspaceFactory::Instance().create(ws, g.groups.size(), ws->readX(0).size(), ws->blocksize()); for(size_t gi = 0; gi < g.groups.size(); gi++) { Mantid::API::IAlgorithm_sptr alg = AlgorithmManager::Instance().create("GroupDetectors"); alg->setChild(true); // So Output workspace is not added to the ADS alg->initialize(); alg->setProperty("InputWorkspace", boost::const_pointer_cast<MatrixWorkspace>(ws)); alg->setPropertyValue("SpectraList", g.groups[gi]); alg->setPropertyValue("OutputWorkspace", "grouped"); // Is not actually used, just to make validators happy alg->execute(); MatrixWorkspace_sptr grouped = alg->getProperty("OutputWorkspace"); // Copy the spectrum *(outWs->getSpectrum(gi)) = *(grouped->getSpectrum(0)); // Update spectrum number outWs->getSpectrum(gi)->setSpectrumNo(static_cast<specid_t>(gi)); // Copy to the output workspace outWs->dataY(gi) = grouped->readY(0); outWs->dataX(gi) = grouped->readX(0); outWs->dataE(gi) = grouped->readE(0); } return outWs; }
/** Execute the algorithm. */ void PDFFT::exec() { // Accept d-space S(d) // // 1. Generate a Workspace for G const double rmax = getProperty("RMax"); const double deltarc = getProperty("DeltaR"); double qmax = getProperty("Qmax"); double qmin = getProperty("Qmin"); std::string typeSofQ = getProperty("InputSofQType"); //std::string typeGofR = getProperty("PDFType"); // b) Process input, including defaults double deltar; if (deltarc <= 0){ deltar = M_PI/qmax; } else { deltar = deltarc; } int sizer = static_cast<int>(rmax/deltar); bool sofq = true; if (typeSofQ == "S(Q)-1"){ sofq = false; g_log.information() << "Input is S(Q)-1" << std::endl; } else { g_log.information() << "Input is S(Q)" << std::endl; } // 2. Set up G(r) dataX(0) Gspace = WorkspaceFactory::Instance().create("Workspace2D", 1, sizer, sizer); Gspace->getAxis(0)->unit() = UnitFactory::Instance().create("Label"); Unit_sptr unit = Gspace->getAxis(0)->unit(); boost::shared_ptr<Units::Label> label = boost::dynamic_pointer_cast<Units::Label>(unit); label->setLabel("AtomicDistance", "Angstrom"); // Gspace->getAxis(0)->unit()->setLabel("caption", "label"); Gspace->setYUnitLabel("PDF"); MantidVec& vr = Gspace->dataX(0); MantidVec& vg = Gspace->dataY(0); MantidVec& vge = Gspace->dataE(0); for (int i = 0; i < sizer; i++) { vr[i] = deltar * (1 + i); } Sspace = getProperty("InputWorkspace"); // 3. Check input workgroup, esp. the UNIT std::string strunit; Unit_sptr& iunit = Sspace->getAxis(0)->unit(); if (iunit->unitID() == "dSpacing") { strunit = "d"; } else if (iunit->unitID() == "MomentumTransfer") { strunit = "Q"; } else { g_log.error() << "Unit " << iunit->unitID() << " is not supported" << std::endl; throw std::invalid_argument("Unit of input Workspace is not supported"); } g_log.information() << "Range of Q for F.T. : (" << qmin << ", " << qmax << ")\n"; // 4. Check datamax, datamin and do Fourier transform const MantidVec& inputx = Sspace->readX(0); int sizesq = static_cast<int>(inputx.size()); double error; if (strunit == "d") { // d-Spacing g_log.information()<< "Fourier Transform in d-Space" << std::endl; double datadmax = 2 * M_PI / inputx[inputx.size() - 1]; double datadmin = 2 * M_PI / inputx[0]; double dmin = 2*M_PI/qmax; double dmax = 2*M_PI/qmin; if (dmin < datadmin) { g_log.notice() << "User input dmin = " << dmin << "is out of range. Using Min(d) = " << datadmin << "instead\n"; dmin = datadmin; } if (dmax > datadmax) { g_log.notice() << "User input dmax = " << dmax << "is out of range. Using Max(d) = " << datadmax << "instead\n"; dmax = datadmax; } for (int i = 0; i < sizer; i ++){ vg[i] = CalculateGrFromD(vr[i], error, dmin, dmax, sofq); vge[i] = error; } } else if (strunit == "Q"){ // Q-spacing g_log.information()<< "Fourier Transform in Q-Space" << std::endl; double dataqmin = inputx[0]; double dataqmax = inputx[inputx.size() - 1]; if (qmin < dataqmin) { g_log.notice() << "User input qmin = " << qmin << "is out of range. Using Min(Q) = " << dataqmin << "instead\n"; qmin = dataqmin; } if (qmax > dataqmax) { g_log.notice() << "User input qmax = " << qmax << "is out of range. Using Max(Q) = " << dataqmax << "instead\n"; qmax = dataqmax; } for (int i = 0; i < sizer; i ++){ vg[i] = CalculateGrFromQ(vr[i], error, qmin, qmax, sofq); vge[i] = error; } } // ENDIF unit // 3. TODO Calculate rho(r)???? // 3.2 Calculate QS(Q) MatrixWorkspace_sptr QSspace = WorkspaceFactory::Instance().create( "Workspace2D", 1, sizesq, sizesq); const MantidVec& vecq = Sspace->readX(0); const MantidVec& vecs = Sspace->readY(0); // const MantidVec& vece = Sspace->dataE(0); MantidVec& qsqq = QSspace->dataX(0); MantidVec& qsqs = QSspace->dataY(0); MantidVec& qsqe = QSspace->dataE(0); for (int i = 0; i < sizesq; i ++){ qsqq[i] = vecq[i]; qsqs[i] = vecq[i]*(vecs[i]-1); qsqe[i] = 0.0; } // 4. Set property setProperty("OutputWorkspace", Gspace); return; }
/** @ throw invalid_argument if the workspaces are not mututially compatible */ void Q1D2::exec() { m_dataWS = getProperty("DetBankWorkspace"); MatrixWorkspace_const_sptr waveAdj = getProperty("WavelengthAdj"); MatrixWorkspace_const_sptr pixelAdj = getProperty("PixelAdj"); MatrixWorkspace_const_sptr wavePixelAdj = getProperty("WavePixelAdj"); const bool doGravity = getProperty("AccountForGravity"); m_doSolidAngle = getProperty("SolidAngleWeighting"); //throws if we don't have common binning or another incompatibility Qhelper helper; helper.examineInput(m_dataWS, waveAdj, pixelAdj); // FIXME: how to examine the wavePixelAdj? g_log.debug() << "All input workspaces were found to be valid\n"; // normalization as a function of wavelength (i.e. centers of x-value bins) double const * const binNorms = waveAdj ? &(waveAdj->readY(0)[0]) : NULL; // error on the wavelength normalization double const * const binNormEs = waveAdj ? &(waveAdj->readE(0)[0]) : NULL; //define the (large number of) data objects that are going to be used in all iterations of the loop below // this will become the output workspace from this algorithm MatrixWorkspace_sptr outputWS = setUpOutputWorkspace(getProperty("OutputBinning")); const MantidVec & QOut = outputWS->readX(0); MantidVec & YOut = outputWS->dataY(0); MantidVec & EOutTo2 = outputWS->dataE(0); // normalisation that is applied to counts in each Q bin MantidVec normSum(YOut.size(), 0.0); // the error on the normalisation MantidVec normError2(YOut.size(), 0.0); const int numSpec = static_cast<int>(m_dataWS->getNumberHistograms()); Progress progress(this, 0.05, 1.0, numSpec+1); PARALLEL_FOR3(m_dataWS, outputWS, pixelAdj) for (int i = 0; i < numSpec; ++i) { PARALLEL_START_INTERUPT_REGION // Get the pixel relating to this spectrum IDetector_const_sptr det; try { det = m_dataWS->getDetector(i); } catch (Exception::NotFoundError&) { g_log.warning() << "Workspace index " << i << " (SpectrumIndex = " << m_dataWS->getSpectrum(i)->getSpectrumNo() << ") has no detector assigned to it - discarding" << std::endl; // Catch if no detector. Next line tests whether this happened - test placed // outside here because Mac Intel compiler doesn't like 'continue' in a catch // in an openmp block. } // If no detector found or if detector is masked shouldn't be included skip onto the next spectrum if ( !det || det->isMonitor() || det->isMasked() ) { continue; } //get the bins that are included inside the RadiusCut/WaveCutcut off, those to calculate for //const size_t wavStart = waveLengthCutOff(i); const size_t wavStart = helper.waveLengthCutOff(m_dataWS, getProperty("RadiusCut"), getProperty("WaveCut"), i); if (wavStart >= m_dataWS->readY(i).size()) { // all the spectra in this detector are out of range continue; } const size_t numWavbins = m_dataWS->readY(i).size()-wavStart; // make just one call to new to reduce CPU overhead on each thread, access to these // three "arrays" is via iterators MantidVec _noDirectUseStorage_(3*numWavbins); //normalization term MantidVec::iterator norms = _noDirectUseStorage_.begin(); // the error on these weights, it contributes to the error calculation on the output workspace MantidVec::iterator normETo2s = norms + numWavbins; // the Q values calculated from input wavelength workspace MantidVec::iterator QIn = normETo2s + numWavbins; // the weighting for this input spectrum that is added to the normalization calculateNormalization(wavStart, i, pixelAdj, wavePixelAdj, binNorms, binNormEs, norms, normETo2s); // now read the data from the input workspace, calculate Q for each bin convertWavetoQ(i, doGravity, wavStart, QIn); // Pointers to the counts data and it's error MantidVec::const_iterator YIn = m_dataWS->readY(i).begin()+wavStart; MantidVec::const_iterator EIn = m_dataWS->readE(i).begin()+wavStart; //when finding the output Q bin remember that the input Q bins (from the convert to wavelength) start high and reduce MantidVec::const_iterator loc = QOut.end(); // sum the Q contributions from each individual spectrum into the output array const MantidVec::const_iterator end = m_dataWS->readY(i).end(); for( ; YIn != end; ++YIn, ++EIn, ++QIn, ++norms, ++normETo2s) { //find the output bin that each input y-value will fall into, remembering there is one more bin boundary than bins getQBinPlus1(QOut, *QIn, loc); // ignore counts that are out of the output range if ( (loc != QOut.begin()) && (loc != QOut.end()) ) { // the actual Q-bin to add something to const size_t bin = loc - QOut.begin() - 1; PARALLEL_CRITICAL(q1d_counts_sum) { YOut[bin] += *YIn; normSum[bin] += *norms; //these are the errors squared which will be summed and square rooted at the end EOutTo2[bin] += (*EIn)*(*EIn); normError2[bin] += *normETo2s; } } } PARALLEL_CRITICAL(q1d_spectra_map) { progress.report("Computing I(Q)"); // Add up the detector IDs in the output spectrum at workspace index 0 const ISpectrum * inSpec = m_dataWS->getSpectrum(i); ISpectrum * outSpec = outputWS->getSpectrum(0); outSpec->addDetectorIDs( inSpec->getDetectorIDs() ); } PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION bool doOutputParts = getProperty("OutputParts"); if (doOutputParts) { MatrixWorkspace_sptr ws_sumOfCounts = WorkspaceFactory::Instance().create(outputWS); ws_sumOfCounts->dataX(0) = outputWS->dataX(0); ws_sumOfCounts->dataY(0) = outputWS->dataY(0); for (size_t i = 0; i < outputWS->dataE(0).size(); i++) { ws_sumOfCounts->dataE(0)[i] = sqrt(outputWS->dataE(0)[i]); } MatrixWorkspace_sptr ws_sumOfNormFactors = WorkspaceFactory::Instance().create(outputWS); ws_sumOfNormFactors->dataX(0) = outputWS->dataX(0); for (size_t i = 0; i < ws_sumOfNormFactors->dataY(0).size(); i++) { ws_sumOfNormFactors->dataY(0)[i] = normSum[i]; ws_sumOfNormFactors->dataE(0)[i] = sqrt(normError2[i]); } helper.outputParts(this, ws_sumOfCounts, ws_sumOfNormFactors); } progress.report("Normalizing I(Q)"); //finally divide the number of counts in each output Q bin by its weighting normalize(normSum, normError2, YOut, EOutTo2); outputWS->updateSpectraUsingMap(); setProperty("OutputWorkspace",outputWS); }
/** Execute the algorithm. */ void LoadNXSPE::exec() { std::string filename = getProperty("Filename"); // quicly check if it's really nxspe try { ::NeXus::File file(filename); std::string mainEntry = (*(file.getEntries().begin())).first; file.openGroup(mainEntry, "NXentry"); file.openData("definition"); if (identiferConfidence(file.getStrData()) < 1) { throw std::invalid_argument("Not NXSPE"); } file.close(); } catch (...) { throw std::invalid_argument("Not NeXus or not NXSPE"); } // Load the data ::NeXus::File file(filename); std::string mainEntry = (*(file.getEntries().begin())).first; file.openGroup(mainEntry, "NXentry"); file.openGroup("NXSPE_info", "NXcollection"); std::map<std::string, std::string> entries = file.getEntries(); std::vector<double> temporary; double fixed_energy, psi = 0.; if (!entries.count("fixed_energy")) { throw std::invalid_argument("fixed_energy field was not found"); } file.openData("fixed_energy"); file.getData(temporary); fixed_energy = temporary.at(0); file.closeData(); if (entries.count("psi")) { file.openData("psi"); file.getData(temporary); psi = temporary.at(0); file.closeData(); } int kikfscaling = 0; if (entries.count("ki_over_kf_scaling")) { file.openData("ki_over_kf_scaling"); std::vector<int> temporaryint; file.getData(temporaryint); kikfscaling = temporaryint.at(0); file.closeData(); } file.closeGroup(); // NXSPE_Info file.openGroup("data", "NXdata"); entries = file.getEntries(); if (!entries.count("data")) { throw std::invalid_argument("data field was not found"); } file.openData("data"); ::NeXus::Info info = file.getInfo(); std::size_t numSpectra = static_cast<std::size_t>(info.dims.at(0)); std::size_t numBins = static_cast<std::size_t>(info.dims.at(1)); std::vector<double> data; file.getData(data); file.closeData(); if (!entries.count("error")) { throw std::invalid_argument("error field was not found"); } file.openData("error"); std::vector<double> error; file.getData(error); file.closeData(); if (!entries.count("energy")) { throw std::invalid_argument("energy field was not found"); } file.openData("energy"); std::vector<double> energies; file.getData(energies); file.closeData(); if (!entries.count("azimuthal")) { throw std::invalid_argument("azimuthal field was not found"); } file.openData("azimuthal"); std::vector<double> azimuthal; file.getData(azimuthal); file.closeData(); if (!entries.count("azimuthal_width")) { throw std::invalid_argument("azimuthal_width field was not found"); } file.openData("azimuthal_width"); std::vector<double> azimuthal_width; file.getData(azimuthal_width); file.closeData(); if (!entries.count("polar")) { throw std::invalid_argument("polar field was not found"); } file.openData("polar"); std::vector<double> polar; file.getData(polar); file.closeData(); if (!entries.count("polar_width")) { throw std::invalid_argument("polar_width field was not found"); } file.openData("polar_width"); std::vector<double> polar_width; file.getData(polar_width); file.closeData(); // distance might not have been saved in all NXSPE files std::vector<double> distance; if (entries.count("distance")) { file.openData("distance"); file.getData(distance); file.closeData(); } file.closeGroup(); // data group file.closeGroup(); // Main entry file.close(); // check if dimensions of the vectors are correct if ((error.size() != data.size()) || (azimuthal.size() != numSpectra) || (azimuthal_width.size() != numSpectra) || (polar.size() != numSpectra) || (polar_width.size() != numSpectra) || ((energies.size() != numBins) && (energies.size() != numBins + 1))) { throw std::invalid_argument( "incompatible sizes of fields in the NXSPE file"); } MatrixWorkspace_sptr outputWS = boost::dynamic_pointer_cast<MatrixWorkspace>( WorkspaceFactory::Instance().create("Workspace2D", numSpectra, energies.size(), numBins)); // Need to get hold of the parameter map outputWS->getAxis(0)->unit() = UnitFactory::Instance().create("DeltaE"); outputWS->setYUnit("SpectraNumber"); // add logs outputWS->mutableRun().addLogData( new PropertyWithValue<double>("Ei", fixed_energy)); outputWS->mutableRun().addLogData(new PropertyWithValue<double>("psi", psi)); outputWS->mutableRun().addLogData(new PropertyWithValue<std::string>( "ki_over_kf_scaling", kikfscaling == 1 ? "true" : "false")); // Set Goniometer Geometry::Goniometer gm; gm.pushAxis("psi", 0, 1, 0, psi); outputWS->mutableRun().setGoniometer(gm, true); // generate instrument Geometry::Instrument_sptr instrument(new Geometry::Instrument("NXSPE")); outputWS->setInstrument(instrument); Geometry::ObjComponent *source = new Geometry::ObjComponent("source"); source->setPos(0.0, 0.0, -10.0); instrument->add(source); instrument->markAsSource(source); Geometry::ObjComponent *sample = new Geometry::ObjComponent("sample"); instrument->add(sample); instrument->markAsSamplePos(sample); Geometry::Object_const_sptr cuboid( createCuboid(0.1, 0.1, 0.1)); // FIXME: memory hog on rendering. Also, // make each detector separate size for (std::size_t i = 0; i < numSpectra; ++i) { double r = 1.0; if (!distance.empty()) { r = distance.at(i); } Kernel::V3D pos; pos.spherical(r, polar.at(i), azimuthal.at(i)); Geometry::Detector *det = new Geometry::Detector("pixel", static_cast<int>(i + 1), sample); det->setPos(pos); det->setShape(cuboid); instrument->add(det); instrument->markAsDetector(det); } Geometry::ParameterMap &pmap = outputWS->instrumentParameters(); std::vector<double>::iterator itdata = data.begin(), iterror = error.begin(), itdataend, iterrorend; API::Progress prog = API::Progress(this, 0.0, 0.9, numSpectra); for (std::size_t i = 0; i < numSpectra; ++i) { itdataend = itdata + numBins; iterrorend = iterror + numBins; outputWS->dataX(i) = energies; if ((!boost::math::isfinite(*itdata)) || (*itdata <= -1e10)) // masked bin { outputWS->dataY(i) = std::vector<double>(numBins, 0); outputWS->dataE(i) = std::vector<double>(numBins, 0); pmap.addBool(outputWS->getDetector(i)->getComponentID(), "masked", true); } else { outputWS->dataY(i) = std::vector<double>(itdata, itdataend); outputWS->dataE(i) = std::vector<double>(iterror, iterrorend); } itdata = (itdataend); iterror = (iterrorend); prog.report(); } setProperty("OutputWorkspace", outputWS); }
/** Executes the algorithm * * @throw runtime_error Thrown if algorithm cannot execute */ void MaxMin::exec() { // Try and retrieve the optional properties m_MinRange = getProperty("RangeLower"); m_MaxRange = getProperty("RangeUpper"); m_MinSpec = getProperty("StartWorkspaceIndex"); m_MaxSpec = getProperty("EndWorkspaceIndex"); showMin = getProperty("ShowMin"); // Get the input workspace MatrixWorkspace_const_sptr localworkspace = getProperty("InputWorkspace"); const int numberOfSpectra = static_cast<int>(localworkspace->getNumberHistograms()); // Check 'StartSpectrum' is in range 0-numberOfSpectra if ( m_MinSpec > numberOfSpectra ) { g_log.warning("StartSpectrum out of range! Set to 0."); m_MinSpec = 0; } if ( isEmpty(m_MaxSpec) ) m_MaxSpec = numberOfSpectra-1; if ( m_MaxSpec > numberOfSpectra-1 || m_MaxSpec < m_MinSpec ) { g_log.warning("EndSpectrum out of range! Set to max detector number"); m_MaxSpec = numberOfSpectra; } if ( m_MinRange > m_MaxRange ) { g_log.warning("Range_upper is less than Range_lower. Will integrate up to frame maximum."); m_MaxRange = 0.0; } // Create the 1D workspace for the output MatrixWorkspace_sptr outputWorkspace = API::WorkspaceFactory::Instance().create(localworkspace,m_MaxSpec-m_MinSpec+1,2,1); Progress progress(this,0,1,(m_MaxSpec-m_MinSpec+1)); PARALLEL_FOR2(localworkspace,outputWorkspace) // Loop over spectra for (int i = m_MinSpec; i <= m_MaxSpec; ++i) { PARALLEL_START_INTERUPT_REGION int newindex=i-m_MinSpec; // Copy over spectrum and detector number info outputWorkspace->getSpectrum(newindex)->copyInfoFrom(*localworkspace->getSpectrum(i)); // Retrieve the spectrum into a vector const MantidVec& X = localworkspace->readX(i); const MantidVec& Y = localworkspace->readY(i); // Find the range [min,max] MantidVec::const_iterator lowit, highit; if (m_MinRange == EMPTY_DBL()) lowit=X.begin(); else lowit=std::lower_bound(X.begin(),X.end(),m_MinRange); if (m_MaxRange == EMPTY_DBL()) highit=X.end(); else highit=std::find_if(lowit,X.end(),std::bind2nd(std::greater<double>(),m_MaxRange)); // If range specified doesn't overlap with this spectrum then bail out if ( lowit == X.end() || highit == X.begin() ) continue; --highit; // Upper limit is the bin before, i.e. the last value smaller than MaxRange MantidVec::difference_type distmin=std::distance(X.begin(),lowit); MantidVec::difference_type distmax=std::distance(X.begin(),highit); MantidVec::const_iterator maxY; // Find the max/min element if (showMin==true) { maxY=std::min_element(Y.begin()+distmin,Y.begin()+distmax); } else { maxY=std::max_element(Y.begin()+distmin,Y.begin()+distmax); } MantidVec::difference_type d=std::distance(Y.begin(),maxY); // X boundaries for the max/min element outputWorkspace->dataX(newindex)[0]=*(X.begin()+d); outputWorkspace->dataX(newindex)[1]=*(X.begin()+d+1); //This is safe since X is of dimension Y+1 outputWorkspace->dataY(newindex)[0]=*maxY; progress.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION // Assign it to the output workspace property setProperty("OutputWorkspace",outputWorkspace); return; }
/** Read a data file that contains only one spectrum into a workspace * @return the new workspace */ const API::MatrixWorkspace_sptr LoadRKH::read1D() { g_log.information() << "file appears to contain 1D information, reading in 1D data mode\n"; //The 3rd line contains information regarding the number of points in the file and // start and end reading points int totalPoints(0), readStart(0), readEnd(0), buried(0); std::string fileline; getline(m_fileIn, fileline); std::istringstream is(fileline); //Get data information for( int counter = 1; counter < 8; ++counter ) { switch( counter ) { case 1: is >> totalPoints; break; case 5: is >> readStart; break; case 6: is >> readEnd; break; default: is >> buried; break; } } g_log.information() << "Total number of data points declared to be in the data file: " << totalPoints << "\n"; //What are we reading? std::string firstColVal = getProperty("FirstColumnValue"); bool colIsUnit(true); if( m_RKHKeys.find( firstColVal ) != m_RKHKeys.end() ) { colIsUnit = false; readStart = 1; readEnd = totalPoints; } if( readStart < 1 || readEnd < 1 || readEnd < readStart || readStart > totalPoints || readEnd > totalPoints ) { g_log.error("Invalid data range specfied."); m_fileIn.close(); throw std::invalid_argument("Invalid data range specfied."); } g_log.information() << "Reading started on data line: " << readStart << "\n"; g_log.information() << "Reading finished on data line: " << readEnd << "\n"; //The 4th and 5th line do not contain useful information either skipLines(m_fileIn, 2); int pointsToRead = readEnd - readStart + 1; //Now stream sits at the first line of data fileline = ""; std::vector<double> columnOne, ydata, errdata; columnOne.reserve(readEnd); ydata.reserve(readEnd); errdata.reserve(readEnd); Progress prog(this,0.0,1.0,readEnd); for( int index = 1; index <= readEnd; ++index ) { getline(m_fileIn, fileline); if( index < readStart ) continue; double x(0.), y(0.), yerr(0.); std::istringstream datastr(fileline); datastr >> x >> y >> yerr; columnOne.push_back(x); ydata.push_back(y); errdata.push_back(yerr); prog.report(); } m_fileIn.close(); assert( pointsToRead == static_cast<int>(columnOne.size()) ); assert( pointsToRead == static_cast<int>(ydata.size()) ); assert( pointsToRead == static_cast<int>(errdata.size()) ); if( colIsUnit ) { MatrixWorkspace_sptr localworkspace = WorkspaceFactory::Instance().create("Workspace2D", 1, pointsToRead, pointsToRead); localworkspace->getAxis(0)->unit() = UnitFactory::Instance().create(firstColVal); localworkspace->dataX(0) = columnOne; localworkspace->dataY(0) = ydata; localworkspace->dataE(0) = errdata; return localworkspace; } else { MatrixWorkspace_sptr localworkspace = WorkspaceFactory::Instance().create("Workspace2D", pointsToRead, 1, 1); //Set the appropriate values for( int index = 0; index < pointsToRead; ++index ) { localworkspace->getAxis(1)->setValue(index, static_cast<int>(columnOne[index])); localworkspace->dataY(index)[0] = ydata[index]; localworkspace->dataE(index)[0] = errdata[index]; } return localworkspace; } }
void Linear::exec() { // Get the input workspace MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace"); // Get the spectrum to fit const int histNumber = getProperty("WorkspaceIndex"); // Check validity if ( histNumber >= static_cast<int>(inputWorkspace->getNumberHistograms()) ) { g_log.error() << "WorkspaceIndex set to an invalid value of " << histNumber << std::endl; throw Exception::IndexError(histNumber,inputWorkspace->getNumberHistograms(),"Linear WorkspaceIndex property"); } // Get references to the data in the chosen spectrum const MantidVec& X = inputWorkspace->dataX(histNumber); const MantidVec& Y = inputWorkspace->dataY(histNumber); const MantidVec& E = inputWorkspace->dataE(histNumber); // Check if this spectrum has errors double errorsCount = 0.0; // Retrieve the Start/EndX properties, if set this->setRange(X,Y); const bool isHistogram = inputWorkspace->isHistogramData(); // If the spectrum to be fitted has masked bins, we want to exclude them (even if only partially masked) const MatrixWorkspace::MaskList * const maskedBins = ( inputWorkspace->hasMaskedBins(histNumber) ? &(inputWorkspace->maskedBins(histNumber)) : NULL ); // Put indices of masked bins into a set for easy searching later std::set<size_t> maskedIndices; if (maskedBins) { MatrixWorkspace::MaskList::const_iterator it; for (it = maskedBins->begin(); it != maskedBins->end(); ++it) maskedIndices.insert(it->first); } progress(0); // Declare temporary vectors and reserve enough space if they're going to be used std::vector<double> XCen, unmaskedY, weights; int numPoints = m_maxX - m_minX; if (isHistogram) XCen.reserve(numPoints); if (maskedBins) unmaskedY.reserve(numPoints); weights.reserve(numPoints); for (int i = 0; i < numPoints; ++i) { // If the current bin is masked, skip it if ( maskedBins && maskedIndices.count(m_minX+i) ) continue; // Need to adjust X to centre of bin, if a histogram if (isHistogram) XCen.push_back( 0.5*(X[m_minX+i]+X[m_minX+i+1]) ); // If there are masked bins present, we need to copy the unmasked Y values if (maskedBins) unmaskedY.push_back(Y[m_minX+i]); // GSL wants the errors as weights, i.e. 1/sigma^2 // We need to be careful if E is zero because that would naively lead to an infinite weight on the point. // Solution taken here is to zero weight if error is zero, which typically means Y is zero // (so it is effectively excluded from the fit). const double& currentE = E[m_minX+i]; weights.push_back( currentE ? 1.0/(currentE*currentE) : 0.0 ); // However, if the spectrum given has all errors of zero, then we should use the gsl function that // doesn't take account of the errors. if ( currentE ) ++errorsCount; } progress(0.3); // If masked bins present, need to recalculate numPoints here if (maskedBins) numPoints = static_cast<int>(unmaskedY.size()); // If no points left for any reason, bail out if (numPoints == 0) { g_log.error("No points in this range to fit"); throw std::runtime_error("No points in this range to fit"); } // Set up pointer variables to pass to gsl, pointing them to the right place const double * const xVals = ( isHistogram ? &XCen[0] : &X[m_minX] ); const double * const yVals = ( maskedBins ? &unmaskedY[0] : &Y[m_minX] ); // Call the gsl fitting function // The stride value of 1 reflects that fact that we want every element of our input vectors const int stride = 1; double *c0(new double),*c1(new double),*cov00(new double),*cov01(new double),*cov11(new double),*chisq(new double); int status; // Unless our spectrum has error values for vast majority of points, // call the gsl function that doesn't use errors if ( errorsCount/numPoints < 0.9 ) { g_log.debug("Calling gsl_fit_linear (doesn't use errors in fit)"); status = gsl_fit_linear(xVals,stride,yVals,stride,numPoints,c0,c1,cov00,cov01,cov11,chisq); } // Otherwise, call the one that does account for errors on the data points else { g_log.debug("Calling gsl_fit_wlinear (uses errors in fit)"); status = gsl_fit_wlinear(xVals,stride,&weights[0],stride,yVals,stride,numPoints,c0,c1,cov00,cov01,cov11,chisq); } progress(0.8); // Check that the fit succeeded std::string fitStatus = gsl_strerror(status); // For some reason, a fit where c0,c1 & chisq are all infinity doesn't report as a // failure, so check explicitly. if ( !gsl_finite(*chisq) || !gsl_finite(*c0) || !gsl_finite(*c1) ) fitStatus = "Fit gives infinities"; if (fitStatus != "success") g_log.error() << "The fit failed: " << fitStatus << "\n"; else g_log.information() << "The fit succeeded, giving y = " << *c0 << " + " << *c1 << "*x, with a Chi^2 of " << *chisq << "\n"; // Set the fit result output properties setProperty("FitStatus",fitStatus); setProperty("FitIntercept",*c0); setProperty("FitSlope",*c1); setProperty("Cov00",*cov00); setProperty("Cov11",*cov11); setProperty("Cov01",*cov01); setProperty("Chi2",*chisq); // Create and fill a workspace2D with the same bins as the fitted spectrum and the value of the fit for the centre of each bin const size_t YSize = Y.size(); MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create(inputWorkspace,1,X.size(),YSize); // Copy over the X bins outputWorkspace->dataX(0).assign(X.begin(),X.end()); // Now loop over the spectrum and use gsl function to calculate the Y & E values for the function for (size_t i = 0; i < YSize; ++i) { const double x = ( isHistogram ? 0.5*(X[i]+X[i+1]) : X[i] ); const int err = gsl_fit_linear_est(x,*c0,*c1,*cov00,*cov01,*cov11,&(outputWorkspace->dataY(0)[i]),&(outputWorkspace->dataE(0)[i])); if (err) g_log.warning() << "Problem in filling the output workspace: " << gsl_strerror(err) << std::endl; } setProperty("OutputWorkspace",outputWorkspace); progress(1); // Clean up delete c0; delete c1; delete cov00; delete cov01; delete cov11; delete chisq; }
/** * Make 2D MatrixWorkspace */ void ConvertMDHistoToMatrixWorkspace::make2DWorkspace() { // get the input workspace IMDHistoWorkspace_sptr inputWorkspace = getProperty("InputWorkspace"); // find the non-integrated dimensions Mantid::Geometry::VecIMDDimension_const_sptr nonIntegDims = inputWorkspace->getNonIntegratedDimensions(); auto xDim = nonIntegDims[0]; auto yDim = nonIntegDims[1]; size_t nx = xDim->getNBins(); size_t ny = yDim->getNBins(); size_t xDimIndex = inputWorkspace->getDimensionIndexById(xDim->getDimensionId()); size_t xStride = calcStride(*inputWorkspace, xDimIndex); size_t yDimIndex = inputWorkspace->getDimensionIndexById(yDim->getDimensionId()); size_t yStride = calcStride(*inputWorkspace, yDimIndex); // get the normalization of the output std::string normProp = getPropertyValue("Normalization"); Mantid::API::MDNormalization normalization; if (normProp == "NoNormalization") { normalization = NoNormalization; } else if (normProp == "VolumeNormalization") { normalization = VolumeNormalization; } else if (normProp == "NumEventsNormalization") { normalization = NumEventsNormalization; } else { normalization = NoNormalization; } signal_t inverseVolume = static_cast<signal_t>(inputWorkspace->getInverseVolume()); // create the output workspace MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create("Workspace2D", ny, nx + 1, nx); // set the x-values Mantid::MantidVec &X = outputWorkspace->dataX(0); double dx = xDim->getBinWidth(); double x = xDim->getMinimum(); for (auto ix = X.begin(); ix != X.end(); ++ix, x += dx) { *ix = x; } // set the y-values and errors for (size_t i = 0; i < ny; ++i) { if (i > 0) outputWorkspace->setX(i, X); auto &Y = outputWorkspace->dataY(i); auto &E = outputWorkspace->dataE(i); size_t yOffset = i * yStride; for (size_t j = 0; j < nx; ++j) { size_t linearIndex = yOffset + j * xStride; signal_t signal = inputWorkspace->getSignalArray()[linearIndex]; signal_t error = inputWorkspace->getErrorSquaredArray()[linearIndex]; // apply normalization if (normalization != NoNormalization) { if (normalization == VolumeNormalization) { signal *= inverseVolume; error *= inverseVolume; } else // normalization == NumEventsNormalization { signal_t factor = inputWorkspace->getNumEventsArray()[linearIndex]; factor = factor != 0.0 ? 1.0 / factor : 1.0; signal *= factor; error *= factor; } } Y[j] = signal; E[j] = sqrt(error); } } // set the first axis auto labelX = boost::dynamic_pointer_cast<Kernel::Units::Label>( Kernel::UnitFactory::Instance().create("Label")); labelX->setLabel(xDim->getName()); outputWorkspace->getAxis(0)->unit() = labelX; // set the second axis auto yAxis = new NumericAxis(ny); for (size_t i = 0; i < ny; ++i) { yAxis->setValue(i, yDim->getX(i)); } auto labelY = boost::dynamic_pointer_cast<Kernel::Units::Label>( Kernel::UnitFactory::Instance().create("Label")); labelY->setLabel(yDim->getName()); yAxis->unit() = labelY; outputWorkspace->replaceAxis(1, yAxis); // set the "units" for the y values outputWorkspace->setYUnitLabel("Signal"); // done setProperty("OutputWorkspace", outputWorkspace); }
void SANSSolidAngleCorrection::exec() { // Reduction property manager const std::string reductionManagerName = getProperty("ReductionProperties"); boost::shared_ptr<PropertyManager> reductionManager; if (PropertyManagerDataService::Instance().doesExist(reductionManagerName)) { reductionManager = PropertyManagerDataService::Instance().retrieve(reductionManagerName); } else { reductionManager = boost::make_shared<PropertyManager>(); PropertyManagerDataService::Instance().addOrReplace(reductionManagerName, reductionManager); } // If the solid angle algorithm isn't in the reduction properties, add it if (!reductionManager->existsProperty("SolidAngleAlgorithm")) { AlgorithmProperty *algProp = new AlgorithmProperty("SolidAngleAlgorithm"); algProp->setValue(toString()); reductionManager->declareProperty(algProp); } MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace"); DataObjects::EventWorkspace_const_sptr inputEventWS = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS); if (inputEventWS) return execEvent(); // Now create the output workspace MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); if (outputWS != inputWS) { outputWS = WorkspaceFactory::Instance().create(inputWS); outputWS->isDistribution(true); outputWS->setYUnit(""); outputWS->setYUnitLabel("Steradian"); setProperty("OutputWorkspace", outputWS); } const int numHists = static_cast<int>(inputWS->getNumberHistograms()); Progress progress(this, 0.0, 1.0, numHists); // Number of X bins const int xLength = static_cast<int>(inputWS->readY(0).size()); PARALLEL_FOR2(outputWS, inputWS) for (int i = 0; i < numHists; ++i) { PARALLEL_START_INTERUPT_REGION outputWS->dataX(i) = inputWS->readX(i); IDetector_const_sptr det; try { det = inputWS->getDetector(i); } catch (Exception::NotFoundError &) { g_log.warning() << "Spectrum index " << i << " has no detector assigned to it - discarding" << std::endl; // Catch if no detector. Next line tests whether this happened - test // placed // outside here because Mac Intel compiler doesn't like 'continue' in a // catch // in an openmp block. } // If no detector found, skip onto the next spectrum if (!det) continue; // Skip if we have a monitor or if the detector is masked. if (det->isMonitor() || det->isMasked()) continue; const MantidVec &YIn = inputWS->readY(i); const MantidVec &EIn = inputWS->readE(i); MantidVec &YOut = outputWS->dataY(i); MantidVec &EOut = outputWS->dataE(i); // Compute solid angle correction factor const bool is_tube = getProperty("DetectorTubes"); const double tanTheta = tan(inputWS->detectorTwoTheta(det)); const double theta_term = sqrt(tanTheta * tanTheta + 1.0); double corr; if (is_tube) { const double tanAlpha = tan(getYTubeAngle(det, inputWS)); const double alpha_term = sqrt(tanAlpha * tanAlpha + 1.0); corr = alpha_term * theta_term * theta_term; } else { corr = theta_term * theta_term * theta_term; } // Correct data for all X bins for (int j = 0; j < xLength; j++) { YOut[j] = YIn[j] * corr; EOut[j] = fabs(EIn[j] * corr); } progress.report("Solid Angle Correction"); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION setProperty("OutputMessage", "Solid angle correction applied"); }
void FFTDerivative::execRealFFT() { MatrixWorkspace_sptr inWS = getProperty("InputWorkspace"); MatrixWorkspace_sptr outWS; size_t n = inWS->getNumberHistograms(); API::Progress progress(this,0,1,n); size_t ny = inWS->readY(0).size(); size_t nx = inWS->readX(0).size(); // Workspace for holding a copy of a spectrum. Each spectrum is symmetrized to minimize // possible edge effects. MatrixWorkspace_sptr copyWS = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace> (Mantid::API::WorkspaceFactory::Instance().create(inWS,1,nx+ny,ny+ny)); bool isHist = (nx != ny); for(size_t spec = 0; spec < n; ++spec) { const Mantid::MantidVec& x0 = inWS->readX(spec); const Mantid::MantidVec& y0 = inWS->readY(spec); Mantid::MantidVec& x1 = copyWS->dataX(0); Mantid::MantidVec& y1 = copyWS->dataY(0); double xx = 2*x0[0]; x1[ny] = x0[0]; y1[ny] = y0[0]; for(size_t i = 1; i < ny; ++i) { size_t j1 = ny - i; size_t j2 = ny + i; x1[j1] = xx - x0[i]; x1[j2] = x0[i]; y1[j1] = y1[j2] = y0[i]; } x1[0] = 2*x1[1] - x1[2]; y1[0] = y0.back(); if (isHist) { x1[y1.size()] = x0[ny]; } // Transform symmetrized spectrum IAlgorithm_sptr fft = createChildAlgorithm("RealFFT"); fft->setProperty("InputWorkspace",copyWS); fft->setProperty("WorkspaceIndex",0); fft->setProperty("Transform","Forward"); fft->execute(); MatrixWorkspace_sptr transWS = fft->getProperty("OutputWorkspace"); Mantid::MantidVec& nu = transWS->dataX(0); Mantid::MantidVec& re = transWS->dataY(0); Mantid::MantidVec& im = transWS->dataY(1); int dn = getProperty("Order"); bool swap_re_im = dn % 2 != 0; int sign_re = 1; int sign_im = -1; switch(dn % 4) { case 1: sign_re = 1; sign_im = -1; break; case 2: sign_re = -1; sign_im = -1; break; case 3: sign_re = -1; sign_im = 1; break; } // Multiply the transform by (2*pi*i*w)**dn for(size_t j=0; j < re.size(); ++j) { double w = 2 * M_PI * nu[j]; double ww = w; for(int k = dn; k > 1; --k) { ww *= w; } double a = sign_re * re[j]*ww; double b = sign_im * im[j]*ww; if (swap_re_im) { re[j] = b; im[j] = a; } else { re[j] = a; im[j] = b; } } // Inverse transform fft = createChildAlgorithm("RealFFT"); fft->setProperty("InputWorkspace",transWS); fft->setProperty("Transform","Backward"); fft->execute(); transWS = fft->getProperty("OutputWorkspace"); size_t m2 = transWS->readY(0).size() / 2; size_t my = m2 + ((transWS->readY(0).size() % 2) ? 1 : 0); size_t mx = my + (transWS->isHistogramData() ? 1 : 0); if (!outWS) { outWS = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace> (Mantid::API::WorkspaceFactory::Instance().create(inWS,n,mx,my)); } // Save the upper half of the inverse transform for output Mantid::MantidVec& x = outWS->dataX(spec); Mantid::MantidVec& y = outWS->dataY(spec); double dx = x1[0]; std::copy(transWS->dataX(0).begin() + m2,transWS->dataX(0).end(),x.begin()); std::transform(x.begin(),x.end(),x.begin(),std::bind2nd(std::plus<double>(),dx)); std::copy(transWS->dataY(0).begin() + m2,transWS->dataY(0).end(),y.begin()); // shift the data to make x and x0 match. using linear interpolation. if (x.size() != x0.size() && false)// TODO: doesn't work at the moment. needs to be working { std::cerr << "(my != x0.size()) " << x0[0] << "!=" << x[0] << std::endl; dx = x0[0] - x[0]; assert(dx > 0.0); double f = (x0[0] - x[0]) / (x0[1] - x0[0]); for(size_t i = 0; i < my - 1; ++i) { y[i] += (y[i+1] - y[i]) * f; x[i] = x0[i]; } x.back() += dx; } progress.report(); } setProperty("OutputWorkspace",outWS); }
/** Create a Workspace2D (MatrixWorkspace) with given spectra and bin parameters */ MatrixWorkspace_sptr GeneratePeaks::createDataWorkspace(std::vector<double> binparameters) { // Check validity if (m_spectraSet.size() == 0) throw std::invalid_argument("Input spectra list is empty. Unable to generate a new workspace."); if (binparameters.size() < 3) { std::stringstream errss; errss << "Number of input binning parameters are not enough (" << binparameters.size() << "). " << "Binning parameters should be 3 (x0, step, xf)."; g_log.error(errss.str()); throw std::invalid_argument(errss.str()); } double x0 = binparameters[0]; double dx = binparameters[1]; double xf = binparameters[2]; if (x0 >= xf || (xf - x0) < dx || dx == 0.) { std::stringstream errss; errss << "Order of input binning parameters is not correct. It is not logical to have " << "x0 = " << x0 << ", xf = " << xf << ", dx = " << dx; g_log.error(errss.str()); throw std::invalid_argument(errss.str()); } // Determine number of x values std::vector<double> xarray; double xvalue = x0; while (xvalue <= xf) { // Push current value to vector xarray.push_back(xvalue); // Calculate next value, linear or logarithmic if (dx > 0) xvalue += dx; else xvalue += fabs(dx)*xvalue; } size_t numxvalue = xarray.size(); // Create new workspace MatrixWorkspace_sptr ws = API::WorkspaceFactory::Instance().create("Workspace2D", m_spectraSet.size(), numxvalue, numxvalue-1); for (size_t ip = 0; ip < m_spectraSet.size(); ip ++) std::copy(xarray.begin(), xarray.end(), ws->dataX(ip).begin()); // Set spectrum numbers std::map<specid_t, specid_t>::iterator spiter; for (spiter = m_SpectrumMap.begin(); spiter != m_SpectrumMap.end(); ++spiter) { specid_t specid = spiter->first; specid_t wsindex = spiter->second; g_log.debug() << "Build WorkspaceIndex-Spectrum " << wsindex << " , " << specid << "\n"; ws->getSpectrum(wsindex)->setSpectrumNo(specid); } return ws; }
void ModeratorTzero::exec() { m_tolTOF = getProperty("tolTOF"); //Tolerance in the calculation of the emission time, in microseconds m_niter=getProperty("Niter"); // number of iterations const MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); m_instrument = inputWS->getInstrument(); // pointer to the instrument //deltaE-mode (should be "indirect") std::vector<std::string> Emode=m_instrument->getStringParameter("deltaE-mode"); if(Emode.empty()) throw Exception::InstrumentDefinitionError("Unable to retrieve instrument geometry (direct or indirect) parameter", inputWS->getTitle()); if(Emode[0]!= "indirect") throw Exception::InstrumentDefinitionError("Instrument geometry must be of type indirect."); // extract formula from instrument parameters std::vector<std::string> t0_formula=m_instrument->getStringParameter("t0_formula"); if(t0_formula.empty()) throw Exception::InstrumentDefinitionError("Unable to retrieve t0_formula among instrument parameters"); m_formula=t0_formula[0]; //Run execEvent if eventWorkSpace EventWorkspace_const_sptr eventWS = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS); if (eventWS != NULL) { execEvent(); return; } MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); //Check whether input == output to see whether a new workspace is required. if ( outputWS != inputWS ) { //Create new workspace for output from old outputWS = WorkspaceFactory::Instance().create(inputWS); } const size_t numHists = static_cast<size_t>(inputWS->getNumberHistograms()); Progress prog(this,0.0,1.0,numHists); //report progress of algorithm PARALLEL_FOR2(inputWS, outputWS) // iterate over the spectra for (int i=0; i < static_cast<int>(numHists); ++i) { PARALLEL_START_INTERUPT_REGION size_t wsIndex = static_cast<size_t>(i); double L1=CalculateL1(inputWS, wsIndex); // distance from source to sample or monitor double t2=CalculateT2(inputWS, wsIndex); // time from sample to detector // shift the time of flights by the emission time from the moderator if(t2 >= 0) //t2 < 0 when no detector info is available { double E1; mu::Parser parser; parser.DefineVar("incidentEnergy", &E1); // associate E1 to this parser parser.SetExpr(m_formula); E1=m_convfactor*(L1/m_t1min)*(L1/m_t1min); double min_t0_next=parser.Eval(); // fast neutrons are shifted by min_t0_next, irrespective of tof MantidVec &inbins = inputWS->dataX(i); MantidVec &outbins = outputWS->dataX(i); // iterate over the time-of-flight values for(unsigned int ibin=0; ibin < inbins.size(); ibin++) { double tof=inbins[ibin]; // current time-of-flight if(tof<m_t1min+t2) tof-=min_t0_next; else tof-=CalculateT0(tof, L1, t2, E1, parser); outbins[ibin] = tof; } } else { outputWS->dataX(i) = inputWS->dataX(i); } //Copy y and e data outputWS->dataY(i) = inputWS->dataY(i); outputWS->dataE(i) = inputWS->dataE(i); prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION // Copy units if (inputWS->getAxis(0)->unit().get()) { outputWS->getAxis(0)->unit() = inputWS->getAxis(0)->unit(); } try { if(inputWS->getAxis(1)->unit().get()) { outputWS->getAxis(1)->unit() = inputWS->getAxis(1)->unit(); } } catch(Exception::IndexError &) { // OK, so this isn't a Workspace2D } // Assign it to the output workspace property setProperty("OutputWorkspace",outputWS); }
void FFTDerivative::execComplexFFT() { MatrixWorkspace_sptr inWS = getProperty("InputWorkspace"); MatrixWorkspace_sptr outWS; size_t n = inWS->getNumberHistograms(); API::Progress progress(this,0,1,n); size_t ny = inWS->readY(0).size(); size_t nx = inWS->readX(0).size(); // Workspace for holding a copy of a spectrum. Each spectrum is symmetrized to minimize // possible edge effects. MatrixWorkspace_sptr copyWS = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace> (Mantid::API::WorkspaceFactory::Instance().create(inWS,1,nx+ny,ny+ny)); bool isHist = (nx != ny); for(size_t spec = 0; spec < n; ++spec) { const Mantid::MantidVec& x0 = inWS->readX(spec); const Mantid::MantidVec& y0 = inWS->readY(spec); Mantid::MantidVec& x1 = copyWS->dataX(0); Mantid::MantidVec& y1 = copyWS->dataY(0); double xx = 2*x0[0]; x1[ny] = x0[0]; y1[ny] = y0[0]; for(size_t i = 1; i < ny; ++i) { size_t j1 = ny - i; size_t j2 = ny + i; x1[j1] = xx - x0[i]; x1[j2] = x0[i]; y1[j1] = y1[j2] = y0[i]; } x1[0] = 2*x1[1] - x1[2]; y1[0] = y0.back(); if (isHist) { x1[y1.size()] = x0[ny]; } // Transform symmetrized spectrum IAlgorithm_sptr fft = createChildAlgorithm("FFT"); fft->setProperty("InputWorkspace",copyWS); fft->setProperty("Real",0); fft->setProperty("Transform","Forward"); fft->execute(); MatrixWorkspace_sptr transWS = fft->getProperty("OutputWorkspace"); Mantid::MantidVec& nu = transWS->dataX(3); Mantid::MantidVec& re = transWS->dataY(3); Mantid::MantidVec& im = transWS->dataY(4); int dn = getProperty("Order"); bool swap_re_im = dn % 2 != 0; int sign_re = 1; int sign_im = -1; switch(dn % 4) { case 1: sign_re = 1; sign_im = -1; break; case 2: sign_re = -1; sign_im = -1; break; case 3: sign_re = -1; sign_im = 1; break; } // Multiply the transform by (2*pi*i*w)**dn for(size_t j=0; j < re.size(); ++j) { double w = 2 * M_PI * nu[j]; double ww = w; for(int k = dn; k > 1; --k) { ww *= w; } double a = sign_re * re[j]*ww; double b = sign_im * im[j]*ww; if (swap_re_im) { re[j] = b; im[j] = a; } else { re[j] = a; im[j] = b; } } // Inverse transform fft = createChildAlgorithm("FFT"); fft->setProperty("InputWorkspace",transWS); fft->setProperty("Real",3); fft->setProperty("Imaginary",4); fft->setProperty("Transform","Backward"); fft->execute(); transWS = fft->getProperty("OutputWorkspace"); size_t m2 = transWS->readY(0).size() / 2; //size_t my = m2 + (transWS->readY(0).size() % 2 ? 1 : 0); //size_t mx = my + (transWS->isHistogramData() ? 1 : 0); if (!outWS) { outWS = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace> //(Mantid::API::WorkspaceFactory::Instance().create(inWS,n,mx,my)); (Mantid::API::WorkspaceFactory::Instance().create(inWS)); } // Save the upper half of the inverse transform for output Mantid::MantidVec& x = outWS->dataX(spec); Mantid::MantidVec& y = outWS->dataY(spec); double dx = x1[m2]; std::copy(transWS->dataX(0).begin() + m2,transWS->dataX(0).end(),x.begin()); std::transform(x.begin(),x.end(),x.begin(),std::bind2nd(std::plus<double>(),dx)); std::copy(transWS->dataY(0).begin() + m2,transWS->dataY(0).end(),y.begin()); progress.report(); } setProperty("OutputWorkspace",outWS); }
/** Execute the algorithm. */ void MaxEnt::exec() { // MaxEnt parameters // Complex data? bool complex = getProperty("ComplexData"); // Image must be positive? bool positiveImage = getProperty("PositiveImage"); // Autoshift bool autoShift = getProperty("AutoShift"); // Increase the number of points in the image by this factor size_t densityFactor = getProperty("DensityFactor"); // Background (default level, sky background, etc) double background = getProperty("A"); // Chi target double chiTarget = getProperty("ChiTarget"); // Required precision for Chi arget double chiEps = getProperty("ChiEps"); // Maximum degree of non-parallelism between S and C double angle = getProperty("MaxAngle"); // Distance penalty for current image double distEps = getProperty("DistancePenalty"); // Maximum number of iterations size_t niter = getProperty("MaxIterations"); // Maximum number of iterations in alpha chop size_t alphaIter = getProperty("AlphaChopIterations"); // Number of spectra and datapoints // Read input workspace MatrixWorkspace_sptr inWS = getProperty("InputWorkspace"); // Number of spectra size_t nspec = inWS->getNumberHistograms(); // Number of data points size_t npoints = inWS->blocksize() * densityFactor; // Number of X bins size_t npointsX = inWS->isHistogramData() ? npoints + 1 : npoints; // The type of entropy we are going to use (depends on the type of image, // positive only, or positive and/or negative) MaxentData_sptr maxentData; if (positiveImage) { maxentData = boost::make_shared<MaxentData>( boost::make_shared<MaxentEntropyPositiveValues>()); } else { maxentData = boost::make_shared<MaxentData>( boost::make_shared<MaxentEntropyNegativeValues>()); } // Output workspaces MatrixWorkspace_sptr outImageWS; MatrixWorkspace_sptr outDataWS; MatrixWorkspace_sptr outEvolChi; MatrixWorkspace_sptr outEvolTest; nspec = complex ? nspec / 2 : nspec; outImageWS = WorkspaceFactory::Instance().create(inWS, 2 * nspec, npointsX, npoints); outDataWS = WorkspaceFactory::Instance().create(inWS, 2 * nspec, npointsX, npoints); outEvolChi = WorkspaceFactory::Instance().create(inWS, nspec, niter, niter); outEvolTest = WorkspaceFactory::Instance().create(inWS, nspec, niter, niter); npoints *= 2; for (size_t s = 0; s < nspec; s++) { // Start distribution (flat background) std::vector<double> image(npoints, background); if (complex) { auto dataRe = inWS->readY(s); auto dataIm = inWS->readY(s + nspec); auto errorsRe = inWS->readE(s); auto errorsIm = inWS->readE(s + nspec); maxentData->loadComplex(dataRe, dataIm, errorsRe, errorsIm, image, background); } else { auto data = inWS->readY(s); auto error = inWS->readE(s); maxentData->loadReal(data, error, image, background); } // To record the algorithm's progress std::vector<double> evolChi(niter, 0.); std::vector<double> evolTest(niter, 0.); // Progress Progress progress(this, 0, 1, niter); // Run maxent algorithm for (size_t it = 0; it < niter; it++) { // Calculate quadratic model coefficients // (SB eq. 21 and 24) maxentData->calculateQuadraticCoefficients(); double currAngle = maxentData->getAngle(); double currChisq = maxentData->getChisq(); auto coeffs = maxentData->getQuadraticCoefficients(); // Calculate delta to construct new image (SB eq. 25) auto delta = move(coeffs, chiTarget / currChisq, chiEps, alphaIter); // Apply distance penalty (SB eq. 33) image = maxentData->getImage(); delta = applyDistancePenalty(delta, coeffs, image, background, distEps); // Update image according to 'delta' and calculate the new Chi-square maxentData->updateImage(delta); currChisq = maxentData->getChisq(); // Record the evolution of Chi-square and angle(S,C) evolChi[it] = currChisq; evolTest[it] = currAngle; // Stop condition, solution found if ((std::abs(currChisq / chiTarget - 1.) < chiEps) && (currAngle < angle)) { break; } // Check for canceling the algorithm if (!(it % 1000)) { interruption_point(); } progress.report(); } // iterations // Get calculated data auto solData = maxentData->getReconstructedData(); auto solImage = maxentData->getImage(); // Populate the output workspaces populateDataWS(inWS, s, nspec, solData, outDataWS); populateImageWS(inWS, s, nspec, solImage, outImageWS, autoShift); // Populate workspaces recording the evolution of Chi and Test // X values for (size_t it = 0; it < niter; it++) { outEvolChi->dataX(s)[it] = static_cast<double>(it); outEvolTest->dataX(s)[it] = static_cast<double>(it); } // Y values outEvolChi->dataY(s).assign(evolChi.begin(), evolChi.end()); outEvolTest->dataY(s).assign(evolTest.begin(), evolTest.end()); // No errors } // Next spectrum setProperty("EvolChi", outEvolChi); setProperty("EvolAngle", outEvolTest); setProperty("ReconstructedImage", outImageWS); setProperty("ReconstructedData", outDataWS); }
/** Populates the output workspaces * @param inWS :: [input] The input workspace * @param spec :: [input] The current spectrum being analyzed * @param nspec :: [input] The total number of histograms in the input workspace * @param result :: [input] The result to be written in the output workspace * @param outWS :: [input] The output workspace to populate * @param autoShift :: [input] Whether or not to correct the phase shift */ void MaxEnt::populateImageWS(const MatrixWorkspace_sptr &inWS, size_t spec, size_t nspec, const std::vector<double> &result, MatrixWorkspace_sptr &outWS, bool autoShift) { if (result.size() % 2) throw std::invalid_argument("Cannot write results to output workspaces"); int npoints = static_cast<int>(result.size() / 2); int npointsX = inWS->isHistogramData() ? npoints + 1 : npoints; MantidVec X(npointsX); MantidVec YR(npoints); MantidVec YI(npoints); MantidVec E(npoints, 0.); double x0 = inWS->readX(spec)[0]; double dx = inWS->readX(spec)[1] - x0; double delta = 1. / dx / npoints; int isOdd = (inWS->blocksize() % 2) ? 1 : 0; double shift = x0 * 2 * M_PI; if (!autoShift) shift = 0; for (int i = 0; i < npoints; i++) { int j = (npoints / 2 + i + isOdd) % npoints; X[i] = delta * (-npoints / 2 + i); double xShift = X[i] * shift; double c = cos(xShift); double s = sin(xShift); YR[i] = result[2 * j] * c - result[2 * j + 1] * s; YI[i] = result[2 * j] * s + result[2 * j + 1] * c; YR[i] *= dx; YI[i] *= dx; } if (npointsX == npoints + 1) X[npoints] = X[npoints - 1] + delta; // Caption & label auto inputUnit = inWS->getAxis(0)->unit(); if (inputUnit) { boost::shared_ptr<Kernel::Units::Label> lblUnit = boost::dynamic_pointer_cast<Kernel::Units::Label>( UnitFactory::Instance().create("Label")); if (lblUnit) { lblUnit->setLabel( inverseCaption[inWS->getAxis(0)->unit()->caption()], inverseLabel[inWS->getAxis(0)->unit()->label().ascii()]); outWS->getAxis(0)->unit() = lblUnit; } } outWS->dataX(spec).assign(X.begin(), X.end()); outWS->dataY(spec).assign(YR.begin(), YR.end()); outWS->dataE(spec).assign(E.begin(), E.end()); outWS->dataX(nspec + spec).assign(X.begin(), X.end()); outWS->dataY(nspec + spec).assign(YI.begin(), YI.end()); outWS->dataE(nspec + spec).assign(E.begin(), E.end()); }
/** Filter non-background data points out and create a background workspace */ Workspace2D_sptr ProcessBackground::filterForBackground(BackgroundFunction_sptr bkgdfunction) { double posnoisetolerance = getProperty("NoiseTolerance"); double negnoisetolerance = getProperty("NegativeNoiseTolerance"); if (isEmpty(negnoisetolerance)) negnoisetolerance = posnoisetolerance; // Calcualte theoretical values const std::vector<double> x = m_dataWS->readX(m_wsIndex); API::FunctionDomain1DVector domain(x); API::FunctionValues values(domain); bkgdfunction->function(domain, values); g_log.information() << "Function used to select background points : " << bkgdfunction->asString() << "\n"; // Optional output string userbkgdwsname = getPropertyValue("UserBackgroundWorkspace"); if (userbkgdwsname.size() == 0) throw runtime_error("In mode SelectBackgroundPoints, " "UserBackgroundWorkspace must be given!"); size_t sizex = domain.size(); size_t sizey = values.size(); MatrixWorkspace_sptr visualws = boost::dynamic_pointer_cast<MatrixWorkspace>( WorkspaceFactory::Instance().create("Workspace2D", 4, sizex, sizey)); for (size_t i = 0; i < sizex; ++i) { for (size_t j = 0; j < 4; ++j) { visualws->dataX(j)[i] = domain[i]; } } for (size_t i = 0; i < sizey; ++i) { visualws->dataY(0)[i] = values[i]; visualws->dataY(1)[i] = m_dataWS->readY(m_wsIndex)[i] - values[i]; visualws->dataY(2)[i] = posnoisetolerance; visualws->dataY(3)[i] = -negnoisetolerance; } setProperty("UserBackgroundWorkspace", visualws); // Filter for background std::vector<double> vecx, vecy, vece; for (size_t i = 0; i < domain.size(); ++i) { // double y = m_dataWS->readY(m_wsIndex)[i]; // double theoryy = values[i]; y-theoryy double purey = visualws->readY(1)[i]; if (purey < posnoisetolerance && purey > -negnoisetolerance) { // Selected double x = domain[i]; double y = m_dataWS->readY(m_wsIndex)[i]; double e = m_dataWS->readE(m_wsIndex)[i]; vecx.push_back(x); vecy.push_back(y); vece.push_back(e); } } g_log.information() << "Found " << vecx.size() << " background points out of " << m_dataWS->readX(m_wsIndex).size() << " total data points. " << "\n"; // Build new workspace for OutputWorkspace size_t nspec = 3; Workspace2D_sptr outws = boost::dynamic_pointer_cast<DataObjects::Workspace2D>( API::WorkspaceFactory::Instance().create("Workspace2D", nspec, vecx.size(), vecy.size())); for (size_t i = 0; i < vecx.size(); ++i) { for (size_t j = 0; j < nspec; ++j) outws->dataX(j)[i] = vecx[i]; outws->dataY(0)[i] = vecy[i]; outws->dataE(0)[i] = vece[i]; } return outws; }
/** Executes the algorithm * */ void CalculateEfficiency::exec() { // Minimum efficiency. Pixels with lower efficiency will be masked double min_eff = getProperty("MinEfficiency"); // Maximum efficiency. Pixels with higher efficiency will be masked double max_eff = getProperty("MaxEfficiency"); // Get the input workspace MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); MatrixWorkspace_sptr rebinnedWS;// = inputWS; // Now create the output workspace MatrixWorkspace_sptr outputWS;// = getProperty("OutputWorkspace"); // DataObjects::EventWorkspace_const_sptr inputEventWS = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS); // Sum up all the wavelength bins IAlgorithm_sptr childAlg = createChildAlgorithm("Integration", 0.0, 0.2); childAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", inputWS); childAlg->executeAsChildAlg(); rebinnedWS = childAlg->getProperty("OutputWorkspace"); outputWS = WorkspaceFactory::Instance().create(rebinnedWS); WorkspaceFactory::Instance().initializeFromParent(inputWS, outputWS, false); for (int i=0; i<(int)rebinnedWS->getNumberHistograms(); i++) { outputWS->dataX(i) = rebinnedWS->readX(i); } setProperty("OutputWorkspace",outputWS); double sum = 0.0; double err = 0.0; int npixels = 0; // Loop over spectra and sum all the counts to get normalization // Skip monitors and masked detectors sumUnmaskedDetectors(rebinnedWS, sum, err, npixels); // Normalize each detector pixel by the sum we just found to get the // relative efficiency. If the minimum and maximum efficiencies are // provided, the pixels falling outside this range will be marked // as 'masked' in both the input and output workspace. // We mask detectors in the input workspace so that we can resum the // counts to find a new normalization factor that takes into account // the newly masked detectors. normalizeDetectors(rebinnedWS, outputWS, sum, err, npixels, min_eff, max_eff); if ( !isEmpty(min_eff) || !isEmpty(max_eff) ) { // Recompute the normalization, excluding the pixels that were outside // the acceptable efficiency range. sumUnmaskedDetectors(rebinnedWS, sum, err, npixels); // Now that we have a normalization factor that excludes bad pixels, // recompute the relative efficiency. // We pass EMPTY_DBL() to avoid masking pixels that might end up high or low // after the new normalization. normalizeDetectors(rebinnedWS, outputWS, sum, err, npixels, EMPTY_DBL(), EMPTY_DBL()); } return; }