/** Check whether the spectra for the given workspaces are the same. @param ws1 : First workspace to compare @param ws2 : Second workspace to compare against exception. Otherwise a warning is generated. */ void ReflectometryReductionOne2::verifySpectrumMaps( MatrixWorkspace_const_sptr ws1, MatrixWorkspace_const_sptr ws2) { bool mismatch = false; // Check that the number of histograms is the same if (ws1->getNumberHistograms() != ws2->getNumberHistograms()) { mismatch = true; } // Check that the spectrum numbers match for each histogram if (!mismatch) { for (size_t i = 0; i < ws1->getNumberHistograms(); ++i) { if (ws1->indexInfo().spectrumNumber(i) != ws2->indexInfo().spectrumNumber(i)) { mismatch = true; break; } } } // Handle if error if (mismatch) { const std::string message = "Spectrum maps between workspaces do NOT match up."; g_log.warning(message); } }
/** * Construct a DataSource object around the specifed MatrixWorkspace. * * @param matWs Shared pointer to the matrix workspace being "wrapped" */ MatrixWSDataSource::MatrixWSDataSource( MatrixWorkspace_const_sptr matWs ) : SpectrumDataSource( 0.0, 1.0, 0.0, 1.0, 0, 0 ), m_matWs(matWs), m_emodeHandler(NULL) { m_totalXMin = matWs->getXMin(); m_totalXMax = matWs->getXMax(); m_totalYMin = 0; // Y direction is spectrum index m_totalYMax = (double)matWs->getNumberHistograms(); m_totalRows = matWs->getNumberHistograms(); m_totalCols = 1000000; // Default data resolution m_instrument = m_matWs->getInstrument(); if ( m_instrument ) { m_source = m_instrument->getSource(); if ( !m_source ) { g_log.debug("No SOURCE on instrument in MatrixWorkspace"); } m_sample = m_instrument->getSample(); if ( !m_sample ) { g_log.debug("No SAMPLE on instrument in MatrixWorkspace"); } } else { g_log.debug("No INSTRUMENT on MatrixWorkspace"); } }
/** Initialise a workspace from its parent * This sets values such as title, instrument, units, sample, spectramap. * This does NOT copy any data. * * @param parent :: the parent workspace * @param child :: the child workspace * @param differentSize :: A flag to indicate if the two workspace will be different sizes */ void WorkspaceFactoryImpl::initializeFromParent(const MatrixWorkspace_const_sptr parent, const MatrixWorkspace_sptr child, const bool differentSize) const { child->setTitle(parent->getTitle()); child->setComment(parent->getComment()); child->setInstrument(parent->getInstrument()); // This call also copies the SHARED POINTER to the parameter map // This call will (should) perform a COPY of the parameter map. child->instrumentParameters(); child->m_sample = parent->m_sample; child->m_run = parent->m_run; child->setYUnit(parent->m_YUnit); child->setYUnitLabel(parent->m_YUnitLabel); child->isDistribution(parent->isDistribution()); // Only copy the axes over if new sizes are not given if ( !differentSize ) { // Only copy mask map if same size for now. Later will need to check continued validity. child->m_masks = parent->m_masks; } // Same number of histograms = copy over the spectra data if (parent->getNumberHistograms() == child->getNumberHistograms()) { for (size_t wi=0; wi<parent->getNumberHistograms(); wi++) { ISpectrum * childSpec = child->getSpectrum(wi); const ISpectrum * parentSpec = parent->getSpectrum(wi); // Copy spectrum number and detector IDs childSpec->copyInfoFrom(*parentSpec); } } // deal with axis for (size_t i = 0; i < parent->m_axes.size(); ++i) { const size_t newAxisLength = child->getAxis(i)->length(); const size_t oldAxisLength = parent->getAxis(i)->length(); if ( !differentSize || newAxisLength == oldAxisLength ) { // Need to delete the existing axis created in init above delete child->m_axes[i]; // Now set to a copy of the parent workspace's axis child->m_axes[i] = parent->m_axes[i]->clone(child.get()); } else { if (! parent->getAxis(i)->isSpectra()) // WHY??? { delete child->m_axes[i]; // Call the 'different length' clone variant child->m_axes[i] = parent->m_axes[i]->clone(newAxisLength,child.get()); } } } return; }
/** Create a new instance of the same type of workspace as that given as * argument. * If the optional size parameters are given, the workspace will be initialised * using * those; otherwise it will be initialised to the same size as the parent. * This method should be used when you want to carry over the Workspace data * members * relating to the Instrument, Spectra-Detector Map, Sample & Axes to the new * workspace. * If the workspace is the same size as its parent, then the X data, axes and * mask list are * copied. If its a different size then they are not. * @param parent A shared pointer to the parent workspace * @param NVectors (Optional) The number of vectors/histograms/detectors in * the workspace * @param XLength (Optional) The number of X data points/bin boundaries in * each vector (must all be the same) * @param YLength (Optional) The number of data/error points in each vector * (must all be the same) * @return A shared pointer to the newly created instance * @throw std::out_of_range If invalid (0 or less) size arguments are given * @throw NotFoundException If the class is not registered in the factory */ MatrixWorkspace_sptr WorkspaceFactoryImpl::create(const MatrixWorkspace_const_sptr &parent, size_t NVectors, size_t XLength, size_t YLength) const { bool differentSize(true); // Use the parent sizes if new ones are not specified if (NVectors == size_t(-1)) NVectors = parent->getNumberHistograms(); if (XLength == size_t(-1)) XLength = parent->dataX(0).size(); if (YLength == size_t(-1)) { differentSize = false; YLength = parent->blocksize(); } // If the parent is an EventWorkspace, we want it to spawn a Workspace2D (or // managed variant) as a child std::string id(parent->id()); if (id == "EventWorkspace") id = "Workspace2D"; // Create an 'empty' workspace of the appropriate type and size MatrixWorkspace_sptr ws = create(id, NVectors, XLength, YLength); // Copy over certain parent data members initializeFromParent(parent, ws, differentSize); return ws; }
/** * Execute the algorithm */ void ExtractMasking::exec() { MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace"); const int nHist = static_cast<int>(inputWS->getNumberHistograms()); const int xLength(1), yLength(1); // Create a new workspace for the results, copy from the input to ensure that we copy over the instrument and current masking MatrixWorkspace_sptr outputWS = WorkspaceFactory::Instance().create(inputWS, nHist, xLength, yLength); Progress prog(this,0.0,1.0,nHist); MantidVecPtr xValues; xValues.access() = MantidVec(1, 0.0); PARALLEL_FOR2(inputWS, outputWS) for( int i = 0; i < nHist; ++i ) { PARALLEL_START_INTERUPT_REGION // Spectrum in the output workspace ISpectrum * outSpec = outputWS->getSpectrum(i); // Spectrum in the input workspace const ISpectrum * inSpec = inputWS->getSpectrum(i); // Copy X, spectrum number and detector IDs outSpec->setX(xValues); outSpec->copyInfoFrom(*inSpec); IDetector_const_sptr inputDet; bool inputIsMasked(false); try { inputDet = inputWS->getDetector(i); if( inputDet->isMasked() ) { inputIsMasked = true; } } catch(Kernel::Exception::NotFoundError &) { inputIsMasked = false; } if( inputIsMasked ) { outSpec->dataY()[0] = 0.0; outSpec->dataE()[0] = 0.0; } else { outSpec->dataY()[0] = 1.0; outSpec->dataE()[0] = 1.0; } prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION setProperty("OutputWorkspace", outputWS); }
/** 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 }
/** * Perform validation of input properties: * - input workspace must not be empty * - X values must be evenly spaced (unless accepting rounding errors) * - Real and Imaginary spectra must be in range of input workspace * - If complex, real and imaginary workspaces must be the same size * @returns :: map of property names to errors (empty map if no errors) */ std::map<std::string, std::string> FFT::validateInputs() { std::map<std::string, std::string> errors; MatrixWorkspace_const_sptr inWS = getProperty("InputWorkspace"); if (inWS) { const int iReal = getProperty("Real"); const int iImag = getProperty("Imaginary"); const MantidVec &X = inWS->readX(iReal); // check that the workspace isn't empty if (X.size() < 2) { errors["InputWorkspace"] = "Input workspace must have at least two values"; } else { // Check that the x values are evenly spaced // If accepting rounding errors, just give a warning if bins are // different. if (areBinWidthsUneven(X)) { errors["InputWorkspace"] = "X axis must be linear (all bins have same width)"; } } // check real, imaginary spectrum numbers and workspace sizes int nHist = static_cast<int>(inWS->getNumberHistograms()); if (iReal >= nHist) { errors["Real"] = "Real out of range"; } if (iImag != EMPTY_INT()) { MatrixWorkspace_const_sptr inImagWS = getProperty("InputImagWorkspace"); if (inImagWS) { if (inWS->blocksize() != inImagWS->blocksize()) { errors["Imaginary"] = "Real and Imaginary sizes do not match"; } nHist = static_cast<int>(inImagWS->getNumberHistograms()); } if (iImag >= nHist) { errors["Imaginary"] = "Imaginary out of range"; } } } return errors; }
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); }
std::map<std::string, std::string> EditInstrumentGeometry::validateInputs() { std::map<std::string, std::string> result; // everything depends on being parallel to the workspace # histo size_t numHist(0); bool hasWorkspacePtr(false); { MatrixWorkspace_const_sptr workspace = getProperty("Workspace"); // this is to guard against WorkspaceGroups // fallthrough is to skip workspace check and make sure if (bool(workspace)) { hasWorkspacePtr = true; numHist = workspace->getNumberHistograms(); } } std::string error; const std::vector<int32_t> specids = this->getProperty("SpectrumIDs"); if (!hasWorkspacePtr) { // use the number of spectra for the number of histograms numHist = specids.size(); // give up if it is empty if (numHist == 0) { return result; } } error = checkValues(specids, numHist); if (!error.empty()) result["SpectrumIDs"] = error; const std::vector<double> l2 = this->getProperty("L2"); error = checkValues(l2, numHist); if (!error.empty()) result["L2"] = error; const std::vector<double> tth = this->getProperty("Polar"); error = checkValues(tth, numHist); if (!error.empty()) result["Polar"] = error; const std::vector<double> phi = this->getProperty("Azimuthal"); error = checkValues(phi, numHist); if (!error.empty()) result["Azimuthal"] = error; const vector<int> detids = getProperty("DetectorIDs"); error = checkValues(detids, numHist); if (!error.empty()) result["DetectorIDs"] = error; // TODO verify that SpectrumIDs, L2, Polar, Azimuthal, and DetectorIDs are // parallel or not specified return result; }
/** Get the list of workspace indices to use * * @param spec :: returns the list of workspace indices */ void SaveNexusProcessed::getSpectrumList(std::vector<int> & spec, MatrixWorkspace_const_sptr matrixWorkspace) { std::vector<int> spec_list = getProperty("WorkspaceIndexList"); int spec_min = getProperty("WorkspaceIndexMin"); int spec_max = getProperty("WorkspaceIndexMax"); const bool list = !spec_list.empty(); const bool interval = (spec_max != Mantid::EMPTY_INT()); if ( spec_max == Mantid::EMPTY_INT() ) spec_max = 0; const int numberOfHist = static_cast<int>(matrixWorkspace->getNumberHistograms()); if( interval ) { if ( spec_max < spec_min || spec_max > numberOfHist-1 ) { g_log.error("Invalid WorkspaceIndex min/max properties"); throw std::invalid_argument("Inconsistent properties defined"); } spec.reserve(1+spec_max-spec_min); for(int i=spec_min;i<=spec_max;i++) spec.push_back(i); if (list) { for(size_t i=0;i<spec_list.size();i++) { int s = spec_list[i]; if ( s < 0 ) continue; if (s < spec_min || s > spec_max) spec.push_back(s); } } } else if (list) { spec_max=0; spec_min=numberOfHist-1; for(size_t i=0;i<spec_list.size();i++) { int s = spec_list[i]; if ( s < 0 ) continue; spec.push_back(s); if (s > spec_max) spec_max = s; if (s < spec_min) spec_min = s; } } else { spec_min=0; spec_max=numberOfHist-1; spec.reserve(1+spec_max-spec_min); for(int i=spec_min;i<=spec_max;i++) spec.push_back(i); } }
/** Validates input properties. * @return A map of input properties as keys and (error) messages as values. */ std::map<std::string, std::string> NormaliseToMonitor::validateInputs() { std::map<std::string, std::string> issues; // Check where the monitor spectrum should come from const Property *monSpecProp = getProperty("MonitorSpectrum"); const Property *monIDProp = getProperty("MonitorID"); MatrixWorkspace_const_sptr monWS = getProperty("MonitorWorkspace"); // something has to be set if (monSpecProp->isDefault() && !monWS && monIDProp->isDefault()) { const std::string mess("Either MonitorSpectrum, MonitorID or " "MonitorWorkspace has to be provided."); issues["MonitorSpectrum"] = mess; issues["MonitorID"] = mess; issues["MonitorWorkspace"] = mess; } const double intMin = getProperty("IntegrationRangeMin"); const double intMax = getProperty("IntegrationRangeMax"); if (!isEmpty(intMin) && !isEmpty(intMax)) { if (intMin > intMax) { issues["IntegrationRangeMin"] = "Range minimum set to a larger value than maximum."; issues["IntegrationRangeMax"] = "Range maximum set to a smaller value than minimum."; } } if (monWS && monSpecProp->isDefault()) { const int monIndex = getProperty("MonitorWorkspaceIndex"); if (monIndex < 0) { issues["MonitorWorkspaceIndex"] = "A workspace index cannot be negative."; } else if (monWS->getNumberHistograms() <= static_cast<size_t>(monIndex)) { issues["MonitorWorkspaceIndex"] = "The MonitorWorkspace must contain the MonitorWorkspaceIndex."; } MatrixWorkspace_const_sptr inWS = getProperty("InputWorkspace"); if (monWS->getInstrument()->getName() != inWS->getInstrument()->getName()) { issues["MonitorWorkspace"] = "The Input and Monitor workspaces must come " "from the same instrument."; } if (monWS->getAxis(0)->unit()->unitID() != inWS->getAxis(0)->unit()->unitID()) { issues["MonitorWorkspace"] = "The Input and Monitor workspaces must have the same unit"; } } return issues; }
/** * Determine the minimum and maximum spectra ids. * * @param axis The axis to search through. * @param min The minimum id (output). * @param max The maximum id (output). */ void getMinMax(MatrixWorkspace_const_sptr ws, specid_t& min, specid_t& max) { specid_t temp; size_t length = ws->getNumberHistograms(); // initial values min = max = ws->getSpectrum(0)->getSpectrumNo(); for (size_t i = 0; i < length; i++) { temp = ws->getSpectrum(i)->getSpectrumNo(); // Adjust min/max if (temp < min) min = temp; if (temp > max) max = temp; } }
/* Execute the transformtion. Generates an output IMDEventWorkspace. @return the constructed IMDEventWorkspace following the transformation. @param ws: Input MatrixWorkspace const shared pointer */ IMDEventWorkspace_sptr ReflectometryTransformQxQz::execute(MatrixWorkspace_const_sptr inputWs) const { const size_t nbinsx = 10; const size_t nbinsz = 10; auto ws = boost::make_shared<MDEventWorkspace<MDLeanEvent<2>,2> >(); MDHistoDimension_sptr qxDim = MDHistoDimension_sptr(new MDHistoDimension("Qx","qx","(Ang^-1)", static_cast<Mantid::coord_t>(m_qxMin), static_cast<Mantid::coord_t>(m_qxMax), nbinsx)); MDHistoDimension_sptr qzDim = MDHistoDimension_sptr(new MDHistoDimension("Qz","qz","(Ang^-1)", static_cast<Mantid::coord_t>(m_qzMin), static_cast<Mantid::coord_t>(m_qzMax), nbinsz)); ws->addDimension(qxDim); ws->addDimension(qzDim); // Set some reasonable values for the box controller BoxController_sptr bc = ws->getBoxController(); bc->setSplitInto(2); bc->setSplitThreshold(10); // Initialize the workspace. ws->initialize(); // Start with a MDGridBox. ws->splitBox(); auto spectraAxis = inputWs->getAxis(1); for(size_t index = 0; index < inputWs->getNumberHistograms(); ++index) { auto counts = inputWs->readY(index); auto wavelengths = inputWs->readX(index); auto errors = inputWs->readE(index); const size_t nInputBins = wavelengths.size() -1; const double theta_final = spectraAxis->getValue(index); m_QxCalculation.setThetaFinal(theta_final); m_QzCalculation.setThetaFinal(theta_final); //Loop over all bins in spectra for(size_t binIndex = 0; binIndex < nInputBins; ++binIndex) { const double& wavelength = 0.5*(wavelengths[binIndex] + wavelengths[binIndex+1]); double _qx = m_QxCalculation.execute(wavelength); double _qz = m_QzCalculation.execute(wavelength); double centers[2] = {_qx, _qz}; ws->addEvent(MDLeanEvent<2>(float(counts[binIndex]), float(errors[binIndex]*errors[binIndex]), centers)); } ws->splitAllIfNeeded(NULL); } return ws; }
void ConvertToMatrixWorkspace::exec() { MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace"); // Let's see if we have to do anything first. Basically we want to avoid the data copy if we can DataObjects::EventWorkspace_const_sptr eventW = boost::dynamic_pointer_cast<const DataObjects::EventWorkspace>(inputWorkspace); MatrixWorkspace_sptr outputWorkspace; if( eventW ) { g_log.information() << "Converting EventWorkspace to Workspace2D.\n"; const size_t numHists = inputWorkspace->getNumberHistograms(); Progress prog(this,0.0,1.0,numHists*2); // Sort the input workspace in-place by TOF. This can be faster if there are few event lists. eventW->sortAll(TOF_SORT, &prog); // Create the output workspace. This will copy many aspects fron the input one. outputWorkspace = WorkspaceFactory::Instance().create(inputWorkspace); // ...but not the data, so do that here. PARALLEL_FOR2(inputWorkspace,outputWorkspace) for (int64_t i = 0; i < (int64_t)numHists; ++i) { PARALLEL_START_INTERUPT_REGION const ISpectrum * inSpec = inputWorkspace->getSpectrum(i); ISpectrum * outSpec = outputWorkspace->getSpectrum(i); outSpec->copyInfoFrom(*inSpec); outSpec->setX(inSpec->ptrX()); outSpec->dataY() = inSpec->dataY(); outSpec->dataE() = inSpec->dataE(); prog.report("Binning"); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION outputWorkspace->generateSpectraMap(); } else {
/** * Plots the loaded file to the miniplot and sets the guides * and the range * * @param filename :: The name of the workspace to plot */ void Stretch::handleSampleInputReady(const QString &filename) { m_uiForm.ppPlot->addSpectrum("Sample", filename, 0); // update the maximum and minimum range bar positions QPair<double, double> range = m_uiForm.ppPlot->getCurveRange("Sample"); auto eRangeSelector = m_uiForm.ppPlot->getRangeSelector("StretchERange"); setRangeSelector(eRangeSelector, m_properties["EMin"], m_properties["EMax"], range); setPlotPropertyRange(eRangeSelector, m_properties["EMin"], m_properties["EMax"], range); // update the current positions of the range bars eRangeSelector->setMinimum(range.first); eRangeSelector->setMaximum(range.second); // set the max spectrum MatrixWorkspace_const_sptr sampleWs = getADSMatrixWorkspace(filename.toStdString()); const int spectra = static_cast<int>(sampleWs->getNumberHistograms()); m_uiForm.spPreviewSpectrum->setMaximum(spectra - 1); }
/** * Add -1.*minValue on each spectra. * * @param minWS A workspace of minimum values for each spectra. This is *calculated in * the @see exec portion of the algorithm. * @param wksp The workspace to modify. * @param prog The progress. */ void ResetNegatives::pushMinimum(MatrixWorkspace_const_sptr minWS, MatrixWorkspace_sptr wksp, Progress &prog) { int64_t nHist = minWS->getNumberHistograms(); PARALLEL_FOR_IF(Kernel::threadSafe(*wksp, *minWS)) for (int64_t i = 0; i < nHist; i++) { PARALLEL_START_INTERUPT_REGION double minValue = minWS->y(i)[0]; if (minValue <= 0) { minValue *= -1.; auto &y = wksp->mutableY(i); for (double &value : y) { value = fixZero(value + minValue); } } prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION }
/** * Determine the minimum spectrum id for summing. This requires that * SumSpectra::indices has already been set. * @param localworkspace The workspace to use. * @return The minimum spectrum id for all the spectra being summed. */ specid_t SumSpectra::getOutputSpecId(MatrixWorkspace_const_sptr localworkspace) { // initial value specid_t specId = localworkspace->getSpectrum(*(this->m_indices.begin()))->getSpectrumNo(); // the total number of spectra int totalSpec = static_cast<int>(localworkspace->getNumberHistograms()); specid_t temp; for (auto index : this->m_indices) { if (index < totalSpec) { temp = localworkspace->getSpectrum(index)->getSpectrumNo(); if (temp < specId) specId = temp; } } return specId; }
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 }
/** * Add -1.*minValue on each spectra. * * @param minWS A workspace of minimum values for each spectra. This is calculated in * the @see exec portion of the algorithm. * @param wksp The workspace to modify. * @param prog The progress. */ void ResetNegatives::pushMinimum(MatrixWorkspace_const_sptr minWS, MatrixWorkspace_sptr wksp, Progress &prog) { int64_t nHist = minWS->getNumberHistograms(); PARALLEL_FOR2(wksp, minWS) for (int64_t i = 0; i < nHist; i++) { PARALLEL_START_INTERUPT_REGION double minValue = minWS->readY(i)[0]; if (minValue <= 0) { minValue *= -1.; MantidVec & y = wksp->dataY(i); for (MantidVec::iterator it = y.begin(); it != y.end(); ++it) { *it = fixZero(*it + minValue); } } prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION }
void SofQW::exec() { // Find the approopriate algorithm std::string method = this->getProperty("Method"); std::string child = "SofQW" + method; // Setup and run Algorithm_sptr childAlg = boost::dynamic_pointer_cast<Algorithm>( createChildAlgorithm(child, 0.0, 1.0)); // This will add the Method property to the child algorithm but it will be // ignored anyway... childAlg->copyPropertiesFrom(*this); childAlg->execute(); MatrixWorkspace_sptr outputWS = childAlg->getProperty("OutputWorkspace"); this->setProperty("OutputWorkspace", outputWS); // Progress reports & cancellation MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace"); const size_t nHistos = inputWorkspace->getNumberHistograms(); auto m_progress = make_unique<Progress>(this, 0.0, 1.0, nHistos); m_progress->report("Creating output workspace"); }
IMDHistoWorkspace_sptr ReflectometryTransform::executeMDNormPoly( MatrixWorkspace_const_sptr inputWs) const { auto input_x_dim = inputWs->getXDimension(); MDHistoDimension_sptr dim0 = MDHistoDimension_sptr(new MDHistoDimension( input_x_dim->getName(), input_x_dim->getDimensionId(), input_x_dim->getMDFrame(), static_cast<Mantid::coord_t>(input_x_dim->getMinimum()), static_cast<Mantid::coord_t>(input_x_dim->getMaximum()), input_x_dim->getNBins())); auto input_y_dim = inputWs->getYDimension(); MDHistoDimension_sptr dim1 = MDHistoDimension_sptr(new MDHistoDimension( input_y_dim->getName(), input_y_dim->getDimensionId(), input_y_dim->getMDFrame(), static_cast<Mantid::coord_t>(input_y_dim->getMinimum()), static_cast<Mantid::coord_t>(input_y_dim->getMaximum()), input_y_dim->getNBins())); auto outWs = boost::make_shared<MDHistoWorkspace>(dim0, dim1); for (size_t nHistoIndex = 0; nHistoIndex < inputWs->getNumberHistograms(); ++nHistoIndex) { const MantidVec X = inputWs->readX(nHistoIndex); const MantidVec Y = inputWs->readY(nHistoIndex); const MantidVec E = inputWs->readE(nHistoIndex); for (size_t nBinIndex = 0; nBinIndex < inputWs->blocksize(); ++nBinIndex) { auto value_index = outWs->getLinearIndex(nBinIndex, nHistoIndex); outWs->setSignalAt(value_index, Y[nBinIndex]); outWs->setErrorSquaredAt(value_index, E[nBinIndex] * E[nBinIndex]); } } return outWs; }
void SANSDirectBeamScaling::exec() { MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace"); const double beamRadius = getProperty("BeamRadius"); const double attTrans = getProperty("AttenuatorTransmission"); const double attTransErr = getProperty("AttenuatorTransmissionError"); // Extract the required spectra into separate workspaces std::vector<detid_t> udet; std::vector<size_t> index; udet.push_back(getProperty("BeamMonitor")); // Convert UDETs to workspace indices inputWS->getIndicesFromDetectorIDs(udet,index); if (index.size() < 1) { g_log.debug() << "inputWS->getIndicesFromDetectorIDs() returned empty\n"; throw std::invalid_argument("Could not find the incident beam monitor spectra\n"); } const int64_t numHists = inputWS->getNumberHistograms(); Progress progress(this,0.0,1.0,numHists); // Number of X bins const int64_t xLength = inputWS->readY(0).size(); // Monitor counts double monitor = 0.0; const MantidVec& MonIn = inputWS->readY(index[0]); for (int64_t j = 0; j < xLength; j++) monitor += MonIn[j]; const V3D sourcePos = inputWS->getInstrument()->getSource()->getPos(); double counts = 0.0; double error = 0.0; int nPixels = 0; // Sample-detector distance for the contributing pixels double sdd = 0.0; for (int64_t i = 0; i < int64_t(numHists); ++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; 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); // Sum up all the counts V3D pos = det->getPos() - V3D(sourcePos.X(), sourcePos.Y(), 0.0); const double pixelDistance = pos.Z(); pos.setZ(0.0); if (pos.norm() <= beamRadius) { // Correct data for all X bins for (int64_t j = 0; j < xLength; j++) { counts += YIn[j]; error += EIn[j]*EIn[j]; } nPixels += 1; sdd += pixelDistance; } progress.report("Absolute Scaling"); } // Get the average SDD for the counted pixels, and transform to mm. sdd = sdd/nPixels*1000.0; error = std::sqrt(error); // Transform from m to mm double sourceAperture = getProperty("SourceApertureRadius"); sourceAperture *= 1000.0; // Transform from m to mm double sampleAperture = getProperty("SampleApertureRadius"); sampleAperture *= 1000.0; //TODO: replace this by some meaningful value const double KCG2FluxPerMon_SUGAR = 1.0; // Solid angle correction scale in 1/(cm^2)/steradian double solidAngleCorrScale = sdd/(M_PI*sourceAperture*sampleAperture); solidAngleCorrScale = solidAngleCorrScale*solidAngleCorrScale*100.0; // Scaling factor in n/(monitor count)/(cm^2)/steradian double scale = counts/monitor*solidAngleCorrScale/KCG2FluxPerMon_SUGAR; double scaleErr = std::abs(error/monitor)*solidAngleCorrScale/KCG2FluxPerMon_SUGAR; scaleErr = std::abs(scale/attTrans)*sqrt( (scaleErr/scale)*(scaleErr/scale) +(attTransErr/attTrans)*(attTransErr/attTrans) ); scale /= attTrans; std::vector<double> output; output.push_back(scale); output.push_back(scaleErr); setProperty("ScaleFactor", output); }
/** * Execution path for NormalisedPolygon Rebinning * @param inputWS : Workspace to be rebinned * @param vertexes : TableWorkspace for debugging purposes * @param dumpVertexes : determines whether vertexes will be written to for * debugging purposes or not * @param outputDimensions : used for the column headings for Dump Vertexes */ MatrixWorkspace_sptr ReflectometryTransform::executeNormPoly( MatrixWorkspace_const_sptr inputWS, boost::shared_ptr<Mantid::DataObjects::TableWorkspace> &vertexes, bool dumpVertexes, std::string outputDimensions) const { MatrixWorkspace_sptr temp = WorkspaceFactory::Instance().create( "RebinnedOutput", m_d1NumBins, m_d0NumBins, m_d0NumBins); RebinnedOutput_sptr outWS = boost::static_pointer_cast<RebinnedOutput>(temp); const double widthD0 = (m_d0Max - m_d0Min) / double(m_d0NumBins); const double widthD1 = (m_d1Max - m_d1Min) / double(m_d1NumBins); std::vector<double> xBinsVec; std::vector<double> zBinsVec; VectorHelper::createAxisFromRebinParams({m_d1Min, widthD1, m_d1Max}, zBinsVec); VectorHelper::createAxisFromRebinParams({m_d0Min, widthD0, m_d0Max}, xBinsVec); // Put the correct bin boundaries into the workspace auto verticalAxis = new BinEdgeAxis(zBinsVec); outWS->replaceAxis(1, verticalAxis); for (size_t i = 0; i < zBinsVec.size() - 1; ++i) outWS->setX(i, xBinsVec); verticalAxis->title() = m_d1Label; // Prepare the required theta values DetectorAngularCache cache = initAngularCaches(inputWS.get()); m_theta = cache.thetas; m_thetaWidths = cache.thetaWidths; const size_t nHistos = inputWS->getNumberHistograms(); const size_t nBins = inputWS->blocksize(); // Holds the spectrum-detector mapping std::vector<specnum_t> specNumberMapping; std::vector<detid_t> detIDMapping; // Create a table for the output if we want to debug vertex positioning addColumnHeadings(vertexes, outputDimensions); for (size_t i = 0; i < nHistos; ++i) { IDetector_const_sptr detector = inputWS->getDetector(i); if (!detector || detector->isMasked() || detector->isMonitor()) { continue; } // Compute polygon points const double theta = m_theta[i]; const double thetaWidth = m_thetaWidths[i]; const double thetaHalfWidth = 0.5 * thetaWidth; const double thetaLower = theta - thetaHalfWidth; const double thetaUpper = theta + thetaHalfWidth; const MantidVec &X = inputWS->readX(i); const MantidVec &Y = inputWS->readY(i); const MantidVec &E = inputWS->readE(i); for (size_t j = 0; j < nBins; ++j) { const double lamLower = X[j]; const double lamUpper = X[j + 1]; const double signal = Y[j]; const double error = E[j]; auto inputQ = m_calculator->createQuad(lamUpper, lamLower, thetaUpper, thetaLower); FractionalRebinning::rebinToFractionalOutput(inputQ, inputWS, i, j, outWS, zBinsVec); // Find which qy bin this point lies in const auto qIndex = std::upper_bound(zBinsVec.begin(), zBinsVec.end(), inputQ[0].Y()) - zBinsVec.begin(); if (qIndex != 0 && qIndex < static_cast<int>(zBinsVec.size())) { // Add this spectra-detector pair to the mapping specNumberMapping.push_back( outWS->getSpectrum(qIndex - 1).getSpectrumNo()); detIDMapping.push_back(detector->getID()); } // Debugging if (dumpVertexes) { writeRow(vertexes, inputQ[0], i, j, signal, error); writeRow(vertexes, inputQ[1], i, j, signal, error); writeRow(vertexes, inputQ[2], i, j, signal, error); writeRow(vertexes, inputQ[3], i, j, signal, error); } } } outWS->finalize(); FractionalRebinning::normaliseOutput(outWS, inputWS); // Set the output spectrum-detector mapping SpectrumDetectorMapping outputDetectorMap(specNumberMapping, detIDMapping); outWS->updateSpectraUsing(outputDetectorMap); outWS->getAxis(0)->title() = m_d0Label; outWS->setYUnit(""); outWS->setYUnitLabel("Intensity"); return outWS; }
/** Executes the algorithm * * @throw Exception::FileError If the grouping file cannot be opened or read successfully * @throw runtime_error If unable to run one of the Child Algorithms successfully */ void ReadGroupsFromFile::exec() { MatrixWorkspace_const_sptr ws = getProperty("InstrumentWorkspace"); // Get the instrument. Instrument_const_sptr inst = ws->getInstrument(); // Create a copy (without the data) of the workspace - it will contain the Workspace2D_sptr localWorkspace = boost::dynamic_pointer_cast<Workspace2D>(WorkspaceFactory::Instance().create(ws, ws->getNumberHistograms(), 2, 1)); if (!localWorkspace) throw std::runtime_error("Failed when creating a Workspace2D from the input!"); const std::string groupfile=getProperty("GroupingFilename"); if ( ! groupfile.empty() ) { std::string filename(groupfile); std::transform(filename.begin(), filename.end(), filename.begin(), tolower); if ( filename.find(".xml") != std::string::npos ) { readXMLGroupingFile(groupfile); } else { readGroupingFile(groupfile); } } // Get the instrument. const int64_t nHist=localWorkspace->getNumberHistograms(); // Determine whether the user wants to see unselected detectors or not const std::string su=getProperty("ShowUnselected"); bool showunselected=(!su.compare("True")); bool success=false; for (int64_t i=0;i<nHist;i++) { ISpectrum * spec = localWorkspace->getSpectrum(i); const std::set<detid_t> & dets = spec->getDetectorIDs(); if (dets.empty()) // Nothing { spec->dataY()[0]=0.0; continue; } // Find the first detector ID in the list calmap::const_iterator it=calibration.find(*dets.begin()); if (it==calibration.end()) //Could not find the detector { spec->dataY()[0]=0.0; continue; } if (showunselected) { if (((*it).second).second==0) spec->dataY()[0]=0.0; else spec->dataY()[0]=static_cast<double>(((*it).second).first); } else spec->dataY()[0]=static_cast<double>(((*it).second).first); if (!success) success=true; //At least one detector is found in the cal file } progress(1); calibration.clear(); if (!success) //Do some cleanup { localWorkspace.reset(); throw std::runtime_error("Fail to found a detector in "+groupfile+" existing in instrument "+inst->getName()); } setProperty("OutputWorkspace",localWorkspace); return; }
void GroupDetectors2::exec() { // Get the input workspace const MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace"); //Check if it is an event workspace const bool preserveEvents = getProperty("PreserveEvents"); EventWorkspace_const_sptr eventW = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS); if (eventW != NULL && preserveEvents) { this->execEvent(); return; } const size_t numInHists = inputWS->getNumberHistograms(); // Bin boundaries need to be the same, so do the full check on whether they actually are if (!API::WorkspaceHelpers::commonBoundaries(inputWS)) { g_log.error() << "Can only group if the histograms have common bin boundaries\n"; throw std::invalid_argument("Can only group if the histograms have common bin boundaries"); } progress( m_FracCompl = CHECKBINS ); interruption_point(); // some values loaded into this vector can be negative so this needs to be a signed type std::vector<int64_t> unGroupedInds; //the ungrouped list could be very big but might be none at all unGroupedInds.reserve(numInHists); for( size_t i = 0; i < numInHists ; i++ ) { unGroupedInds.push_back(i); } // read in the input parameters to make that map, if KeepUngroupedSpectra was set we'll need a list of the ungrouped spectrra too getGroups(inputWS, unGroupedInds); // converting the list into a set gets rid of repeated values, here the multiple GroupDetectors2::USED become one USED at the start const std::set<int64_t> unGroupedSet(unGroupedInds.begin(), unGroupedInds.end()); // Check what the user asked to be done with ungrouped spectra const bool keepAll = getProperty("KeepUngroupedSpectra"); // ignore the one USED value in set or ignore all the ungrouped if the user doesn't want them const size_t numUnGrouped = keepAll ? unGroupedSet.size()-1 : 0; MatrixWorkspace_sptr outputWS = WorkspaceFactory::Instance().create(inputWS, m_GroupSpecInds.size()+ numUnGrouped, inputWS->readX(0).size(), inputWS->blocksize()); // prepare to move the requested histograms into groups, first estimate how long for progress reporting. +1 in the demonator gets rid of any divide by zero risk double prog4Copy=( (1.0 - m_FracCompl)/(static_cast<double>(numInHists-unGroupedSet.size())+1.) )* (keepAll ? static_cast<double>(numInHists-unGroupedSet.size())/static_cast<double>(numInHists): 1.); // Build a new map const size_t outIndex = formGroups(inputWS, outputWS, prog4Copy); // If we're keeping ungrouped spectra if (keepAll) { // copy them into the output workspace moveOthers(unGroupedSet, inputWS, outputWS, outIndex); } g_log.information() << name() << " algorithm has finished\n"; 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; }
/** Executes the algorithm * * @throw runtime_error Thrown if algorithm cannot execute */ void Fit1D::exec() { // Custom initialization prepare(); // check if derivative defined in derived class bool isDerivDefined = true; gsl_matrix *M = NULL; try { const std::vector<double> inTest(m_parameterNames.size(), 1.0); std::vector<double> outTest(m_parameterNames.size()); const double xValuesTest = 0; JacobianImpl J; M = gsl_matrix_alloc(m_parameterNames.size(), 1); J.setJ(M); // note nData set to zero (last argument) hence this should avoid further // memory problems functionDeriv(&(inTest.front()), &J, &xValuesTest, 0); } catch (Exception::NotImplementedError &) { isDerivDefined = false; } gsl_matrix_free(M); // Try to retrieve optional properties int histNumber = getProperty("WorkspaceIndex"); const int maxInterations = getProperty("MaxIterations"); // Get the input workspace MatrixWorkspace_const_sptr localworkspace = getProperty("InputWorkspace"); // number of histogram is equal to the number of spectra const size_t numberOfSpectra = localworkspace->getNumberHistograms(); // Check that the index given is valid if (histNumber >= static_cast<int>(numberOfSpectra)) { g_log.warning("Invalid Workspace index given, using first Workspace"); histNumber = 0; } // Retrieve the spectrum into a vector const MantidVec &XValues = localworkspace->readX(histNumber); const MantidVec &YValues = localworkspace->readY(histNumber); const MantidVec &YErrors = localworkspace->readE(histNumber); // Read in the fitting range data that we were sent double startX = getProperty("StartX"); double endX = getProperty("EndX"); // check if the values had been set, otherwise use defaults if (isEmpty(startX)) { startX = XValues.front(); modifyStartOfRange(startX); // does nothing by default but derived class may // provide a more intelligent value } if (isEmpty(endX)) { endX = XValues.back(); modifyEndOfRange(endX); // does nothing by default but derived class may // previde a more intelligent value } int m_minX; int m_maxX; // Check the validity of startX if (startX < XValues.front()) { g_log.warning("StartX out of range! Set to start of frame."); startX = XValues.front(); } // Get the corresponding bin boundary that comes before (or coincides with) // this value for (m_minX = 0; XValues[m_minX + 1] < startX; ++m_minX) { } // Check the validity of endX and get the bin boundary that come after (or // coincides with) it if (endX >= XValues.back() || endX < startX) { g_log.warning("EndX out of range! Set to end of frame"); endX = XValues.back(); m_maxX = static_cast<int>(YValues.size()); } else { for (m_maxX = m_minX; XValues[m_maxX] < endX; ++m_maxX) { } } afterDataRangedDetermined(m_minX, m_maxX); // create and populate GSL data container warn user if l_data.n < l_data.p // since as a rule of thumb this is required as a minimum to obtained // 'accurate' // fitting parameter values. FitData l_data(this, getProperty("Fix")); l_data.n = m_maxX - m_minX; // m_minX and m_maxX are array index markers. I.e. e.g. 0 & 19. if (l_data.n == 0) { g_log.error("The data set is empty."); throw std::runtime_error("The data set is empty."); } if (l_data.n < l_data.p) { g_log.error( "Number of data points less than number of parameters to be fitted."); throw std::runtime_error( "Number of data points less than number of parameters to be fitted."); } l_data.X = new double[l_data.n]; l_data.sigmaData = new double[l_data.n]; l_data.forSimplexLSwrap = new double[l_data.n]; l_data.parameters = new double[nParams()]; // check if histogram data in which case use mid points of histogram bins const bool isHistogram = localworkspace->isHistogramData(); for (unsigned int i = 0; i < l_data.n; ++i) { if (isHistogram) l_data.X[i] = 0.5 * (XValues[m_minX + i] + XValues[m_minX + i + 1]); // take mid-point if histogram bin else l_data.X[i] = XValues[m_minX + i]; } l_data.Y = &YValues[m_minX]; // check that no error is negative or zero for (unsigned int i = 0; i < l_data.n; ++i) { if (YErrors[m_minX + i] <= 0.0) { l_data.sigmaData[i] = 1.0; } else l_data.sigmaData[i] = YErrors[m_minX + i]; } // create array of fitted parameter. Take these to those input by the user. // However, for doing the // underlying fitting it might be more efficient to actually perform the // fitting on some of other // form of the fitted parameters. For instance, take the Gaussian sigma // parameter. In practice it // in fact more efficient to perform the fitting not on sigma but 1/sigma^2. // The methods // modifyInitialFittedParameters() and modifyFinalFittedParameters() are used // to allow for this; // by default these function do nothing. m_fittedParameter.clear(); for (size_t i = 0; i < nParams(); i++) { m_fittedParameter.push_back(getProperty(m_parameterNames[i])); } modifyInitialFittedParameters( m_fittedParameter); // does nothing except if overwritten by derived class for (size_t i = 0; i < nParams(); i++) { l_data.parameters[i] = m_fittedParameter[i]; } // set-up initial guess for fit parameters gsl_vector *initFuncArg; initFuncArg = gsl_vector_alloc(l_data.p); for (size_t i = 0, j = 0; i < nParams(); i++) { if (l_data.active[i]) gsl_vector_set(initFuncArg, j++, m_fittedParameter[i]); } // set-up GSL container to be used with GSL simplex algorithm gsl_multimin_function gslSimplexContainer; gslSimplexContainer.n = l_data.p; // n here refers to number of parameters gslSimplexContainer.f = &gsl_costFunction; gslSimplexContainer.params = &l_data; // set-up GSL least squares container gsl_multifit_function_fdf f; f.f = &gsl_f; f.df = &gsl_df; f.fdf = &gsl_fdf; f.n = l_data.n; f.p = l_data.p; f.params = &l_data; // set-up remaining GSL machinery for least squared const gsl_multifit_fdfsolver_type *T = gsl_multifit_fdfsolver_lmsder; gsl_multifit_fdfsolver *s = NULL; if (isDerivDefined) { s = gsl_multifit_fdfsolver_alloc(T, l_data.n, l_data.p); gsl_multifit_fdfsolver_set(s, &f, initFuncArg); } // set-up remaining GSL machinery to use simplex algorithm const gsl_multimin_fminimizer_type *simplexType = gsl_multimin_fminimizer_nmsimplex; gsl_multimin_fminimizer *simplexMinimizer = NULL; gsl_vector *simplexStepSize = NULL; if (!isDerivDefined) { simplexMinimizer = gsl_multimin_fminimizer_alloc(simplexType, l_data.p); simplexStepSize = gsl_vector_alloc(l_data.p); gsl_vector_set_all(simplexStepSize, 1.0); // is this always a sensible starting step size? gsl_multimin_fminimizer_set(simplexMinimizer, &gslSimplexContainer, initFuncArg, simplexStepSize); } // finally do the fitting int iter = 0; int status; double finalCostFuncVal; double dof = static_cast<double>( l_data.n - l_data.p); // dof stands for degrees of freedom // Standard least-squares used if derivative function defined otherwise // simplex Progress prog(this, 0.0, 1.0, maxInterations); if (isDerivDefined) { do { iter++; status = gsl_multifit_fdfsolver_iterate(s); if (status) // break if error break; status = gsl_multifit_test_delta(s->dx, s->x, 1e-4, 1e-4); prog.report(); } while (status == GSL_CONTINUE && iter < maxInterations); double chi = gsl_blas_dnrm2(s->f); finalCostFuncVal = chi * chi / dof; // put final converged fitting values back into m_fittedParameter for (size_t i = 0, j = 0; i < nParams(); i++) if (l_data.active[i]) m_fittedParameter[i] = gsl_vector_get(s->x, j++); } else { do { iter++; status = gsl_multimin_fminimizer_iterate(simplexMinimizer); if (status) // break if error break; double size = gsl_multimin_fminimizer_size(simplexMinimizer); status = gsl_multimin_test_size(size, 1e-2); prog.report(); } while (status == GSL_CONTINUE && iter < maxInterations); finalCostFuncVal = simplexMinimizer->fval / dof; // put final converged fitting values back into m_fittedParameter for (unsigned int i = 0, j = 0; i < m_fittedParameter.size(); i++) if (l_data.active[i]) m_fittedParameter[i] = gsl_vector_get(simplexMinimizer->x, j++); } modifyFinalFittedParameters( m_fittedParameter); // do nothing except if overwritten by derived class // Output summary to log file std::string reportOfFit = gsl_strerror(status); g_log.information() << "Iteration = " << iter << "\n" << "Status = " << reportOfFit << "\n" << "Chi^2/DoF = " << finalCostFuncVal << "\n"; for (size_t i = 0; i < m_fittedParameter.size(); i++) g_log.information() << m_parameterNames[i] << " = " << m_fittedParameter[i] << " \n"; // also output summary to properties setProperty("OutputStatus", reportOfFit); setProperty("OutputChi2overDoF", finalCostFuncVal); for (size_t i = 0; i < m_fittedParameter.size(); i++) setProperty(m_parameterNames[i], m_fittedParameter[i]); std::string output = getProperty("Output"); if (!output.empty()) { // calculate covariance matrix if derivatives available gsl_matrix *covar(NULL); std::vector<double> standardDeviations; std::vector<double> sdExtended; if (isDerivDefined) { covar = gsl_matrix_alloc(l_data.p, l_data.p); gsl_multifit_covar(s->J, 0.0, covar); int iPNotFixed = 0; for (size_t i = 0; i < nParams(); i++) { sdExtended.push_back(1.0); if (l_data.active[i]) { sdExtended[i] = sqrt(gsl_matrix_get(covar, iPNotFixed, iPNotFixed)); iPNotFixed++; } } modifyFinalFittedParameters(sdExtended); for (size_t i = 0; i < nParams(); i++) if (l_data.active[i]) standardDeviations.push_back(sdExtended[i]); declareProperty( new WorkspaceProperty<API::ITableWorkspace>( "OutputNormalisedCovarianceMatrix", "", Direction::Output), "The name of the TableWorkspace in which to store the final " "covariance matrix"); setPropertyValue("OutputNormalisedCovarianceMatrix", output + "_NormalisedCovarianceMatrix"); Mantid::API::ITableWorkspace_sptr m_covariance = Mantid::API::WorkspaceFactory::Instance().createTable( "TableWorkspace"); m_covariance->addColumn("str", "Name"); std::vector<std::string> paramThatAreFitted; // used for populating 1st "name" column for (size_t i = 0; i < nParams(); i++) { if (l_data.active[i]) { m_covariance->addColumn("double", m_parameterNames[i]); paramThatAreFitted.push_back(m_parameterNames[i]); } } for (size_t i = 0; i < l_data.p; i++) { Mantid::API::TableRow row = m_covariance->appendRow(); row << paramThatAreFitted[i]; for (size_t j = 0; j < l_data.p; j++) { if (j == i) row << 1.0; else { row << 100.0 * gsl_matrix_get(covar, i, j) / sqrt(gsl_matrix_get(covar, i, i) * gsl_matrix_get(covar, j, j)); } } } setProperty("OutputNormalisedCovarianceMatrix", m_covariance); } declareProperty(new WorkspaceProperty<API::ITableWorkspace>( "OutputParameters", "", Direction::Output), "The name of the TableWorkspace in which to store the " "final fit parameters"); declareProperty( new WorkspaceProperty<MatrixWorkspace>("OutputWorkspace", "", Direction::Output), "Name of the output Workspace holding resulting simlated spectrum"); setPropertyValue("OutputParameters", output + "_Parameters"); setPropertyValue("OutputWorkspace", output + "_Workspace"); // Save the final fit parameters in the output table workspace Mantid::API::ITableWorkspace_sptr m_result = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace"); m_result->addColumn("str", "Name"); m_result->addColumn("double", "Value"); if (isDerivDefined) m_result->addColumn("double", "Error"); Mantid::API::TableRow row = m_result->appendRow(); row << "Chi^2/DoF" << finalCostFuncVal; for (size_t i = 0; i < nParams(); i++) { Mantid::API::TableRow row = m_result->appendRow(); row << m_parameterNames[i] << m_fittedParameter[i]; if (isDerivDefined && l_data.active[i]) { // perhaps want to scale standard deviations with sqrt(finalCostFuncVal) row << sdExtended[i]; } } setProperty("OutputParameters", m_result); // Save the fitted and simulated spectra in the output workspace MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace"); int iSpec = getProperty("WorkspaceIndex"); const MantidVec &inputX = inputWorkspace->readX(iSpec); const MantidVec &inputY = inputWorkspace->readY(iSpec); int histN = isHistogram ? 1 : 0; Mantid::DataObjects::Workspace2D_sptr ws = boost::dynamic_pointer_cast<Mantid::DataObjects::Workspace2D>( Mantid::API::WorkspaceFactory::Instance().create( "Workspace2D", 3, l_data.n + histN, l_data.n)); ws->setTitle(""); ws->getAxis(0)->unit() = inputWorkspace->getAxis(0) ->unit(); // UnitFactory::Instance().create("TOF"); for (int i = 0; i < 3; i++) ws->dataX(i) .assign(inputX.begin() + m_minX, inputX.begin() + m_maxX + histN); ws->dataY(0).assign(inputY.begin() + m_minX, inputY.begin() + m_maxX); MantidVec &Y = ws->dataY(1); MantidVec &E = ws->dataY(2); double *lOut = new double[l_data.n]; // to capture output from call to function() modifyInitialFittedParameters(m_fittedParameter); // does nothing except if // overwritten by derived // class function(&m_fittedParameter[0], lOut, l_data.X, l_data.n); modifyInitialFittedParameters(m_fittedParameter); // reverse the effect of // modifyInitialFittedParameters - if any for (unsigned int i = 0; i < l_data.n; i++) { Y[i] = lOut[i]; E[i] = l_data.Y[i] - Y[i]; } delete[] lOut; setProperty("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(ws)); if (isDerivDefined) gsl_matrix_free(covar); } // clean up dynamically allocated gsl stuff if (isDerivDefined) gsl_multifit_fdfsolver_free(s); else { gsl_vector_free(simplexStepSize); gsl_multimin_fminimizer_free(simplexMinimizer); } delete[] l_data.X; delete[] l_data.sigmaData; delete[] l_data.forSimplexLSwrap; delete[] l_data.parameters; gsl_vector_free(initFuncArg); return; }
/** * Execute the algorithm */ void ExtractMask::exec() { MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace"); Geometry::Instrument_const_sptr instr = inputWS->getInstrument(); // convert input to a mask workspace DataObjects::MaskWorkspace_const_sptr inputMaskWS = boost::dynamic_pointer_cast<const DataObjects::MaskWorkspace>(inputWS); bool inputWSIsSpecial = bool(inputMaskWS); if (inputWSIsSpecial) { g_log.notice() << "Input workspace is a MaskWorkspace.\n"; } DataObjects::MaskWorkspace_sptr maskWS; // List masked of detector IDs std::vector<detid_t> detectorList; if (instr) { const int nHist = static_cast<int>(inputWS->getNumberHistograms()); // Create a new workspace for the results, copy from the input to ensure that we copy over the instrument and current masking maskWS = DataObjects::MaskWorkspace_sptr(new DataObjects::MaskWorkspace(inputWS)); maskWS->setTitle(inputWS->getTitle()); Progress prog(this,0.0,1.0,nHist); MantidVecPtr xValues; xValues.access() = MantidVec(1, 0.0); PARALLEL_FOR2(inputWS, maskWS) for( int i = 0; i < nHist; ++i ) { PARALLEL_START_INTERUPT_REGION bool inputIsMasked(false); IDetector_const_sptr inputDet; try { inputDet = inputWS->getDetector(i); if (inputWSIsSpecial) { inputIsMasked = inputMaskWS->isMaskedIndex(i); } // special workspaces can mysteriously have the mask bit set // but only check if we haven't already decided to mask the spectrum if( !inputIsMasked && inputDet->isMasked() ) { inputIsMasked = true; } if (inputIsMasked) { detid_t id = inputDet->getID(); PARALLEL_CRITICAL(name) { detectorList.push_back(id); } } } catch(Kernel::Exception::NotFoundError &) { inputIsMasked = false; } maskWS->setMaskedIndex(i, inputIsMasked); prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION // Clear all the "masked" bits on the output masked workspace Geometry::ParameterMap & pmap = maskWS->instrumentParameters(); pmap.clearParametersByName("masked"); } else // no instrument { // TODO should fill this in throw std::runtime_error("No instrument");
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; }
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"); }