/** * Create FITS file information for each file selected. Loads headers * and data from the files and creates and fills the output * workspace(s). * * @param paths File names as given in the algorithm input property * * @param outWSName name of the output (group) workspace to create * * @param loadAsRectImg Load files with 1 spectrum per row and 1 bin * per column, so a color fill plot displays the image * * @param binSize size to rebin (1 == no re-bin == default) * * @param noiseThresh threshold for noise filtering * * @throw std::runtime_error when load fails (for example a memory * allocation issue, wrong rebin requested, etc.) */ void LoadFITS::doLoadFiles(const std::vector<std::string> &paths, const std::string &outWSName, bool loadAsRectImg, int binSize, double noiseThresh) { std::vector<FITSInfo> headers; headers.resize(paths.size()); loadHeader(paths[0], headers[0]); // No extension is set -> it's the standard format which we can parse. if (headers[0].numberOfAxis > 0) m_pixelCount += headers[0].axisPixelLengths[0]; // Presumably 2 axis, but futureproofing. for (int i = 1; i < headers[0].numberOfAxis; ++i) { m_pixelCount *= headers[0].axisPixelLengths[i]; } // Check consistency of binSize asap for (int i = 0; i < headers[0].numberOfAxis; ++i) { if (0 != (headers[0].axisPixelLengths[i] % binSize)) { throw std::runtime_error( "Cannot rebin this image in blocks of " + std::to_string(binSize) + " x " + std::to_string(binSize) + " pixels as requested because the size of dimension " + std::to_string(i + 1) + " (" + std::to_string(headers[0].axisPixelLengths[i]) + ") is not a multiple of the bin size."); } } MantidImage imageY(headers[0].axisPixelLengths[1], std::vector<double>(headers[0].axisPixelLengths[0])); MantidImage imageE(headers[0].axisPixelLengths[1], std::vector<double>(headers[0].axisPixelLengths[0])); size_t bytes = (headers[0].bitsPerPixel / 8) * m_pixelCount; std::vector<char> buffer; try { buffer.resize(bytes); } catch (std::exception &) { throw std::runtime_error( "Could not allocate enough memory to run when trying to allocate " + std::to_string(bytes) + " bytes."); } // Create a group for these new workspaces, if the group already exists, add // to it. std::string groupName = outWSName; size_t fileNumberInGroup = 0; WorkspaceGroup_sptr wsGroup; if (!AnalysisDataService::Instance().doesExist(groupName)) { wsGroup = WorkspaceGroup_sptr(new WorkspaceGroup()); wsGroup->setTitle(groupName); } else { // Get the name of the latest file in group to start numbering from if (AnalysisDataService::Instance().doesExist(groupName)) wsGroup = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(groupName); std::string latestName = wsGroup->getNames().back(); // Set next file number fileNumberInGroup = fetchNumber(latestName) + 1; } size_t totalWS = headers.size(); // Create a progress reporting object API::Progress progress(this, 0, 1, totalWS + 1); progress.report(0, "Loading file(s) into workspace(s)"); // Create first workspace (with instrument definition). This is also used as // a template for creating others Workspace2D_sptr imgWS; imgWS = makeWorkspace(headers[0], fileNumberInGroup, buffer, imageY, imageE, imgWS, loadAsRectImg, binSize, noiseThresh); progress.report(1, "First file loaded."); wsGroup->addWorkspace(imgWS); if (isInstrOtherThanIMAT(headers[0])) { // For now we assume IMAT except when specific headers are found by // isInstrOtherThanIMAT() // // TODO: do this conditional on INSTR='IMAT' when we have proper IMAT .fits // files try { IAlgorithm_sptr loadInst = createChildAlgorithm("LoadInstrument"); std::string directoryName = Kernel::ConfigService::Instance().getInstrumentDirectory(); directoryName = directoryName + "/IMAT_Definition.xml"; loadInst->setPropertyValue("Filename", directoryName); loadInst->setProperty<MatrixWorkspace_sptr>( "Workspace", boost::dynamic_pointer_cast<MatrixWorkspace>(imgWS)); loadInst->execute(); } catch (std::exception &ex) { g_log.information("Cannot load the instrument definition. " + std::string(ex.what())); } } // don't feel tempted to parallelize this loop as it is - it uses the same // imageY and imageE buffers for all the workspaces for (int64_t i = 1; i < static_cast<int64_t>(totalWS); ++i) { loadHeader(paths[i], headers[i]); // Check each header is valid/supported: standard (no extension to // FITS), has two axis, and it is consistent with the first header headerSanityCheck(headers[i], headers[0]); imgWS = makeWorkspace(headers[i], fileNumberInGroup, buffer, imageY, imageE, imgWS, loadAsRectImg, binSize, noiseThresh); progress.report("Loaded file " + std::to_string(i + 1) + " of " + std::to_string(totalWS)); wsGroup->addWorkspace(imgWS); } setProperty("OutputWorkspace", wsGroup); }
/** * Handles creating a diff of two workspaces and plotting it. */ void DataComparison::plotDiffWorkspace() { // Detach old curve if (m_diffCurve != NULL) m_diffCurve->attach(NULL); // Do nothing if there are not two workspaces if (m_diffWorkspaceNames.first.isEmpty() || m_diffWorkspaceNames.second.isEmpty()) return; // Get pointers to the workspaces to be diffed MatrixWorkspace_sptr ws1 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( m_diffWorkspaceNames.first.toStdString()); MatrixWorkspace_sptr ws2 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( m_diffWorkspaceNames.second.toStdString()); int ws1Spec = 0; int ws2Spec = 0; // Get the current spectrum for each workspace int numRows = m_uiForm.twCurrentData->rowCount(); for (int row = 0; row < numRows; row++) { QString workspaceName = m_uiForm.twCurrentData->item(row, WORKSPACE_NAME)->text(); QString currentSpecName = m_uiForm.twCurrentData->item(row, CURRENT_SPEC)->text(); bool ok = false; bool found = false; if (workspaceName == m_diffWorkspaceNames.first) { ws1Spec = currentSpecName.toInt(&ok); found = true; } if (workspaceName == m_diffWorkspaceNames.second) { ws2Spec = currentSpecName.toInt(&ok); found = true; } // Check that the spectra are not out of range if (!ok && found) { // Set info message QString infoMessage = workspaceName + ": Index out of range."; m_uiForm.lbDiffInfo->setText(infoMessage); return; } } // Extract the current spectrum for both workspaces IAlgorithm_sptr extractWs1Alg = AlgorithmManager::Instance().create("ExtractSingleSpectrum"); extractWs1Alg->setChild(true); extractWs1Alg->initialize(); extractWs1Alg->setProperty("InputWorkspace", ws1); extractWs1Alg->setProperty("OutputWorkspace", "__ws1_spec"); extractWs1Alg->setProperty("WorkspaceIndex", ws1Spec); extractWs1Alg->execute(); MatrixWorkspace_sptr ws1SpecWs = extractWs1Alg->getProperty("OutputWorkspace"); IAlgorithm_sptr extractWs2Alg = AlgorithmManager::Instance().create("ExtractSingleSpectrum"); extractWs2Alg->setChild(true); extractWs2Alg->initialize(); extractWs2Alg->setProperty("InputWorkspace", ws2); extractWs2Alg->setProperty("OutputWorkspace", "__ws2_spec"); extractWs2Alg->setProperty("WorkspaceIndex", ws2Spec); extractWs2Alg->execute(); MatrixWorkspace_sptr ws2SpecWs = extractWs2Alg->getProperty("OutputWorkspace"); // Rebin the second workspace to the first // (needed for identical binning for Minus algorithm) IAlgorithm_sptr rebinAlg = AlgorithmManager::Instance().create("RebinToWorkspace"); rebinAlg->setChild(true); rebinAlg->initialize(); rebinAlg->setProperty("WorkspaceToRebin", ws2SpecWs); rebinAlg->setProperty("WorkspaceToMatch", ws1SpecWs); rebinAlg->setProperty("OutputWorkspace", "__ws2_spec_rebin"); rebinAlg->execute(); MatrixWorkspace_sptr rebinnedWs2SpecWs = rebinAlg->getProperty("OutputWorkspace"); // Subtract the two extracted spectra IAlgorithm_sptr minusAlg = AlgorithmManager::Instance().create("Minus"); minusAlg->setChild(true); minusAlg->initialize(); minusAlg->setProperty("LHSWorkspace", ws1SpecWs); minusAlg->setProperty("RHSWorkspace", rebinnedWs2SpecWs); minusAlg->setProperty("OutputWorkspace", "__diff"); minusAlg->execute(); MatrixWorkspace_sptr diffWorkspace = minusAlg->getProperty("OutputWorkspace"); // Create curve and add to plot QwtWorkspaceSpectrumData wsData(*diffWorkspace, 0, false, false); auto curve = boost::make_shared<QwtPlotCurve>(); curve->setData(wsData); curve->setPen(QColor(Qt::green)); curve->attach(m_plot); m_diffCurve = curve; // Set info message QString infoMessage = m_diffWorkspaceNames.first + "(" + QString::number(ws1Spec) + ") - " + m_diffWorkspaceNames.second + "(" + QString::number(ws2Spec) + ")"; m_uiForm.lbDiffInfo->setText(infoMessage); }
/** Execute the algorithm. */ void UnaryOperationMD::exec() { // Get the properties m_in = getProperty(inputPropName()); m_out = getProperty(outputPropName()); // For MatrixWorkspace's ... if (boost::dynamic_pointer_cast<MatrixWorkspace>(m_in)) { // Pass-through to the same function without "MD" std::string matrixAlg = this->name(); matrixAlg = matrixAlg.substr(0, matrixAlg.size() - 2); IAlgorithm_sptr alg = this->createChildAlgorithm(matrixAlg); // Copy all properties from THIS to the non-MD version std::vector<Property *> props = this->getProperties(); for (auto prop : props) { alg->setPropertyValue(prop->name(), prop->value()); } alg->execute(); // Copy the output too MatrixWorkspace_sptr outMW = alg->getProperty("OutputWorkspace"); IMDWorkspace_sptr out = boost::dynamic_pointer_cast<IMDWorkspace>(outMW); setProperty("OutputWorkspace", out); return; } // Check for validity m_in_event = boost::dynamic_pointer_cast<IMDEventWorkspace>(m_in); m_in_histo = boost::dynamic_pointer_cast<MDHistoWorkspace>(m_in); this->checkInputs(); if (m_out != m_in) { // B = f(A) -> So first we clone A (lhs) into B IAlgorithm_sptr clone = this->createChildAlgorithm("CloneMDWorkspace", 0.0, 0.5, true); clone->setProperty("InputWorkspace", m_in); clone->executeAsChildAlg(); m_out = clone->getProperty("OutputWorkspace"); } // Okay, at this point we are ready to do, e.g., // "log(m_out)" if (!m_out) throw std::runtime_error("Error creating the output workspace"); IMDEventWorkspace_sptr m_out_event = boost::dynamic_pointer_cast<IMDEventWorkspace>(m_out); MDHistoWorkspace_sptr m_out_histo = boost::dynamic_pointer_cast<MDHistoWorkspace>(m_out); // Call the appropriate sub-function if (m_out_event) this->execEvent(m_out_event); else if (m_out_histo) this->execHisto(m_out_histo); else { throw std::runtime_error( "Unexpected output workspace type. Expected MDEventWorkspace or " "MDHistoWorkspace, got " + m_out->id()); } // Give the output setProperty("OutputWorkspace", m_out); }
void CalculateEfficiency::normalizeDetectors(MatrixWorkspace_sptr rebinnedWS, MatrixWorkspace_sptr outputWS, double sum, double error, int nPixels, double min_eff, double max_eff) { // Number of spectra const size_t numberOfSpectra = rebinnedWS->getNumberHistograms(); // Empty vector to store the pixels that outside the acceptable efficiency range std::vector<size_t> dets_to_mask; for (size_t i = 0; i < numberOfSpectra; i++) { const double currProgress = 0.4+0.2*((double)i/(double)numberOfSpectra); progress(currProgress, "Computing sensitivity"); // Get the detector object for this spectrum IDetector_const_sptr det = rebinnedWS->getDetector(i); // If this detector is masked, skip to the next one if ( det->isMasked() ) continue; // Retrieve the spectrum into a vector const MantidVec& YIn = rebinnedWS->readY(i); const MantidVec& EIn = rebinnedWS->readE(i); MantidVec& YOut = outputWS->dataY(i); MantidVec& EOut = outputWS->dataE(i); // If this detector is a monitor, skip to the next one if ( det->isMonitor() ) { YOut[0] = 1.0; EOut[0] = 0.0; continue; } // Normalize counts to get relative efficiency YOut[0] = nPixels/sum * YIn[0]; const double err_sum = YIn[0]/sum*error; EOut[0] = nPixels/std::abs(sum) * std::sqrt(EIn[0]*EIn[0] + err_sum*err_sum); // Mask this detector if the signal is outside the acceptable band if ( !isEmpty(min_eff) && YOut[0] < min_eff ) dets_to_mask.push_back(i); if ( !isEmpty(max_eff) && YOut[0] > max_eff ) dets_to_mask.push_back(i); } // If we identified pixels to be masked, mask them now if ( !dets_to_mask.empty() ) { // Mask detectors that were found to be outside the acceptable efficiency band try { IAlgorithm_sptr mask = createChildAlgorithm("MaskDetectors", 0.8, 0.9); // First we mask detectors in the output workspace mask->setProperty<MatrixWorkspace_sptr>("Workspace", outputWS); mask->setProperty< std::vector<size_t> >("WorkspaceIndexList", dets_to_mask); mask->execute(); mask = createChildAlgorithm("MaskDetectors", 0.9, 1.0); // Then we mask the same detectors in the input workspace mask->setProperty<MatrixWorkspace_sptr>("Workspace", rebinnedWS); mask->setProperty< std::vector<size_t> >("WorkspaceIndexList", dets_to_mask); mask->execute(); } catch (std::invalid_argument& err) { std::stringstream e; e << "Invalid argument to MaskDetectors Child Algorithm: " << err.what(); g_log.error(e.str()); } catch (std::runtime_error& err) { std::stringstream e; e << "Unable to successfully run MaskDetectors Child Algorithm: " << err.what(); g_log.error(e.str()); } } }
/** Loads the instrument into a workspace. */ void VesuvioL1ThetaResolution::loadInstrument() { // Get the filename for the VESUVIO IDF MatrixWorkspace_sptr tempWS = WorkspaceFactory::Instance().create("Workspace2D", 1, 1, 1); const std::string vesuvioIPF = tempWS->getInstrumentFilename("VESUVIO"); // Load an empty VESUVIO instrument workspace IAlgorithm_sptr loadInst = AlgorithmManager::Instance().create("LoadEmptyInstrument"); loadInst->initialize(); loadInst->setChild(true); loadInst->setLogging(false); loadInst->setProperty("OutputWorkspace", "__evs"); loadInst->setProperty("Filename", vesuvioIPF); loadInst->execute(); m_instWorkspace = loadInst->getProperty("OutputWorkspace"); // Load the PAR file if provided const std::string parFilename = getPropertyValue("PARFile"); if (!parFilename.empty()) { g_log.information() << "Loading PAR file: " << parFilename << '\n'; // Get header format std::map<size_t, std::string> headerFormats; headerFormats[5] = "spectrum,theta,t0,-,R"; headerFormats[6] = "spectrum,-,theta,t0,-,R"; std::ifstream parFile(parFilename); if (!parFile) { throw std::runtime_error("Cannot open PAR file"); } std::string header; getline(parFile, header); g_log.debug() << "PAR file header: " << header << '\n'; boost::trim(header); std::vector<std::string> headers; boost::split(headers, header, boost::is_any_of("\t "), boost::token_compress_on); size_t numCols = headers.size(); g_log.debug() << "PAR file columns: " << numCols << '\n'; std::string headerFormat = headerFormats[numCols]; if (headerFormat.empty()) { std::stringstream error; error << "Unrecognised PAR file header. Number of colums: " << numCols << " (expected either 5 or 6."; throw std::runtime_error(error.str()); } g_log.debug() << "PAR file header format: " << headerFormat << '\n'; // Update instrument IAlgorithm_sptr updateInst = AlgorithmManager::Instance().create("UpdateInstrumentFromFile"); updateInst->initialize(); updateInst->setChild(true); updateInst->setLogging(false); updateInst->setProperty("Workspace", m_instWorkspace); updateInst->setProperty("Filename", parFilename); updateInst->setProperty("MoveMonitors", false); updateInst->setProperty("IgnorePhi", true); updateInst->setProperty("AsciiHeader", headerFormat); updateInst->execute(); m_instWorkspace = updateInst->getProperty("Workspace"); } const int specIdxMin = static_cast<int>( m_instWorkspace->getIndexFromSpectrumNumber(getProperty("SpectrumMin"))); const int specIdxMax = static_cast<int>( m_instWorkspace->getIndexFromSpectrumNumber(getProperty("SpectrumMax"))); // Crop the workspace to just the detectors we are interested in IAlgorithm_sptr crop = AlgorithmManager::Instance().create("CropWorkspace"); crop->initialize(); crop->setChild(true); crop->setLogging(false); crop->setProperty("InputWorkspace", m_instWorkspace); crop->setProperty("OutputWorkspace", "__evs"); crop->setProperty("StartWorkspaceIndex", specIdxMin); crop->setProperty("EndWorkspaceIndex", specIdxMax); crop->execute(); m_instWorkspace = crop->getProperty("OutputWorkspace"); m_sample = m_instWorkspace->getInstrument()->getSample(); }
/** * Replots the energy mini plot */ void ISISCalibration::calPlotEnergy() { if (!m_uiForm.leRunNo->isValid()) { emit showMessageBox("Run number not valid."); return; } QString files = m_uiForm.leRunNo->getFilenames().join(","); QFileInfo fi(m_uiForm.leRunNo->getFirstFilename()); QString detRange = QString::number(m_dblManager->value(m_properties["ResSpecMin"])) + "," + QString::number(m_dblManager->value(m_properties["ResSpecMax"])); IAlgorithm_sptr reductionAlg = AlgorithmManager::Instance().create("ISISIndirectEnergyTransfer"); reductionAlg->initialize(); reductionAlg->setProperty( "Instrument", getInstrumentConfiguration()->getInstrumentName().toStdString()); reductionAlg->setProperty( "Analyser", getInstrumentConfiguration()->getAnalyserName().toStdString()); reductionAlg->setProperty( "Reflection", getInstrumentConfiguration()->getReflectionName().toStdString()); reductionAlg->setProperty("InputFiles", files.toStdString()); reductionAlg->setProperty("OutputWorkspace", "__IndirectCalibration_reduction"); reductionAlg->setProperty("SpectraRange", detRange.toStdString()); reductionAlg->execute(); if (!reductionAlg->isExecuted()) { g_log.warning("Could not generate energy preview plot."); return; } WorkspaceGroup_sptr reductionOutputGroup = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>( "__IndirectCalibration_reduction"); if (reductionOutputGroup->size() == 0) { g_log.warning("No result workspaces, cannot plot energy preview."); return; } MatrixWorkspace_sptr energyWs = boost::dynamic_pointer_cast<MatrixWorkspace>( reductionOutputGroup->getItem(0)); if (!energyWs) { g_log.warning("No result workspaces, cannot plot energy preview."); return; } const Mantid::MantidVec &dataX = energyWs->readX(0); QPair<double, double> range(dataX.front(), dataX.back()); auto resBackground = m_uiForm.ppResolution->getRangeSelector("ResBackground"); setPlotPropertyRange(resBackground, m_properties["ResStart"], m_properties["ResEnd"], range); m_uiForm.ppResolution->clear(); m_uiForm.ppResolution->addSpectrum("Energy", energyWs, 0); m_uiForm.ppResolution->resizeX(); calSetDefaultResolution(energyWs); m_uiForm.ppResolution->replot(); }
void EQSANSLoad::exec() { // Verify the validity of the inputs //TODO: this should be done by the new data management algorithm used for // live data reduction (when it's implemented...) const std::string fileName = getPropertyValue("Filename"); EventWorkspace_sptr inputEventWS = getProperty("InputWorkspace"); if (fileName.size()==0 && !inputEventWS) { g_log.error() << "EQSANSLoad input error: Either a valid file path or an input workspace must be provided" << std::endl; throw std::runtime_error("EQSANSLoad input error: Either a valid file path or an input workspace must be provided"); } else if (fileName.size()>0 && inputEventWS) { g_log.error() << "EQSANSLoad input error: Either a valid file path or an input workspace must be provided, but not both" << std::endl; throw std::runtime_error("EQSANSLoad input error: Either a valid file path or an input workspace must be provided, but not both"); } // Read in default TOF cuts const bool skipTOFCorrection = getProperty("SkipTOFCorrection"); m_low_TOF_cut = getProperty("LowTOFCut"); m_high_TOF_cut = getProperty("HighTOFCut"); // Read in default beam center m_center_x = getProperty("BeamCenterX"); m_center_y = getProperty("BeamCenterY"); const bool noBeamCenter = getProperty("NoBeamCenter"); // Reduction property manager const std::string reductionManagerName = getProperty("ReductionProperties"); boost::shared_ptr<PropertyManager> reductionManager; if (PropertyManagerDataService::Instance().doesExist(reductionManagerName)) { reductionManager = PropertyManagerDataService::Instance().retrieve(reductionManagerName); } else { reductionManager = boost::make_shared<PropertyManager>(); PropertyManagerDataService::Instance().addOrReplace(reductionManagerName, reductionManager); } if (!reductionManager->existsProperty("LoadAlgorithm")) { AlgorithmProperty *loadProp = new AlgorithmProperty("LoadAlgorithm"); setPropertyValue("InputWorkspace", ""); setProperty("NoBeamCenter", false); loadProp->setValue(toString()); reductionManager->declareProperty(loadProp); } if (!reductionManager->existsProperty("InstrumentName")) { reductionManager->declareProperty(new PropertyWithValue<std::string>("InstrumentName", "EQSANS") ); } // Output log m_output_message = ""; // Check whether we need to load the data if (!inputEventWS) { const bool loadMonitors = getProperty("LoadMonitors"); IAlgorithm_sptr loadAlg = createChildAlgorithm("LoadEventNexus", 0, 0.2); loadAlg->setProperty("LoadMonitors", loadMonitors); loadAlg->setProperty("MonitorsAsEvents", false); loadAlg->setProperty("Filename", fileName); if (skipTOFCorrection) { if (m_low_TOF_cut>0.0) loadAlg->setProperty("FilterByTofMin", m_low_TOF_cut); if (m_high_TOF_cut>0.0) loadAlg->setProperty("FilterByTofMax", m_high_TOF_cut); } loadAlg->execute(); IEventWorkspace_sptr dataWS_asWks = loadAlg->getProperty("OutputWorkspace"); dataWS = boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS_asWks); // Get monitor workspace as necessary std::string mon_wsname = getPropertyValue("OutputWorkspace")+"_monitors"; if (loadMonitors && loadAlg->existsProperty("MonitorWorkspace")) { MatrixWorkspace_sptr monWS = loadAlg->getProperty("MonitorWorkspace"); declareProperty(new WorkspaceProperty<>("MonitorWorkspace", mon_wsname, Direction::Output), "Monitors from the Event NeXus file"); setProperty("MonitorWorkspace", monWS); } } else { MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); EventWorkspace_sptr outputEventWS = boost::dynamic_pointer_cast<EventWorkspace>(outputWS); if (inputEventWS != outputEventWS) { IAlgorithm_sptr copyAlg = createChildAlgorithm("CloneWorkspace", 0, 0.2); copyAlg->setProperty("InputWorkspace", inputEventWS); copyAlg->executeAsChildAlg(); Workspace_sptr dataWS_asWks = copyAlg->getProperty("OutputWorkspace"); dataWS = boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS_asWks); } else { dataWS = boost::dynamic_pointer_cast<MatrixWorkspace>(inputEventWS); } } // Get the sample-detector distance double sdd = 0.0; const double sample_det_dist = getProperty("SampleDetectorDistance"); if (!isEmpty(sample_det_dist)) { sdd = sample_det_dist; } else { if (!dataWS->run().hasProperty("detectorZ")) { g_log.error() << "Could not determine Z position: the SampleDetectorDistance property was not set " "and the run logs do not contain the detectorZ property" << std::endl; throw std::invalid_argument("Could not determine Z position: stopping execution"); } Mantid::Kernel::Property* prop = dataWS->run().getProperty("detectorZ"); Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop); sdd = dp->getStatistics().mean; // Modify SDD according to offset if given const double sample_det_offset = getProperty("SampleDetectorDistanceOffset"); if (!isEmpty(sample_det_offset)) { sdd += sample_det_offset; } } dataWS->mutableRun().addProperty("sample_detector_distance", sdd, "mm", true); // Move the detector to its correct position IAlgorithm_sptr mvAlg = createChildAlgorithm("MoveInstrumentComponent", 0.2, 0.4); mvAlg->setProperty<MatrixWorkspace_sptr>("Workspace", dataWS); mvAlg->setProperty("ComponentName", "detector1"); mvAlg->setProperty("Z", sdd/1000.0); mvAlg->setProperty("RelativePosition", false); mvAlg->executeAsChildAlg(); g_log.information() << "Moving detector to " << sdd/1000.0 << " meters" << std::endl; m_output_message += " Detector position: " + Poco::NumberFormatter::format(sdd/1000.0, 3) + " m\n"; // Get the run number so we can find the proper config file int run_number = 0; std::string config_file = ""; if (dataWS->run().hasProperty("run_number")) { Mantid::Kernel::Property* prop = dataWS->run().getProperty("run_number"); Mantid::Kernel::PropertyWithValue<std::string>* dp = dynamic_cast<Mantid::Kernel::PropertyWithValue<std::string>* >(prop); const std::string run_str = *dp; Poco::NumberParser::tryParse(run_str, run_number); // Find a proper config file config_file = findConfigFile(run_number); } else { g_log.error() << "Could not find run number for workspace " << getPropertyValue("OutputWorkspace") << std::endl; m_output_message += " Could not find run number for data file\n"; } // Process the config file bool use_config = getProperty("UseConfig"); if (use_config && config_file.size()>0) { // Special case to force reading the beam center from the config file // We're adding this to be compatible with the original EQSANS load // written in python if (m_center_x==0.0 && m_center_y==0.0) { setProperty("UseConfigBeam", true); } readConfigFile(config_file); } else if (use_config) { use_config = false; g_log.error() << "Cound not find config file for workspace " << getPropertyValue("OutputWorkspace") << std::endl; m_output_message += " Could not find configuration file for run " + Poco::NumberFormatter::format(run_number) + "\n"; } // If we use the config file, move the moderator position if (use_config) { if (m_moderator_position > -13.0) g_log.error() << "Moderator position seems close to the sample, please check" << std::endl; g_log.information() << "Moving moderator to " << m_moderator_position << std::endl; m_output_message += " Moderator position: " + Poco::NumberFormatter::format(m_moderator_position, 3) + " m\n"; mvAlg = createChildAlgorithm("MoveInstrumentComponent", 0.4, 0.45); mvAlg->setProperty<MatrixWorkspace_sptr>("Workspace", dataWS); mvAlg->setProperty("ComponentName", "moderator"); mvAlg->setProperty("Z", m_moderator_position); mvAlg->setProperty("RelativePosition", false); mvAlg->executeAsChildAlg(); } // Get source aperture radius getSourceSlitSize(); // Move the beam center to its proper position if (!noBeamCenter) { if (isEmpty(m_center_x) || isEmpty(m_center_y)) { if (reductionManager->existsProperty("LatestBeamCenterX") && reductionManager->existsProperty("LatestBeamCenterY")) { m_center_x = reductionManager->getProperty("LatestBeamCenterX"); m_center_y = reductionManager->getProperty("LatestBeamCenterY"); } } moveToBeamCenter(); // Add beam center to reduction properties, as the last beam center position that was used. // This will give us our default position next time. if (!reductionManager->existsProperty("LatestBeamCenterX")) reductionManager->declareProperty(new PropertyWithValue<double>("LatestBeamCenterX", m_center_x) ); else reductionManager->setProperty("LatestBeamCenterX", m_center_x); if (!reductionManager->existsProperty("LatestBeamCenterY")) reductionManager->declareProperty(new PropertyWithValue<double>("LatestBeamCenterY", m_center_y) ); else reductionManager->setProperty("LatestBeamCenterY", m_center_y); } // Modify TOF const bool correct_for_flight_path = getProperty("CorrectForFlightPath"); double wl_min = 0.0; double wl_max = 0.0; double wl_combined_max = 0.0; if (skipTOFCorrection) { m_output_message += " Skipping EQSANS TOF correction: assuming a single frame\n"; dataWS->mutableRun().addProperty("is_frame_skipping", 0, true); if (correct_for_flight_path) { g_log.error() << "CorrectForFlightPath and SkipTOFCorrection can't be set to true at the same time" << std::endl; m_output_message += " Skipped flight path correction: see error log\n"; } } else { m_output_message += " Flight path correction "; if (!correct_for_flight_path) m_output_message += "NOT "; m_output_message += "applied\n"; DataObjects::EventWorkspace_sptr dataWS_evt = boost::dynamic_pointer_cast<EventWorkspace>(dataWS); IAlgorithm_sptr tofAlg = createChildAlgorithm("EQSANSTofStructure", 0.5, 0.7); tofAlg->setProperty<EventWorkspace_sptr>("InputWorkspace", dataWS_evt); tofAlg->setProperty("LowTOFCut", m_low_TOF_cut); tofAlg->setProperty("HighTOFCut", m_high_TOF_cut); tofAlg->setProperty("FlightPathCorrection", correct_for_flight_path); tofAlg->executeAsChildAlg(); wl_min = tofAlg->getProperty("WavelengthMin"); wl_max = tofAlg->getProperty("WavelengthMax"); if (wl_min != wl_min || wl_max != wl_max) { g_log.error() << "Bad wavelength range" << std::endl; g_log.error() << m_output_message << std::endl; } const bool frame_skipping = tofAlg->getProperty("FrameSkipping"); dataWS->mutableRun().addProperty("wavelength_min", wl_min, "Angstrom", true); dataWS->mutableRun().addProperty("wavelength_max", wl_max, "Angstrom", true); dataWS->mutableRun().addProperty("is_frame_skipping", int(frame_skipping), true); wl_combined_max = wl_max; m_output_message += " Wavelength range: " + Poco::NumberFormatter::format(wl_min, 1) + " - " + Poco::NumberFormatter::format(wl_max, 1); if (frame_skipping) { const double wl_min2 = tofAlg->getProperty("WavelengthMinFrame2"); const double wl_max2 = tofAlg->getProperty("WavelengthMaxFrame2"); wl_combined_max = wl_max2; dataWS->mutableRun().addProperty("wavelength_min_frame2", wl_min2, "Angstrom", true); dataWS->mutableRun().addProperty("wavelength_max_frame2", wl_max2, "Angstrom", true); m_output_message += " and " + Poco::NumberFormatter::format(wl_min2, 1) + " - " + Poco::NumberFormatter::format(wl_max2, 1) + " Angstrom\n"; } else m_output_message += " Angstrom\n"; } // Convert to wavelength const double ssd = fabs(dataWS->getInstrument()->getSource()->getPos().Z())*1000.0; const double conversion_factor = 3.9560346 / (sdd+ssd); m_output_message += " TOF to wavelength conversion factor: " + Poco::NumberFormatter::format(conversion_factor) + "\n"; if (skipTOFCorrection) { DataObjects::EventWorkspace_sptr dataWS_evt = boost::dynamic_pointer_cast<EventWorkspace>(dataWS); if (dataWS_evt->getNumberEvents()==0) throw std::invalid_argument("No event to process: check your TOF cuts"); wl_min = dataWS_evt->getTofMin()*conversion_factor; wl_max = dataWS_evt->getTofMax()*conversion_factor; wl_combined_max = wl_max; g_log.information() << "Wavelength range: " << wl_min << " to " << wl_max << std::endl; dataWS->mutableRun().addProperty("wavelength_min", wl_min, "Angstrom", true); dataWS->mutableRun().addProperty("wavelength_max", wl_max, "Angstrom", true); } IAlgorithm_sptr scAlg = createChildAlgorithm("ScaleX", 0.7, 0.71); scAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", dataWS); scAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", dataWS); scAlg->setProperty("Factor", conversion_factor); scAlg->executeAsChildAlg(); dataWS->getAxis(0)->setUnit("Wavelength"); // Rebin so all the wavelength bins are aligned const bool preserveEvents = getProperty("PreserveEvents"); const double wl_step = getProperty("WavelengthStep"); std::string params = Poco::NumberFormatter::format(wl_min, 2) + "," + Poco::NumberFormatter::format(wl_step, 2) + "," + Poco::NumberFormatter::format(wl_combined_max, 2); IAlgorithm_sptr rebinAlg = createChildAlgorithm("Rebin", 0.71, 0.72); rebinAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", dataWS); if (preserveEvents) rebinAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", dataWS); rebinAlg->setPropertyValue("Params", params); rebinAlg->setProperty("PreserveEvents", preserveEvents); rebinAlg->executeAsChildAlg(); if (!preserveEvents) dataWS = rebinAlg->getProperty("OutputWorkspace"); dataWS->mutableRun().addProperty("event_ws", getPropertyValue("OutputWorkspace"), true); setProperty<MatrixWorkspace_sptr>("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS)); //m_output_message = "Loaded " + fileName + '\n' + m_output_message; setPropertyValue("OutputMessage", m_output_message); }
/** * 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 HFIRDarkCurrentSubtraction::exec() { std::string output_message = ""; // Reduction property manager const std::string reductionManagerName = getProperty("ReductionProperties"); boost::shared_ptr<PropertyManager> reductionManager; if (PropertyManagerDataService::Instance().doesExist(reductionManagerName)) { reductionManager = PropertyManagerDataService::Instance().retrieve(reductionManagerName); } else { reductionManager = boost::make_shared<PropertyManager>(); PropertyManagerDataService::Instance().addOrReplace(reductionManagerName, reductionManager); } // If the load algorithm isn't in the reduction properties, add it const bool persistent = getProperty("PersistentCorrection"); if (!reductionManager->existsProperty("DarkCurrentAlgorithm") && persistent) { AlgorithmProperty *algProp = new AlgorithmProperty("DarkCurrentAlgorithm"); algProp->setValue(toString()); reductionManager->declareProperty(algProp); } Progress progress(this,0.0,1.0,10); MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); const std::string fileName = getPropertyValue("Filename"); MatrixWorkspace_sptr darkWS; std::string darkWSName = getPropertyValue("OutputDarkCurrentWorkspace"); progress.report("Subtracting dark current"); // Look for an entry for the dark current in the reduction table Poco::Path path(fileName); const std::string entryName = "DarkCurrent"+path.getBaseName(); if (reductionManager->existsProperty(entryName)) { darkWS = reductionManager->getProperty(entryName); darkWSName = reductionManager->getPropertyValue(entryName); output_message += darkWSName + '\n'; } else { // Load the dark current if we don't have it already if (darkWSName.size()==0) { darkWSName = "__dark_current_"+path.getBaseName(); setPropertyValue("OutputDarkCurrentWorkspace", darkWSName); } IAlgorithm_sptr loadAlg; if (!reductionManager->existsProperty("LoadAlgorithm")) { loadAlg = createChildAlgorithm("HFIRLoad", 0.1, 0.3); loadAlg->setProperty("Filename", fileName); loadAlg->setProperty("ReductionProperties", reductionManagerName); loadAlg->executeAsChildAlg(); } else { IAlgorithm_sptr loadAlg0 = reductionManager->getProperty("LoadAlgorithm"); const std::string loadString = loadAlg0->toString(); loadAlg = Algorithm::fromString(loadString); loadAlg->setChild(true); loadAlg->setProperty("Filename", fileName); loadAlg->setProperty("ReductionProperties", reductionManagerName); loadAlg->setPropertyValue("OutputWorkspace", darkWSName); loadAlg->execute(); } darkWS = loadAlg->getProperty("OutputWorkspace"); output_message += "\n Loaded " + fileName + "\n"; if (loadAlg->existsProperty("OutputMessage")) { std::string msg = loadAlg->getPropertyValue("OutputMessage"); output_message += " |" + Poco::replace(msg, "\n", "\n |") + "\n"; } setProperty("OutputDarkCurrentWorkspace", darkWS); reductionManager->declareProperty(new WorkspaceProperty<>(entryName,"",Direction::Output)); reductionManager->setPropertyValue(entryName, darkWSName); reductionManager->setProperty(entryName, darkWS); } progress.report(3, "Loaded dark current"); // Perform subtraction double darkTimer = getCountingTime(darkWS); double dataTimer = getCountingTime(inputWS); IAlgorithm_sptr scaleAlg = createChildAlgorithm("Scale", 0.3, 0.5); scaleAlg->setProperty("InputWorkspace", darkWS); scaleAlg->setProperty("Factor", dataTimer/darkTimer); scaleAlg->setProperty("Operation", "Multiply"); scaleAlg->executeAsChildAlg(); MatrixWorkspace_sptr scaledDarkWS = scaleAlg->getProperty("OutputWorkspace"); // Zero out timer and monitor so that we don't subtract them out for(size_t i=0; i<scaledDarkWS->dataY(0).size(); i++) { scaledDarkWS->dataY(DEFAULT_TIMER_ID)[i]=0.0; scaledDarkWS->dataE(DEFAULT_TIMER_ID)[i]=0.0; scaledDarkWS->dataY(DEFAULT_MONITOR_ID)[i]=0.0; scaledDarkWS->dataE(DEFAULT_MONITOR_ID)[i]=0.0; } IAlgorithm_sptr minusAlg = createChildAlgorithm("Minus", 0.5, 0.7); minusAlg->setProperty("LHSWorkspace", inputWS); minusAlg->setProperty("RHSWorkspace", scaledDarkWS); MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); minusAlg->setProperty("OutputWorkspace", outputWS); minusAlg->executeAsChildAlg(); MatrixWorkspace_sptr correctedWS = minusAlg->getProperty("OutputWorkspace"); setProperty("OutputWorkspace", correctedWS); setProperty("OutputMessage", "Dark current subtracted: "+output_message); progress.report("Subtracted dark current"); }
void SavePAR::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 IComponent_const_sptr sample = inputWorkspace->getInstrument()->getSample(); std::ofstream outPAR_file(filename.c_str()); if (!outPAR_file) { g_log.error("Failed to open (PAR) file:" + filename); throw Kernel::Exception::FileError("Failed to open (PAR) file:", filename); } // execute the ChildAlgorithm to calculate the detector's parameters; IAlgorithm_sptr spCalcDetPar = this->createChildAlgorithm("FindDetectorsPar", 0, 1, true, 1); spCalcDetPar->initialize(); spCalcDetPar->setPropertyValue("InputWorkspace", inputWorkspace->getName()); // calculate linear rather then angular detector's sizes; spCalcDetPar->setPropertyValue("ReturnLinearRanges", "1"); // in test mode, request the ChildAlgortithm 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. outPAR_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. outPAR_file << std::fixed << std::setprecision(3); outPAR_file.width(10); outPAR_file <<secondary_flightpath[i]; outPAR_file.width(10); outPAR_file<< polar[i]; outPAR_file.width(10); outPAR_file << (-azimuthal[i]); outPAR_file.width(10); outPAR_file << polar_width[i]; outPAR_file.width(10); outPAR_file << azimuthal_width[i]; outPAR_file.width(10); outPAR_file << det_ID[i] << std::endl; } // Close the file outPAR_file.close(); }
/** * 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 = createSubAlgorithm("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); }
/** 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 = createSubAlgorithm("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 = createSubAlgorithm("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 = createSubAlgorithm("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 ); } }
/** 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 = createSubAlgorithm("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 = createSubAlgorithm("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 = createSubAlgorithm("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 = createSubAlgorithm("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]; } }
/** * Create histogram workspace * @returns Created workspace */ MatrixWorkspace_sptr LoadFITS::initAndPopulateHistogramWorkspace() { MantidVecPtr x; x.access().resize(m_allHeaderInfo.size() + 1); // Init time bins double binCount = 0; for(size_t i=0;i<m_allHeaderInfo.size() + 1; ++i) { x.access()[i] = binCount; if(i != m_allHeaderInfo.size()) binCount += m_allHeaderInfo[i].timeBin; } size_t spectraCount = 0; if(m_allHeaderInfo[0].numberOfAxis > 0) spectraCount += m_allHeaderInfo[0].axisPixelLengths[0]; // Presumably 2 axis, but futureproofing. for(int i=1;i<m_allHeaderInfo[0].numberOfAxis;++i) { spectraCount *= m_allHeaderInfo[0].axisPixelLengths[i]; } MatrixWorkspace_sptr retVal(new DataObjects::Workspace2D); retVal->initialize(spectraCount, m_allHeaderInfo.size()+1, m_allHeaderInfo.size()); IAlgorithm_sptr loadInst = createChildAlgorithm("LoadInstrument"); try { std::string directoryName = Kernel::ConfigService::Instance().getInstrumentDirectory(); directoryName = directoryName + "/IMAT_Definition.xml"; loadInst->setPropertyValue("Filename", directoryName); loadInst->setProperty<MatrixWorkspace_sptr>("Workspace", retVal); loadInst->execute(); } catch (std::exception & ex) { g_log.information("Cannot load the instrument definition. " + string(ex.what()) ); } int bitsPerPixel = m_allHeaderInfo[0].bitsPerPixel; // assumes all files have the same, which they should. vector<vector<double> > yVals(spectraCount, std::vector<double>(m_binChunkSize)); vector<vector<double> > eVals(spectraCount, std::vector<double>(m_binChunkSize)); // allocate memory to contain the data section of the file: void * bufferAny = NULL; bufferAny = malloc ((bitsPerPixel/8)*spectraCount); if (bufferAny == NULL) { throw std::runtime_error("FITS loader couldn't allocate enough memory to run. Try a smaller chunk size."); } size_t steps = static_cast<size_t>(ceil(m_allHeaderInfo.size()/m_binChunkSize)); Progress prog(this,0.0,1.0,steps); // Load a chunk of files at a time into workspace try { for(size_t i=0; i<m_allHeaderInfo.size(); i+=m_binChunkSize) { loadChunkOfBinsFromFile(retVal, yVals, eVals, bufferAny, x, spectraCount, bitsPerPixel, i); prog.report(name()); } } catch(...) { // Exceptions should be handled internally, but catch here to free any memory. Belt and braces. free(bufferAny); g_log.error("FITS Loader unable to correctly parse files."); throw std::runtime_error("FITS loader unable to correctly parse files."); } // Memory no longer needed free (bufferAny); retVal->mutableRun().addProperty("Filename", m_allHeaderInfo[0].filePath); // Set the Unit of the X Axis try { retVal->getAxis(0)->unit() = UnitFactory::Instance().create("TOF"); } catch ( Exception::NotFoundError & ) { retVal->getAxis(0)->unit() = UnitFactory::Instance().create("Label"); Unit_sptr unit = retVal->getAxis(0)->unit(); boost::shared_ptr<Units::Label> label = boost::dynamic_pointer_cast<Units::Label>(unit); label->setLabel("TOF", "TOF"); } retVal->setYUnit("Counts"); retVal->setTitle("Test Workspace"); return retVal; }
void SANSSensitivityCorrection::exec() { // Output log m_output_message = ""; Progress progress(this, 0.0, 1.0, 10); // Reduction property manager const std::string reductionManagerName = getProperty("ReductionProperties"); boost::shared_ptr<PropertyManager> reductionManager; if (PropertyManagerDataService::Instance().doesExist(reductionManagerName)) { reductionManager = PropertyManagerDataService::Instance().retrieve(reductionManagerName); } else { reductionManager = boost::make_shared<PropertyManager>(); PropertyManagerDataService::Instance().addOrReplace(reductionManagerName, reductionManager); } if (!reductionManager->existsProperty("SensitivityAlgorithm")) { auto algProp = make_unique<AlgorithmProperty>("SensitivityAlgorithm"); algProp->setValue(toString()); reductionManager->declareProperty(std::move(algProp)); } progress.report("Loading sensitivity file"); const std::string fileName = getPropertyValue("Filename"); // Look for an entry for the dark current in the reduction table Poco::Path path(fileName); const std::string entryName = "Sensitivity" + path.getBaseName(); MatrixWorkspace_sptr floodWS; std::string floodWSName = "__sensitivity_" + path.getBaseName(); if (reductionManager->existsProperty(entryName)) { std::string wsName = reductionManager->getPropertyValue(entryName); floodWS = boost::dynamic_pointer_cast<MatrixWorkspace>( AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(wsName)); m_output_message += " |Using " + wsName + "\n"; g_log.debug() << "SANSSensitivityCorrection :: Using sensitivity workspace: " << wsName << "\n"; } else { // Load the flood field if we don't have it already // First, try to determine whether we need to load data or a sensitivity // workspace... if (!floodWS && fileCheck(fileName)) { g_log.debug() << "SANSSensitivityCorrection :: Loading sensitivity file: " << fileName << "\n"; IAlgorithm_sptr loadAlg = createChildAlgorithm("Load", 0.1, 0.3); loadAlg->setProperty("Filename", fileName); loadAlg->executeAsChildAlg(); Workspace_sptr floodWS_ws = loadAlg->getProperty("OutputWorkspace"); floodWS = boost::dynamic_pointer_cast<MatrixWorkspace>(floodWS_ws); // Check that it's really a sensitivity file if (!floodWS->run().hasProperty("is_sensitivity")) { // Reset pointer floodWS.reset(); g_log.error() << "A processed Mantid workspace was loaded but it " "wasn't a sensitivity file!\n"; } } // ... if we don't, just load the data and process it if (!floodWS) { // Read in default beam center double center_x = getProperty("BeamCenterX"); double center_y = getProperty("BeamCenterY"); if (isEmpty(center_x) || isEmpty(center_y)) { if (reductionManager->existsProperty("LatestBeamCenterX") && reductionManager->existsProperty("LatestBeamCenterY")) { center_x = reductionManager->getProperty("LatestBeamCenterX"); center_y = reductionManager->getProperty("LatestBeamCenterY"); m_output_message += " |Setting beam center to [" + Poco::NumberFormatter::format(center_x, 1) + ", " + Poco::NumberFormatter::format(center_y, 1) + "]\n"; } else m_output_message += " |No beam center provided: skipping!\n"; } const std::string rawFloodWSName = "__flood_data_" + path.getBaseName(); MatrixWorkspace_sptr rawFloodWS; if (!reductionManager->existsProperty("LoadAlgorithm")) { IAlgorithm_sptr loadAlg = createChildAlgorithm("Load", 0.1, 0.3); loadAlg->setProperty("Filename", fileName); if (!isEmpty(center_x) && loadAlg->existsProperty("BeamCenterX")) loadAlg->setProperty("BeamCenterX", center_x); if (!isEmpty(center_y) && loadAlg->existsProperty("BeamCenterY")) loadAlg->setProperty("BeamCenterY", center_y); loadAlg->setPropertyValue("OutputWorkspace", rawFloodWSName); loadAlg->executeAsChildAlg(); Workspace_sptr tmpWS = loadAlg->getProperty("OutputWorkspace"); rawFloodWS = boost::dynamic_pointer_cast<MatrixWorkspace>(tmpWS); m_output_message += " | Loaded " + fileName + " (Load algorithm)\n"; } else { // Get load algorithm as a string so that we can create a completely // new proxy and ensure that we don't overwrite existing properties IAlgorithm_sptr loadAlg0 = reductionManager->getProperty("LoadAlgorithm"); const std::string loadString = loadAlg0->toString(); IAlgorithm_sptr loadAlg = Algorithm::fromString(loadString); loadAlg->setChild(true); loadAlg->setProperty("Filename", fileName); loadAlg->setPropertyValue("OutputWorkspace", rawFloodWSName); if (!isEmpty(center_x) && loadAlg->existsProperty("BeamCenterX")) loadAlg->setProperty("BeamCenterX", center_x); if (!isEmpty(center_y) && loadAlg->existsProperty("BeamCenterY")) loadAlg->setProperty("BeamCenterY", center_y); loadAlg->execute(); rawFloodWS = loadAlg->getProperty("OutputWorkspace"); m_output_message += " |Loaded " + fileName + "\n"; if (loadAlg->existsProperty("OutputMessage")) { std::string msg = loadAlg->getPropertyValue("OutputMessage"); m_output_message += " |" + Poco::replace(msg, "\n", "\n |") + "\n"; } } // Check whether we just loaded a flood field data set, or the actual // sensitivity if (!rawFloodWS->run().hasProperty("is_sensitivity")) { const std::string darkCurrentFile = getPropertyValue("DarkCurrentFile"); // Look for a dark current subtraction algorithm std::string dark_result; if (reductionManager->existsProperty("DarkCurrentAlgorithm")) { IAlgorithm_sptr darkAlg = reductionManager->getProperty("DarkCurrentAlgorithm"); darkAlg->setChild(true); darkAlg->setProperty("InputWorkspace", rawFloodWS); darkAlg->setProperty("OutputWorkspace", rawFloodWS); // Execute as-is if we use the sample dark current, otherwise check // whether a dark current file was provided. // Otherwise do nothing if (getProperty("UseSampleDC")) { darkAlg->execute(); if (darkAlg->existsProperty("OutputMessage")) dark_result = darkAlg->getPropertyValue("OutputMessage"); } else if (!darkCurrentFile.empty()) { darkAlg->setProperty("Filename", darkCurrentFile); darkAlg->setProperty("PersistentCorrection", false); darkAlg->execute(); if (darkAlg->existsProperty("OutputMessage")) dark_result = darkAlg->getPropertyValue("OutputMessage"); else dark_result = " Dark current subtracted\n"; } } else if (!darkCurrentFile.empty()) { // We need to subtract the dark current for the flood field but no // dark // current subtraction was set for the sample! Use the default dark // current algorithm if we can find it. if (reductionManager->existsProperty("DefaultDarkCurrentAlgorithm")) { IAlgorithm_sptr darkAlg = reductionManager->getProperty("DefaultDarkCurrentAlgorithm"); darkAlg->setChild(true); darkAlg->setProperty("InputWorkspace", rawFloodWS); darkAlg->setProperty("OutputWorkspace", rawFloodWS); darkAlg->setProperty("Filename", darkCurrentFile); darkAlg->setProperty("PersistentCorrection", false); darkAlg->execute(); if (darkAlg->existsProperty("OutputMessage")) dark_result = darkAlg->getPropertyValue("OutputMessage"); } else { // We are running out of options g_log.error() << "No dark current algorithm provided to load [" << getPropertyValue("DarkCurrentFile") << "]: skipped!\n"; dark_result = " No dark current algorithm provided: skipped\n"; } } m_output_message += " |" + Poco::replace(dark_result, "\n", "\n |") + "\n"; // Look for solid angle correction algorithm if (reductionManager->existsProperty("SANSSolidAngleCorrection")) { IAlgorithm_sptr solidAlg = reductionManager->getProperty("SANSSolidAngleCorrection"); solidAlg->setChild(true); solidAlg->setProperty("InputWorkspace", rawFloodWS); solidAlg->setProperty("OutputWorkspace", rawFloodWS); solidAlg->execute(); std::string msg = "Solid angle correction applied\n"; if (solidAlg->existsProperty("OutputMessage")) msg = solidAlg->getPropertyValue("OutputMessage"); m_output_message += " |" + Poco::replace(msg, "\n", "\n |") + "\n"; } // Apply transmission correction as needed double floodTransmissionValue = getProperty("FloodTransmissionValue"); double floodTransmissionError = getProperty("FloodTransmissionError"); if (!isEmpty(floodTransmissionValue)) { g_log.debug() << "SANSSensitivityCorrection :: Applying transmission " "to flood field\n"; IAlgorithm_sptr transAlg = createChildAlgorithm("ApplyTransmissionCorrection"); transAlg->setProperty("InputWorkspace", rawFloodWS); transAlg->setProperty("OutputWorkspace", rawFloodWS); transAlg->setProperty("TransmissionValue", floodTransmissionValue); transAlg->setProperty("TransmissionError", floodTransmissionError); transAlg->setProperty("ThetaDependent", true); transAlg->execute(); rawFloodWS = transAlg->getProperty("OutputWorkspace"); m_output_message += " |Applied transmission to flood field\n"; } // Calculate detector sensitivity IAlgorithm_sptr effAlg = createChildAlgorithm("CalculateEfficiency"); effAlg->setProperty("InputWorkspace", rawFloodWS); const double minEff = getProperty("MinEfficiency"); const double maxEff = getProperty("MaxEfficiency"); const std::string maskFullComponent = getPropertyValue("MaskedFullComponent"); const std::string maskEdges = getPropertyValue("MaskedEdges"); const std::string maskComponent = getPropertyValue("MaskedComponent"); effAlg->setProperty("MinEfficiency", minEff); effAlg->setProperty("MaxEfficiency", maxEff); effAlg->setProperty("MaskedFullComponent", maskFullComponent); effAlg->setProperty("MaskedEdges", maskEdges); effAlg->setProperty("MaskedComponent", maskComponent); effAlg->execute(); floodWS = effAlg->getProperty("OutputWorkspace"); } else { floodWS = rawFloodWS; } // Patch as needed if (reductionManager->existsProperty("SensitivityPatchAlgorithm")) { IAlgorithm_sptr patchAlg = reductionManager->getProperty("SensitivityPatchAlgorithm"); patchAlg->setChild(true); patchAlg->setProperty("Workspace", floodWS); patchAlg->execute(); m_output_message += " |Sensitivity patch applied\n"; } floodWS->mutableRun().addProperty("is_sensitivity", 1, "", true); } std::string floodWSOutputName = getPropertyValue("OutputSensitivityWorkspace"); if (floodWSOutputName.empty()) { setPropertyValue("OutputSensitivityWorkspace", floodWSName); AnalysisDataService::Instance().addOrReplace(floodWSName, floodWS); reductionManager->declareProperty( Kernel::make_unique<WorkspaceProperty<>>(entryName, floodWSName, Direction::InOut)); reductionManager->setPropertyValue(entryName, floodWSName); reductionManager->setProperty(entryName, floodWS); } setProperty("OutputSensitivityWorkspace", floodWS); } progress.report(3, "Loaded flood field"); // Check whether we need to apply the correction to a workspace MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); if (inputWS) { // Divide sample data by detector efficiency IAlgorithm_sptr divideAlg = createChildAlgorithm("Divide", 0.6, 0.7); divideAlg->setProperty("LHSWorkspace", inputWS); divideAlg->setProperty("RHSWorkspace", floodWS); divideAlg->executeAsChildAlg(); MatrixWorkspace_sptr outputWS = divideAlg->getProperty("OutputWorkspace"); // Copy over the efficiency's masked pixels to the reduced workspace IAlgorithm_sptr maskAlg = createChildAlgorithm("MaskDetectors", 0.75, 0.85); maskAlg->setProperty("Workspace", outputWS); maskAlg->setProperty("MaskedWorkspace", floodWS); maskAlg->executeAsChildAlg(); setProperty("OutputWorkspace", outputWS); } setProperty("OutputMessage", "Sensitivity correction computed\n" + m_output_message); progress.report("Performed sensitivity correction"); }