/** Loads, checks and passes back the values passed to the algorithm * @param whiteBeam1 :: A white beam vanadium spectrum that will be used to * check detector efficiency variations * @param whiteBeam2 :: The other white beam vanadium spectrum from the same * instrument to use for comparison * @param variation :: The maximum fractional variation above the median that is * allowed for god detectors * @param startWsIndex :: Index number of the first spectrum to use * @param endWsIndex :: Index number of the last spectrum to use * @throw invalid_argument if there is an incapatible property value and so the * algorithm can't continue */ void DetectorEfficiencyVariation::retrieveProperties( API::MatrixWorkspace_sptr &whiteBeam1, API::MatrixWorkspace_sptr &whiteBeam2, double &variation, int &startWsIndex, int &endWsIndex) { whiteBeam1 = getProperty("WhiteBeamBase"); whiteBeam2 = getProperty("WhiteBeamCompare"); if (whiteBeam1->getInstrument()->getName() != whiteBeam2->getInstrument()->getName()) { throw std::invalid_argument("The two input white beam vanadium workspaces " "must be from the same instrument"); } int maxWsIndex = static_cast<int>(whiteBeam1->getNumberHistograms()) - 1; if (maxWsIndex != static_cast<int>(whiteBeam2->getNumberHistograms()) - 1) { // we would get a crash later on if this were not true throw std::invalid_argument("The input white beam vanadium workspaces must " "be have the same number of histograms"); } variation = getProperty("Variation"); startWsIndex = getProperty("StartWorkspaceIndex"); if ((startWsIndex < 0) || (startWsIndex > maxWsIndex)) { g_log.warning("StartWorkspaceIndex out of range, changed to 0"); startWsIndex = 0; } endWsIndex = getProperty("EndWorkspaceIndex"); if (endWsIndex == Mantid::EMPTY_INT()) endWsIndex = maxWsIndex; if ((endWsIndex < 0) || (endWsIndex > maxWsIndex)) { g_log.warning( "EndWorkspaceIndex out of range, changed to max Workspace number"); endWsIndex = maxWsIndex; } if ((endWsIndex < startWsIndex)) { g_log.warning( "EndWorkspaceIndex can not be less than the StartWorkspaceIndex, " "changed to max Workspace number"); endWsIndex = maxWsIndex; } }
/// Validate the some of the algorithm's input properties. std::map<std::string, std::string> ReflectometrySumInQ::validateInputs() { std::map<std::string, std::string> issues; API::MatrixWorkspace_sptr inWS; Indexing::SpectrumIndexSet indices; // validateInputs is called on the individual workspaces when the algorithm // is executed, it but may get called on a group from AlgorithmDialog. This // isn't handled in getWorkspaceAndIndices. We should fix this properly but // for now skip validation for groups to avoid an exception. See #22933 try { std::tie(inWS, indices) = getWorkspaceAndIndices<API::MatrixWorkspace>(Prop::INPUT_WS); } catch (std::runtime_error &) { return issues; } const auto &spectrumInfo = inWS->spectrumInfo(); const double beamCentre = getProperty(Prop::BEAM_CENTRE); const size_t beamCentreIndex = static_cast<size_t>(beamCentre); bool beamCentreFound{false}; for (const auto i : indices) { if (spectrumInfo.isMonitor(i)) { issues["InputWorkspaceIndexSet"] = "Index set cannot include monitors."; break; } else if ((i > 0 && spectrumInfo.isMonitor(i - 1)) || (i < spectrumInfo.size() - 1 && spectrumInfo.isMonitor(i + 1))) { issues["InputWorkspaceIndexSet"] = "A neighbour to any detector in the index set cannot be a monitor"; break; } if (i == beamCentreIndex) { beamCentreFound = true; break; } } if (!beamCentreFound) { issues[Prop::BEAM_CENTRE] = "Beam centre is not included in InputWorkspaceIndexSet."; } return issues; }
/* * Convert DAS log to a vector of absolute time * @param orderedtofs: tofs with abstimevec */ void ProcessDasNexusLog::convertToAbsoluteTime( API::MatrixWorkspace_sptr ws, std::string logname, std::vector<Kernel::DateAndTime> &abstimevec, std::vector<double> &orderedtofs) { // 1. Get log Kernel::Property *log = ws->run().getProperty(logname); Kernel::TimeSeriesProperty<double> *tslog = dynamic_cast<Kernel::TimeSeriesProperty<double> *>(log); if (!tslog) throw std::runtime_error("Invalid time series log: it could not be cast " "(interpreted) as a time series property"); std::vector<Kernel::DateAndTime> times = tslog->timesAsVector(); std::vector<double> values = tslog->valuesAsVector(); // 2. Get converted size_t numsamepulses = 0; std::vector<double> tofs; Kernel::DateAndTime prevtime(0); for (size_t i = 0; i < times.size(); i++) { Kernel::DateAndTime tnow = times[i]; if (tnow > prevtime) { // (a) Process previous logs std::sort(tofs.begin(), tofs.end()); for (double tof : tofs) { Kernel::DateAndTime temptime = prevtime + static_cast<int64_t>(tof * 100); abstimevec.push_back(temptime); orderedtofs.push_back(tof); } // (b) Clear tofs.clear(); // (c) Update time prevtime = tnow; } else { numsamepulses++; } // (d) Push the current value tofs.push_back(values[i]); } // ENDFOR // Clear the last if (!tofs.empty()) { // (a) Process previous logs: note value is in unit of 100 nano-second std::sort(tofs.begin(), tofs.end()); for (double tof : tofs) { Kernel::DateAndTime temptime = prevtime + static_cast<int64_t>(tof * 100); abstimevec.push_back(temptime); orderedtofs.push_back(tof); } } else { throw std::runtime_error("Impossible for this to happen!"); } } // END Function
std::vector<std::vector<size_t> > DetectorDiagnostic::makeInstrumentMap(API::MatrixWorkspace_sptr countsWS) { std::vector<std::vector<size_t> > mymap; std::vector<size_t> single; for(size_t i=0;i < countsWS->getNumberHistograms();i++) { single.push_back(i); } mymap.push_back(single); return mymap; }
void ConvertEmptyToTof::setTofInWS(const std::vector<double> &tofAxis, API::MatrixWorkspace_sptr outputWS) { const size_t numberOfSpectra = m_inputWS->getNumberHistograms(); g_log.debug() << "Setting the TOF X Axis for numberOfSpectra=" << numberOfSpectra << '\n'; auto axisPtr = Kernel::make_cow<HistogramData::HistogramX>(tofAxis); HistogramData::BinEdges edges(tofAxis); Progress prog(this, 0.0, 0.2, numberOfSpectra); for (size_t i = 0; i < numberOfSpectra; ++i) { // Replace bin edges with tof axis outputWS->setBinEdges(i, edges); prog.report(); } // end for i outputWS->getAxis(0)->unit() = UnitFactory::Instance().create("TOF"); }
/** Smoothing using Butterworth filter. * @param n :: The cutoff frequency control parameter. * Cutoff frequency = my/n where my is the * number of sample points in the data. * As with the "Zeroing" case, the cutoff * frequency is truncated to an integer value * and set to 1 if the truncated value was zero. * @param order :: The order of the Butterworth filter, 1, 2, etc. * This must be a positive integer. * @param unfilteredWS :: workspace for storing the unfiltered Fourier * transform of the input spectrum * @param filteredWS :: workspace for storing the filtered spectrum */ void FFTSmooth2::Butterworth(int n, int order, API::MatrixWorkspace_sptr &unfilteredWS, API::MatrixWorkspace_sptr &filteredWS) { int mx = static_cast<int>(unfilteredWS->readX(0).size()); int my = static_cast<int>(unfilteredWS->readY(0).size()); int ny = my / n; if (ny == 0) ny = 1; filteredWS = API::WorkspaceFactory::Instance().create(unfilteredWS, 2, mx, my); const Mantid::MantidVec &Yr = unfilteredWS->readY(0); const Mantid::MantidVec &Yi = unfilteredWS->readY(1); const Mantid::MantidVec &X = unfilteredWS->readX(0); Mantid::MantidVec &yr = filteredWS->dataY(0); Mantid::MantidVec &yi = filteredWS->dataY(1); Mantid::MantidVec &xr = filteredWS->dataX(0); Mantid::MantidVec &xi = filteredWS->dataX(1); xr.assign(X.begin(), X.end()); xi.assign(X.begin(), X.end()); yr.assign(Yr.size(), 0); yi.assign(Yr.size(), 0); double cutoff = ny; for (int i = 0; i < my; i++) { double scale = 1.0 / (1.0 + pow(i / cutoff, 2 * order)); yr[i] = scale * Yr[i]; yi[i] = scale * Yi[i]; } }
/** Smoothing by zeroing. * @param n :: The order of truncation * @param unfilteredWS :: workspace for storing the unfiltered Fourier * transform of the input spectrum * @param filteredWS :: workspace for storing the filtered spectrum */ void FFTSmooth2::zero(int n, API::MatrixWorkspace_sptr &unfilteredWS, API::MatrixWorkspace_sptr &filteredWS) { int mx = static_cast<int>(unfilteredWS->readX(0).size()); int my = static_cast<int>(unfilteredWS->readY(0).size()); int ny = my / n; if (ny == 0) ny = 1; filteredWS = API::WorkspaceFactory::Instance().create(unfilteredWS, 2, mx, my); const Mantid::MantidVec &Yr = unfilteredWS->readY(0); const Mantid::MantidVec &Yi = unfilteredWS->readY(1); const Mantid::MantidVec &X = unfilteredWS->readX(0); Mantid::MantidVec &yr = filteredWS->dataY(0); Mantid::MantidVec &yi = filteredWS->dataY(1); Mantid::MantidVec &xr = filteredWS->dataX(0); Mantid::MantidVec &xi = filteredWS->dataX(1); xr.assign(X.begin(), X.end()); xi.assign(X.begin(), X.end()); yr.assign(Yr.size(), 0); yi.assign(Yr.size(), 0); for (int i = 0; i < ny; i++) { yr[i] = Yr[i]; yi[i] = Yi[i]; } }
/*** * This will ensure the spectrum numbers do not overlap by starting the second *on at the first + 1 * * @param ws1 The first workspace supplied to the algorithm. * @param ws2 The second workspace supplied to the algorithm. * @param output The workspace that is going to be returned by the algorithm. */ void ConjoinWorkspaces::fixSpectrumNumbers(API::MatrixWorkspace_const_sptr ws1, API::MatrixWorkspace_const_sptr ws2, API::MatrixWorkspace_sptr output) { bool needsFix(false); if (this->getProperty("CheckOverlapping")) { // If CheckOverlapping is required, then either skip fixing spectrum number // or get stopped by an exception if (!m_overlapChecked) checkForOverlap(ws1, ws2, true); needsFix = false; } else { // It will be determined later whether spectrum number needs to be fixed. needsFix = true; } if (!needsFix) return; // is everything possibly ok? specid_t min; specid_t max; getMinMax(output, min, max); if (max - min >= static_cast<specid_t>( output->getNumberHistograms())) // nothing to do then return; // information for remapping the spectra numbers specid_t ws1min; specid_t ws1max; getMinMax(ws1, ws1min, ws1max); // change the axis by adding the maximum existing spectrum number to the // current value for (size_t i = ws1->getNumberHistograms(); i < output->getNumberHistograms(); i++) { specid_t origid; origid = output->getSpectrum(i)->getSpectrumNo(); output->getSpectrum(i)->setSpectrumNo(origid + ws1max); } }
/** Checks and retrieves the requested spectrum out of the input workspace * @param inputWorkspace The input workspace. * @param spectra_num The spectra number. * @returns A workspace containing the monitor spectrum only. * @returns spectra number (WS ID) which is used to normalize by. * @throw std::runtime_error If the properties are invalid */ API::MatrixWorkspace_sptr NormaliseToMonitor::getInWSMonitorSpectrum(API::MatrixWorkspace_sptr inputWorkspace,int &spectra_num) { // this is the index of the spectra within the workspace and we need to indetnify it either from DetID or fron SpecID // size_t spectra_num(-1); // try monitor spectrum. If it is specified, it overides everything int monitorSpec = getProperty("MonitorSpectrum"); if(monitorSpec<0){ // Get hold of the monitor spectrum through detector ID int monitorID = getProperty("MonitorID"); if (monitorID < 0) { throw std::runtime_error("Both MonitorSpectrum and MonitorID can not be negative"); } // set spectra of detector's ID of one selected monitor ID std::vector<detid_t> detID(1,monitorID); // got the index of correspondent spectras (should be only one). std::vector<size_t> indexList; inputWorkspace->getIndicesFromDetectorIDs(detID,indexList); if(indexList.empty()){ throw std::runtime_error("Can not find spectra, coorespoinding to the requested monitor ID"); } if(indexList.size()>1){ throw std::runtime_error("More then one spectra coorespods to the requested monitor ID, which is unheard of"); } spectra_num = (int)indexList[0]; }else{ // monitor spectrum is specified. spec2index_map specs; const SpectraAxis* axis = dynamic_cast<const SpectraAxis*>(inputWorkspace->getAxis(1)); if ( ! axis) { throw std::runtime_error("Cannot retrieve monitor spectrum - spectrum numbers not attached to workspace"); } axis->getSpectraIndexMap(specs); if ( ! specs.count(monitorSpec) ) { throw std::runtime_error("Input workspace does not contain spectrum number given for MonitorSpectrum"); } spectra_num = (int)specs[monitorSpec]; } return this->extractMonitorSpectrum(inputWorkspace,spectra_num); }
/** Load logs from Nexus file. Logs are expected to be in * /run/sample group of the file. * @param ws :: The workspace to load the logs to. * @param entry :: The Nexus entry * @param period :: The period of this workspace */ void LoadMuonNexus2::loadLogs(API::MatrixWorkspace_sptr ws, NXEntry &entry, int period) { // Avoid compiler warning (void)period; std::string start_time = entry.getString("start_time"); std::string sampleName = entry.getString("sample/name"); NXMainClass runlogs = entry.openNXClass<NXMainClass>("sample"); ws->mutableSample().setName(sampleName); for (std::vector<NXClassInfo>::const_iterator it = runlogs.groups().begin(); it != runlogs.groups().end(); ++it) { NXLog nxLog = runlogs.openNXLog(it->nxname); Kernel::Property *logv = nxLog.createTimeSeries(start_time); if (!logv) continue; ws->mutableRun().addLogData(logv); } ws->setTitle(entry.getString("title")); if (entry.containsDataSet("notes")) { ws->setComment(entry.getString("notes")); } std::string run_num = std::to_string(entry.getInt("run_number")); // The sample is left to delete the property ws->mutableRun().addLogData( new PropertyWithValue<std::string>("run_number", run_num)); ws->populateInstrumentParameters(); }
/** Execute the algorithm. */ void CalculateDIFC::exec() { DataObjects::OffsetsWorkspace_const_sptr offsetsWs = getProperty("OffsetsWorkspace"); API::ITableWorkspace_const_sptr calibWs = getProperty("CalibrationWorkspace"); API::MatrixWorkspace_sptr inputWs = getProperty("InputWorkspace"); API::MatrixWorkspace_sptr outputWs = getProperty("OutputWorkspace"); if ((!bool(inputWs == outputWs)) || (!bool(boost::dynamic_pointer_cast<SpecialWorkspace2D>(outputWs)))) { outputWs = boost::dynamic_pointer_cast<MatrixWorkspace>( boost::make_shared<SpecialWorkspace2D>(inputWs->getInstrument())); outputWs->setTitle("DIFC workspace"); } // convert to actual type being used DataObjects::SpecialWorkspace2D_sptr outputSpecialWs = boost::dynamic_pointer_cast<DataObjects::SpecialWorkspace2D>(outputWs); API::Progress progress(this, 0.0, 1.0, inputWs->getNumberHistograms()); if (bool(calibWs)) { calculateFromTable(progress, *outputSpecialWs, *calibWs); } else { // this method handles calculating from instrument geometry as well const auto &detectorInfo = inputWs->detectorInfo(); calculateFromOffset(progress, *outputSpecialWs, offsetsWs.get(), detectorInfo); } setProperty("OutputWorkspace", outputWs); }
/** * Here is the main logic to perform the transformation, to calculate the bin position in degree for each spectrum. * * The first part of the method is to check if the pixel position is inside the ring defined as minRadio and maxRadio. * * To do this, it deducts the pixel position. This deduction follows the followin assumption: * * - the spectrum_index == row number * - the position in the 'Y' direction is given by getAxis(1)[spectrum_index] * - the position in the 'X' direction is the central point of the bin (dataX[column] + dataX[column+1])/2 * * Having the position of the pixel, as defined above, if the distance is outside the ring defined by minRadio, maxRadio, * it defines the bin position as -1. * * If the pixel is inside the ring, it calculates the angle of the pixel and calls fromAngleToBin to define the bin * position. * @param ws: pointer to the workspace * @param spectrum_index: index of the spectrum * @param bins_pos: bin positions (for each column inside the spectrum, the correspondent bin_pos) */ void RingProfile::getBinForPixel(const API::MatrixWorkspace_sptr ws, int spectrum_index, std::vector<int> & bins_pos ){ if (bins_pos.size() != ws->dataY(spectrum_index).size()) throw std::runtime_error("Invalid bin positions vector"); API::NumericAxis *oldAxis2 = dynamic_cast<API::NumericAxis*>(ws->getAxis(1)); // assumption y position is the ws->getAxis(1)(spectrum_index) // calculate ypos, the difference of y - centre and the square of this difference double ypos = (*oldAxis2)(spectrum_index); double diffy = ypos-centre_y; double diffy_quad = pow(diffy, 2.0); // the reference to X bins (the limits for each pixel in the horizontal direction) auto xvec = ws->dataX(spectrum_index); // for each pixel inside this row for (size_t i = 0; i< xvec.size()-1; i++){ double xpos = (xvec[i] + xvec[i+1])/2.0; // the x position is the centre of the bins boundaries double diffx = xpos - centre_x; // calculate the distance => norm of pixel position - centre double distance = sqrt(pow(diffx, 2.0) + diffy_quad); // check if the distance is inside the ring if (distance < min_radius || distance > max_radius || distance == 0){ bins_pos[i] = -1; continue; } double angle = atan2(diffy, diffx); // call fromAngleToBin (radians) bins_pos[i] = fromAngleToBin(angle, false); } };
/* * Get instrument property as double * @s - input property name * */ double LoadHelper::getInstrumentProperty(const API::MatrixWorkspace_sptr &workspace, std::string s) { std::vector<std::string> prop = workspace->getInstrument()->getStringParameter(s); if (prop.empty()) { g_log.debug("Property <" + s + "> doesn't exist!"); return EMPTY_DBL(); } else { g_log.debug() << "Property <" + s + "> = " << prop[0] << '\n'; return boost::lexical_cast<double>(prop[0]); } }
V3D LoadHelper::getComponentPosition(API::MatrixWorkspace_sptr ws, const std::string &componentName) { try { Geometry::Instrument_const_sptr instrument = ws->getInstrument(); Geometry::IComponent_const_sptr component = instrument->getComponentByName(componentName); V3D pos = component->getPos(); return pos; } catch (Mantid::Kernel::Exception::NotFoundError&) { throw std::runtime_error("Error when trying to move the " + componentName + " : NotFoundError"); } }
/** Convert the workspace units according to a simple output = a * (input^b) relationship * @param outputWS :: the output workspace * @param factor :: the conversion factor a to apply * @param power :: the Power b to apply to the conversion */ void ConvertUnits::convertQuickly(API::MatrixWorkspace_sptr outputWS, const double& factor, const double& power) { Progress prog(this,0.2,1.0,m_numberOfSpectra); int64_t numberOfSpectra_i = static_cast<int64_t>(m_numberOfSpectra); // cast to make openmp happy // See if the workspace has common bins - if so the X vector can be common // First a quick check using the validator CommonBinsValidator sameBins; bool commonBoundaries = false; if ( sameBins.isValid(outputWS) == "" ) { commonBoundaries = WorkspaceHelpers::commonBoundaries(outputWS); // Only do the full check if the quick one passes if (commonBoundaries) { // Calculate the new (common) X values MantidVec::iterator iter; for (iter = outputWS->dataX(0).begin(); iter != outputWS->dataX(0).end(); ++iter) { *iter = factor * std::pow(*iter,power); } MantidVecPtr xVals; xVals.access() = outputWS->dataX(0); PARALLEL_FOR1(outputWS) for (int64_t j = 1; j < numberOfSpectra_i; ++j) { PARALLEL_START_INTERUPT_REGION outputWS->setX(j,xVals); prog.report("Convert to " + m_outputUnit->unitID()); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION if (!m_inputEvents) // if in event mode the work is done return; } }
/** * The main method to calculate the ring profile for workspaces based on instruments. * * It will iterate over all the spectrum inside the workspace. * For each spectrum, it will use the RingProfile::getBinForPixel method to identify * where, in the output_bins, the sum of all the spectrum values should be placed in. * * @param inputWS: pointer to the input workspace * @param output_bins: the reference to the vector to be filled with the integration values */ void RingProfile::processInstrumentRingProfile(const API::MatrixWorkspace_sptr inputWS, std::vector<double> & output_bins){ for (int i= 0; i< (int) inputWS->getNumberHistograms(); i++){ m_progress->report("Computing ring bins positions for detectors"); // for the detector based, the positions will be taken from the detector itself. try{ Mantid::Geometry::IDetector_const_sptr det = inputWS->getDetector(i); // skip monitors if (det->isMonitor()){ continue; } // this part will be executed if the instrument is attached to the workspace // get the bin position int bin_n = getBinForPixel(det); if (bin_n < 0) // -1 is the agreement for an invalid bin, or outside the ring being integrated continue; g_log.debug() << "Bin for the index " << i << " = " << bin_n << " Pos = " << det->getPos() << std::endl; // get the reference to the spectrum auto spectrum_pt = inputWS->getSpectrum(i); const MantidVec & refY = spectrum_pt->dataY(); // accumulate the values of this spectrum inside this bin for (size_t sp_ind = 0; sp_ind < inputWS->blocksize(); sp_ind ++) output_bins[bin_n] += refY[sp_ind]; }catch(Kernel::Exception::NotFoundError & ex){ g_log.information() << "It found that detector for " << i << " is not valid. " << ex.what() << std::endl; continue; } } }
/** Performs the Debye-Bueche transformation: 1/sqrt(I) v Q^2 * The output is set to zero for negative input Y values * @param ws The workspace to be transformed */ void IQTransform::debyeBueche(API::MatrixWorkspace_sptr ws) { MantidVec& X = ws->dataX(0); MantidVec& Y = ws->dataY(0); MantidVec& E = ws->dataE(0); std::transform(X.begin(),X.end(),X.begin(),VectorHelper::Squares<double>()); for(size_t i = 0; i < Y.size(); ++i) { if ( Y[i] > 0.0 ) { Y[i] = 1.0 / std::sqrt(Y[i]); E[i] *= std::pow(Y[i],3); } else { Y[i] = 0.0; E[i] = 0.0; } } ws->setYUnitLabel("1/sqrt(I)"); m_label->setLabel("Q^2"); }
/** Extracts a single spectrum from a Workspace2D into a new workspaces. Uses CropWorkspace to do this. * @param WS :: The workspace containing the spectrum to extract * @param index :: The workspace index of the spectrum to extract * @return A Workspace2D containing the extracted spectrum */ API::MatrixWorkspace_sptr CalculateTransmissionBeamSpreader::extractSpectrum(API::MatrixWorkspace_sptr WS, const size_t index) { // Check that given spectra are monitors if ( !WS->getDetector(index)->isMonitor() ) { g_log.information("The Incident Beam Monitor UDET provided is not marked as a monitor"); } Algorithm_sptr childAlg = createSubAlgorithm("ExtractSingleSpectrum",0.0,0.4); childAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", WS); childAlg->setProperty<int>("WorkspaceIndex", static_cast<int>(index)); childAlg->executeAsSubAlg(); return childAlg->getProperty("OutputWorkspace"); }
/** * Perform a call to nxgetslab, via the NexusClasses wrapped methods for a given blocksize. This assumes that the * xbins have alread been cached * @param data :: The NXDataSet object of y values * @param errors :: The NXDataSet object of error values * @param blocksize :: The blocksize to use * @param nchannels :: The number of channels for the block * @param hist :: The workspace index to start reading into * @param local_workspace :: A pointer to the workspace */ void LoadNexusProcessed::loadBlock(NXDataSetTyped<double> & data, NXDataSetTyped<double> & errors, int64_t blocksize, int64_t nchannels, int64_t &hist, API::MatrixWorkspace_sptr local_workspace) { data.load(static_cast<int>(blocksize),static_cast<int>(hist)); errors.load(static_cast<int>(blocksize),static_cast<int>(hist)); double *data_start = data(); double *data_end = data_start + nchannels; double *err_start = errors(); double *err_end = err_start + nchannels; int64_t final(hist + blocksize); while( hist < final ) { MantidVec& Y = local_workspace->dataY(hist); Y.assign(data_start, data_end); data_start += nchannels; data_end += nchannels; MantidVec& E = local_workspace->dataE(hist); E.assign(err_start, err_end); err_start += nchannels; err_end += nchannels; local_workspace->setX(hist, m_xbins); ++hist; } }
/** Initialization method: @param bkgWS -- shared pointer to the workspace which contains background @param sourceWS -- shared pointer to the workspace to remove background from @param emode -- energy conversion mode used during internal units conversion (0 -- elastic, 1-direct, 2 indirect, as defined in Units conversion @param pLog -- pointer to the logger class which would report errors @param nThreads -- number of threads to be used for background removal @param inPlace -- if the background removal occurs from the existing workspace or target workspace has to be cloned. */ void BackgroundHelper::initialize(const API::MatrixWorkspace_const_sptr &bkgWS, const API::MatrixWorkspace_sptr &sourceWS, int emode, Kernel::Logger *pLog, int nThreads, bool inPlace) { m_bgWs = bkgWS; m_wkWS = sourceWS; m_Emode = emode; m_pgLog = pLog; m_inPlace = inPlace; std::string bgUnits = bkgWS->getAxis(0)->unit()->unitID(); if (bgUnits != "TOF") throw std::invalid_argument(" Background Workspace: " + bkgWS->getName() + " should be in the units of TOF"); if (!(bkgWS->getNumberHistograms() == 1 || sourceWS->getNumberHistograms() == bkgWS->getNumberHistograms())) throw std::invalid_argument(" Background Workspace: " + bkgWS->getName() + " should have the same number of spectra as " "source workspace or be a single histogram " "workspace"); auto WSUnit = sourceWS->getAxis(0)->unit(); if (!WSUnit) throw std::invalid_argument(" Source Workspace: " + sourceWS->getName() + " should have units"); Geometry::IComponent_const_sptr source = sourceWS->getInstrument()->getSource(); m_Sample = sourceWS->getInstrument()->getSample(); if ((!source) || (!m_Sample)) throw std::invalid_argument( "Instrument on Source workspace:" + sourceWS->getName() + "is not sufficiently defined: failed to get source and/or sample"); m_L1 = source->getDistance(*m_Sample); // just in case. this->deleteUnitsConverters(); // allocate the array of units converters to avoid units reallocation within a // loop m_WSUnit.assign(nThreads, NULL); for (int i = 0; i < nThreads; i++) { m_WSUnit[i] = WSUnit->clone(); } m_singleValueBackground = false; if (bkgWS->getNumberHistograms() == 0) m_singleValueBackground = true; const MantidVec &dataX = bkgWS->dataX(0); const MantidVec &dataY = bkgWS->dataY(0); // const MantidVec& dataE = bkgWS->dataE(0); m_NBg = dataY[0]; m_dtBg = dataX[1] - dataX[0]; // m_ErrSq = dataE[0]*dataE[0]; // needs further clarification m_Efix = this->getEi(sourceWS); }
/** Execute the algorithm. */ void CreateEPP::exec() { API::MatrixWorkspace_sptr inputWS = getProperty(PropertyNames::INPUT_WORKSPACE); const auto &spectrumInfo = inputWS->spectrumInfo(); API::ITableWorkspace_sptr outputWS = API::WorkspaceFactory::Instance().createTable("TableWorkspace"); addEPPColumns(outputWS); const double sigma = getProperty(PropertyNames::SIGMA); const size_t spectraCount = spectrumInfo.size(); outputWS->setRowCount(spectraCount); const auto l1 = spectrumInfo.l1(); const double EFixed = inputWS->run().getPropertyAsSingleValue("Ei"); for (size_t i = 0; i < spectraCount; ++i) { const auto l2 = spectrumInfo.l2(i); const auto elasticTOF = Kernel::UnitConversion::run( "Energy", "TOF", EFixed, l1, l2, 0, Kernel::DeltaEMode::Direct, EFixed); outputWS->getRef<int>(ColumnNames::WS_INDEX, i) = static_cast<int>(i); outputWS->getRef<double>(ColumnNames::PEAK_CENTRE, i) = elasticTOF; outputWS->getRef<double>(ColumnNames::PEAK_CENTRE_ERR, i) = 0; outputWS->getRef<double>(ColumnNames::SIGMA, i) = sigma; outputWS->getRef<double>(ColumnNames::SIGMA_ERR, i) = 0; double height = 0; try { const auto elasticIndex = inputWS->binIndexOf(elasticTOF, i); height = inputWS->y(i)[elasticIndex]; } catch (std::out_of_range &) { std::ostringstream sout; sout << "EPP out of TOF range for workspace index " << i << ". Peak height set to zero."; g_log.warning() << sout.str(); } outputWS->getRef<double>(ColumnNames::HEIGHT, i) = height; outputWS->getRef<double>(ColumnNames::CHI_SQUARED, i) = 1; outputWS->getRef<std::string>(ColumnNames::STATUS, i) = "success"; } setProperty(PropertyNames::OUTPUT_WORKSPACE, outputWS); }
/** Performs a transformation of the form: Q^A x I^B x Ln(Q^C x I^D x E) v Q^F x I^G x Ln(Q^H x I^I x J). * Uses the 'GeneralFunctionConstants' property where A-J are the 10 (ordered) input constants. * @param ws The workspace to be transformed * @throw std::range_error if an attempt is made to take log of a negative number */ void IQTransform::general(API::MatrixWorkspace_sptr ws) { MantidVec& X = ws->dataX(0); MantidVec& Y = ws->dataY(0); MantidVec& E = ws->dataE(0); const std::vector<double> C = getProperty("GeneralFunctionConstants"); // Check for the correct number of elements if ( C.size() != 10 ) { std::string mess("The General transformation requires 10 values to be provided."); g_log.error(mess); throw std::invalid_argument(mess); } for(size_t i = 0; i < Y.size(); ++i) { double tmpX = std::pow(X[i],C[7]) * std::pow(Y[i],C[8]) * C[9]; if ( tmpX <= 0.0 ) throw std::range_error("Attempt to take log of a zero or negative number."); tmpX = std::pow(X[i],C[5]) * std::pow(Y[i],C[6]) * std::log(tmpX); const double tmpY = std::pow(X[i],C[2]) * std::pow(Y[i],C[3]) * C[4]; if ( tmpY <= 0.0 ) throw std::range_error("Attempt to take log of a zero or negative number."); const double newY = std::pow(X[i],C[0]) * std::pow(Y[i],C[1]) * std::log(tmpY); E[i] *= std::pow(X[i],C[0]) * ( C[1]*std::pow(Y[i],C[1]-1) * std::log(tmpY) + (( std::pow(Y[i],C[1]) * std::pow(X[i],C[2]) * C[4] * C[3]*std::pow(Y[i],C[3]-1) ) / tmpY ) ); X[i] = tmpX; Y[i] = newY; } std::stringstream ylabel; ylabel << "Q^" << C[0] << " x I^" << C[1] << " x Ln( Q^" << C[2] << " x I^" << C[3] << " x " << C[4] << ")"; ws->setYUnitLabel(ylabel.str()); std::stringstream xlabel; xlabel << "Q^" << C[5] << " x I^" << C[6] << " x Ln( Q^" << C[7] << " x I^" << C[8] << " x " << C[9] << ")"; m_label->setLabel(xlabel.str()); }
/** Create output workspace */ API::MatrixWorkspace_sptr GeneratePeaks::createOutputWorkspace() { // Reference workspace and output workspace API::MatrixWorkspace_sptr outputWS; m_newWSFromParent = true; if (!inputWS && binParameters.empty()) { // Error! Neither bin parameters or reference workspace is given. std::string errmsg( "Must define either InputWorkspace or BinningParameters."); g_log.error(errmsg); throw std::invalid_argument(errmsg); } else if (inputWS) { // Generate Workspace2D from input workspace if (!binParameters.empty()) g_log.notice() << "Both binning parameters and input workspace are given. " << "Using input worksapce to generate output workspace!\n"; outputWS = API::WorkspaceFactory::Instance().create( inputWS, inputWS->getNumberHistograms(), inputWS->x(0).size(), inputWS->y(0).size()); // Only copy the X-values from spectra with peaks specified in the table // workspace. for (const auto &iws : m_spectraSet) { outputWS->setSharedX(iws, inputWS->sharedX(iws)); } m_newWSFromParent = true; } else { // Generate a one-spectrum Workspace2D from binning outputWS = createDataWorkspace(binParameters); m_newWSFromParent = false; } return outputWS; }
/** * Construct an "empty" output workspace in virtual-lambda for summation in Q. * * @param detectorWS [in] :: the input workspace * @param indices [in] :: the workspace indices of the foreground histograms * @param refAngles [in] :: the reference angles * @return :: a 1D workspace where y values are all zero */ API::MatrixWorkspace_sptr ReflectometrySumInQ::constructIvsLamWS( const API::MatrixWorkspace &detectorWS, const Indexing::SpectrumIndexSet &indices, const Angles &refAngles) { // Calculate the number of bins based on the min/max wavelength, using // the same bin width as the input workspace const auto &edges = detectorWS.binEdges(refAngles.referenceWSIndex); const double binWidth = (edges.back() - edges.front()) / static_cast<double>(edges.size()); const auto wavelengthRange = findWavelengthMinMax(detectorWS, indices, refAngles); if (std::abs(wavelengthRange.max - wavelengthRange.min) < binWidth) { throw std::runtime_error("Given wavelength range too small."); } const int numBins = static_cast<int>( std::ceil((wavelengthRange.max - wavelengthRange.min) / binWidth)); // Construct the histogram with these X values. Y and E values are zero. const HistogramData::BinEdges bins( numBins + 1, HistogramData::LinearGenerator(wavelengthRange.min, binWidth)); const HistogramData::Counts counts(numBins, 0.); const HistogramData::Histogram modelHistogram(std::move(bins), std::move(counts)); // Create the output workspace API::MatrixWorkspace_sptr outputWS = DataObjects::create<DataObjects::Workspace2D>(detectorWS, 1, std::move(modelHistogram)); // Set the detector IDs and specturm number from the twoThetaR detector. const auto &thetaSpec = detectorWS.getSpectrum(refAngles.referenceWSIndex); auto &outSpec = outputWS->getSpectrum(0); outSpec.clearDetectorIDs(); outSpec.addDetectorIDs(thetaSpec.getDetectorIDs()); outSpec.setSpectrumNo(thetaSpec.getSpectrumNo()); return outputWS; }
/* * Export time stamps looking erroreous */ void ProcessDasNexusLog::exportErrorLog( API::MatrixWorkspace_sptr ws, std::vector<Kernel::DateAndTime> abstimevec, std::vector<Kernel::DateAndTime> pulsetimes, std::vector<double> orderedtofs, double dts) { std::string outputdir = getProperty("OutputDirectory"); if (outputdir[outputdir.size() - 1] != '/') outputdir += "/"; std::string ofilename = outputdir + "errordeltatime.txt"; g_log.notice() << ofilename << std::endl; std::ofstream ofs; ofs.open(ofilename.c_str(), std::ios::out); size_t numbaddt = 0; Kernel::DateAndTime t0(ws->run().getProperty("run_start")->value()); for (size_t i = 1; i < abstimevec.size(); i++) { double tempdts = static_cast<double>(abstimevec[i].totalNanoseconds() - abstimevec[i - 1].totalNanoseconds()) * 1.0E-9; double dev = (tempdts - dts) / dts; bool baddt = false; if (fabs(dev) > 0.5) baddt = true; if (baddt) { numbaddt++; double deltapulsetimeSec1 = static_cast<double>(pulsetimes[i - 1].totalNanoseconds() - t0.totalNanoseconds()) * 1.0E-9; double deltapulsetimeSec2 = static_cast<double>(pulsetimes[i].totalNanoseconds() - t0.totalNanoseconds()) * 1.0E-9; int index1 = static_cast<int>(deltapulsetimeSec1 * 60); int index2 = static_cast<int>(deltapulsetimeSec2 * 60); ofs << "Error d(T) = " << tempdts << " vs Correct d(T) = " << dts << std::endl; ofs << index1 << "\t\t" << pulsetimes[i - 1].totalNanoseconds() << "\t\t" << orderedtofs[i - 1] << std::endl; ofs << index2 << "\t\t" << pulsetimes[i].totalNanoseconds() << "\t\t" << orderedtofs[i] << std::endl; } } ofs.close(); }
/// Run ConvertUnits as a sub-algorithm to convert to dSpacing MatrixWorkspace_sptr DiffractionFocussing::convertUnitsToDSpacing(const API::MatrixWorkspace_sptr& workspace) { const std::string CONVERSION_UNIT = "dSpacing"; Unit_const_sptr xUnit = workspace->getAxis(0)->unit(); g_log.information() << "Converting units from "<< xUnit->label() << " to " << CONVERSION_UNIT<<".\n"; API::IAlgorithm_sptr childAlg = createSubAlgorithm("ConvertUnits", 0.34, 0.66); childAlg->setProperty("InputWorkspace", workspace); childAlg->setPropertyValue("Target",CONVERSION_UNIT); childAlg->executeAsSubAlg(); return childAlg->getProperty("OutputWorkspace"); }
void LoadHelper::rotateComponent(API::MatrixWorkspace_sptr ws, const std::string &componentName, const Kernel::Quat & rot) { try { Geometry::Instrument_const_sptr instrument = ws->getInstrument(); Geometry::IComponent_const_sptr component = instrument->getComponentByName(componentName); //g_log.debug() << tube->getName() << " : t = " << theta << " ==> t = " << newTheta << "\n"; Geometry::ParameterMap& pmap = ws->instrumentParameters(); Geometry::ComponentHelper::rotateComponent(*component, pmap, rot, Geometry::ComponentHelper::Absolute); } catch (Mantid::Kernel::Exception::NotFoundError&) { throw std::runtime_error("Error when trying to move the " + componentName + " : NotFoundError"); } catch (std::runtime_error &) { throw std::runtime_error("Error when trying to move the " + componentName + " : runtime_error"); } }
/** Apply dead time correction to spectra in inputWs and create temporary workspace with corrected spectra * @param inputWs :: [input] input workspace containing spectra to correct * @param deadTimeTable :: [input] table containing dead times * @param tempWs :: [output] workspace containing corrected spectra */ void PhaseQuadMuon::deadTimeCorrection(API::MatrixWorkspace_sptr inputWs, API::ITableWorkspace_sptr deadTimeTable, API::MatrixWorkspace_sptr& tempWs) { // Apply correction only from t = m_tPulseOver // To do so, we first apply corrections to the whole spectrum (ApplyDeadTimeCorr // does not allow to select a range in the spectrum) // Then we recover counts from 0 to m_tPulseOver auto alg = this->createChildAlgorithm("ApplyDeadTimeCorr",-1,-1); alg->initialize(); alg->setProperty("DeadTimeTable", deadTimeTable); alg->setPropertyValue("InputWorkspace", inputWs->getName()); alg->setPropertyValue("OutputWorkspace", inputWs->getName()+"_deadtime"); bool sucDeadTime = alg->execute(); if (!sucDeadTime) { g_log.error() << "PhaseQuad: Unable to apply dead time corrections" << std::endl; throw std::runtime_error("PhaseQuad: Unable to apply dead time corrections"); } tempWs = alg->getProperty("OutputWorkspace"); // Now recover counts from t=0 to m_tPulseOver // Errors are set to m_bigNumber for (int h=0; h<m_nHist; h++) { auto specOld = inputWs->getSpectrum(h); auto specNew = tempWs->getSpectrum(h); for (int t=0; t<m_tPulseOver; t++) { specNew->dataY()[t] = specOld->dataY()[t]; specNew->dataE()[t] = m_bigNumber; } } }
void RadiusSum::setUpOutputWorkspace(std::vector<double> &values) { g_log.debug() << "Output calculated, setting up the output workspace" << std::endl; API::MatrixWorkspace_sptr outputWS = API::WorkspaceFactory::Instance().create( inputWS, 1, values.size() + 1, values.size()); g_log.debug() << "Set the data" << std::endl; MantidVec &refY = outputWS->dataY(0); std::copy(values.begin(), values.end(), refY.begin()); g_log.debug() << "Set the bins limits" << std::endl; MantidVec &refX = outputWS->dataX(0); double bin_size = (max_radius - min_radius) / num_bins; for (int i = 0; i < (static_cast<int>(refX.size())) - 1; i++) refX[i] = min_radius + i * bin_size; refX[refX.size() - 1] = max_radius; // configure the axis: // for numeric images, the axis are the same as the input workspace, and are // copied in the creation. // for instrument related, the axis Y (1) continues to be the same. // it is necessary to change only the axis X. We have to change it to radius. if (inputWorkspaceHasInstrumentAssociated(inputWS)) { API::Axis *const horizontal = new API::NumericAxis(refX.size()); auto labelX = UnitFactory::Instance().create("Label"); boost::dynamic_pointer_cast<Units::Label>(labelX)->setLabel("Radius"); horizontal->unit() = labelX; outputWS->replaceAxis(0, horizontal); } setProperty("OutputWorkspace", outputWS); }
/** Executes the algorithm. Moving detectors of input workspace to positions indicated in table workspace * * @throw FileError Thrown if unable to get instrument from workspace, * table workspace is incompatible with instrument */ void ApplyCalibration::exec() { // Get pointers to the workspace, parameter map and table API::MatrixWorkspace_sptr inputWS = getProperty("Workspace"); m_pmap = &(inputWS->instrumentParameters()); // Avoids a copy if you get the reference before the instrument API::ITableWorkspace_sptr PosTable = getProperty("PositionTable"); Geometry::Instrument_const_sptr instrument = inputWS->getInstrument(); if(!instrument) { throw std::runtime_error("Workspace to apply calibration to has no defined instrument"); } size_t numDetector = PosTable->rowCount(); ColumnVector<int> detID = PosTable->getVector("Detector ID"); ColumnVector<V3D> detPos = PosTable->getVector("Detector Position"); // numDetector needs to be got as the number of rows in the table and the detID got from the (i)th row of table. for (size_t i = 0; i < numDetector; ++i) { setDetectorPosition(instrument, detID[i], detPos[i], false ); } // Ensure pointer is only valid for execution m_pmap = NULL; }