/** Makes sure that the input properties are set correctly * @param inputWorkspace The input workspace */ void NormaliseToMonitor::checkProperties( const MatrixWorkspace_sptr &inputWorkspace) { // Check where the monitor spectrum should come from Property *monSpec = getProperty("MonitorSpectrum"); MatrixWorkspace_sptr monWS = getProperty("MonitorWorkspace"); Property *monID = getProperty("MonitorID"); // Is the monitor spectrum within the main input workspace const bool inWS = !monSpec->isDefault(); m_scanInput = inputWorkspace->detectorInfo().isScanning(); // Or is it in a separate workspace bool sepWS{monWS}; if (m_scanInput && sepWS) throw std::runtime_error("Can not currently use a separate monitor " "workspace with a detector scan input workspace."); // or monitor ID bool monIDs = !monID->isDefault(); // something has to be set // One and only one of these properties should have been set // input from separate workspace is overwritten by monitor spectrum if (inWS && sepWS) { g_log.information("Both input workspace MonitorSpectrum number and monitor " "workspace are specified. Ignoring Monitor Workspace"); sepWS = false; } // input from detector ID is rejected in favor of monitor sp if (inWS && monIDs) { g_log.information("Both input workspace MonitorSpectrum number and " "detector ID are specified. Ignoring Detector ID"); monIDs = false; } // separate ws takes over detectorID (this logic is duplicated within // getInWSMonitorSpectrum) if (sepWS && monIDs) { g_log.information("Both input MonitorWorkspace and detector ID are " "specified. Ignoring Detector ID"); } // Do a check for common binning and store m_commonBins = inputWorkspace->isCommonBins(); // Check the monitor spectrum or workspace and extract into new workspace m_monitor = sepWS ? getMonitorWorkspace(inputWorkspace) : getInWSMonitorSpectrum(inputWorkspace); // Check that the 'monitor' spectrum actually relates to a monitor - warn if // not try { const auto &monitorSpecInfo = m_monitor->spectrumInfo(); for (const auto workspaceIndex : m_workspaceIndexes) if (!monitorSpecInfo.isMonitor(workspaceIndex)) g_log.warning() << "The spectrum N: " << workspaceIndex << " in MonitorWorkspace does not refer to a monitor.\n" << "Continuing with normalization regardless."; } catch (Kernel::Exception::NotFoundError &e) { g_log.warning("Unable to check if the spectrum provided relates to a " "monitor - the instrument is not fully specified.\n " "Continuing with normalization regardless."); g_log.warning() << "Error was: " << e.what() << "\n"; if (m_scanInput) throw std::runtime_error("Can not continue, spectrum can not be obtained " "for monitor workspace, but the input workspace " "has a detector scan."); } }
void TOFSANSResolutionByPixel::exec() { MatrixWorkspace_sptr inOutWS = getProperty("InputWorkspace"); double deltaR = getProperty("DeltaR"); double R1 = getProperty("SourceApertureRadius"); double R2 = getProperty("SampleApertureRadius"); // Convert to meters deltaR /= 1000.0; R1 /= 1000.0; R2 /= 1000.0; const double sigmaModeratorMicroSec = getProperty("SigmaModerator"); const V3D samplePos = inOutWS->getInstrument()->getSample()->getPos(); const V3D sourcePos = inOutWS->getInstrument()->getSource()->getPos(); const V3D SSD = samplePos - sourcePos; const double L1 = SSD.norm(); const int numberOfSpectra = static_cast<int>(inOutWS->getNumberHistograms()); Progress progress(this,0.0,1.0,numberOfSpectra); //PARALLEL_FOR1(inOutWS) for (int i = 0; i < numberOfSpectra; i++) { //PARALLEL_START_INTERUPT_REGION IDetector_const_sptr det; try { det = inOutWS->getDetector(i); } catch (Exception::NotFoundError&) { g_log.information() << "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 or if it's masked or a monitor, skip onto the next spectrum if ( !det || det->isMonitor() || det->isMasked() ) continue; // Get the flight path from the sample to the detector pixel const V3D scatteredFlightPathV3D = det->getPos() - samplePos; const double L2 = scatteredFlightPathV3D.norm(); const double Lsum = L1+L2; // calculate part that is wavelenght independent const double dTheta2 = (4.0 * M_PI * M_PI / 12.0) * ( 3.0*R1*R1/(L1*L1) + 3.0*R2*R2*Lsum*Lsum/(L1*L1*L2*L2) + (deltaR*deltaR)/(L2*L2) ); // Multiplicative factor to go from lambda to Q // Don't get fooled by the function name... const double theta = inOutWS->detectorTwoTheta(det); const double factor = 4.0 * M_PI * sin( theta/2.0 ); const MantidVec& xIn = inOutWS->readX(i); MantidVec& yIn = inOutWS->dataY(i); const size_t xLength = xIn.size(); for ( size_t j = 0; j < xLength-1; j++) { // Calculate q. Alternatively q could be calculated using ConvertUnit const double wl = (xIn[j+1]+xIn[j])/2.0; const double q = factor/wl; // calculate wavelenght resolution from moderator and histogram time bin width and // convert to from unit of micro-seconds to Aangstrom const double sigmaLambda = sigmaModeratorMicroSec*3.9560/(1000.0*Lsum); // calculate sigmaQ for a given lambda and pixel const double sigmaOverLambdaTimesQ = q*sigmaLambda/wl; const double sigmaQ = std::sqrt(dTheta2/(wl*wl)+sigmaOverLambdaTimesQ*sigmaOverLambdaTimesQ); // update inout workspace with this sigmaQ yIn[j] = sigmaQ; } progress.report("Computing Q resolution"); //PARALLEL_END_INTERUPT_REGION } }
/// Execute the algorithm in case of a histogrammed data. void ExtractSpectra::execHistogram() { // Retrieve and validate the input properties this->checkProperties(); // Create the output workspace MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create( m_inputWorkspace, m_workspaceIndexList.size(), m_maxX - m_minX, m_maxX - m_minX - m_histogram); outputWorkspace->setIndexInfo( Indexing::extract(m_inputWorkspace->indexInfo(), m_workspaceIndexList)); // If this is a Workspace2D, get the spectra axes for copying in the spectraNo // later Axis *inAxis1(nullptr); TextAxis *outTxtAxis(nullptr); NumericAxis *outNumAxis(nullptr); if (m_inputWorkspace->axes() > 1) { inAxis1 = m_inputWorkspace->getAxis(1); auto outAxis1 = outputWorkspace->getAxis(1); outTxtAxis = dynamic_cast<TextAxis *>(outAxis1); if (!outTxtAxis) outNumAxis = dynamic_cast<NumericAxis *>(outAxis1); } cow_ptr<HistogramData::HistogramX> newX(nullptr); if (m_commonBoundaries) { auto &oldX = m_inputWorkspace->x(m_workspaceIndexList.front()); newX = make_cow<HistogramData::HistogramX>(oldX.begin() + m_minX, oldX.begin() + m_maxX); } bool doCrop = ((m_minX != 0) || (m_maxX != m_inputWorkspace->x(0).size())); Progress prog(this, 0.0, 1.0, (m_workspaceIndexList.size())); // Loop over the required workspace indices, copying in the desired bins for (int j = 0; j < static_cast<int>(m_workspaceIndexList.size()); ++j) { auto i = m_workspaceIndexList[j]; bool hasDx = m_inputWorkspace->hasDx(i); // Preserve/restore sharing if X vectors are the same if (m_commonBoundaries) { outputWorkspace->setSharedX(j, newX); if (hasDx) { auto &oldDx = m_inputWorkspace->dx(i); outputWorkspace->setSharedDx( j, make_cow<HistogramData::HistogramDx>( oldDx.begin() + m_minX, oldDx.begin() + m_maxX - m_histogram)); } } else { // Safe to just copy whole vector 'cos can't be cropping in X if not // common outputWorkspace->setSharedX(j, m_inputWorkspace->sharedX(i)); outputWorkspace->setSharedDx(j, m_inputWorkspace->sharedDx(i)); } if (doCrop) { auto &oldY = m_inputWorkspace->y(i); outputWorkspace->mutableY(j) .assign(oldY.begin() + m_minX, oldY.begin() + (m_maxX - m_histogram)); auto &oldE = m_inputWorkspace->e(i); outputWorkspace->mutableE(j) .assign(oldE.begin() + m_minX, oldE.begin() + (m_maxX - m_histogram)); } else { outputWorkspace->setSharedY(j, m_inputWorkspace->sharedY(i)); outputWorkspace->setSharedE(j, m_inputWorkspace->sharedE(i)); } // copy over the axis entry for each spectrum, regardless of the type of // axes present if (inAxis1) { if (outTxtAxis) { outTxtAxis->setLabel(j, inAxis1->label(i)); } else if (outNumAxis) { outNumAxis->setValue(j, inAxis1->operator()(i)); } // spectra axis is implicit in workspace creation } if (!m_commonBoundaries) this->cropRagged(outputWorkspace, static_cast<int>(i), j); // Propagate bin masking if there is any if (m_inputWorkspace->hasMaskedBins(i)) { const MatrixWorkspace::MaskList &inputMasks = m_inputWorkspace->maskedBins(i); MatrixWorkspace::MaskList::const_iterator it; for (it = inputMasks.begin(); it != inputMasks.end(); ++it) { const size_t maskIndex = (*it).first; if (maskIndex >= m_minX && maskIndex < m_maxX - m_histogram) outputWorkspace->flagMasked(j, maskIndex - m_minX, (*it).second); } } prog.report(); } setProperty("OutputWorkspace", outputWorkspace); }
/** Calculate the integral asymmetry for a workspace (red & green). * The calculation is done by MuonAsymmetryCalc and SimpleIntegration algorithms. * @param ws_red :: The red workspace * @param ws_green :: The green workspace * @param Y :: Reference to a variable receiving the value of asymmetry * @param E :: Reference to a variable receiving the value of the error */ void PlotAsymmetryByLogValue::calcIntAsymmetry(API::MatrixWorkspace_sptr ws_red, API::MatrixWorkspace_sptr ws_green,double& Y, double& E) { if ( !m_autogroup ) { groupDetectors(ws_red,m_backward_list); groupDetectors(ws_red,m_forward_list); groupDetectors(ws_green,m_backward_list); groupDetectors(ws_green,m_forward_list); } Property* startXprop = getProperty("TimeMin"); Property* endXprop = getProperty("TimeMax"); bool setX = !startXprop->isDefault() && !endXprop->isDefault(); double startX(0.0),endX(0.0); if (setX) { startX = getProperty("TimeMin"); endX = getProperty("TimeMax"); } if (!m_int) { // "Differential asymmetry" API::MatrixWorkspace_sptr tmpWS = API::WorkspaceFactory::Instance().create( ws_red,1,ws_red->readX(0).size(),ws_red->readY(0).size()); for(size_t i=0; i<tmpWS->dataY(0).size(); i++) { double FNORM = ws_green->readY(0)[i] + ws_red->readY(0)[i]; FNORM = FNORM != 0.0 ? 1.0 / FNORM : 1.0; double BNORM = ws_green->readY(1)[i] + ws_red->readY(1)[i]; BNORM = BNORM != 0.0 ? 1.0 / BNORM : 1.0; double ZF = ( ws_green->readY(0)[i] - ws_red->readY(0)[i] ) * FNORM; double ZB = ( ws_green->readY(1)[i] - ws_red->readY(1)[i] ) * BNORM; tmpWS->dataY(0)[i] = ZB - ZF; tmpWS->dataE(0)[i] = (1.0+ZF*ZF)*FNORM+(1.0+ZB*ZB)*BNORM; } IAlgorithm_sptr integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace",tmpWS); integr->setPropertyValue("OutputWorkspace","tmp"); if (setX) { integr->setProperty("RangeLower",startX); integr->setProperty("RangeUpper",endX); } integr->execute(); MatrixWorkspace_sptr out = integr->getProperty("OutputWorkspace"); Y = out->readY(0)[0] / static_cast<double>(tmpWS->dataY(0).size()); E = out->readE(0)[0] / static_cast<double>(tmpWS->dataY(0).size()); } else { // "Integral asymmetry" IAlgorithm_sptr integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace", ws_red); integr->setPropertyValue("OutputWorkspace","tmp"); if (setX) { integr->setProperty("RangeLower",startX); integr->setProperty("RangeUpper",endX); } integr->execute(); API::MatrixWorkspace_sptr intWS_red = integr->getProperty("OutputWorkspace"); integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace", ws_green); integr->setPropertyValue("OutputWorkspace","tmp"); if (setX) { integr->setProperty("RangeLower",startX); integr->setProperty("RangeUpper",endX); } integr->execute(); API::MatrixWorkspace_sptr intWS_green = integr->getProperty("OutputWorkspace"); double YIF = ( intWS_green->readY(0)[0] - intWS_red->readY(0)[0] ) / ( intWS_green->readY(0)[0] + intWS_red->readY(0)[0] ); double YIB = ( intWS_green->readY(1)[0] - intWS_red->readY(1)[0] ) / ( intWS_green->readY(1)[0] + intWS_red->readY(1)[0] ); Y = YIB - YIF; double VARIF = (1.0 + YIF*YIF) / ( intWS_green->readY(0)[0] + intWS_red->readY(0)[0] ); double VARIB = (1.0 + YIB*YIB) / ( intWS_green->readY(1)[0] + intWS_red->readY(1)[0] ); E = sqrt( VARIF + VARIB ); } }
MatrixWorkspace_sptr CreateFloodWorkspace::scaleToCentralPixel(MatrixWorkspace_sptr ws) { int const centralSpectrum = getProperty(Prop::CENTRAL_PIXEL); auto const nHisto = static_cast<int>(ws->getNumberHistograms()); if (centralSpectrum >= nHisto) { throw std::invalid_argument( "Spectrum index " + std::to_string(centralSpectrum) + " passed to property " + Prop::CENTRAL_PIXEL + " is outside the range 0-" + std::to_string(nHisto - 1)); } auto const spectraMap = ws->getSpectrumToWorkspaceIndexMap(); auto const centralIndex = spectraMap.at(centralSpectrum); auto const scaleFactor = ws->y(centralIndex).front(); g_log.information() << "Scale to central pixel, factor = " << scaleFactor << '\n'; if (scaleFactor <= 0.0) { throw std::runtime_error("Scale factor muhst be > 0, found " + std::to_string(scaleFactor)); } auto const axis = ws->getAxis(1); auto const sa = dynamic_cast<const SpectraAxis *>(axis); double const startX = isDefault(Prop::START_X) ? sa->getMin() : getProperty(Prop::START_X); double const endX = isDefault(Prop::END_X) ? sa->getMax() : getProperty(Prop::END_X); PARALLEL_FOR_IF(Kernel::threadSafe(*ws)) for (int i = 0; i < nHisto; ++i) { PARALLEL_START_INTERUPT_REGION auto const spec = ws->getSpectrum(i).getSpectrumNo(); if (isExcludedSpectrum(spec)) { ws->mutableY(i)[0] = VERY_BIG_VALUE; ws->mutableE(i)[0] = 0.0; } else if (spec >= startX && spec <= endX) { ws->mutableY(i)[0] /= scaleFactor; ws->mutableE(i)[0] /= scaleFactor; } else { ws->mutableY(i)[0] = 1.0; ws->mutableE(i)[0] = 0.0; } PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION return ws; }
WorkspaceGroup_sptr PolarizationCorrection::execPA(WorkspaceGroup_sptr inWS) { if (isPropertyDefault(cAlphaLabel())) { throw std::invalid_argument("Must provide as input for PA: " + cAlphaLabel()); } if (isPropertyDefault(cApLabel())) { throw std::invalid_argument("Must provide as input for PA: " + cApLabel()); } size_t itemIndex = 0; MatrixWorkspace_sptr Ipp = boost::dynamic_pointer_cast<MatrixWorkspace>(inWS->getItem(itemIndex++)); MatrixWorkspace_sptr Ipa = boost::dynamic_pointer_cast<MatrixWorkspace>(inWS->getItem(itemIndex++)); MatrixWorkspace_sptr Iap = boost::dynamic_pointer_cast<MatrixWorkspace>(inWS->getItem(itemIndex++)); MatrixWorkspace_sptr Iaa = boost::dynamic_pointer_cast<MatrixWorkspace>(inWS->getItem(itemIndex++)); Ipp->setTitle("Ipp"); Iaa->setTitle("Iaa"); Ipa->setTitle("Ipa"); Iap->setTitle("Iap"); auto cropAlg = this->createChildAlgorithm("CropWorkspace"); cropAlg->initialize(); cropAlg->setProperty("InputWorkspace", Ipp); cropAlg->setProperty("EndWorkspaceIndex", 0); cropAlg->execute(); MatrixWorkspace_sptr croppedIpp = cropAlg->getProperty("OutputWorkspace"); MatrixWorkspace_sptr ones = copyShapeAndFill(croppedIpp, 1.0); // The ones workspace is now identical to the input workspaces in x, but has 1 // as y values. It can therefore be used to build real polynomial functions. const VecDouble c_rho = getProperty(crhoLabel()); const VecDouble c_alpha = getProperty(cAlphaLabel()); const VecDouble c_pp = getProperty(cppLabel()); const VecDouble c_ap = getProperty(cApLabel()); const auto rho = this->execPolynomialCorrection( ones, c_rho); // Execute polynomial expression const auto pp = this->execPolynomialCorrection( ones, c_pp); // Execute polynomial expression const auto alpha = this->execPolynomialCorrection( ones, c_alpha); // Execute polynomial expression const auto ap = this->execPolynomialCorrection( ones, c_ap); // Execute polynomial expression const auto A0 = (Iaa * pp * ap) + (ap * Ipa * rho * pp) + (ap * Iap * alpha * pp) + (Ipp * ap * alpha * rho * pp); const auto A1 = pp * Iaa; const auto A2 = pp * Iap; const auto A3 = ap * Iaa; const auto A4 = ap * Ipa; const auto A5 = ap * alpha * Ipp; const auto A6 = ap * alpha * Iap; const auto A7 = pp * rho * Ipp; const auto A8 = pp * rho * Ipa; const auto D = pp * ap * (rho + alpha + 1.0 + (rho * alpha)); const auto nIpp = (A0 - A1 + A2 - A3 + A4 + A5 - A6 + A7 - A8 + Ipp + Iaa - Ipa - Iap) / D; const auto nIaa = (A0 + A1 - A2 + A3 - A4 - A5 + A6 - A7 + A8 + Ipp + Iaa - Ipa - Iap) / D; const auto nIpa = (A0 - A1 + A2 + A3 - A4 - A5 + A6 + A7 - A8 - Ipp - Iaa + Ipa + Iap) / D; const auto nIap = (A0 + A1 - A2 - A3 + A4 + A5 - A6 - A7 + A8 - Ipp - Iaa + Ipa + Iap) / D; WorkspaceGroup_sptr dataOut = boost::make_shared<WorkspaceGroup>(); dataOut->addWorkspace(nIpp); dataOut->addWorkspace(nIpa); dataOut->addWorkspace(nIap); dataOut->addWorkspace(nIaa); size_t totalGroupEntries(dataOut->getNumberOfEntries()); for (size_t i = 1; i < totalGroupEntries; i++) { auto alg = this->createChildAlgorithm("ReplaceSpecialValues"); alg->setProperty("InputWorkspace", dataOut->getItem(i)); alg->setProperty("OutputWorkspace", "dataOut_" + std::to_string(i)); alg->setProperty("NaNValue", 0.0); alg->setProperty("NaNError", 0.0); alg->setProperty("InfinityValue", 0.0); alg->setProperty("InfinityError", 0.0); alg->execute(); } // Preserve the history of the inside workspaces nIpp->history().addHistory(Ipp->getHistory()); nIaa->history().addHistory(Iaa->getHistory()); nIpa->history().addHistory(Ipa->getHistory()); nIap->history().addHistory(Iap->getHistory()); return dataOut; }
/** * Executes the algorithm */ void PlotAsymmetryByLogValue::exec() { m_forward_list = getProperty("ForwardSpectra"); m_backward_list = getProperty("BackwardSpectra"); m_autogroup = ( m_forward_list.size() == 0 && m_backward_list.size() == 0); //double alpha = getProperty("Alpha"); std::string logName = getProperty("LogValue"); int red = getProperty("Red"); int green = getProperty("Green"); std::string stype = getProperty("Type"); m_int = stype == "Integral"; std::string firstFN = getProperty("FirstRun"); std::string lastFN = getProperty("LastRun"); std::string ext = firstFN.substr(firstFN.find_last_of(".")); firstFN.erase(firstFN.size()-4); lastFN.erase(lastFN.size()-4); std::string fnBase = firstFN; size_t i = fnBase.size()-1; while(isdigit(fnBase[i])) i--; if (i == fnBase.size()-1) { g_log.error("File name must end with a number."); throw Exception::FileError("File name must end with a number.",firstFN); } fnBase.erase(i+1); firstFN.erase(0,fnBase.size()); lastFN.erase(0,fnBase.size()); size_t is = atoi(firstFN.c_str()); // starting run number size_t ie = atoi(lastFN.c_str()); // last run number int w = static_cast<int>(firstFN.size()); // The number of runs size_t npoints = ie - is + 1; // Create the 2D workspace for the output int nplots = green != EMPTY_INT() ? 4 : 1; MatrixWorkspace_sptr outWS = WorkspaceFactory::Instance().create("Workspace2D", nplots, // the number of plots npoints, // the number of data points on a plot npoints // it's not a histogram ); TextAxis* tAxis = new TextAxis(nplots); if (nplots == 1) { tAxis->setLabel(0,"Asymmetry"); } else { tAxis->setLabel(0,"Red-Green"); tAxis->setLabel(1,"Red"); tAxis->setLabel(2,"Green"); tAxis->setLabel(3,"Red+Green"); } outWS->replaceAxis(1,tAxis); Progress progress(this,0,1,ie-is+2); for(size_t i=is; i<=ie; i++) { std::ostringstream fn,fnn; fnn << std::setw(w) << std::setfill('0') << i ; fn << fnBase << fnn.str() << ext; // Load a muon nexus file with auto_group set to true IAlgorithm_sptr loadNexus = createChildAlgorithm("LoadMuonNexus"); loadNexus->setPropertyValue("Filename", fn.str()); loadNexus->setPropertyValue("OutputWorkspace","tmp"+fnn.str()); if (m_autogroup) loadNexus->setPropertyValue("AutoGroup","1"); loadNexus->execute(); std::string wsProp = "OutputWorkspace"; DataObjects::Workspace2D_sptr ws_red; DataObjects::Workspace2D_sptr ws_green; // Run through the periods of the loaded file and do calculations on the selected ones Workspace_sptr tmp = loadNexus->getProperty(wsProp); WorkspaceGroup_sptr wsGroup = boost::dynamic_pointer_cast<WorkspaceGroup>(tmp); if (!wsGroup) { ws_red = boost::dynamic_pointer_cast<DataObjects::Workspace2D>(tmp); TimeSeriesProperty<double>* logp = dynamic_cast<TimeSeriesProperty<double>*>(ws_red->run().getLogData(logName)); if (!logp) { throw std::invalid_argument("Log "+logName+" does not exist or not a double type"); } double Y,E; calcIntAsymmetry(ws_red,Y,E); outWS->dataY(0)[i-is] = Y; outWS->dataX(0)[i-is] = logp->lastValue(); outWS->dataE(0)[i-is] = E; } else { for( int period = 1; period <= wsGroup->getNumberOfEntries(); ++period ) { std::stringstream suffix; suffix << period; wsProp = "OutputWorkspace_" + suffix.str();// form the property name for higher periods // Do only one period if (green == EMPTY_INT() && period == red) { Workspace_sptr tmpff = loadNexus->getProperty(wsProp); ws_red = boost::dynamic_pointer_cast<DataObjects::Workspace2D>(tmpff); TimeSeriesProperty<double>* logp = dynamic_cast<TimeSeriesProperty<double>*>(ws_red->run().getLogData(logName)); if (!logp) { throw std::invalid_argument("Log "+logName+" does not exist or not a double type"); } double Y,E; calcIntAsymmetry(ws_red,Y,E); outWS->dataY(0)[i-is] = Y; outWS->dataX(0)[i-is] = logp->lastValue(); outWS->dataE(0)[i-is] = E; } else // red & green { if (period == red) { Workspace_sptr temp = loadNexus->getProperty(wsProp); ws_red = boost::dynamic_pointer_cast<Workspace2D>(temp); } if (period == green) { Workspace_sptr temp = loadNexus->getProperty(wsProp); ws_green = boost::dynamic_pointer_cast<Workspace2D>(temp); } } } // red & green claculation if (green != EMPTY_INT()) { if (!ws_red || !ws_green) throw std::invalid_argument("Red or green period is out of range"); TimeSeriesProperty<double>* logp = dynamic_cast<TimeSeriesProperty<double>*>(ws_red->run().getLogData(logName)); if (!logp) { throw std::invalid_argument("Log "+logName+" does not exist or not a double type"); } double Y,E; double Y1,E1; calcIntAsymmetry(ws_red,Y,E); calcIntAsymmetry(ws_green,Y1,E1); outWS->dataY(1)[i-is] = Y; outWS->dataX(1)[i-is] = logp->lastValue(); outWS->dataE(1)[i-is] = E; outWS->dataY(2)[i-is] = Y1; outWS->dataX(2)[i-is] = logp->lastValue(); outWS->dataE(2)[i-is] = E1; outWS->dataY(3)[i-is] = Y + Y1; outWS->dataX(3)[i-is] = logp->lastValue(); outWS->dataE(3)[i-is] = sqrt(E*E+E1*E1); // move to last for safety since some grouping takes place in the // calcIntAsymmetry call below calcIntAsymmetry(ws_red,ws_green,Y,E); outWS->dataY(0)[i-is] = Y; outWS->dataX(0)[i-is] = logp->lastValue(); outWS->dataE(0)[i-is] = E; } else if (!ws_red) throw std::invalid_argument("Red period is out of range"); } progress.report(); } outWS->getAxis(0)->title() = logName; outWS->setYUnitLabel("Asymmetry"); // Assign the result to the output workspace property setProperty("OutputWorkspace", outWS); }
/** * Execute the algorithm. */ void SofQW3::exec() { MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); // Do the full check for common binning if( !WorkspaceHelpers::commonBoundaries(inputWS) ) { throw std::invalid_argument("The input workspace must have common binning across all spectra"); } RebinnedOutput_sptr outputWS = this->setUpOutputWorkspace(inputWS, getProperty("QAxisBinning"), m_Qout); g_log.debug() << "Workspace type: " << outputWS->id() << std::endl; setProperty("OutputWorkspace", outputWS); const size_t nEnergyBins = inputWS->blocksize(); const size_t nHistos = inputWS->getNumberHistograms(); // Progress reports & cancellation const size_t nreports(nHistos * nEnergyBins); m_progress = boost::shared_ptr<API::Progress>(new API::Progress(this, 0.0, 1.0, nreports)); // Compute input caches this->initCachedValues(inputWS); std::vector<double> par = inputWS->getInstrument()->getNumberParameter("detector-neighbour-offset"); if (par.empty()) { // Index theta cache this->initThetaCache(inputWS); } else { g_log.debug() << "Offset: " << par[0] << std::endl; this->m_detNeighbourOffset = static_cast<int>(par[0]); this->getValuesAndWidths(inputWS); } const MantidVec & X = inputWS->readX(0); PARALLEL_FOR2(inputWS, outputWS) for (int64_t i = 0; i < static_cast<int64_t>(nHistos); ++i) // signed for openmp { PARALLEL_START_INTERUPT_REGION DetConstPtr detector = inputWS->getDetector(i); if (detector->isMasked() || detector->isMonitor()) { continue; } double theta = this->m_theta[i]; double phi = 0.0; double thetaWidth = 0.0; double phiWidth = 0.0; // Non-PSD mode if (par.empty()) { thetaWidth = this->m_thetaWidth; } // PSD mode else { phi = this->m_phi[i]; thetaWidth = this->m_thetaWidths[i]; phiWidth = this->m_phiWidths[i]; } double thetaHalfWidth = 0.5 * thetaWidth; double phiHalfWidth = 0.5 * phiWidth; const double thetaLower = theta - thetaHalfWidth; const double thetaUpper = theta + thetaHalfWidth; const double phiLower = phi - phiHalfWidth; const double phiUpper = phi + phiHalfWidth; const double efixed = this->getEFixed(detector); for(size_t j = 0; j < nEnergyBins; ++j) { m_progress->report("Computing polygon intersections"); // For each input polygon test where it intersects with // the output grid and assign the appropriate weights of Y/E const double dE_j = X[j]; const double dE_jp1 = X[j+1]; const V2D ll(dE_j, this->calculateQ(efixed, dE_j, thetaLower, phiLower)); const V2D lr(dE_jp1, this->calculateQ(efixed, dE_jp1, thetaLower, phiLower)); const V2D ur(dE_jp1, this->calculateQ(efixed, dE_jp1, thetaUpper, phiUpper)); const V2D ul(dE_j, this->calculateQ(efixed, dE_j, thetaUpper, phiUpper)); Quadrilateral inputQ = Quadrilateral(ll, lr, ur, ul); this->rebinToFractionalOutput(inputQ, inputWS, i, j, outputWS, m_Qout); } PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION outputWS->finalize(); this->normaliseOutput(outputWS, inputWS); }
/** * Reads the data from the file. It is assumed that the provided file stream has its position * set such that the first call to getline will be give the first line of data * @param file :: A reference to a file stream * @returns A pointer to a new workspace */ API::Workspace_sptr LoadAscii::readData(std::ifstream & file) const { // Get the first line and find the number of spectra from the number of columns std::string line; getline(file,line); boost::trim(line); std::list<std::string> columns; const int numCols = splitIntoColumns(columns, line); if( numCols < 2 ) { g_log.error() << "Invalid data format found in file \"" << getPropertyValue("Filename") << "\"\n"; throw std::runtime_error("Invalid data format. Fewer than 2 columns found."); } size_t numSpectra(0); bool haveErrors(false); bool haveXErrors(false); // Assume single data set with no errors if( numCols == 2 ) { numSpectra = numCols/2; } // Data with errors else if( (numCols-1) % 2 == 0 ) { numSpectra = (numCols - 1)/2; haveErrors = true; } // Data with errors on both X and Y (4-column file) else if( numCols == 4 ) { numSpectra = 1; haveErrors = true; haveXErrors = true; } else { g_log.error() << "Invalid data format found in file \"" << getPropertyValue("Filename") << "\"\n"; g_log.error() << "LoadAscii requires the number of columns to be an even multiple of either 2 or 3."; throw std::runtime_error("Invalid data format."); } // A quick check at the number of lines won't be accurate enough as potentially there // could be blank lines and comment lines int numBins(0), lineNo(0); std::vector<DataObjects::Histogram1D> spectra(numSpectra); std::vector<double> values(numCols, 0.); do { ++lineNo; boost::trim(line); if( this->skipLine(line) ) continue; columns.clear(); int lineCols = this->splitIntoColumns(columns, line); if( lineCols != numCols ) { std::ostringstream ostr; ostr << "Number of columns changed at line " << lineNo; throw std::runtime_error(ostr.str()); } try { fillInputValues(values, columns); //ignores nans and replaces them with 0 } catch(boost::bad_lexical_cast&) { g_log.error() << "Invalid value on line " << lineNo << " of \"" << getPropertyValue("Filename") << "\"\n"; throw std::runtime_error("Invalid value encountered."); } for (size_t i = 0; i < numSpectra; ++i) { spectra[i].dataX().push_back(values[0]); spectra[i].dataY().push_back(values[i*2+1]); if( haveErrors ) { spectra[i].dataE().push_back(values[i*2+2]); } if( haveXErrors ) { // Note: we only have X errors with 4-column files. // We are only here when i=0. spectra[i].dataDx().push_back(values[3]); } } ++numBins; } while(getline(file,line)); MatrixWorkspace_sptr localWorkspace = boost::dynamic_pointer_cast<MatrixWorkspace> (WorkspaceFactory::Instance().create("Workspace2D",numSpectra,numBins,numBins)); try { localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create(getProperty("Unit")); } catch (Exception::NotFoundError&) { // Asked for dimensionless workspace (obviously not in unit factory) } for (size_t i = 0; i < numSpectra; ++i) { localWorkspace->dataX(i) = spectra[i].dataX(); localWorkspace->dataY(i) = spectra[i].dataY(); /* If Y or E errors are not there, DON'T copy across as the 'spectra' vectors have not been filled above. The workspace will by default have vectors of the right length filled with zeroes. */ if ( haveErrors ) localWorkspace->dataE(i) = spectra[i].dataE(); if ( haveXErrors ) localWorkspace->dataDx(i) = spectra[i].dataDx(); // Just have spectrum number start at 1 and count up localWorkspace->getSpectrum(i)->setSpectrumNo(static_cast<specid_t>(i)+1); } return localWorkspace; }
/** Executes the rebin algorithm * * @throw runtime_error Thrown if the bin range does not intersect the range of the input workspace */ void Rebin::exec() { // Get the input workspace MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); // Are we preserving event workspace-iness? bool PreserveEvents = getProperty("PreserveEvents"); // Rebinning in-place bool inPlace = (inputWS == outputWS); std::vector<double> rbParams = rebinParamsFromInput(getProperty("Params"), *inputWS, g_log); const bool dist = inputWS->isDistribution(); const bool isHist = inputWS->isHistogramData(); // workspace independent determination of length const int histnumber = static_cast<int>(inputWS->getNumberHistograms()); bool fullBinsOnly = getProperty("FullBinsOnly"); MantidVecPtr XValues_new; // create new output X axis const int ntcnew = VectorHelper::createAxisFromRebinParams(rbParams, XValues_new.access(), true, fullBinsOnly); //--------------------------------------------------------------------------------- //Now, determine if the input workspace is actually an EventWorkspace EventWorkspace_const_sptr eventInputWS = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS); if (eventInputWS != NULL) { //------- EventWorkspace as input ------------------------------------- EventWorkspace_sptr eventOutputWS = boost::dynamic_pointer_cast<EventWorkspace>(outputWS); if (inPlace && PreserveEvents) { // -------------Rebin in-place, preserving events ---------------------------------------------- // This only sets the X axis. Actual rebinning will be done upon data access. eventOutputWS->setAllX(XValues_new); this->setProperty("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(eventOutputWS)); } else if (!inPlace && PreserveEvents) { // -------- NOT in-place, but you want to keep events for some reason. ---------------------- // Must copy the event workspace to a new EventWorkspace (and bin that). //Make a brand new EventWorkspace eventOutputWS = boost::dynamic_pointer_cast<EventWorkspace>( API::WorkspaceFactory::Instance().create("EventWorkspace", inputWS->getNumberHistograms(), 2, 1)); //Copy geometry over. API::WorkspaceFactory::Instance().initializeFromParent(inputWS, eventOutputWS, false); //You need to copy over the data as well. eventOutputWS->copyDataFrom( (*eventInputWS) ); // This only sets the X axis. Actual rebinning will be done upon data access. eventOutputWS->setAllX(XValues_new); //Cast to the matrixOutputWS and save it this->setProperty("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(eventOutputWS)); } else { //--------- Different output, OR you're inplace but not preserving Events --- create a Workspace2D ------- g_log.information() << "Creating a Workspace2D from the EventWorkspace " << eventInputWS->getName() << ".\n"; //Create a Workspace2D // This creates a new Workspace2D through a torturous route using the WorkspaceFactory. // The Workspace2D is created with an EMPTY CONSTRUCTOR outputWS = WorkspaceFactory::Instance().create("Workspace2D",histnumber,ntcnew,ntcnew-1); WorkspaceFactory::Instance().initializeFromParent(inputWS, outputWS, true); //Initialize progress reporting. Progress prog(this,0.0,1.0, histnumber); //Go through all the histograms and set the data PARALLEL_FOR3(inputWS, eventInputWS, outputWS) for (int i=0; i < histnumber; ++i) { PARALLEL_START_INTERUPT_REGION //Set the X axis for each output histogram outputWS->setX(i, XValues_new); //Get a const event list reference. eventInputWS->dataY() doesn't work. const EventList& el = eventInputWS->getEventList(i); MantidVec y_data, e_data; // The EventList takes care of histogramming. el.generateHistogram(*XValues_new, y_data, e_data); //Copy the data over. outputWS->dataY(i).assign(y_data.begin(), y_data.end()); outputWS->dataE(i).assign(e_data.begin(), e_data.end()); //Report progress prog.report(name()); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION //Copy all the axes for (int i=1; i<inputWS->axes(); i++) { outputWS->replaceAxis( i, inputWS->getAxis(i)->clone(outputWS.get()) ); outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit(); } //Copy the units over too. for (int i=0; i < outputWS->axes(); ++i) outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit(); outputWS->setYUnit(eventInputWS->YUnit()); outputWS->setYUnitLabel(eventInputWS->YUnitLabel()); // Assign it to the output workspace property setProperty("OutputWorkspace", outputWS); } } // END ---- EventWorkspace
/**Executes the main part of the algorithm that handles the conversion of the * units * @param inputWS :: the input workspace that will be converted * @throw std::runtime_error :: If the workspace has invalid X axis binning * @return A pointer to a MatrixWorkspace_sptr that contains the converted units */ MatrixWorkspace_sptr ConvertUnits::executeUnitConversion(const API::MatrixWorkspace_sptr inputWS) { // A WS holding BinEdges cannot have less than 2 values, as a bin has // 2 edges, having less than 2 values would mean that the WS contains Points if (inputWS->x(0).size() < 2) { std::stringstream msg; msg << "Input workspace has invalid X axis binning parameters. Should " "have " "at least 2 values. Found " << inputWS->x(0).size() << "."; throw std::runtime_error(msg.str()); } if (inputWS->x(0).front() > inputWS->x(0).back() || inputWS->x(m_numberOfSpectra / 2).front() > inputWS->x(m_numberOfSpectra / 2).back()) throw std::runtime_error("Input workspace has invalid X axis binning " "parameters. X values should be increasing."); MatrixWorkspace_sptr outputWS; // Check whether there is a quick conversion available double factor, power; if (m_inputUnit->quickConversion(*m_outputUnit, factor, power)) // If test fails, could also check whether a quick conversion in the // opposite // direction has been entered { outputWS = this->convertQuickly(inputWS, factor, power); } else { outputWS = this->convertViaTOF(m_inputUnit, inputWS); } // If the units conversion has flipped the ascending direction of X, reverse // all the vectors if (!outputWS->x(0).empty() && (outputWS->x(0).front() > outputWS->x(0).back() || outputWS->x(m_numberOfSpectra / 2).front() > outputWS->x(m_numberOfSpectra / 2).back())) { this->reverse(outputWS); } // Need to lop bins off if converting to energy transfer. // Don't do for EventWorkspaces, where you can easily rebin to recover the // situation without losing information /* This is an ugly test - could be made more general by testing for DBL_MAX values at the ends of all spectra, but that would be less efficient */ if (m_outputUnit->unitID().find("Delta") == 0 && !m_inputEvents) outputWS = this->removeUnphysicalBins(outputWS); // Rebin the data to common bins if requested, and if necessary bool alignBins = getProperty("AlignBins"); if (alignBins && !WorkspaceHelpers::commonBoundaries(outputWS)) outputWS = this->alignBins(outputWS); // If appropriate, put back the bin width division into Y/E. if (m_distribution && !m_inputEvents) // Never do this for event workspaces { this->putBackBinWidth(outputWS); } return outputWS; }
void ApplyAbsorptionCorrections::run() { setRunIsRunning(true); // Create / Initialize algorithm API::BatchAlgorithmRunner::AlgorithmRuntimeProps absCorProps; IAlgorithm_sptr applyCorrAlg = AlgorithmManager::Instance().create("ApplyPaalmanPingsCorrection"); applyCorrAlg->initialize(); // get Sample Workspace MatrixWorkspace_sptr sampleWs = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( m_sampleWorkspaceName); absCorProps["SampleWorkspace"] = m_sampleWorkspaceName; const bool useCan = m_uiForm.ckUseCan->isChecked(); // Get Can and Clone MatrixWorkspace_sptr canClone; if (useCan) { const auto canName = m_uiForm.dsContainer->getCurrentDataName().toStdString(); const auto cloneName = "__algorithm_can"; IAlgorithm_sptr clone = AlgorithmManager::Instance().create("CloneWorkspace"); clone->initialize(); clone->setProperty("InputWorkspace", canName); clone->setProperty("Outputworkspace", cloneName); clone->execute(); canClone = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(cloneName); // Check for same binning across sample and container if (!checkWorkspaceBinningMatches(sampleWs, canClone)) { const char *text = "Binning on sample and container does not match." "Would you like to enable rebinning of the container?"; int result = QMessageBox::question(nullptr, tr("Rebin sample?"), tr(text), QMessageBox::Yes, QMessageBox::No, QMessageBox::NoButton); if (result == QMessageBox::Yes) { m_uiForm.ckRebinContainer->setChecked(true); } else { m_batchAlgoRunner->clearQueue(); setRunIsRunning(false); setPlotSpectrumEnabled(false); setPlotContourEnabled(false); setSaveResultEnabled(false); g_log.error("Cannot apply absorption corrections " "using a sample and " "container with different binning."); return; } } absCorProps["CanWorkspace"] = cloneName; const bool useCanScale = m_uiForm.ckScaleCan->isChecked(); if (useCanScale) { const double canScaleFactor = m_uiForm.spCanScale->value(); applyCorrAlg->setProperty("CanScaleFactor", canScaleFactor); } if (m_uiForm.ckShiftCan->isChecked()) { // If container is shifted const double canShiftFactor = m_uiForm.spCanShift->value(); applyCorrAlg->setProperty("canShiftFactor", canShiftFactor); } const bool rebinContainer = m_uiForm.ckRebinContainer->isChecked(); applyCorrAlg->setProperty("RebinCanToSample", rebinContainer); } QString correctionsWsName = m_uiForm.dsCorrections->getCurrentDataName(); WorkspaceGroup_sptr corrections = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>( correctionsWsName.toStdString()); bool interpolateAll = false; for (size_t i = 0; i < corrections->size(); i++) { MatrixWorkspace_sptr factorWs = boost::dynamic_pointer_cast<MatrixWorkspace>(corrections->getItem(i)); // Check for matching binning if (sampleWs && (factorWs->blocksize() != sampleWs->blocksize() && factorWs->blocksize() != 1)) { int result; if (interpolateAll) { result = QMessageBox::Yes; } else { std::string text = "Number of bins on sample and " + factorWs->getName() + " workspace does not match.\n" + "Would you like to interpolate this workspace to " "match the sample?"; result = QMessageBox::question(nullptr, tr("Interpolate corrections?"), tr(text.c_str()), QMessageBox::YesToAll, QMessageBox::Yes, QMessageBox::No); } switch (result) { case QMessageBox::YesToAll: interpolateAll = true; // fall through case QMessageBox::Yes: addInterpolationStep(factorWs, absCorProps["SampleWorkspace"]); break; default: m_batchAlgoRunner->clearQueue(); setRunIsRunning(false); setPlotSpectrumEnabled(false); setPlotContourEnabled(false); setSaveResultEnabled(false); g_log.error( "ApplyAbsorptionCorrections cannot run with corrections that do " "not match sample binning."); return; } } applyCorrAlg->setProperty("CorrectionsWorkspace", correctionsWsName.toStdString()); } // Generate output workspace name auto QStrSampleWsName = QString::fromStdString(m_sampleWorkspaceName); int nameCutIndex = QStrSampleWsName.lastIndexOf("_"); if (nameCutIndex == -1) nameCutIndex = QStrSampleWsName.length(); QString correctionType; switch (m_uiForm.cbGeometry->currentIndex()) { case 0: correctionType = "flt"; break; case 1: correctionType = "cyl"; break; case 2: correctionType = "anl"; break; } QString outputWsName = QStrSampleWsName.left(nameCutIndex); outputWsName += "_" + correctionType + "_Corrected"; // Using container if (m_uiForm.ckUseCan->isChecked()) { const auto canName = m_uiForm.dsContainer->getCurrentDataName().toStdString(); MatrixWorkspace_sptr containerWs = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(canName); auto run = containerWs->run(); if (run.hasProperty("run_number")) { outputWsName += "_" + QString::fromStdString(run.getProperty("run_number")->value()); } else { auto canCutIndex = QString::fromStdString(canName).indexOf("_"); outputWsName += "_" + QString::fromStdString(canName).left(canCutIndex); } } outputWsName += "_red"; applyCorrAlg->setProperty("OutputWorkspace", outputWsName.toStdString()); // Add corrections algorithm to queue m_batchAlgoRunner->addAlgorithm(applyCorrAlg, absCorProps); // Run algorithm queue connect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this, SLOT(absCorComplete(bool))); m_batchAlgoRunner->executeBatchAsync(); // Set the result workspace for Python script export m_pythonExportWsName = outputWsName.toStdString(); // m_containerWorkspaceName = m_uiForm.dsContainer->getCurrentDataName(); // updateContainer(); }
/** * Start fitting process. */ void MuonSequentialFitDialog::startFit() { if ( m_state != Stopped ) throw std::runtime_error("Couln't start: already running"); setState(Preparing); // Explicitly run the file search. This might be needed when Start is clicked straigh after // editing the run box. In that case, lost focus event might not be processed yet and search // might not have been started yet. Otherwise, search is not done as the widget sees that it // has not been changed. Taken from LoadDialog.cpp:124. m_ui.runs->findFiles(); // Wait for file search to finish. while ( m_ui.runs->isSearching() ) { QApplication::processEvents(); } // To process events from the finished thread QApplication::processEvents(); // Validate input fields if ( ! isInputValid() ) { QMessageBox::critical(this, "Input is not valid", "One or more input fields are invalid.\n\nInvalid fields are marked with a '*'."); setState(Stopped); return; } QStringList runFilenames = m_ui.runs->getFilenames(); const std::string label = m_ui.labelInput->text().toStdString(); const std::string labelGroupName = SEQUENTIAL_PREFIX + label; AnalysisDataServiceImpl& ads = AnalysisDataService::Instance(); if ( ads.doesExist(labelGroupName) ) { QMessageBox::StandardButton answer = QMessageBox::question(this, "Label already exists", "Label you specified was used for one of the previous fits. Do you want to overwrite it?", QMessageBox::Yes | QMessageBox::Cancel); if ( answer != QMessageBox::Yes ) { setState(Stopped); return; } ads.deepRemoveGroup(labelGroupName); } // Create a group for label ads.add(labelGroupName, boost::make_shared<WorkspaceGroup>()); // Tell progress bar how many iterations we will need to make and reset it m_ui.progress->setRange( 0, runFilenames.size() ); m_ui.progress->setFormat("%p%"); m_ui.progress->setValue(0); // Clear diagnosis table for new fit m_ui.diagnosisTable->setRowCount(0); // Get fit function as specified by user in the fit browser IFunction_sptr fitFunction = FunctionFactory::Instance().createInitialized( m_fitPropBrowser->getFittingFunction()->asString() ); // Whether we should use initial function for every fit bool useInitFitFunction = (m_ui.paramTypeGroup->checkedButton() == m_ui.paramTypeInitial); setState(Running); m_stopRequested = false; for ( auto fileIt = runFilenames.constBegin(); fileIt != runFilenames.constEnd(); ++fileIt ) { // Process events (so that Stop button press is processed) QApplication::processEvents(); // Stop if requested by user if ( m_stopRequested ) break; MatrixWorkspace_sptr ws; auto load = boost::dynamic_pointer_cast<AlgorithmProxy>( AlgorithmManager::Instance().create("MuonLoad") ); load->setChild(true); load->setRethrows(true); load->copyPropertiesFrom(*m_loadAlg); try { load->initialize(); load->setPropertyValue( "Filename", fileIt->toStdString() ); load->setPropertyValue( "OutputWorkspace", "__YouDontSeeMeIAmNinja" ); // Is not used if ( m_fitPropBrowser->rawData() ) // TODO: or vice verca? load->setPropertyValue( "RebinParams", "" ); load->execute(); ws = load->getProperty("OutputWorkspace"); } catch(...) { QMessageBox::critical(this, "Loading failed", "Unable to load one of the files.\n\nCheck log for details"); break; } const std::string runTitle = getRunTitle(ws); const std::string wsBaseName = labelGroupName + "_" + runTitle; IFunction_sptr functionToFit; if ( useInitFitFunction ) // Create a copy so that the original function is not changed functionToFit = FunctionFactory::Instance().createInitialized( fitFunction->asString() ); else // Use the same function over and over, so that previous fitted params are used for the next fit functionToFit = fitFunction; IAlgorithm_sptr fit = AlgorithmManager::Instance().create("Fit"); fit->setRethrows(true); try { // Set function. Gets updated when fit is done. fit->setProperty("Function", functionToFit); fit->setProperty("InputWorkspace", ws); fit->setProperty("Output", wsBaseName); // We should have one spectra only in the workspace, so use the first one. fit->setProperty("WorkspaceIndex", 0); // Various properties from the fit prop. browser fit->setProperty("StartX", m_fitPropBrowser->startX()); fit->setProperty("EndX", m_fitPropBrowser->endX()); fit->setProperty("Minimizer", m_fitPropBrowser->minimizer()); fit->setProperty("CostFunction", m_fitPropBrowser->costFunction()); fit->execute(); } catch(...) { QMessageBox::critical(this, "Fitting failed", "Unable to fit one of the files.\n\nCheck log for details"); break; } // Make sure created fit workspaces end-up in the group // TODO: this really should use loop ads.addToGroup(labelGroupName, wsBaseName + "_NormalisedCovarianceMatrix"); ads.addToGroup(labelGroupName, wsBaseName + "_Parameters"); ads.addToGroup(labelGroupName, wsBaseName + "_Workspace"); // Copy log values auto fitWs = ads.retrieveWS<MatrixWorkspace>(wsBaseName + "_Workspace"); fitWs->copyExperimentInfoFrom(ws.get()); // Add information about the fit to the diagnosis table addDiagnosisEntry(runTitle, fit->getProperty("OutputChi2OverDof"), functionToFit); // Update progress m_ui.progress->setFormat("%p% - " + QString::fromStdString(runTitle) ); m_ui.progress->setValue( m_ui.progress->value() + 1 ); } setState(Stopped); }
/** Carries out the bin-by-bin normalization * @param inputWorkspace The input workspace * @param outputWorkspace The result workspace */ void NormaliseToMonitor::normaliseBinByBin( const MatrixWorkspace_sptr &inputWorkspace, MatrixWorkspace_sptr &outputWorkspace) { EventWorkspace_sptr inputEvent = boost::dynamic_pointer_cast<EventWorkspace>(inputWorkspace); // Only create output workspace if different to input one if (outputWorkspace != inputWorkspace) { if (inputEvent) { outputWorkspace = inputWorkspace->clone(); } else outputWorkspace = create<MatrixWorkspace>(*inputWorkspace); } auto outputEvent = boost::dynamic_pointer_cast<EventWorkspace>(outputWorkspace); const auto &inputSpecInfo = inputWorkspace->spectrumInfo(); const auto &monitorSpecInfo = m_monitor->spectrumInfo(); const auto specLength = inputWorkspace->blocksize(); for (auto &workspaceIndex : m_workspaceIndexes) { // Get hold of the monitor spectrum const auto &monX = m_monitor->binEdges(workspaceIndex); auto monY = m_monitor->counts(workspaceIndex); auto monE = m_monitor->countStandardDeviations(workspaceIndex); size_t timeIndex = 0; if (m_scanInput) timeIndex = monitorSpecInfo.spectrumDefinition(workspaceIndex)[0].second; // Calculate the overall normalization just the once if bins are all // matching if (m_commonBins) this->normalisationFactor(monX, monY, monE); const size_t numHists = inputWorkspace->getNumberHistograms(); // Flag set when a division by 0 is found bool hasZeroDivision = false; Progress prog(this, 0.0, 1.0, numHists); // Loop over spectra PARALLEL_FOR_IF( Kernel::threadSafe(*inputWorkspace, *outputWorkspace, *m_monitor)) for (int64_t i = 0; i < int64_t(numHists); ++i) { PARALLEL_START_INTERUPT_REGION prog.report(); const auto &specDef = inputSpecInfo.spectrumDefinition(i); if (!spectrumDefinitionsMatchTimeIndex(specDef, timeIndex)) continue; const auto &X = inputWorkspace->binEdges(i); // If not rebinning, just point to our monitor spectra, otherwise create // new vectors auto Y = (m_commonBins ? monY : Counts(specLength)); auto E = (m_commonBins ? monE : CountStandardDeviations(specLength)); if (!m_commonBins) { // ConvertUnits can give X vectors of all zeros - skip these, they // cause // problems if (X.back() == 0.0 && X.front() == 0.0) continue; // Rebin the monitor spectrum to match the binning of the current data // spectrum VectorHelper::rebinHistogram( monX.rawData(), monY.mutableRawData(), monE.mutableRawData(), X.rawData(), Y.mutableRawData(), E.mutableRawData(), false); // Recalculate the overall normalization factor this->normalisationFactor(X, Y, E); } if (inputEvent) { // --- EventWorkspace --- EventList &outEL = outputEvent->getSpectrum(i); outEL.divide(X.rawData(), Y.mutableRawData(), E.mutableRawData()); } else { // --- Workspace2D --- auto &YOut = outputWorkspace->mutableY(i); auto &EOut = outputWorkspace->mutableE(i); const auto &inY = inputWorkspace->y(i); const auto &inE = inputWorkspace->e(i); outputWorkspace->setSharedX(i, inputWorkspace->sharedX(i)); // The code below comes more or less straight out of Divide.cpp for (size_t k = 0; k < specLength; ++k) { // Get the input Y's const double leftY = inY[k]; const double rightY = Y[k]; if (rightY == 0.0) { hasZeroDivision = true; } // Calculate result and store in local variable to avoid overwriting // original data if output workspace is same as one of the input // ones const double newY = leftY / rightY; if (fabs(rightY) > 1.0e-12 && fabs(newY) > 1.0e-12) { const double lhsFactor = (inE[k] < 1.0e-12 || fabs(leftY) < 1.0e-12) ? 0.0 : pow((inE[k] / leftY), 2); const double rhsFactor = E[k] < 1.0e-12 ? 0.0 : pow((E[k] / rightY), 2); EOut[k] = std::abs(newY) * sqrt(lhsFactor + rhsFactor); } // Now store the result YOut[k] = newY; } // end Workspace2D case } // end loop over current spectrum PARALLEL_END_INTERUPT_REGION } // end loop over spectra PARALLEL_CHECK_INTERUPT_REGION if (hasZeroDivision) { g_log.warning() << "Division by zero in some of the bins.\n"; } if (inputEvent) outputEvent->clearMRU(); } }
/** Populate output workspace with results * @param outWS :: [input/output] Output workspace to populate * @param nplots :: [input] Number of histograms */ void PlotAsymmetryByLogValue::saveResultsToADS(MatrixWorkspace_sptr &outWS, int nplots) { if (nplots == 2) { size_t i = 0; for (auto it = m_logValue.begin(); it != m_logValue.end(); ++it) { size_t run = it->first; outWS->dataX(0)[i] = static_cast<double>(run); // run number outWS->dataY(0)[i] = it->second; // log value outWS->dataY(1)[i] = m_redY[run]; // redY outWS->dataE(1)[i] = m_redE[run]; // redE i++; } } else { size_t i = 0; for (auto it = m_logValue.begin(); it != m_logValue.end(); ++it) { size_t run = it->first; outWS->dataX(0)[i] = static_cast<double>(run); // run number outWS->dataY(0)[i] = it->second; // log value outWS->dataY(1)[i] = m_diffY[run]; // diffY outWS->dataE(1)[i] = m_diffE[run]; // diffE outWS->dataY(2)[i] = m_redY[run]; // redY outWS->dataE(2)[i] = m_redE[run]; // redE outWS->dataY(3)[i] = m_greenY[run]; // greenY outWS->dataE(3)[i] = m_greenE[run]; // greenE outWS->dataY(4)[i] = m_sumY[run]; // sumY outWS->dataE(4)[i] = m_sumE[run]; // sumE i++; } } // Set the title! outWS->setTitle(m_allProperties); // Save results to ADS // We can't set an output property to store the results as this algorithm // is executed as a child algorithm in the Muon ALC interface // If current results were saved as a property we couln't used // the functionality to re-use previous results in ALC AnalysisDataService::Instance().addOrReplace(m_currResName, outWS); }
void SavePHX::exec() { // Get the input workspace MatrixWorkspace_sptr inputWorkspace = getProperty("InputWorkspace"); // Get the sample position const Kernel::V3D samplePos = inputWorkspace->getInstrument()->getSample()->getPos(); // Retrieve the filename from the properties const std::string filename = getProperty("Filename"); // Get a pointer to the sample IObjComponent_const_sptr sample = inputWorkspace->getInstrument()->getSample(); std::ofstream outPHX_file(filename.c_str()); if (!outPHX_file) { g_log.error("Failed to open (PHX) file:" + filename); throw Kernel::Exception::FileError("Failed to open (PHX) file:", filename); } // execute the subalgorithm to calculate the detector's parameters; IAlgorithm_sptr spCalcDetPar = this->createSubAlgorithm("FindDetectorsPar", 0, 1, true, 1); spCalcDetPar->initialize(); spCalcDetPar->setPropertyValue("InputWorkspace", inputWorkspace->getName()); spCalcDetPar->setPropertyValue("ReturnLinearRanges", "0"); // in test mode, request the subalgortithm to create output workspace and add it to dataservice if(!det_par_ws_name.empty()){ spCalcDetPar->setPropertyValue("OutputParTable",det_par_ws_name); } // let's not do this for the time being /* std::string parFileName = this->getPropertyValue("ParFile"); if(!(parFileName.empty()||parFileName=="not_used.par")){ spCalcDetPar->setPropertyValue("ParFile",parFileName); }*/ spCalcDetPar->execute(); // FindDetectorsPar * pCalcDetPar = dynamic_cast<FindDetectorsPar *>(spCalcDetPar.get()); if(!pCalcDetPar){ // "can not get pointer to FindDetectorsPar algorithm" throw(std::bad_cast()); } const std::vector<double> & azimuthal = pCalcDetPar->getAzimuthal(); const std::vector<double> & polar = pCalcDetPar->getPolar(); const std::vector<double> & azimuthal_width = pCalcDetPar->getAzimWidth(); const std::vector<double> & polar_width = pCalcDetPar->getPolarWidth(); const std::vector<double> & secondary_flightpath= pCalcDetPar->getFlightPath(); const std::vector<size_t> & det_ID = pCalcDetPar->getDetID(); size_t nDetectors = pCalcDetPar->getNDetectors(); // Write the number of detectors to the file. outPHX_file <<" "<< nDetectors << std::endl; for (size_t i = 0; i < nDetectors; ++i) { // verify if no detector defined; volatile double NanID = azimuthal[i]; if(NanID !=azimuthal[i] )continue; // skip NaN -s // Now write all the detector info. outPHX_file << std::fixed << std::setprecision(3); outPHX_file <<" "<<secondary_flightpath[i]<<"\t 0 \t\t" << polar[i] << " \t" << azimuthal[i] << " \t" << polar_width[i] << " \t" << azimuthal_width[i] << " \t\t" << det_ID[i] << std::endl; } // Close the file outPHX_file.close(); }
/** Calculate the integral asymmetry for a pair of workspaces (red & green). * @param ws_red :: The red workspace * @param ws_green :: The green workspace * @param Y :: Reference to a variable receiving the value of asymmetry * @param E :: Reference to a variable receiving the value of the error */ void PlotAsymmetryByLogValue::calcIntAsymmetry(MatrixWorkspace_sptr ws_red, MatrixWorkspace_sptr ws_green, double &Y, double &E) { if (!m_int) { // "Differential asymmetry" MatrixWorkspace_sptr tmpWS = WorkspaceFactory::Instance().create( ws_red, 1, ws_red->readX(0).size(), ws_red->readY(0).size()); for (size_t i = 0; i < tmpWS->dataY(0).size(); i++) { double FNORM = ws_green->readY(0)[i] + ws_red->readY(0)[i]; FNORM = FNORM != 0.0 ? 1.0 / FNORM : 1.0; double BNORM = ws_green->readY(1)[i] + ws_red->readY(1)[i]; BNORM = BNORM != 0.0 ? 1.0 / BNORM : 1.0; double ZF = (ws_green->readY(0)[i] - ws_red->readY(0)[i]) * FNORM; double ZB = (ws_green->readY(1)[i] - ws_red->readY(1)[i]) * BNORM; tmpWS->dataY(0)[i] = ZB - ZF; tmpWS->dataE(0)[i] = (1.0 + ZF * ZF) * FNORM + (1.0 + ZB * ZB) * BNORM; } IAlgorithm_sptr integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace", tmpWS); integr->setProperty("RangeLower", m_minTime); integr->setProperty("RangeUpper", m_maxTime); integr->execute(); MatrixWorkspace_sptr out = integr->getProperty("OutputWorkspace"); Y = out->readY(0)[0] / static_cast<double>(tmpWS->dataY(0).size()); E = out->readE(0)[0] / static_cast<double>(tmpWS->dataY(0).size()); } else { // "Integral asymmetry" IAlgorithm_sptr integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace", ws_red); integr->setProperty("RangeLower", m_minTime); integr->setProperty("RangeUpper", m_maxTime); integr->execute(); MatrixWorkspace_sptr intWS_red = integr->getProperty("OutputWorkspace"); integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace", ws_green); integr->setProperty("RangeLower", m_minTime); integr->setProperty("RangeUpper", m_maxTime); integr->execute(); MatrixWorkspace_sptr intWS_green = integr->getProperty("OutputWorkspace"); double YIF = (intWS_green->readY(0)[0] - intWS_red->readY(0)[0]) / (intWS_green->readY(0)[0] + intWS_red->readY(0)[0]); double YIB = (intWS_green->readY(1)[0] - intWS_red->readY(1)[0]) / (intWS_green->readY(1)[0] + intWS_red->readY(1)[0]); Y = YIB - YIF; double VARIF = (1.0 + YIF * YIF) / (intWS_green->readY(0)[0] + intWS_red->readY(0)[0]); double VARIB = (1.0 + YIB * YIB) / (intWS_green->readY(1)[0] + intWS_red->readY(1)[0]); E = sqrt(VARIF + VARIB); } }
void SmoothData::exec() { // Get the input properties MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace"); int npts = getProperty("NPoints"); // Number of smoothing points must always be an odd number, so add 1 if it isn't. if (!(npts%2)) { g_log.information("Adding 1 to number of smoothing points, since it must always be odd"); ++npts; } // Check that the number of points in the smoothing isn't larger than the spectrum length const int vecSize = static_cast<int>(inputWorkspace->blocksize()); if ( npts >= vecSize ) { g_log.error("The number of averaging points requested is larger than the spectrum length"); throw std::out_of_range("The number of averaging points requested is larger than the spectrum length"); } const int halfWidth = (npts-1)/2; // Create the output workspace MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create(inputWorkspace); Progress progress(this,0.0,1.0,inputWorkspace->getNumberHistograms()); PARALLEL_FOR2(inputWorkspace,outputWorkspace) // Loop over all the spectra in the workspace for (int i = 0; i < static_cast<int>(inputWorkspace->getNumberHistograms()); ++i) { PARALLEL_START_INTERUPT_REGION // Copy the X data over. Preserves data sharing if present in input workspace. outputWorkspace->setX(i,inputWorkspace->refX(i)); // Now get references to the Y & E vectors in the input and output workspaces const MantidVec &Y = inputWorkspace->readY(i); const MantidVec &E = inputWorkspace->readE(i); MantidVec &newY = outputWorkspace->dataY(i); MantidVec &newE = outputWorkspace->dataE(i); // Use total to help hold our moving average double total = 0.0, totalE = 0.0; // First push the values ahead of the current point onto total for (int i = 0; i < halfWidth; ++i) { if ( Y[i] == Y[i] ) total += Y[i]; // Exclude if NaN totalE += E[i]*E[i]; } // Now calculate the smoothed values for the 'end' points, where the number contributing // to the smoothing will be less than NPoints for (int j = 0; j <= halfWidth; ++j) { const int index = j+halfWidth; if ( Y[index] == Y[index] ) total += Y[index]; // Exclude if NaN newY[j] = total/(index+1); totalE += E[index]*E[index]; newE[j] = sqrt(totalE)/(index+1); } // This is the main part, where each data point is the average of NPoints points centred on the // current point. Note that the statistical error will be reduced by sqrt(npts) because more // data is now contributing to each point. for (int k = halfWidth+1; k < vecSize-halfWidth; ++k) { const int kp = k+halfWidth; const int km = k-halfWidth-1; total += (Y[kp]!=Y[kp] ? 0.0 : Y[kp]) - (Y[km]!=Y[km] ? 0.0 : Y[km]); // Exclude if NaN newY[k] = total/npts; totalE += E[kp]*E[kp] - E[km]*E[km]; // Use of a moving average can lead to rounding error where what should be // zero actually comes out as a tiny negative number - bad news for sqrt so protect newE[k] = std::sqrt(std::abs(totalE))/npts; } // This deals with the 'end' at the tail of each spectrum for (int l = vecSize-halfWidth; l < vecSize; ++l) { const int index = l-halfWidth; total -= (Y[index-1]!=Y[index-1] ? 0.0 : Y[index-1]); // Exclude if NaN newY[l] = total/(vecSize-index); totalE -= E[index-1]*E[index-1]; newE[l] = std::sqrt(std::abs(totalE))/(vecSize-index); } progress.report(); PARALLEL_END_INTERUPT_REGION } // Loop over spectra PARALLEL_CHECK_INTERUPT_REGION // Set the output workspace to its property setProperty("OutputWorkspace", outputWorkspace); }
/** Execute the algorithm. */ void ConvertToDetectorFaceMD::exec() { // TODO convert matrix to event as needed MatrixWorkspace_sptr mws = this->getProperty("InputWorkspace"); in_ws = boost::dynamic_pointer_cast<EventWorkspace>(mws); if (!in_ws) throw std::runtime_error("InputWorkspace is not an EventWorkspace"); // Fill the map, throw if there are grouped pixels. m_detID_to_WI = in_ws->getDetectorIDToWorkspaceIndexVector(m_detID_to_WI_offset, true); // Get the map of the banks we'll display std::map<int, RectangularDetector_const_sptr> banks = this->getBanks(); // Find the size in the TOF dimension double tof_min, tof_max; Axis *ax0 = in_ws->getAxis(0); in_ws->getXMinMax(tof_min, tof_max); if (ax0->getValue(0) < tof_min) tof_min = ax0->getValue(0); if (ax0->getValue(ax0->length() - 1) > tof_max) tof_max = ax0->getValue(ax0->length() - 1); // Get MDFrame of General Frame type Mantid::Geometry::GeneralFrame framePixel( Mantid::Geometry::GeneralFrame::GeneralFrameName, "pixel"); Mantid::Geometry::GeneralFrame frameTOF( Mantid::Geometry::GeneralFrame::GeneralFrameName, ax0->unit()->label()); // ------------------ Build all the dimensions ---------------------------- MDHistoDimension_sptr dimX( new MDHistoDimension("x", "x", framePixel, static_cast<coord_t>(0), static_cast<coord_t>(m_numXPixels), m_numXPixels)); MDHistoDimension_sptr dimY( new MDHistoDimension("y", "y", framePixel, static_cast<coord_t>(0), static_cast<coord_t>(m_numYPixels), m_numYPixels)); std::string TOFname = ax0->title(); if (TOFname.empty()) TOFname = ax0->unit()->unitID(); MDHistoDimension_sptr dimTOF(new MDHistoDimension( TOFname, TOFname, frameTOF, static_cast<coord_t>(tof_min), static_cast<coord_t>(tof_max), ax0->length())); std::vector<IMDDimension_sptr> dims{dimX, dimY, dimTOF}; if (banks.size() > 1) { Mantid::Geometry::GeneralFrame frameNumber( Mantid::Geometry::GeneralFrame::GeneralFrameName, "number"); int min = banks.begin()->first; int max = banks.rbegin()->first + 1; MDHistoDimension_sptr dimBanks(new MDHistoDimension( "bank", "bank", frameNumber, static_cast<coord_t>(min), static_cast<coord_t>(max), max - min)); dims.push_back(dimBanks); } // --------- Create the workspace with the right number of dimensions // ---------- size_t nd = dims.size(); IMDEventWorkspace_sptr outWS = MDEventFactory::CreateMDWorkspace(nd, "MDEvent"); outWS->initGeometry(dims); outWS->initialize(); this->setBoxController(outWS->getBoxController(), mws->getInstrument()); outWS->splitBox(); MDEventWorkspace3::sptr outWS3 = boost::dynamic_pointer_cast<MDEventWorkspace3>(outWS); MDEventWorkspace4::sptr outWS4 = boost::dynamic_pointer_cast<MDEventWorkspace4>(outWS); // Copy ExperimentInfo (instrument, run, sample) to the output WS ExperimentInfo_sptr ei(in_ws->cloneExperimentInfo()); uint16_t runIndex = outWS->addExperimentInfo(ei); // ---------------- Convert each bank -------------------------------------- for (auto &bank : banks) { int bankNum = bank.first; RectangularDetector_const_sptr det = bank.second; for (int x = 0; x < det->xpixels(); x++) for (int y = 0; y < det->ypixels(); y++) { // Find the workspace index for this pixel coordinate detid_t detID = det->getDetectorIDAtXY(x, y); size_t wi = m_detID_to_WI[detID + m_detID_to_WI_offset]; if (wi >= in_ws->getNumberHistograms()) throw std::runtime_error("Invalid workspace index found in bank " + det->getName() + "!"); coord_t xPos = static_cast<coord_t>(x); coord_t yPos = static_cast<coord_t>(y); coord_t bankPos = static_cast<coord_t>(bankNum); EventList &el = in_ws->getSpectrum(wi); // We want to bind to the right templated function, so we have to know // the type of TofEvent contained in the EventList. boost::function<void()> func; switch (el.getEventType()) { case TOF: if (nd == 3) this->convertEventList<TofEvent, MDEvent<3>, 3>( outWS3, wi, xPos, yPos, bankPos, runIndex, detID); else if (nd == 4) this->convertEventList<TofEvent, MDEvent<4>, 4>( outWS4, wi, xPos, yPos, bankPos, runIndex, detID); break; case WEIGHTED: if (nd == 3) this->convertEventList<WeightedEvent, MDEvent<3>, 3>( outWS3, wi, xPos, yPos, bankPos, runIndex, detID); else if (nd == 4) this->convertEventList<WeightedEvent, MDEvent<4>, 4>( outWS4, wi, xPos, yPos, bankPos, runIndex, detID); break; case WEIGHTED_NOTIME: if (nd == 3) this->convertEventList<WeightedEventNoTime, MDEvent<3>, 3>( outWS3, wi, xPos, yPos, bankPos, runIndex, detID); else if (nd == 4) this->convertEventList<WeightedEventNoTime, MDEvent<4>, 4>( outWS4, wi, xPos, yPos, bankPos, runIndex, detID); break; default: throw std::runtime_error("EventList had an unexpected data type!"); } } } // ---------------------- Perform all box splitting --------------- ThreadScheduler *ts = new ThreadSchedulerLargestCost(); ThreadPool tp(ts); outWS->splitAllIfNeeded(ts); tp.joinAll(); outWS->refreshCache(); // Save the output workspace this->setProperty("OutputWorkspace", outWS); }
IEventWorkspace_sptr RefReduction::loadData(const std::string dataRun, const std::string polarization) { const std::string instrument = getProperty("Instrument"); // Check whether dataRun refers to an existing workspace // Create a good name for the raw workspace std::string ws_name = "__ref_"+dataRun+"-"+polarization+"_raw"; IEventWorkspace_sptr rawWS; if (AnalysisDataService::Instance().doesExist(dataRun)) { rawWS = AnalysisDataService::Instance().retrieveWS<EventWorkspace>(dataRun); g_log.notice() << "Found workspace: " << dataRun << std::endl; m_output_message += " |Input data run is a workspace: " + dataRun + "\n"; } else if (AnalysisDataService::Instance().doesExist(ws_name)) { rawWS = AnalysisDataService::Instance().retrieveWS<EventWorkspace>(ws_name); g_log.notice() << "Using existing workspace: " << ws_name << std::endl; m_output_message += " |Found workspace from previous reduction: " + ws_name + "\n"; } else { // If we can't find a workspace, find a file to load std::string path = FileFinder::Instance().getFullPath(dataRun); if (path.size()==0 || !Poco::File(path).exists()) { try { std::vector<std::string> paths = FileFinder::Instance().findRuns(instrument+dataRun); path = paths[0]; } catch(Exception::NotFoundError&) { /* Pass. We report the missing file later. */ } } if (path.size()==0 || !Poco::File(path).exists()) { try { std::vector<std::string> paths = FileFinder::Instance().findRuns(dataRun); path = paths[0]; } catch(Exception::NotFoundError&) { /* Pass. We report the missing file later. */ } } if (Poco::File(path).exists()) { g_log.notice() << "Found: " << path << std::endl; m_output_message += " |Loading from " + path + "\n"; IAlgorithm_sptr loadAlg = createChildAlgorithm("LoadEventNexus", 0, 0.2); loadAlg->setProperty("Filename", path); if (polarization.compare(PolStateNone)!=0) loadAlg->setProperty("NXentryName", polarization); loadAlg->executeAsChildAlg(); rawWS = loadAlg->getProperty("OutputWorkspace"); if (rawWS->getNumberEvents()==0) { g_log.notice() << "No data in " << polarization << std::endl; m_output_message += " |No data for " + polarization + "\n"; return rawWS; } // Move the detector to the right position if (instrument.compare("REF_M")==0) { double det_distance = rawWS->getInstrument()->getDetector(0)->getPos().Z(); Mantid::Kernel::Property* prop = rawWS->run().getProperty("SampleDetDis"); Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop); double sdd = dp->getStatistics().mean/1000.0; IAlgorithm_sptr mvAlg = createChildAlgorithm("MoveInstrumentComponent", 0.2, 0.25); mvAlg->setProperty<MatrixWorkspace_sptr>("Workspace", rawWS); mvAlg->setProperty("ComponentName", "detector1"); mvAlg->setProperty("Z", sdd-det_distance); mvAlg->setProperty("RelativePosition", true); mvAlg->executeAsChildAlg(); g_log.notice() << "Ensuring correct Z position: Correction = " << Poco::NumberFormatter::format(sdd-det_distance) << " m" << std::endl; } AnalysisDataService::Instance().addOrReplace(ws_name, rawWS); } else { g_log.error() << "Could not find a data file for " << dataRun << std::endl; throw std::invalid_argument("Could not find a data file for the given input"); } } // Crop TOF as needed and set binning double tofMin = getProperty("TOFMin"); double tofMax = getProperty("TOFMax"); if (isEmpty(tofMin) || isEmpty(tofMax)) { const MantidVec& x = rawWS->readX(0); if (isEmpty(tofMin)) tofMin = *std::min_element(x.begin(), x.end()); if (isEmpty(tofMax)) tofMax = *std::max_element(x.begin(), x.end()); } int nBins = getProperty("NBins"); double tofStep = getProperty("TOFStep"); if (!isEmpty(nBins)) tofStep = (tofMax-tofMin)/nBins; else nBins = (int)floor( (tofMax-tofMin)/tofStep ); std::vector<double> params; params.push_back(tofMin); params.push_back(tofStep); params.push_back(tofMax); IAlgorithm_sptr rebinAlg = createChildAlgorithm("Rebin", 0.25, 0.3); rebinAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", rawWS); rebinAlg->setProperty("Params", params); rebinAlg->setProperty("PreserveEvents", true); rebinAlg->executeAsChildAlg(); MatrixWorkspace_sptr outputWS = rebinAlg->getProperty("OutputWorkspace"); m_output_message += " |TOF binning: " + Poco::NumberFormatter::format(tofMin) + " to " + Poco::NumberFormatter::format(tofMax) + " in steps of " + Poco::NumberFormatter::format(tofStep) + " microsecs\n"; // Normalise by current IAlgorithm_sptr normAlg = createChildAlgorithm("NormaliseByCurrent", 0.3, 0.35); normAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", outputWS); //normAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", outputWS); normAlg->executeAsChildAlg(); outputWS = normAlg->getProperty("OutputWorkspace"); // Convert to wavelength IAlgorithm_sptr convAlg = createChildAlgorithm("ConvertUnits", 0.35, 0.4); convAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", outputWS); convAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", outputWS); convAlg->setProperty("Target", "Wavelength"); convAlg->executeAsChildAlg(); // Rebin in wavelength const MantidVec& x = outputWS->readX(0); double wlMin = *std::min_element(x.begin(), x.end()); double wlMax = *std::max_element(x.begin(), x.end()); std::vector<double> wl_params; wl_params.push_back(wlMin); wl_params.push_back((wlMax-wlMin)/nBins); wl_params.push_back(wlMax); IAlgorithm_sptr rebinAlg2 = createChildAlgorithm("Rebin", 0.25, 0.3); rebinAlg2->setProperty<MatrixWorkspace_sptr>("InputWorkspace", outputWS); rebinAlg2->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", outputWS); rebinAlg2->setProperty("Params", wl_params); rebinAlg2->setProperty("PreserveEvents", true); rebinAlg2->executeAsChildAlg(); IEventWorkspace_sptr outputEvtWS = boost::dynamic_pointer_cast<IEventWorkspace>(outputWS); return outputEvtWS; }
/** Calculate the integral asymmetry for a workspace. * The calculation is done by MuonAsymmetryCalc and SimpleIntegration algorithms. * @param ws :: The workspace * @param Y :: Reference to a variable receiving the value of asymmetry * @param E :: Reference to a variable receiving the value of the error */ void PlotAsymmetryByLogValue::calcIntAsymmetry(API::MatrixWorkspace_sptr ws, double& Y, double& E) { Property* startXprop = getProperty("TimeMin"); Property* endXprop = getProperty("TimeMax"); bool setX = !startXprop->isDefault() && !endXprop->isDefault(); double startX(0.0),endX(0.0); if (setX) { startX = getProperty("TimeMin"); endX = getProperty("TimeMax"); } if (!m_int) { // "Differential asymmetry" IAlgorithm_sptr asym = createChildAlgorithm("AsymmetryCalc"); asym->initialize(); asym->setProperty("InputWorkspace",ws); asym->setPropertyValue("OutputWorkspace","tmp"); if ( !m_autogroup ) { asym->setProperty("ForwardSpectra",m_forward_list); asym->setProperty("BackwardSpectra",m_backward_list); } asym->execute(); MatrixWorkspace_sptr asymWS = asym->getProperty("OutputWorkspace"); IAlgorithm_sptr integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace",asymWS); integr->setPropertyValue("OutputWorkspace","tmp"); if (setX) { integr->setProperty("RangeLower",startX); integr->setProperty("RangeUpper",endX); } integr->execute(); API::MatrixWorkspace_sptr out = integr->getProperty("OutputWorkspace"); Y = out->readY(0)[0]; E = out->readE(0)[0]; } else { // "Integral asymmetry" IAlgorithm_sptr integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace", ws); integr->setPropertyValue("OutputWorkspace","tmp"); if (setX) { integr->setProperty("RangeLower",startX); integr->setProperty("RangeUpper",endX); } integr->execute(); API::MatrixWorkspace_sptr intWS = integr->getProperty("OutputWorkspace"); IAlgorithm_sptr asym = createChildAlgorithm("AsymmetryCalc"); asym->initialize(); asym->setProperty("InputWorkspace",intWS); asym->setPropertyValue("OutputWorkspace","tmp"); if ( !m_autogroup ) { asym->setProperty("ForwardSpectra",m_forward_list); asym->setProperty("BackwardSpectra",m_backward_list); } asym->execute(); MatrixWorkspace_sptr out = asym->getProperty("OutputWorkspace"); Y = out->readY(0)[0]; E = out->readE(0)[0]; } }
void SofQWCentre::exec() { using namespace Geometry; MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace"); // Do the full check for common binning if (!WorkspaceHelpers::commonBoundaries(*inputWorkspace)) { g_log.error( "The input workspace must have common binning across all spectra"); throw std::invalid_argument( "The input workspace must have common binning across all spectra"); } std::vector<double> verticalAxis; MatrixWorkspace_sptr outputWorkspace = setUpOutputWorkspace( inputWorkspace, getProperty("QAxisBinning"), verticalAxis); setProperty("OutputWorkspace", outputWorkspace); // Holds the spectrum-detector mapping std::vector<specnum_t> specNumberMapping; std::vector<detid_t> detIDMapping; m_EmodeProperties.initCachedValues(*inputWorkspace, this); int emode = m_EmodeProperties.m_emode; // Get a pointer to the instrument contained in the workspace Instrument_const_sptr instrument = inputWorkspace->getInstrument(); // Get the distance between the source and the sample (assume in metres) IComponent_const_sptr source = instrument->getSource(); IComponent_const_sptr sample = instrument->getSample(); V3D beamDir = sample->getPos() - source->getPos(); beamDir.normalize(); try { double l1 = source->getDistance(*sample); g_log.debug() << "Source-sample distance: " << l1 << '\n'; } catch (Exception::NotFoundError &) { g_log.error("Unable to calculate source-sample distance"); throw Exception::InstrumentDefinitionError( "Unable to calculate source-sample distance", inputWorkspace->getTitle()); } // Conversion constant for E->k. k(A^-1) = sqrt(energyToK*E(meV)) const double energyToK = 8.0 * M_PI * M_PI * PhysicalConstants::NeutronMass * PhysicalConstants::meV * 1e-20 / (PhysicalConstants::h * PhysicalConstants::h); // Loop over input workspace bins, reassigning data to correct bin in output // qw workspace const size_t numHists = inputWorkspace->getNumberHistograms(); const size_t numBins = inputWorkspace->blocksize(); Progress prog(this, 0.0, 1.0, numHists); for (int64_t i = 0; i < int64_t(numHists); ++i) { try { // Now get the detector object for this histogram IDetector_const_sptr spectrumDet = inputWorkspace->getDetector(i); if (spectrumDet->isMonitor()) continue; const double efixed = m_EmodeProperties.getEFixed(*spectrumDet); // For inelastic scattering the simple relationship q=4*pi*sinTheta/lambda // does not hold. In order to // be completely general we must calculate the momentum transfer by // calculating the incident and final // wave vectors and then use |q| = sqrt[(ki - kf)*(ki - kf)] DetectorGroup_const_sptr detGroup = boost::dynamic_pointer_cast<const DetectorGroup>(spectrumDet); std::vector<IDetector_const_sptr> detectors; if (detGroup) { detectors = detGroup->getDetectors(); } else { detectors.push_back(spectrumDet); } const size_t numDets = detectors.size(); // cache to reduce number of static casts const double numDets_d = static_cast<double>(numDets); const auto &Y = inputWorkspace->y(i); const auto &E = inputWorkspace->e(i); const auto &X = inputWorkspace->x(i); // Loop over the detectors and for each bin calculate Q for (size_t idet = 0; idet < numDets; ++idet) { IDetector_const_sptr det = detectors[idet]; // Calculate kf vector direction and then Q for each energy bin V3D scatterDir = (det->getPos() - sample->getPos()); scatterDir.normalize(); for (size_t j = 0; j < numBins; ++j) { const double deltaE = 0.5 * (X[j] + X[j + 1]); // Compute ki and kf wave vectors and therefore q = ki - kf double ei(0.0), ef(0.0); if (emode == 1) { ei = efixed; ef = efixed - deltaE; if (ef < 0) { std::string mess = "Energy transfer requested in Direct mode exceeds incident " "energy.\n Found for det ID: " + std::to_string(idet) + " bin No " + std::to_string(j) + " with Ei=" + boost::lexical_cast<std::string>(efixed) + " and energy transfer: " + boost::lexical_cast<std::string>(deltaE); throw std::runtime_error(mess); } } else { ei = efixed + deltaE; ef = efixed; if (ef < 0) { std::string mess = "Incident energy of a neutron is negative. Are you trying to " "process Direct data in Indirect mode?\n Found for det ID: " + std::to_string(idet) + " bin No " + std::to_string(j) + " with efied=" + boost::lexical_cast<std::string>(efixed) + " and energy transfer: " + boost::lexical_cast<std::string>(deltaE); throw std::runtime_error(mess); } } if (ei < 0) throw std::runtime_error( "Negative incident energy. Check binning."); const V3D ki = beamDir * sqrt(energyToK * ei); const V3D kf = scatterDir * (sqrt(energyToK * (ef))); const double q = (ki - kf).norm(); // Test whether it's in range of the Q axis if (q < verticalAxis.front() || q > verticalAxis.back()) continue; // Find which q bin this point lies in const MantidVec::difference_type qIndex = std::upper_bound(verticalAxis.begin(), verticalAxis.end(), q) - verticalAxis.begin() - 1; // Add this spectra-detector pair to the mapping specNumberMapping.push_back( outputWorkspace->getSpectrum(qIndex).getSpectrumNo()); detIDMapping.push_back(det->getID()); // And add the data and it's error to that bin, taking into account // the number of detectors contributing to this bin outputWorkspace->mutableY(qIndex)[j] += Y[j] / numDets_d; // Standard error on the average outputWorkspace->mutableE(qIndex)[j] = sqrt((pow(outputWorkspace->e(qIndex)[j], 2) + pow(E[j], 2)) / numDets_d); } } } catch (Exception::NotFoundError &) { // Get to here if exception thrown when calculating distance to detector // Presumably, if we get to here the spectrum will be all zeroes anyway // (from conversion to E) continue; } prog.report(); } // If the input workspace was a distribution, need to divide by q bin width if (inputWorkspace->isDistribution()) this->makeDistribution(outputWorkspace, verticalAxis); // Set the output spectrum-detector mapping SpectrumDetectorMapping outputDetectorMap(specNumberMapping, detIDMapping); outputWorkspace->updateSpectraUsing(outputDetectorMap); // Replace any NaNs in outputWorkspace with zeroes if (this->getProperty("ReplaceNaNs")) { auto replaceNans = this->createChildAlgorithm("ReplaceSpecialValues"); replaceNans->setChild(true); replaceNans->initialize(); replaceNans->setProperty("InputWorkspace", outputWorkspace); replaceNans->setProperty("OutputWorkspace", outputWorkspace); replaceNans->setProperty("NaNValue", 0.0); replaceNans->setProperty("InfinityValue", 0.0); replaceNans->setProperty("BigNumberThreshold", DBL_MAX); replaceNans->execute(); } }
API::MatrixWorkspace_sptr CreateFloodWorkspace::removeBackground(API::MatrixWorkspace_sptr ws) { g_log.information() << "Remove background " << getPropertyValue(Prop::BACKGROUND) << '\n'; auto fitWS = transpose(ws); auto const &x = fitWS->x(0); // Define the fitting interval double startX = getProperty(Prop::START_X); double endX = getProperty(Prop::END_X); std::vector<double> excludeFromFit; if (isDefault(Prop::START_X)) { startX = x.front(); } else { excludeFromFit.push_back(x.front()); excludeFromFit.push_back(startX); } if (isDefault(Prop::END_X)) { endX = x.back(); } else { excludeFromFit.push_back(endX); excludeFromFit.push_back(x.back()); } // Exclude any bad detectors. for (auto i : m_excludedSpectra) { excludeFromFit.push_back(i); excludeFromFit.push_back(i); } std::string const function = getBackgroundFunction(); // Fit the data to determine unwanted background auto alg = createChildAlgorithm("Fit", 0.9, 0.99); alg->setProperty("Function", function); alg->setProperty("InputWorkspace", fitWS); alg->setProperty("WorkspaceIndex", 0); if (!excludeFromFit.empty()) { alg->setProperty("Exclude", excludeFromFit); } alg->setProperty("Output", "fit"); alg->execute(); IFunction_sptr func = alg->getProperty("Function"); g_log.information() << "Background function parameters:\n"; for (size_t i = 0; i < func->nParams(); ++i) { g_log.information() << " " << func->parameterName(i) << ": " << func->getParameter(i) << '\n'; } // Divide the workspace by the fitted curve to remove the background // and scale to values around 1 MatrixWorkspace_sptr bkgWS = alg->getProperty("OutputWorkspace"); auto const &bkg = bkgWS->y(1); auto const nHisto = static_cast<int>(ws->getNumberHistograms()); PARALLEL_FOR_IF(Kernel::threadSafe(*ws, *bkgWS)) for (int i = 0; i < nHisto; ++i) { PARALLEL_START_INTERUPT_REGION auto const xVal = x[i]; if (isExcludedSpectrum(xVal)) { ws->mutableY(i)[0] = VERY_BIG_VALUE; ws->mutableE(i)[0] = 0.0; } else if (xVal >= startX && xVal <= endX) { auto const background = bkg[i]; if (background <= 0.0) { throw std::runtime_error( "Background is expected to be positive, found value " + std::to_string(background) + " at spectrum with workspace index " + std::to_string(i)); } ws->mutableY(i)[0] /= background; ws->mutableE(i)[0] /= background; } else { ws->mutableY(i)[0] = 1.0; ws->mutableE(i)[0] = 0.0; } PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION // Remove the logs ws->setSharedRun(make_cow<Run>()); return ws; }
/** * Determine the instrument from the various input parameters. * * @return The correct instrument. */ Instrument_const_sptr CreateChunkingFromInstrument::getInstrument() { // try the input workspace MatrixWorkspace_sptr inWS = getProperty(PARAM_IN_WKSP); if (inWS) { return inWS->getInstrument(); } // temporary workspace to hang everything else off of MatrixWorkspace_sptr tempWS(new Workspace2D()); // name of the instrument string instName = getPropertyValue(PARAM_INST_NAME); // see if there is an input file string filename = getPropertyValue(PARAM_IN_FILE); if (!filename.empty()) { string top_entry_name("entry"); // TODO make more flexible // get the instrument name from the filename size_t n = filename.rfind('/'); if (n != std::string::npos) { std::string temp = filename.substr(n+1, filename.size()-n-1); n = temp.find('_'); if (n != std::string::npos && n > 0) { instName = temp.substr(0, n); } } // read information from the nexus file itself try { NeXus::File nxsfile(filename); // get the run start time string start_time; nxsfile.openGroup(top_entry_name, "NXentry"); nxsfile.readData("start_time", start_time); tempWS->mutableRun().addProperty("run_start", DateAndTime(start_time).toISO8601String(), true ); // get the instrument name nxsfile.openGroup("instrument", "NXinstrument"); nxsfile.readData("name", instName); nxsfile.closeGroup(); // Test if IDF exists in file, move on quickly if not nxsfile.openPath("instrument/instrument_xml"); nxsfile.close(); IAlgorithm_sptr loadInst= createChildAlgorithm("LoadIDFFromNexus",0.0,0.2); // Now execute the Child Algorithm. Catch and log any error, but don't stop. try { loadInst->setPropertyValue("Filename", filename); loadInst->setProperty<MatrixWorkspace_sptr> ("Workspace", tempWS); loadInst->setPropertyValue("InstrumentParentPath",top_entry_name); loadInst->execute(); } catch( std::invalid_argument&) { g_log.error("Invalid argument to LoadIDFFromNexus Child Algorithm "); } catch (std::runtime_error&) { g_log.debug("No instrument definition found in "+filename+" at "+top_entry_name+"/instrument"); } if ( loadInst->isExecuted() ) return tempWS->getInstrument(); else g_log.information("No IDF loaded from Nexus file."); } catch (::NeXus::Exception&) { g_log.information("No instrument definition found in "+filename+" at "+top_entry_name+"/instrument"); } } // run LoadInstrument if other methods have not run string instFilename = getPropertyValue(PARAM_INST_FILE); Algorithm_sptr childAlg = createChildAlgorithm("LoadInstrument",0.0,0.2); childAlg->setProperty<MatrixWorkspace_sptr>("Workspace", tempWS); childAlg->setPropertyValue("Filename", instFilename); childAlg->setPropertyValue("InstrumentName", instName); childAlg->executeAsChildAlg(); return tempWS->getInstrument(); }
void FFTDerivative::execRealFFT() { MatrixWorkspace_sptr inWS = getProperty("InputWorkspace"); MatrixWorkspace_sptr outWS; size_t n = inWS->getNumberHistograms(); API::Progress progress(this,0,1,n); size_t ny = inWS->readY(0).size(); size_t nx = inWS->readX(0).size(); // Workspace for holding a copy of a spectrum. Each spectrum is symmetrized to minimize // possible edge effects. MatrixWorkspace_sptr copyWS = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace> (Mantid::API::WorkspaceFactory::Instance().create(inWS,1,nx+ny,ny+ny)); bool isHist = (nx != ny); for(size_t spec = 0; spec < n; ++spec) { const Mantid::MantidVec& x0 = inWS->readX(spec); const Mantid::MantidVec& y0 = inWS->readY(spec); Mantid::MantidVec& x1 = copyWS->dataX(0); Mantid::MantidVec& y1 = copyWS->dataY(0); double xx = 2*x0[0]; x1[ny] = x0[0]; y1[ny] = y0[0]; for(size_t i = 1; i < ny; ++i) { size_t j1 = ny - i; size_t j2 = ny + i; x1[j1] = xx - x0[i]; x1[j2] = x0[i]; y1[j1] = y1[j2] = y0[i]; } x1[0] = 2*x1[1] - x1[2]; y1[0] = y0.back(); if (isHist) { x1[y1.size()] = x0[ny]; } // Transform symmetrized spectrum IAlgorithm_sptr fft = createSubAlgorithm("RealFFT"); fft->setProperty("InputWorkspace",copyWS); fft->setProperty("WorkspaceIndex",0); fft->setProperty("Transform","Forward"); fft->execute(); MatrixWorkspace_sptr transWS = fft->getProperty("OutputWorkspace"); Mantid::MantidVec& nu = transWS->dataX(0); Mantid::MantidVec& re = transWS->dataY(0); Mantid::MantidVec& im = transWS->dataY(1); int dn = getProperty("Order"); bool swap_re_im = dn % 2 != 0; int sign_re = 1; int sign_im = -1; switch(dn % 4) { case 1: sign_re = 1; sign_im = -1; break; case 2: sign_re = -1; sign_im = -1; break; case 3: sign_re = -1; sign_im = 1; break; } // Multiply the transform by (2*pi*i*w)**dn for(size_t j=0; j < re.size(); ++j) { double w = 2 * M_PI * nu[j]; double ww = w; for(int k = dn; k > 1; --k) { ww *= w; } double a = sign_re * re[j]*ww; double b = sign_im * im[j]*ww; if (swap_re_im) { re[j] = b; im[j] = a; } else { re[j] = a; im[j] = b; } } // Inverse transform fft = createSubAlgorithm("RealFFT"); fft->setProperty("InputWorkspace",transWS); fft->setProperty("Transform","Backward"); fft->execute(); transWS = fft->getProperty("OutputWorkspace"); size_t m2 = transWS->readY(0).size() / 2; size_t my = m2 + (transWS->readY(0).size() % 2 ? 1 : 0); size_t mx = my + (transWS->isHistogramData() ? 1 : 0); if (!outWS) { outWS = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace> (Mantid::API::WorkspaceFactory::Instance().create(inWS,n,mx,my)); } // Save the upper half of the inverse transform for output Mantid::MantidVec& x = outWS->dataX(spec); Mantid::MantidVec& y = outWS->dataY(spec); double dx = x1[0]; std::copy(transWS->dataX(0).begin() + m2,transWS->dataX(0).end(),x.begin()); std::transform(x.begin(),x.end(),x.begin(),std::bind2nd(std::plus<double>(),dx)); std::copy(transWS->dataY(0).begin() + m2,transWS->dataY(0).end(),y.begin()); // shift the data to make x and x0 match. using linear interpolation. if (x.size() != x0.size() && false)// TODO: doesn't work at the moment. needs to be working { std::cerr << "(my != x0.size()) " << x0[0] << "!=" << x[0] << std::endl; dx = x0[0] - x[0]; assert(dx > 0.0); double f = (x0[0] - x[0]) / (x0[1] - x0[0]); for(size_t i = 0; i < my - 1; ++i) { y[i] += (y[i+1] - y[i]) * f; x[i] = x0[i]; } x.back() += dx; } progress.report(); } setProperty("OutputWorkspace",outWS); }
/** Checks input properties and compares them to previous values * @param is :: [output] Number of the first run * @param ie :: [output] Number of the last run */ void PlotAsymmetryByLogValue::checkProperties(size_t &is, size_t &ie) { // Log Value m_logName = getPropertyValue("LogValue"); // Get function to apply to logValue m_logFunc = getPropertyValue("Function"); // Get type of computation m_int = (getPropertyValue("Type") == "Integral"); // Get grouping properties m_forward_list = getProperty("ForwardSpectra"); m_backward_list = getProperty("BackwardSpectra"); // Get green and red periods m_red = getProperty("Red"); m_green = getProperty("Green"); // Get time min and time max m_minTime = getProperty("TimeMin"); m_maxTime = getProperty("TimeMax"); // Get type of dead-time corrections m_dtcType = getPropertyValue("DeadTimeCorrType"); m_dtcFile = getPropertyValue("DeadTimeCorrFile"); // Get runs std::string firstFN = getProperty("FirstRun"); std::string lastFN = getProperty("LastRun"); // Parse run names and get the number of runs parseRunNames(firstFN, lastFN, m_filenameBase, m_filenameExt, m_filenameZeros); is = atoi(firstFN.c_str()); // starting run number ie = atoi(lastFN.c_str()); // last run number if (ie < is) { throw std::runtime_error( "First run number is greater than last run number"); } // Create a string holding all the properties std::ostringstream ss; ss << m_filenameBase << "," << m_filenameExt << "," << m_filenameZeros << ","; ss << m_dtcType << "," << m_dtcFile << ","; ss << getPropertyValue("ForwardSpectra") << "," << getPropertyValue("BackwardSpectra") << ","; ss << m_int << "," << m_minTime << "," << m_maxTime << ","; ss << m_red << "," << m_green << ","; ss << m_logName << ", " << m_logFunc; m_allProperties = ss.str(); // Check if we can re-use results from previous run // We can reuse results if: // 1. There is a ws in the ADS with name m_currResName // 2. It is a MatrixWorkspace // 3. It has a title equatl to m_allProperties // This ws stores previous results as described below if (AnalysisDataService::Instance().doesExist(m_currResName)) { MatrixWorkspace_sptr prevResults = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( m_currResName); if (prevResults) { if (m_allProperties == prevResults->getTitle()) { // We can re-use results size_t nPoints = prevResults->blocksize(); size_t nHisto = prevResults->getNumberHistograms(); if (nHisto == 2) { // Only 'red' data for (size_t i = 0; i < nPoints; i++) { // The first spectrum contains: X -> run number, Y -> log value // The second spectrum contains: Y -> redY, E -> redE size_t run = static_cast<size_t>(prevResults->readX(0)[i]); if ((run >= is) && (run <= ie)) { m_logValue[run] = prevResults->readY(0)[i]; m_redY[run] = prevResults->readY(1)[i]; m_redE[run] = prevResults->readE(1)[i]; } } } else { // 'Red' and 'Green' data for (size_t i = 0; i < nPoints; i++) { // The first spectrum contains: X -> run number, Y -> log value // The second spectrum contains: Y -> diffY, E -> diffE // The third spectrum contains: Y -> redY, E -> redE // The fourth spectrum contains: Y -> greenY, E -> greeE // The fifth spectrum contains: Y -> sumY, E -> sumE size_t run = static_cast<size_t>(prevResults->readX(0)[i]); if ((run >= is) && (run <= ie)) { m_logValue[run] = prevResults->readY(0)[i]; m_diffY[run] = prevResults->readY(1)[i]; m_diffE[run] = prevResults->readE(1)[i]; m_redY[run] = prevResults->readY(2)[i]; m_redE[run] = prevResults->readE(2)[i]; m_greenY[run] = prevResults->readY(3)[i]; m_greenE[run] = prevResults->readE(3)[i]; m_sumY[run] = prevResults->readY(4)[i]; m_sumE[run] = prevResults->readE(4)[i]; } } } } } } }
/** * Executes the algorithm. */ void LoadSpec::exec() { std::string filename = getProperty("Filename"); std::string separator = " "; //separator can be 1 or more spaces std::ifstream file(filename.c_str()); file.seekg (0, std::ios::end); Progress progress(this,0,1,static_cast<int>(file.tellg())); file.seekg (0, std::ios::beg); std::string str; std::vector<DataObjects::Histogram1D> spectra; //size_t iLine=0; // line number size_t ncols = 3; // number of columns int nSpectra = 0; int nBins = 0; //number of rows std::string first_character; std::string axes_infos; //bool numeric = true; std::vector<double> input; //determine the number of lines starting by #L //as there is one per set of data int spectra_nbr = 0; while(getline(file,str)) { if (str[0] == '#' && str[1] == 'L') { spectra_nbr++; } } spectra.resize(spectra_nbr); file.clear(); //end of file has been reached so we need to clear file state file.seekg (0, std::ios::beg); //go back to beginning of file int working_with_spectrum_nbr = -1; //spectrum number while(getline(file,str)) { progress.report(static_cast<int>(file.tellg())); //line with data, need to be parsed by white spaces if (!str.empty() && str[0] != '#') { typedef boost::tokenizer<boost::char_separator<char> > tokenizer; boost::char_separator<char> sep(" "); tokenizer tok(str, sep); ncols = 0; for (tokenizer::iterator beg=tok.begin(); beg!=tok.end(); ++beg) { std::stringstream ss; ss << *beg; double d; ss >> d; input.push_back(d); } } if (str.empty()) { if (working_with_spectrum_nbr != -1) { for(int j=0; j<static_cast<int>(input.size()-1); j++) { spectra[working_with_spectrum_nbr].dataX().push_back(input[j]); j++; spectra[working_with_spectrum_nbr].dataY().push_back(input[j]); j++; spectra[working_with_spectrum_nbr].dataE().push_back(input[j]); nBins = j/3; } } working_with_spectrum_nbr++; input.clear(); } } //end of read file try { if (spectra_nbr == 0) throw "Undefined number of spectra"; if (working_with_spectrum_nbr == (spectra_nbr-1)) { for(int j=0; j<static_cast<int>(input.size()-1); j++) { spectra[working_with_spectrum_nbr].dataX().push_back(input[j]); j++; spectra[working_with_spectrum_nbr].dataY().push_back(input[j]); j++; spectra[working_with_spectrum_nbr].dataE().push_back(input[j]); nBins = j/3; } } } catch (...) { } try { nSpectra = spectra_nbr; MatrixWorkspace_sptr localWorkspace = boost::dynamic_pointer_cast<MatrixWorkspace> (WorkspaceFactory::Instance().create("Workspace2D",nSpectra,nBins,nBins)); localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create(getProperty("Unit")); for(int i=0;i<nSpectra;i++) { localWorkspace->dataX(i) = spectra[i].dataX(); localWorkspace->dataY(i) = spectra[i].dataY(); localWorkspace->dataE(i) = spectra[i].dataE(); // Just have spectrum number start at 1 and count up localWorkspace->getAxis(1)->spectraNo(i) = i+1; } setProperty("OutputWorkspace",localWorkspace); } catch (Exception::NotFoundError&) { // Asked for dimensionless workspace (obviously not in unit factory) } }
/** Populate output workspace with results * @param outWS :: [input/output] Output workspace to populate * @param nplots :: [input] Number of histograms */ void PlotAsymmetryByLogValue::populateOutputWorkspace( MatrixWorkspace_sptr &outWS, int nplots) { TextAxis *tAxis = new TextAxis(nplots); if (nplots == 1) { size_t i = 0; for (auto it = m_logValue.begin(); it != m_logValue.end(); ++it) { outWS->dataX(0)[i] = it->second; outWS->dataY(0)[i] = m_redY[it->first]; outWS->dataE(0)[i] = m_redE[it->first]; i++; } tAxis->setLabel(0, "Asymmetry"); } else { size_t i = 0; for (auto it = m_logValue.begin(); it != m_logValue.end(); ++it) { outWS->dataX(0)[i] = it->second; outWS->dataY(0)[i] = m_diffY[it->first]; outWS->dataE(0)[i] = m_diffE[it->first]; outWS->dataX(1)[i] = it->second; outWS->dataY(1)[i] = m_redY[it->first]; outWS->dataE(1)[i] = m_redE[it->first]; outWS->dataX(2)[i] = it->second; outWS->dataY(2)[i] = m_greenY[it->first]; outWS->dataE(2)[i] = m_greenE[it->first]; outWS->dataX(3)[i] = it->second; outWS->dataY(3)[i] = m_sumY[it->first]; outWS->dataE(3)[i] = m_sumE[it->first]; i++; } tAxis->setLabel(0, "Red-Green"); tAxis->setLabel(1, "Red"); tAxis->setLabel(2, "Green"); tAxis->setLabel(3, "Red+Green"); } outWS->replaceAxis(1, tAxis); outWS->getAxis(0)->title() = m_logName; outWS->setYUnitLabel("Asymmetry"); }
/** Load an individual "<SASentry>" element into a new workspace. It extends the *LoadCanSAS1D * in the direction of loading the SAStransmission_spectrum as well. (which was *introduced in version 1.1) * * @param[in] workspaceData points to a "<SASentry>" element * @param[out] runName the name this workspace should take * @return dataWS this workspace will be filled with data * @throw NotFoundError if any expected elements couldn't be read * @throw NotImplementedError if the entry doesn't contain exactly one run */ MatrixWorkspace_sptr LoadCanSAS1D2::loadEntry(Poco::XML::Node *const workspaceData, std::string &runName) { MatrixWorkspace_sptr main_out = LoadCanSAS1D::loadEntry(workspaceData, runName); bool loadTrans = getProperty("LoadTransmission"); if (!loadTrans) return main_out; // all done. It is not to load the transmission, nor check // if it exists. Element *workspaceElem = dynamic_cast<Element *>(workspaceData); // check(workspaceElem, "<SASentry>"); // already done at // LoadCanSAS1D::loadEntry Poco::AutoPtr<NodeList> sasTransList = workspaceElem->getElementsByTagName("SAStransmission_spectrum"); if (!sasTransList->length()) { g_log.warning() << "There is no transmission data for this file " << getPropertyValue("Filename") << std::endl; return main_out; } for (unsigned short trans_index = 0; trans_index < sasTransList->length(); trans_index++) { // foreach SAStransmission_spectrum Node *idataElem = sasTransList->item(trans_index); Element *sasTrasElem = dynamic_cast<Element *>(idataElem); if (!sasTrasElem) continue; std::vector<API::MatrixWorkspace_sptr> &group = (sasTrasElem->getAttribute("name") == "sample") ? trans_gp : trans_can_gp; // getting number of Tdata elements in the xml file Poco::AutoPtr<NodeList> tdataElemList = sasTrasElem->getElementsByTagName("Tdata"); size_t nBins = tdataElemList->length(); MatrixWorkspace_sptr dataWS = WorkspaceFactory::Instance().create("Workspace2D", 1, nBins, nBins); createLogs(workspaceElem, dataWS); std::string title = main_out->getTitle(); title += ":trans"; title += sasTrasElem->getAttribute("name"); dataWS->setTitle(title); dataWS->isDistribution(true); dataWS->setYUnit(""); // load workspace data MantidVec &X = dataWS->dataX(0); MantidVec &Y = dataWS->dataY(0); MantidVec &E = dataWS->dataE(0); int vecindex = 0; // iterate through each Tdata element and get the values of "Lambda", //"T" and "Tdev" text nodes and fill X,Y,E vectors for (unsigned long index = 0; index < nBins; ++index) { Node *idataElem = tdataElemList->item(index); Element *elem = dynamic_cast<Element *>(idataElem); if (elem) { // setting X vector std::string nodeVal; Element *qElem = elem->getChildElement("Lambda"); check(qElem, "Lambda"); nodeVal = qElem->innerText(); std::stringstream x(nodeVal); double d; x >> d; X[vecindex] = d; // setting Y vector Element *iElem = elem->getChildElement("T"); check(qElem, "T"); nodeVal = iElem->innerText(); std::stringstream y(nodeVal); y >> d; Y[vecindex] = d; // setting the error vector Element *idevElem = elem->getChildElement("Tdev"); check(qElem, "Tdev"); nodeVal = idevElem->innerText(); std::stringstream e(nodeVal); e >> d; E[vecindex] = d; ++vecindex; } } runLoadInstrument(main_out->getInstrument()->getName(), dataWS); dataWS->getAxis(0)->setUnit("Wavelength"); // add to group group.push_back(dataWS); } return main_out; }
/** * Read histogram data * @param histogramEntries map of the file entries that have histogram * @param outputGroup pointer to the workspace group * @param nxFile Reads data from inside first first top entry */ void LoadMcStas::readHistogramData( const std::map<std::string, std::string> &histogramEntries, WorkspaceGroup_sptr &outputGroup, ::NeXus::File &nxFile) { std::string nameAttrValueYLABEL; for (const auto &histogramEntry : histogramEntries) { const std::string &dataName = histogramEntry.first; const std::string &dataType = histogramEntry.second; // open second level entry nxFile.openGroup(dataName, dataType); // grap title to use to e.g. create workspace name std::string nameAttrValueTITLE; nxFile.getAttr("filename", nameAttrValueTITLE); if (nxFile.hasAttr("ylabel")) { nxFile.getAttr("ylabel", nameAttrValueYLABEL); } // Find the axis names auto nxdataEntries = nxFile.getEntries(); std::string axis1Name, axis2Name; for (auto &nxdataEntry : nxdataEntries) { if (nxdataEntry.second == "NXparameters") continue; if (nxdataEntry.first == "ncount") continue; nxFile.openData(nxdataEntry.first); if (nxFile.hasAttr("axis")) { int axisNo(0); nxFile.getAttr("axis", axisNo); if (axisNo == 1) axis1Name = nxdataEntry.first; else if (axisNo == 2) axis2Name = nxdataEntry.first; else throw std::invalid_argument("Unknown axis number"); } nxFile.closeData(); } std::vector<double> axis1Values, axis2Values; nxFile.readData<double>(axis1Name, axis1Values); if (axis2Name.length() == 0) { axis2Name = nameAttrValueYLABEL; axis2Values.push_back(0.0); } else { nxFile.readData<double>(axis2Name, axis2Values); } const size_t axis1Length = axis1Values.size(); const size_t axis2Length = axis2Values.size(); g_log.debug() << "Axis lengths=" << axis1Length << " " << axis2Length << '\n'; // Require "data" field std::vector<double> data; nxFile.readData<double>("data", data); // Optional errors field std::vector<double> errors; try { nxFile.readData<double>("errors", errors); } catch (::NeXus::Exception &) { g_log.information() << "Field " << dataName << " contains no error information.\n"; } // close second level entry nxFile.closeGroup(); MatrixWorkspace_sptr ws = WorkspaceFactory::Instance().create( "Workspace2D", axis2Length, axis1Length, axis1Length); Axis *axis1 = ws->getAxis(0); axis1->title() = axis1Name; // Set caption auto lblUnit = boost::make_shared<Units::Label>(); lblUnit->setLabel(axis1Name, ""); axis1->unit() = lblUnit; Axis *axis2 = new NumericAxis(axis2Length); axis2->title() = axis2Name; // Set caption lblUnit = boost::make_shared<Units::Label>(); lblUnit->setLabel(axis2Name, ""); axis2->unit() = lblUnit; ws->setYUnit(axis2Name); ws->replaceAxis(1, axis2); for (size_t wsIndex = 0; wsIndex < axis2Length; ++wsIndex) { auto &dataY = ws->dataY(wsIndex); auto &dataE = ws->dataE(wsIndex); auto &dataX = ws->dataX(wsIndex); for (size_t j = 0; j < axis1Length; ++j) { // Data is stored in column-major order so we are translating to // row major for Mantid const size_t fileDataIndex = j * axis2Length + wsIndex; dataY[j] = data[fileDataIndex]; dataX[j] = axis1Values[j]; if (!errors.empty()) dataE[j] = errors[fileDataIndex]; } axis2->setValue(wsIndex, axis2Values[wsIndex]); } // set the workspace title ws->setTitle(nameAttrValueTITLE); // use the workspace title to create the workspace name std::replace(nameAttrValueTITLE.begin(), nameAttrValueTITLE.end(), ' ', '_'); // ensure that specified name is given to workspace (eventWS) when added to // outputGroup std::string nameOfGroupWS = getProperty("OutputWorkspace"); std::string nameUserSee = nameAttrValueTITLE + "_" + nameOfGroupWS; std::string extraProperty = "Outputworkspace_dummy_" + std::to_string(m_countNumWorkspaceAdded); declareProperty(Kernel::make_unique<WorkspaceProperty<Workspace>>( extraProperty, nameUserSee, Direction::Output)); setProperty(extraProperty, boost::static_pointer_cast<Workspace>(ws)); m_countNumWorkspaceAdded++; // need to increment to ensure extraProperty are // unique // Make Mantid store the workspace in the group outputGroup->addWorkspace(ws); } nxFile.closeGroup(); } // finish