/** 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()); }
/** Executes the algorithm */ void MultiplyRange::exec() { // Get the input workspace and other properties MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace"); m_startBin = getProperty("StartBin"); m_endBin = getProperty("EndBin"); m_factor = getProperty("Factor"); // A few checks on the input properties const int specSize = static_cast<int>(inputWS->blocksize()); if ( isEmpty(m_endBin) ) m_endBin = specSize - 1; if ( m_endBin >= specSize ) { g_log.error("EndBin out of range!"); throw std::out_of_range("EndBin out of range!"); } if ( m_endBin < m_startBin ) { g_log.error("StartBin must be less than or equal to EndBin"); throw std::out_of_range("StartBin must be less than or equal to EndBin"); } // Only create the output workspace if it's different to the input one MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); if ( outputWS != inputWS ) { outputWS = WorkspaceFactory::Instance().create(inputWS); setProperty("OutputWorkspace",outputWS); } // Get the count of histograms in the input workspace const int histogramCount = static_cast<int>(inputWS->getNumberHistograms()); Progress progress(this,0.0,1.0,histogramCount); // Loop over spectra PARALLEL_FOR2(inputWS,outputWS) for (int i = 0; i < histogramCount; ++i) { PARALLEL_START_INTERUPT_REGION // Copy over the bin boundaries outputWS->setX(i,inputWS->refX(i)); // Copy over the data outputWS->dataY(i) = inputWS->readY(i); outputWS->dataE(i) = inputWS->readE(i); MantidVec& newY = outputWS->dataY(i); MantidVec& newE = outputWS->dataE(i); // Now multiply the requested range std::transform(newY.begin()+m_startBin,newY.begin()+m_endBin+1,newY.begin()+m_startBin, std::bind2nd(std::multiplies<double>(),m_factor)); std::transform(newE.begin()+m_startBin,newE.begin()+m_endBin+1,newE.begin()+m_startBin, std::bind2nd(std::multiplies<double>(),m_factor)); progress.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION }
/** 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); }
/** Converts an EventWorkspace to an equivalent Workspace2D * @param inputMatrixW :: input event workspace * @return a MatrixWorkspace_sptr */ MatrixWorkspace_sptr EventWorkspaceHelpers::convertEventTo2D(MatrixWorkspace_sptr inputMatrixW) { EventWorkspace_sptr inputW = boost::dynamic_pointer_cast<EventWorkspace>(inputMatrixW); if (!inputW) throw std::invalid_argument("EventWorkspaceHelpers::convertEventTo2D(): " "Input workspace is not an EventWorkspace."); size_t numBins = inputW->blocksize(); // Make a workspace 2D version of it MatrixWorkspace_sptr outputW; outputW = WorkspaceFactory::Instance().create( "Workspace2D", inputW->getNumberHistograms(), numBins + 1, numBins); WorkspaceFactory::Instance().initializeFromParent(inputW, outputW, false); // Now let's set all the X bins and values for (size_t i = 0; i < inputW->getNumberHistograms(); i++) { outputW->getSpectrum(i).copyInfoFrom(inputW->getSpectrum(i)); outputW->setX(i, inputW->refX(i)); MantidVec &Yout = outputW->dataY(i); const MantidVec &Yin = inputW->readY(i); for (size_t j = 0; j < numBins; j++) Yout[j] = Yin[j]; MantidVec &Eout = outputW->dataE(i); const MantidVec &Ein = inputW->readE(i); for (size_t j = 0; j < numBins; j++) Eout[j] = Ein[j]; } return outputW; }
/** Reads from the third line of the input file to the end assuming it contains * 2D data * @param firstLine :: the second line in the file * @return a workspace containing the loaded data * @throw NotFoundError if there is compulsulary data is missing from the file * @throw invalid_argument if there is an inconsistency in the header * information */ const MatrixWorkspace_sptr LoadRKH::read2D(const std::string &firstLine) { g_log.information() << "file appears to contain 2D information, reading in 2D data mode\n"; MatrixWorkspace_sptr outWrksp; MantidVec axis0Data; Progress prog(read2DHeader(firstLine, outWrksp, axis0Data)); const size_t nAxis1Values = outWrksp->getNumberHistograms(); for (size_t i = 0; i < nAxis1Values; ++i) { // set the X-values to the common bin values we read above MantidVecPtr toPass; toPass.access() = axis0Data; outWrksp->setX(i, toPass); // now read in the Y values MantidVec &YOut = outWrksp->dataY(i); for (double &value : YOut) { m_fileIn >> value; } prog.report("Loading Y data"); } // loop on to the next spectrum // the error values form one big block after the Y-values for (size_t i = 0; i < nAxis1Values; ++i) { MantidVec &EOut = outWrksp->dataE(i); for (double &value : EOut) { m_fileIn >> value; } prog.report("Loading error estimates"); } // loop on to the next spectrum return outWrksp; }
/** * Computes the square root of the errors and if the input was a distribution * this divides by the new bin-width * @param outputWS The workspace containing the output data * @param inputWS The input workspace used for testing distribution state */ void Rebin2D::normaliseOutput(MatrixWorkspace_sptr outputWS, MatrixWorkspace_const_sptr inputWS) { //PARALLEL_FOR1(outputWS) for(int64_t i = 0; i < static_cast<int64_t>(outputWS->getNumberHistograms()); ++i) { PARALLEL_START_INTERUPT_REGION MantidVec & outputY = outputWS->dataY(i); MantidVec & outputE = outputWS->dataE(i); for(size_t j = 0; j < outputWS->blocksize(); ++j) { m_progress->report("Calculating errors"); const double binWidth = (outputWS->readX(i)[j+1] - outputWS->readX(i)[j]); double eValue = std::sqrt(outputE[j]); // Don't do this for a RebinnedOutput workspace. The fractions // take care of such things. if( inputWS->isDistribution() && inputWS->id() != "RebinnedOutput") { outputY[j] /= binWidth; eValue /= binWidth; } outputE[j] = eValue; } PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION outputWS->isDistribution(inputWS->isDistribution()); }
/** * 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; } } }
/** Rebins the distributions and sets error values. */ MatrixWorkspace_sptr VesuvioL1ThetaResolution::processDistribution(MatrixWorkspace_sptr ws, const double binWidth) { const size_t numHist = ws->getNumberHistograms(); double xMin(DBL_MAX); double xMax(DBL_MIN); for (size_t i = 0; i < numHist; i++) { const std::vector<double> &x = ws->readX(i); xMin = std::min(xMin, x.front()); xMax = std::max(xMax, x.back()); } std::stringstream binParams; binParams << xMin << "," << binWidth << "," << xMax; IAlgorithm_sptr rebin = AlgorithmManager::Instance().create("Rebin"); rebin->initialize(); rebin->setChild(true); rebin->setLogging(false); rebin->setProperty("InputWorkspace", ws); rebin->setProperty("OutputWorkspace", "__rebin"); rebin->setProperty("Params", binParams.str()); rebin->execute(); ws = rebin->getProperty("OutputWorkspace"); for (size_t i = 0; i < numHist; i++) { const std::vector<double> &y = ws->readY(i); std::vector<double> &e = ws->dataE(i); std::transform(y.begin(), y.end(), e.begin(), SquareRoot()); } return ws; }
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); }
/** * Sum counts from the input workspace in lambda along lines of constant Q by * projecting to "virtual lambda" at a reference angle twoThetaR. * * @param detectorWS [in] :: the input workspace in wavelength * @return :: the output workspace in wavelength */ MatrixWorkspace_sptr ReflectometryReductionOne2::sumInQ(MatrixWorkspace_sptr detectorWS) { // Construct the output array in virtual lambda MatrixWorkspace_sptr IvsLam = constructIvsLamWS(detectorWS); // Loop through each input group (and corresponding output spectrum) const size_t numGroups = detectorGroups().size(); for (size_t groupIdx = 0; groupIdx < numGroups; ++groupIdx) { auto &detectors = detectorGroups()[groupIdx]; auto &outputE = IvsLam->dataE(groupIdx); // Loop through each spectrum in the detector group for (auto spIdx : detectors) { // Get the angle of this detector and its size in twoTheta const double twoTheta = getDetectorTwoTheta(m_spectrumInfo, spIdx); const double bTwoTheta = getDetectorTwoThetaRange(spIdx); // Check X length is Y length + 1 const auto &inputX = detectorWS->x(spIdx); const auto &inputY = detectorWS->y(spIdx); const auto &inputE = detectorWS->e(spIdx); if (inputX.size() != inputY.size() + 1) { throw std::runtime_error( "Expected input workspace to be histogram data (got X len=" + std::to_string(inputX.size()) + ", Y len=" + std::to_string(inputY.size()) + ")"); } // Create a vector for the projected errors for this spectrum. // (Output Y values can simply be accumulated directly into the output // workspace, but for error values we need to create a separate error // vector for the projected errors from each input spectrum and then // do an overall sum in quadrature.) std::vector<double> projectedE(outputE.size(), 0.0); // Process each value in the spectrum const int ySize = static_cast<int>(inputY.size()); for (int inputIdx = 0; inputIdx < ySize; ++inputIdx) { // Do the summation in Q sumInQProcessValue(inputIdx, twoTheta, bTwoTheta, inputX, inputY, inputE, detectors, groupIdx, IvsLam, projectedE); } // Sum errors in quadrature const int eSize = static_cast<int>(outputE.size()); for (int outIdx = 0; outIdx < eSize; ++outIdx) { outputE[outIdx] += projectedE[outIdx] * projectedE[outIdx]; } } // Take the square root of all the accumulated squared errors for this // detector group. Assumes Gaussian errors double (*rs)(double) = std::sqrt; std::transform(outputE.begin(), outputE.end(), outputE.begin(), rs); } return IvsLam; }
/** Calculate the integral asymmetry for a pair of workspaces (red & green). * @param ws_red :: The red workspace * @param ws_green :: The green workspace * @param Y :: Reference to a variable receiving the value of asymmetry * @param E :: Reference to a variable receiving the value of the error */ void PlotAsymmetryByLogValue::calcIntAsymmetry(MatrixWorkspace_sptr ws_red, MatrixWorkspace_sptr ws_green, double &Y, double &E) { if (!m_int) { // "Differential asymmetry" MatrixWorkspace_sptr tmpWS = WorkspaceFactory::Instance().create( ws_red, 1, ws_red->readX(0).size(), ws_red->readY(0).size()); for (size_t i = 0; i < tmpWS->dataY(0).size(); i++) { double FNORM = ws_green->readY(0)[i] + ws_red->readY(0)[i]; FNORM = FNORM != 0.0 ? 1.0 / FNORM : 1.0; double BNORM = ws_green->readY(1)[i] + ws_red->readY(1)[i]; BNORM = BNORM != 0.0 ? 1.0 / BNORM : 1.0; double ZF = (ws_green->readY(0)[i] - ws_red->readY(0)[i]) * FNORM; double ZB = (ws_green->readY(1)[i] - ws_red->readY(1)[i]) * BNORM; tmpWS->dataY(0)[i] = ZB - ZF; tmpWS->dataE(0)[i] = (1.0 + ZF * ZF) * FNORM + (1.0 + ZB * ZB) * BNORM; } IAlgorithm_sptr integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace", tmpWS); integr->setProperty("RangeLower", m_minTime); integr->setProperty("RangeUpper", m_maxTime); integr->execute(); MatrixWorkspace_sptr out = integr->getProperty("OutputWorkspace"); Y = out->readY(0)[0] / static_cast<double>(tmpWS->dataY(0).size()); E = out->readE(0)[0] / static_cast<double>(tmpWS->dataY(0).size()); } else { // "Integral asymmetry" IAlgorithm_sptr integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace", ws_red); integr->setProperty("RangeLower", m_minTime); integr->setProperty("RangeUpper", m_maxTime); integr->execute(); MatrixWorkspace_sptr intWS_red = integr->getProperty("OutputWorkspace"); integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace", ws_green); integr->setProperty("RangeLower", m_minTime); integr->setProperty("RangeUpper", m_maxTime); integr->execute(); MatrixWorkspace_sptr intWS_green = integr->getProperty("OutputWorkspace"); double YIF = (intWS_green->readY(0)[0] - intWS_red->readY(0)[0]) / (intWS_green->readY(0)[0] + intWS_red->readY(0)[0]); double YIB = (intWS_green->readY(1)[0] - intWS_red->readY(1)[0]) / (intWS_green->readY(1)[0] + intWS_red->readY(1)[0]); Y = YIB - YIF; double VARIF = (1.0 + YIF * YIF) / (intWS_green->readY(0)[0] + intWS_red->readY(0)[0]); double VARIB = (1.0 + YIB * YIB) / (intWS_green->readY(1)[0] + intWS_red->readY(1)[0]); E = sqrt(VARIF + VARIB); } }
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"); }
/** Creates the output workspace, setting the X vector to the bins boundaries in * Qx. * @return A pointer to the newly-created workspace */ API::MatrixWorkspace_sptr Qxy::setUpOutputWorkspace(API::MatrixWorkspace_const_sptr inputWorkspace) { const double max = getProperty("MaxQxy"); const double delta = getProperty("DeltaQ"); int bins = static_cast<int>(max / delta); if (bins * delta != max) ++bins; // Stop at first boundary past MaxQxy if max is not a multiple of // delta const double startVal = -1.0 * delta * bins; bins *= 2; // go from -max to +max bins += 1; // Add 1 - this is a histogram // Create an output workspace with the same meta-data as the input MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create( inputWorkspace, bins - 1, bins, bins - 1); // ... but clear the masking from the parameter map as we don't want to carry // that over since this is essentially // a 2D rebin ParameterMap &pmap = outputWorkspace->instrumentParameters(); pmap.clearParametersByName("masked"); // Create a numeric axis to replace the vertical one Axis *verticalAxis = new BinEdgeAxis(bins); outputWorkspace->replaceAxis(1, verticalAxis); // Build up the X values Kernel::cow_ptr<MantidVec> axis; MantidVec &horizontalAxisRef = axis.access(); horizontalAxisRef.resize(bins); for (int i = 0; i < bins; ++i) { const double currentVal = startVal + i * delta; // Set the X value horizontalAxisRef[i] = currentVal; // Set the Y value on the axis verticalAxis->setValue(i, currentVal); } // Fill the X vectors in the output workspace for (int i = 0; i < bins - 1; ++i) { outputWorkspace->setX(i, axis); for (int j = 0; j < bins - j; ++j) { outputWorkspace->dataY(i)[j] = std::numeric_limits<double>::quiet_NaN(); outputWorkspace->dataE(i)[j] = std::numeric_limits<double>::quiet_NaN(); } } // Set the axis units outputWorkspace->getAxis(1)->unit() = outputWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("MomentumTransfer"); // Set the 'Y' unit (gets confusing here...this is probably a Z axis in this // case) outputWorkspace->setYUnitLabel("Cross Section (1/cm)"); setProperty("OutputWorkspace", outputWorkspace); return outputWorkspace; }
/** 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); }
/** * Rebin the input quadrilateral to the output grid * @param inputQ The input polygon * @param inputWS The input workspace containing the input intensity values * @param i The index in the vertical axis direction that inputQ references * @param j The index in the horizontal axis direction that inputQ references * @param outputWS A pointer to the output workspace that accumulates the data * @param verticalAxis A vector containing the output vertical axis bin boundaries */ void Rebin2D::rebinToOutput(const Geometry::Quadrilateral & inputQ, MatrixWorkspace_const_sptr inputWS, const size_t i, const size_t j, MatrixWorkspace_sptr outputWS, const std::vector<double> & verticalAxis) { const MantidVec & X = outputWS->readX(0); size_t qstart(0), qend(verticalAxis.size()-1), en_start(0), en_end(X.size() - 1); if( !getIntersectionRegion(outputWS, verticalAxis, inputQ, qstart, qend, en_start, en_end)) return; for( size_t qi = qstart; qi < qend; ++qi ) { const double vlo = verticalAxis[qi]; const double vhi = verticalAxis[qi+1]; for( size_t ei = en_start; ei < en_end; ++ei ) { const V2D ll(X[ei], vlo); const V2D lr(X[ei+1], vlo); const V2D ur(X[ei+1], vhi); const V2D ul(X[ei], vhi); const Quadrilateral outputQ(ll, lr, ur, ul); double yValue = inputWS->readY(i)[j]; if (boost::math::isnan(yValue)) { continue; } try { ConvexPolygon overlap = intersectionByLaszlo(outputQ, inputQ); const double weight = overlap.area()/inputQ.area(); yValue *= weight; double eValue = inputWS->readE(i)[j] * weight; const double overlapWidth = overlap.largestX() - overlap.smallestX(); if(inputWS->isDistribution()) { yValue *= overlapWidth; eValue *= overlapWidth; } eValue = eValue*eValue; PARALLEL_CRITICAL(overlap) { outputWS->dataY(qi)[ei] += yValue; outputWS->dataE(qi)[ei] += eValue; } } catch(Geometry::NoIntersectionException &) {} } } }
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; }
/** Uses 'Linear' as a subalgorithm to fit the log of the exponential curve expected for the transmission. * @param WS :: The single-spectrum workspace to fit * @return A workspace containing the fit */ API::MatrixWorkspace_sptr CalculateTransmissionBeamSpreader::fitToData(API::MatrixWorkspace_sptr WS) { g_log.information("Fitting the experimental transmission curve"); Algorithm_sptr childAlg = createSubAlgorithm("Linear",0.6,1.0); childAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", WS); const double lambdaMin = getProperty("MinWavelength"); const double lambdaMax = getProperty("MaxWavelength"); childAlg->setProperty<double>("StartX",lambdaMin); childAlg->setProperty<double>("EndX",lambdaMax); childAlg->executeAsSubAlg(); std::string fitStatus = childAlg->getProperty("FitStatus"); if ( fitStatus != "success" ) { g_log.error("Unable to successfully fit the data: " + fitStatus); throw std::runtime_error("Unable to successfully fit the data"); } // Only get to here if successful MatrixWorkspace_sptr result = childAlg->getProperty("OutputWorkspace"); if (logFit) { // Need to transform back to 'unlogged' double b = childAlg->getProperty("FitIntercept"); double m = childAlg->getProperty("FitSlope"); b = std::pow(10,b); m = std::pow(10,m); const MantidVec & X = result->readX(0); MantidVec & Y = result->dataY(0); MantidVec & E = result->dataE(0); for (size_t i = 0; i < Y.size(); ++i) { Y[i] = b*(std::pow(m,0.5*(X[i]+X[i+1]))); E[i] = std::abs(E[i]*Y[i]); } } return result; }
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; }
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"); }
/** @ 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); }
/** 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; }
/** * Set errors in Diff spectrum after a fit * @param data :: [input/output] Workspace containing spectrum to set errors to */ void ALCBaselineModellingModel::setErrorsAfterFit (MatrixWorkspace_sptr data) { data->dataE(2)=data->readE(0); }
/** * Enable points that were disabled for fit * @param destWs :: Workspace to enable points in * @param sourceWs :: Workspace with original errors */ void ALCBaselineModellingModel::enableDisabledPoints (MatrixWorkspace_sptr destWs, MatrixWorkspace_const_sptr sourceWs) { // Unwanted points were disabled by setting their errors to very high values. // We recover here the original errors stored in sourceWs destWs->dataE(0) = sourceWs->readE(0); }
/** Execute the ghost correction on all events in the input workspace **/ void GhostCorrection::exec() { // Get the input workspace this->inputW = getProperty("InputWorkspace"); //Load the grouping GroupingWorkspace_sptr groupWS = getProperty("GroupingWorkspace"); groupWS->makeDetectorIDToGroupMap(detId_to_group, nGroups); if (this->nGroups <= 0) throw std::runtime_error("The # of groups found in the Grouping file is 0."); // Now the offsets OffsetsWorkspace_sptr offsetsWS = getProperty("OffsetsWorkspace"); //Make the X axis to bin to. MantidVecPtr XValues_new; const int64_t numbins = VectorHelper::createAxisFromRebinParams(getProperty("BinParams"), XValues_new.access()); //Prepare the binfinder class BinFinder binner( getProperty("BinParams") ); if (binner.lastBinIndex() != static_cast<int>(XValues_new.access().size()-1)) { std::stringstream msg; msg << "GhostCorrection: The binner found " << binner.lastBinIndex()+1 << " bins, but the X axis has " << XValues_new.access().size() << ". Try different binning parameters."; throw std::runtime_error(msg.str()); } //Create an output Workspace2D with group # of output spectra MatrixWorkspace_sptr outputW = WorkspaceFactory::Instance().create("Workspace2D", this->nGroups-1, numbins, numbins-1); WorkspaceFactory::Instance().initializeFromParent(inputW, outputW, true); //Set the X bins in the output WS. Workspace2D_sptr outputWS2D = boost::dynamic_pointer_cast<Workspace2D>(outputW); for (std::size_t i=0; i < outputWS2D->getNumberHistograms(); i++) outputWS2D->setX(i, XValues_new); //Prepare the maps you need input_detectorIDToWorkspaceIndexMap = inputW->getDetectorIDToWorkspaceIndexMap(true); //Load the ghostmapping file this->loadGhostMap( getProperty("GhostCorrectionFilename") ); //Initialize progress reporting. int64_t numsteps = 0; //count how many steps for (int64_t gr=1; gr < this->nGroups; ++gr) numsteps += this->groupedGhostMaps[gr]->size(); Progress prog(this, 0.0, 1.0, numsteps); //Set up the tof-to-d_spacing map for all pixel ids. this->tof_to_d = Mantid::Algorithms::AlignDetectors::calcTofToD_ConversionMap(inputW, offsetsWS); // Set the final unit that our output workspace will have outputW->getAxis(0)->unit() = UnitFactory::Instance().create("dSpacing"); //Go through the groups, starting at #1! PARALLEL_FOR2(inputW, outputW) for (int64_t gr=1; gr < this->nGroups; ++gr) { PARALLEL_START_INTERUPT_REGION //TODO: Convert between group # and workspace index. Sigh. //Groups normally start at 1 and so the workspace index will be one below that. int64_t outputWorkspaceIndex = gr-1; //Start by making sure the Y and E values are 0. MantidVec& Y = outputW->dataY(outputWorkspaceIndex); MantidVec& E = outputW->dataE(outputWorkspaceIndex); Y.assign(Y.size(), 0.0); E.assign(E.size(), 0.0); //Perform the GhostCorrection //Ok, this map has as keys the source workspace indices GhostSourcesMap * thisGroupsGhostMap = this->groupedGhostMaps[gr]; GhostSourcesMap::iterator it; for (it = thisGroupsGhostMap->begin(); it != thisGroupsGhostMap->end(); ++it) { //This workspace index is causing 16 ghosts in this group. int64_t inputWorkspaceIndex = it->first; int64_t inputDetectorID = it->second; //This is the events in the pixel CAUSING the ghost. const EventList & sourceEventList = inputW->getEventList(inputWorkspaceIndex); //Now get the actual vector of tofevents const std::vector<TofEvent>& events = sourceEventList.getEvents(); size_t numEvents = events.size(); //Go through all events. for (size_t i=0; i < numEvents; i++) { const TofEvent& event = events[i]; for (int64_t g=0; g < NUM_GHOSTS; g++) { //Find the ghost correction int64_t fileIndex = inputDetectorID * NUM_GHOSTS + g; GhostDestinationValue ghostVal = (*rawGhostMap)[fileIndex]; //Convert to d-spacing using the factor of the GHOST pixel id double d_spacing = event.tof() * (*tof_to_d)[ghostVal.pixelId]; //Find the bin for this d-spacing int64_t binIndex = binner.bin(d_spacing); if (binIndex >= 0) { //Slap it in the Y array for this group; use the weight. Y[binIndex] += ghostVal.weight; } } //for each ghost } //for each event //Report progress prog.report(); } PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION // Assign the workspace to the output workspace property setProperty("OutputWorkspace", outputW); }