//---------------------------------------------------------------------------------------------- /// @copydoc Mantid::API::Algorithm::init() void LoadPreNexus::init() { // runfile to read in declareProperty(new FileProperty(RUNINFO_PARAM, "", FileProperty::Load, "_runinfo.xml"), "The name of the runinfo file to read, including its full or relative path."); // copied (by hand) from LoadEventPreNexus2 declareProperty(new FileProperty(MAP_PARAM, "", FileProperty::OptionalLoad, ".dat"), "File containing the pixel mapping (DAS pixels to pixel IDs) file (typically INSTRUMENT_TS_YYYY_MM_DD.dat). The filename will be found automatically if not specified."); auto mustBePositive = boost::make_shared<BoundedValidator<int> >(); mustBePositive->setLower(1); declareProperty("ChunkNumber", EMPTY_INT(), mustBePositive, "If loading the file by sections ('chunks'), this is the section number of this execution of the algorithm."); declareProperty("TotalChunks", EMPTY_INT(), mustBePositive, "If loading the file by sections ('chunks'), this is the total number of sections."); // TotalChunks is only meaningful if ChunkNumber is set // Would be nice to be able to restrict ChunkNumber to be <= TotalChunks at validation setPropertySettings("TotalChunks", new VisibleWhenProperty("ChunkNumber", IS_NOT_DEFAULT)); std::vector<std::string> propOptions; propOptions.push_back("Auto"); propOptions.push_back("Serial"); propOptions.push_back("Parallel"); declareProperty("UseParallelProcessing", "Auto", boost::make_shared<StringListValidator>(propOptions), "Use multiple cores for loading the data?\n" " Auto: Use serial loading for small data sets, parallel for large data sets.\n" " Serial: Use a single core.\n" " Parallel: Use all available cores."); declareProperty(new PropertyWithValue<bool>("LoadMonitors", true, Direction::Input), "Load the monitors from the file."); declareProperty(new WorkspaceProperty<>("OutputWorkspace","",Direction::Output), "An output workspace."); }
size_t MaskPeaksWorkspace::getWkspIndex(const detid2index_map &pixel_to_wi, Geometry::IComponent_const_sptr comp, const int x, const int y) { Geometry::RectangularDetector_const_sptr det = boost::dynamic_pointer_cast<const Geometry::RectangularDetector>(comp); if (det) { if (x >= det->xpixels() || x < 0 || y >= det->ypixels() || y < 0) return EMPTY_INT(); if ((x >= det->xpixels()) || (x < 0) // this check is unnecessary as callers are doing it too || (y >= det->ypixels()) || (y < 0)) // but just to make debugging easier { std::stringstream msg; msg << "Failed to find workspace index for x=" << x << " y=" << y << "(max x=" << det->xpixels() << ", max y=" << det->ypixels() << ")"; throw std::runtime_error(msg.str()); } int pixelID = det->getAtXY(x, y)->getID(); // Find the corresponding workspace index, if any auto wiEntry = pixel_to_wi.find(pixelID); if (wiEntry == pixel_to_wi.end()) { std::stringstream msg; msg << "Failed to find workspace index for x=" << x << " y=" << y; throw std::runtime_error(msg.str()); } return wiEntry->second; } else { std::vector<Geometry::IComponent_const_sptr> children; boost::shared_ptr<const Geometry::ICompAssembly> asmb = boost::dynamic_pointer_cast<const Geometry::ICompAssembly>(comp); asmb->getChildren(children, false); boost::shared_ptr<const Geometry::ICompAssembly> asmb2 = boost::dynamic_pointer_cast<const Geometry::ICompAssembly>(children[0]); std::vector<Geometry::IComponent_const_sptr> grandchildren; asmb2->getChildren(grandchildren, false); int NROWS = static_cast<int>(grandchildren.size()); int NCOLS = static_cast<int>(children.size()); // Wish pixels and tubes start at 1 not 0 if (x - 1 >= NCOLS || x - 1 < 0 || y - 1 >= NROWS || y - 1 < 0) return EMPTY_INT(); std::string bankName = comp->getName(); detid2index_map::const_iterator it = pixel_to_wi.find(findPixelID(bankName, x, y)); if (it == pixel_to_wi.end()) return EMPTY_INT(); return (it->second); } }
//-------------------------------------------------------------------------- // Private methods //-------------------------------------------------------------------------- /// Initialisation method. void LoadAscii::init() { std::vector<std::string> exts; exts.push_back(".dat"); exts.push_back(".txt"); exts.push_back(".csv"); exts.push_back(""); declareProperty(new FileProperty("Filename", "", FileProperty::Load, exts), "A comma separated Ascii file"); declareProperty(new WorkspaceProperty<Workspace>("OutputWorkspace", "",Direction::Output), "The name of the workspace that will be created."); std::string spacers[5][2] = { {"CSV", ","}, {"Tab", "\t"}, {"Space", " "}, {"Colon", ":"}, {"SemiColon", ";"} }; // For the ListValidator std::vector<std::string> sepOptions; for( size_t i = 0; i < 5; ++i ) { std::string option = spacers[i][0]; m_separatorIndex.insert(std::pair<std::string,std::string>(option, spacers[i][1])); sepOptions.push_back(option); } declareProperty("Separator", "CSV", new ListValidator(sepOptions), "The column separator character (default: CSV)"); std::vector<std::string> units = UnitFactory::Instance().getKeys(); units.insert(units.begin(),"Dimensionless"); declareProperty("Unit","Energy",new Kernel::ListValidator(units), "The unit to assign to the X axis (default: Energy)"); BoundedValidator<int> * mustBePosInt = new BoundedValidator<int>(); mustBePosInt->setLower(0); declareProperty("SkipNumLines", EMPTY_INT(), mustBePosInt, "If set, this number of lines from the top of the file are ignored."); }
/** Returns whether algorithm parameter was left as default EMPTY_INT,LONG,DBL * @returns True if param was unset and value = EMPTY_XXX, else false */ bool PropertyHistory::isEmptyDefault() const { bool emptyDefault = false; // Static lists to be initialised on first call static std::vector<std::string> numberTypes, emptyValues; // Type strings corresponding to numbers if (numberTypes.empty()) { numberTypes.push_back(getUnmangledTypeName(typeid(int))); numberTypes.push_back(getUnmangledTypeName(typeid(int64_t))); numberTypes.push_back(getUnmangledTypeName(typeid(double))); } // Empty values if (emptyValues.empty()) { emptyValues.push_back(std::to_string(EMPTY_INT())); emptyValues.push_back(boost::lexical_cast<std::string>(EMPTY_DBL())); emptyValues.push_back(std::to_string(EMPTY_LONG())); } // If default, input, number type and matches empty value then return true if (m_isDefault && m_direction != Direction::Output) { if (std::find(numberTypes.begin(), numberTypes.end(), m_type) != numberTypes.end()) { if (std::find(emptyValues.begin(), emptyValues.end(), m_value) != emptyValues.end()) { emptyDefault = true; } } } return emptyDefault; }
void CheckWorkspacesMatch::init() { declareProperty( new WorkspaceProperty<Workspace>("Workspace1", "", Direction::Input), "The name of the first input workspace."); declareProperty( new WorkspaceProperty<Workspace>("Workspace2", "", Direction::Input), "The name of the second input workspace."); declareProperty( "Tolerance", 0.0, "The maximum amount by which values may differ between the workspaces."); declareProperty("CheckType", true, "Whether to check that the data types " "(Workspace2D vs EventWorkspace) match."); declareProperty("CheckAxes", true, "Whether to check that the axes match."); declareProperty("CheckSpectraMap", true, "Whether to check that the spectra-detector maps match. "); declareProperty("CheckInstrument", true, "Whether to check that the instruments match. "); declareProperty("CheckMasking", true, "Whether to check that the bin masking matches. "); declareProperty( "CheckSample", false, "Whether to check that the sample (e.g. logs)."); // Have this one false // by default - the logs // are brittle declareProperty("Result", "", Direction::Output); declareProperty( "ToleranceRelErr", false, "Treat tolerance as relative error rather then the absolute error.\n" "This is only applicable to Matrix workspaces."); declareProperty("CheckAllData", false, "Usually checking data ends when first mismatch occurs. This " "forces algorithm to check all data and print mismatch to " "the debug log.\n" "Very often such logs are huge so making it true should be " "the last option."); // Have this one false by default - it can be a lot of printing. declareProperty("NumberMismatchedSpectraToPrint", 1, "Number of mismatched spectra from lowest to be listed. "); declareProperty("DetailedPrintIndex", EMPTY_INT(), "Mismatched spectra that will be printed out in details. "); }
//-------------------------------------------------------------------------- // Private methods //-------------------------------------------------------------------------- /// Initialisation method. void LoadAscii::init() { const std::vector<std::string> extensions{".dat", ".txt", ".csv", ""}; declareProperty(Kernel::make_unique<FileProperty>( "Filename", "", FileProperty::Load, extensions), "The name of the text file to read, including its full or " "relative path. The file extension must be .txt, .dat, or " ".csv"); declareProperty(Kernel::make_unique<WorkspaceProperty<Workspace>>( "OutputWorkspace", "", Direction::Output), "The name of the workspace that will be created, filled with " "the read-in data and stored in the [[Analysis Data " "Service]]."); std::string spacers[6][6] = {{"Automatic", ",\t:; "}, {"CSV", ","}, {"Tab", "\t"}, {"Space", " "}, {"Colon", ":"}, {"SemiColon", ";"}}; // For the ListValidator std::vector<std::string> sepOptions; for (size_t i = 0; i < 5; ++i) { std::string option = spacers[i][0]; m_separatorIndex.insert( std::pair<std::string, std::string>(option, spacers[i][1])); sepOptions.push_back(option); } declareProperty( "Separator", "Automatic", boost::make_shared<StringListValidator>(sepOptions), "The separator between data columns in the data file. The possible " "values are \"CSV\", \"Tab\", " "\"Space\", \"SemiColon\", or \"Colon\" (default: Automatic selection)."); std::vector<std::string> units = UnitFactory::Instance().getKeys(); units.insert(units.begin(), "Dimensionless"); declareProperty("Unit", "Energy", boost::make_shared<StringListValidator>(units), "The unit to assign to the X axis (anything known to the " "[[Unit Factory]] or \"Dimensionless\")"); auto mustBePosInt = boost::make_shared<BoundedValidator<int>>(); mustBePosInt->setLower(0); declareProperty( "SkipNumLines", EMPTY_INT(), mustBePosInt, "If given, skip this number of lines at the start of the file."); }
/** * Perform validation of input properties: * - input workspace must not be empty * - X values must be evenly spaced (unless accepting rounding errors) * - Real and Imaginary spectra must be in range of input workspace * - If complex, real and imaginary workspaces must be the same size * @returns :: map of property names to errors (empty map if no errors) */ std::map<std::string, std::string> FFT::validateInputs() { std::map<std::string, std::string> errors; MatrixWorkspace_const_sptr inWS = getProperty("InputWorkspace"); if (inWS) { const int iReal = getProperty("Real"); const int iImag = getProperty("Imaginary"); const MantidVec &X = inWS->readX(iReal); // check that the workspace isn't empty if (X.size() < 2) { errors["InputWorkspace"] = "Input workspace must have at least two values"; } else { // Check that the x values are evenly spaced // If accepting rounding errors, just give a warning if bins are // different. if (areBinWidthsUneven(X)) { errors["InputWorkspace"] = "X axis must be linear (all bins have same width)"; } } // check real, imaginary spectrum numbers and workspace sizes int nHist = static_cast<int>(inWS->getNumberHistograms()); if (iReal >= nHist) { errors["Real"] = "Real out of range"; } if (iImag != EMPTY_INT()) { MatrixWorkspace_const_sptr inImagWS = getProperty("InputImagWorkspace"); if (inImagWS) { if (inWS->blocksize() != inImagWS->blocksize()) { errors["Imaginary"] = "Real and Imaginary sizes do not match"; } nHist = static_cast<int>(inImagWS->getNumberHistograms()); } if (iImag >= nHist) { errors["Imaginary"] = "Imaginary out of range"; } } } return errors; }
/** * @brief Learn the Q values from the workspace, if possible, and update * attribute Q accordingly. * @param workspace Matrix workspace * @param wi selected spectrum to initialize attributes * @param startX unused * @param endX unused */ void FunctionQDepends::setMatrixWorkspace( boost::shared_ptr<const Mantid::API::MatrixWorkspace> workspace, size_t wi, double startX, double endX) { UNUSED_ARG(startX); UNUSED_ARG(endX); // reset attributes if new workspace is passed if (!m_vQ.empty()) { Mantid::API::IFunction::setAttribute("WorkspaceIndex", Attr(EMPTY_INT())); Mantid::API::IFunction::setAttribute("Q", Attr(EMPTY_DBL())); } // Obtain Q values from the passed workspace, if possible. m_vQ will be // cleared if unsuccessful. if (workspace) { m_vQ = this->extractQValues(*workspace); } if (!m_vQ.empty()) { this->setAttribute("WorkspaceIndex", Attr(static_cast<int>(wi))); } }
/** * Returns a workspace for the second period as specified using SecondPeriod * property. * @param group :: Loaded group of workspaces to use * @return Workspace for the period */ MatrixWorkspace_sptr MuonLoad::getSecondPeriodWS(WorkspaceGroup_sptr group) { int secondPeriod = getProperty("SecondPeriod"); MatrixWorkspace_sptr resultWS; if (secondPeriod != EMPTY_INT()) { if (secondPeriod < 0 || secondPeriod >= static_cast<int>(group->size())) throw std::invalid_argument( "Workspace doesn't contain specified second period"); resultWS = boost::dynamic_pointer_cast<MatrixWorkspace>( group->getItem(secondPeriod)); if (!resultWS) throw std::invalid_argument( "Second period workspace is not a MatrixWorkspace"); } return resultWS; }
/** Loads and checks the values passed to the algorithm * * @throw invalid_argument if there is an incompatible property value so the algorithm can't continue */ void MedianDetectorTest::retrieveProperties() { m_inputWS = getProperty("InputWorkspace"); int maxSpecIndex = static_cast<int>(m_inputWS->getNumberHistograms()) - 1; m_parents = getProperty("LevelsUp"); m_minSpec = getProperty("StartWorkspaceIndex"); if ( (m_minSpec < 0) || (m_minSpec > maxSpecIndex) ) { g_log.warning("StartSpectrum out of range, changed to 0"); m_minSpec = 0; } m_maxSpec = getProperty("EndWorkspaceIndex"); if (m_maxSpec == EMPTY_INT() ) m_maxSpec = maxSpecIndex; if ( (m_maxSpec < 0) || (m_maxSpec > maxSpecIndex ) ) { g_log.warning("EndSpectrum out of range, changed to max spectrum number"); m_maxSpec = maxSpecIndex; } if ( (m_maxSpec < m_minSpec) ) { g_log.warning("EndSpectrum can not be less than the StartSpectrum, changed to max spectrum number"); m_maxSpec = maxSpecIndex; } m_loFrac = getProperty("LowThreshold"); m_hiFrac = getProperty("HighThreshold"); if ( m_loFrac > m_hiFrac ) { throw std::invalid_argument("The threshold for reading high must be greater than the low threshold"); } // Integration Range m_rangeLower = getProperty("RangeLower"); m_rangeUpper = getProperty("RangeUpper"); //Solid angle correction flag m_solidAngle = getProperty("CorrectForSolidAngle"); }
/** * Check the validity of the optional properties of the algorithm and identify if * partial data should be loaded. * @param SpectraExcluded :: set of spectra ID-s to exclude from spectra list to * load */ void LoadISISNexus2::checkOptionalProperties( const std::map<int64_t, std::string> &SpectraExcluded) { // optional properties specify that only some spectra have to be loaded bool range_supplied(false); if (!SpectraExcluded.empty()) { range_supplied = true; m_load_selected_spectra = true; } int64_t spec_min(0); int64_t spec_max(EMPTY_INT()); // spec_min = getProperty("SpectrumMin"); spec_max = getProperty("SpectrumMax"); // default spectra ID-s would not work if spectraID_min!=1 if (m_loadBlockInfo.spectraID_min != 1) { range_supplied = true; m_load_selected_spectra = true; } if (spec_min == 0) spec_min = m_loadBlockInfo.spectraID_min; else { range_supplied = true; m_load_selected_spectra = true; } if (spec_max == EMPTY_INT()) spec_max = m_loadBlockInfo.spectraID_max; else { range_supplied = true; m_load_selected_spectra = true; } // Sanity check for min/max if (spec_min > spec_max) { throw std::invalid_argument("Inconsistent range properties. SpectrumMin is " "larger than SpectrumMax."); } if (spec_max > m_loadBlockInfo.spectraID_max) { std::string err = "Inconsistent range property. SpectrumMax is larger than number of " "spectra: " + boost::lexical_cast<std::string>(m_loadBlockInfo.spectraID_max); throw std::invalid_argument(err); } // Check the entry number m_entrynumber = getProperty("EntryNumber"); if (static_cast<int>(m_entrynumber) > m_loadBlockInfo.numberOfPeriods || m_entrynumber < 0) { std::string err = "Invalid entry number entered. File contains " + boost::lexical_cast<std::string>(m_loadBlockInfo.numberOfPeriods) + " period. "; throw std::invalid_argument(err); } if (m_loadBlockInfo.numberOfPeriods == 1) { m_entrynumber = 1; } // Check the list property std::vector<int64_t> spec_list = getProperty("SpectrumList"); if (!spec_list.empty()) { m_load_selected_spectra = true; // Sort the list so that we can check it's range std::sort(spec_list.begin(), spec_list.end()); if (spec_list.back() > m_loadBlockInfo.spectraID_max) { std::string err = "A spectra number in the spectra list exceeds maximal spectra ID: " + boost::lexical_cast<std::string>(m_loadBlockInfo.spectraID_max) + " in the file "; throw std::invalid_argument(err); } if (spec_list.front() < m_loadBlockInfo.spectraID_min) { std::string err = "A spectra number in the spectra list smaller then minimal spectra " "ID: " + boost::lexical_cast<std::string>(m_loadBlockInfo.spectraID_min) + " in the file"; throw std::invalid_argument(err); } range_check in_range(spec_min, spec_max); if (range_supplied) { spec_list.erase(remove_if(spec_list.begin(), spec_list.end(), in_range), spec_list.end()); // combine spectra numbers from ranges and the list if (spec_list.size() > 0) { for (int64_t i = spec_min; i < spec_max + 1; i++) { specid_t spec_num = static_cast<specid_t>(i); // remove excluded spectra now rather then inserting it here and // removing later if (SpectraExcluded.find(spec_num) == SpectraExcluded.end()) spec_list.push_back(spec_num); } // Sort the list so that lower spectra indexes correspond to smaller // spectra ID-s std::sort(spec_list.begin(), spec_list.end()); // supplied range converted into the list, so no more supplied range range_supplied = false; } } } // if (m_load_selected_spectra) { buildSpectraInd2SpectraNumMap(range_supplied, spec_min, spec_max, spec_list, SpectraExcluded); } else // may be just range supplied and the range have to start from 1 to use // defaults in spectra num to spectra ID map! { m_loadBlockInfo.spectraID_max = spec_max; m_loadBlockInfo.numberOfSpectra = m_loadBlockInfo.spectraID_max - m_loadBlockInfo.spectraID_min + 1; } }
/** Initialize the algorithm, i.e, declare properties */ void LoadEventPreNexus2::init() { // which files to use vector<string> eventExts(EVENT_EXTS, EVENT_EXTS + NUM_EXT); declareProperty( Kernel::make_unique<FileProperty>(EVENT_PARAM, "", FileProperty::Load, eventExts), "The name of the neutron event file to read, including its full or " "relative path. In most cases, the file typically ends in " "neutron_event.dat (N.B. case sensitive if running on Linux)."); vector<string> pulseExts(PULSE_EXTS, PULSE_EXTS + NUM_EXT); declareProperty(Kernel::make_unique<FileProperty>( PULSEID_PARAM, "", FileProperty::OptionalLoad, pulseExts), "File containing the accelerator pulse information; the " "filename will be found automatically if not specified."); declareProperty( Kernel::make_unique<FileProperty>(MAP_PARAM, "", FileProperty::OptionalLoad, ".dat"), "File containing the pixel mapping (DAS pixels to pixel IDs) file " "(typically INSTRUMENT_TS_YYYY_MM_DD.dat). The filename will be found " "automatically if not specified."); // which pixels to load declareProperty(Kernel::make_unique<ArrayProperty<int64_t>>(PID_PARAM), "A list of individual spectra (pixel IDs) to read, specified " "as e.g. 10:20. Only used if set."); auto mustBePositive = boost::make_shared<BoundedValidator<int>>(); mustBePositive->setLower(1); declareProperty("ChunkNumber", EMPTY_INT(), mustBePositive, "If loading the file by sections ('chunks'), this is the " "section number of this execution of the algorithm."); declareProperty("TotalChunks", EMPTY_INT(), mustBePositive, "If loading the file by sections ('chunks'), this is the " "total number of sections."); // TotalChunks is only meaningful if ChunkNumber is set // Would be nice to be able to restrict ChunkNumber to be <= TotalChunks at // validation setPropertySettings("TotalChunks", make_unique<VisibleWhenProperty>( "ChunkNumber", IS_NOT_DEFAULT)); std::vector<std::string> propOptions{"Auto", "Serial", "Parallel"}; declareProperty("UseParallelProcessing", "Auto", boost::make_shared<StringListValidator>(propOptions), "Use multiple cores for loading the data?\n" " Auto: Use serial loading for small data sets, parallel " "for large data sets.\n" " Serial: Use a single core.\n" " Parallel: Use all available cores."); // the output workspace name declareProperty(Kernel::make_unique<WorkspaceProperty<IEventWorkspace>>( OUT_PARAM, "", Direction::Output), "The name of the workspace that will be created, filled " "with the read-in " "data and stored in the [[Analysis Data Service]]."); declareProperty(Kernel::make_unique<WorkspaceProperty<MatrixWorkspace>>( "EventNumberWorkspace", "", Direction::Output, PropertyMode::Optional), "Workspace with number of events per pulse"); // Some debugging options auto mustBeNonNegative = boost::make_shared<BoundedValidator<int>>(); mustBeNonNegative->setLower(0); declareProperty("DBOutputBlockNumber", EMPTY_INT(), mustBeNonNegative, "Index of the loading block for debugging output. "); declareProperty("DBNumberOutputEvents", 40, mustBePositive, "Number of output events for debugging purpose. Must be " "defined with DBOutputBlockNumber."); declareProperty("DBNumberOutputPulses", EMPTY_INT(), mustBePositive, "Number of output pulses for debugging purpose. "); std::string dbgrp = "Investigation Use"; setPropertyGroup("EventNumberWorkspace", dbgrp); setPropertyGroup("DBOutputBlockNumber", dbgrp); setPropertyGroup("DBNumberOutputEvents", dbgrp); setPropertyGroup("DBNumberOutputPulses", dbgrp); }
/** * @brief declare commonattributes Q and WorkspaceIndex. * Subclasses containing additional attributes should override this method by * declaring the additional * attributes and then calling the parent (this) method to declare Q and * WorkspaceIndex. */ void FunctionQDepends::declareAttributes() { this->declareAttribute("Q", Attr(EMPTY_DBL())); this->declareAttribute("WorkspaceIndex", Attr(EMPTY_INT())); }
void LoadBankFromDiskTask::run() { // These give the limits in each file as to which events we actually load // (when filtering by time). m_loadStart.resize(1, 0); m_loadSize.resize(1, 0); m_loadError = false; m_have_weight = m_loader.m_haveWeights; prog->report(entry_name + ": load from disk"); // arrays to load into std::unique_ptr<uint32_t[]> event_id; std::unique_ptr<float[]> event_time_of_flight; std::unique_ptr<float[]> event_weight; std::vector<uint64_t> event_index; // Open the file ::NeXus::File file(m_loader.alg->m_filename); try { // Navigate into the file file.openGroup(m_loader.alg->m_top_entry_name, "NXentry"); // Open the bankN_event group file.openGroup(entry_name, entry_type); // Load the event_index field. event_index = this->loadEventIndex(file); if (!m_loadError) { // Load and validate the pulse times this->loadPulseTimes(file); // The event_index should be the same length as the pulse times from DAS // logs. if (event_index.size() != thisBankPulseTimes->numPulses) m_loader.alg->getLogger().warning() << "Bank " << entry_name << " has a mismatch between the number of event_index entries " "and the number of pulse times in event_time_zero.\n"; // Open and validate event_id field. int64_t start_event = 0; int64_t stop_event = 0; this->prepareEventId(file, start_event, stop_event, event_index); // These are the arguments to getSlab() m_loadStart[0] = start_event; m_loadSize[0] = stop_event - start_event; if ((m_loadSize[0] > 0) && (m_loadStart[0] >= 0)) { // Load pixel IDs event_id = this->loadEventId(file); if (m_loader.alg->getCancel()) { m_loader.alg->getLogger().error() << "Loading bank " << entry_name << " is cancelled.\n"; m_loadError = true; // To allow cancelling the algorithm } // And TOF. if (!m_loadError) { event_time_of_flight = this->loadTof(file); if (m_have_weight) { event_weight = this->loadEventWeights(file); } } } // Size is at least 1 else { // Found a size that was 0 or less; stop processing m_loader.alg->getLogger().error() << "Loading bank " << entry_name << " is stopped due to either zero/negative loading size (" << m_loadStart[0] << ") or negative load start index (" << m_loadStart[0] << ")\n"; m_loadError = true; } } // no error } // try block catch (std::exception &e) { m_loader.alg->getLogger().error() << "Error while loading bank " << entry_name << ":\n"; m_loader.alg->getLogger().error() << e.what() << '\n'; m_loadError = true; } catch (...) { m_loader.alg->getLogger().error() << "Unspecified error while loading bank " << entry_name << '\n'; m_loadError = true; } // Close up the file even if errors occured. file.closeGroup(); file.close(); // Abort if anything failed if (m_loadError) { return; } const auto bank_size = m_max_id - m_min_id; const uint32_t minSpectraToLoad = static_cast<uint32_t>(m_loader.alg->m_specMin); const uint32_t maxSpectraToLoad = static_cast<uint32_t>(m_loader.alg->m_specMax); const uint32_t emptyInt = static_cast<uint32_t>(EMPTY_INT()); // check that if a range of spectra were requested that these fit within // this bank if (minSpectraToLoad != emptyInt && m_min_id < minSpectraToLoad) { if (minSpectraToLoad > m_max_id) { // the minimum spectra to load is more // than the max of this bank return; } // the min spectra to load is higher than the min for this bank m_min_id = minSpectraToLoad; } if (maxSpectraToLoad != emptyInt && m_max_id > maxSpectraToLoad) { if (maxSpectraToLoad < m_min_id) { // the maximum spectra to load is less than the minimum of this bank return; } // the max spectra to load is lower than the max for this bank m_max_id = maxSpectraToLoad; } if (m_min_id > m_max_id) { // the min is now larger than the max, this means the entire block of // spectra to load is outside this bank return; } // schedule the job to generate the event lists auto mid_id = m_max_id; if (m_loader.splitProcessing && m_max_id > (m_min_id + (bank_size / 4))) // only split if told to and the section to load is at least 1/4 the size // of the whole bank mid_id = (m_max_id + m_min_id) / 2; // No error? Launch a new task to process that data. size_t numEvents = static_cast<size_t>(m_loadSize[0]); size_t startAt = static_cast<size_t>(m_loadStart[0]); // convert things to shared_arrays to share between tasks boost::shared_array<uint32_t> event_id_shrd(event_id.release()); boost::shared_array<float> event_time_of_flight_shrd( event_time_of_flight.release()); boost::shared_array<float> event_weight_shrd(event_weight.release()); auto event_index_shrd = boost::make_shared<std::vector<uint64_t>>(std::move(event_index)); ProcessBankData *newTask1 = new ProcessBankData( m_loader, entry_name, prog, event_id_shrd, event_time_of_flight_shrd, numEvents, startAt, event_index_shrd, thisBankPulseTimes, m_have_weight, event_weight_shrd, m_min_id, mid_id); scheduler.push(newTask1); if (m_loader.splitProcessing && (mid_id < m_max_id)) { ProcessBankData *newTask2 = new ProcessBankData( m_loader, entry_name, prog, event_id_shrd, event_time_of_flight_shrd, numEvents, startAt, event_index_shrd, thisBankPulseTimes, m_have_weight, event_weight_shrd, (mid_id + 1), m_max_id); scheduler.push(newTask2); } }
//---------------------------------------------------------------------------------------------- /// @copydoc Mantid::API::Algorithm::exec() void LoadPreNexus::exec() { string runinfo = this->getPropertyValue(RUNINFO_PARAM); string mapfile = this->getPropertyValue(MAP_PARAM); int chunkTotal = this->getProperty("TotalChunks"); int chunkNumber = this->getProperty("ChunkNumber"); if ( isEmpty(chunkTotal) || isEmpty(chunkNumber)) { chunkNumber = EMPTY_INT(); chunkTotal = EMPTY_INT(); } else { if (chunkNumber > chunkTotal) throw std::out_of_range("ChunkNumber cannot be larger than TotalChunks"); } string useParallel = this->getProperty("UseParallelProcessing"); string wsname = this->getProperty("OutputWorkspace"); bool loadmonitors = this->getProperty("LoadMonitors"); // determine the event file names Progress prog(this, 0., .1, 1); vector<string> eventFilenames; string dataDir; this->parseRuninfo(runinfo, dataDir, eventFilenames); prog.doReport("parsed runinfo file"); // do math for the progress bar size_t numFiles = eventFilenames.size() + 1; // extra 1 is nexus logs if (loadmonitors) numFiles++; double prog_start = .1; double prog_delta = (1.-prog_start)/static_cast<double>(numFiles); // load event files string temp_wsname; for (size_t i = 0; i < eventFilenames.size(); i++) { if (i == 0) temp_wsname = wsname; else temp_wsname = "__" + wsname + "_temp__"; IAlgorithm_sptr alg = this->createChildAlgorithm("LoadEventPreNexus", prog_start, prog_start+prog_delta); alg->setProperty("EventFilename", dataDir + eventFilenames[i]); alg->setProperty("MappingFilename", mapfile); alg->setProperty("ChunkNumber", chunkNumber); alg->setProperty("TotalChunks", chunkTotal); alg->setProperty("UseParallelProcessing", useParallel); alg->setPropertyValue("OutputWorkspace", temp_wsname); alg->executeAsChildAlg(); prog_start += prog_delta; if (i == 0) { m_outputWorkspace = alg->getProperty("OutputWorkspace"); } else { IEventWorkspace_sptr tempws = alg->getProperty("OutputWorkspace"); // clean up properties before adding data Run & run = tempws->mutableRun(); if (run.hasProperty("gd_prtn_chrg")) run.removeProperty("gd_prtn_chrg"); if (run.hasProperty("proton_charge")) run.removeProperty("proton_charge"); m_outputWorkspace += tempws; } } // load the logs this->runLoadNexusLogs(runinfo, dataDir, prog_start, prog_start+prog_delta); prog_start += prog_delta; // publish output workspace this->setProperty("OutputWorkspace", m_outputWorkspace); // load the monitor if (loadmonitors) { this->runLoadMonitors(prog_start, 1.); } }
/** * 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); }
std::pair<size_t, size_t> DefaultEventLoader::setupChunking(std::vector<std::string> &bankNames, std::vector<std::size_t> &bankNumEvents) { size_t bank0 = 0; size_t bankn = bankNames.size(); if (chunk != EMPTY_INT()) // We are loading part - work out the bank number range { const size_t total_events = std::accumulate( bankNumEvents.cbegin(), bankNumEvents.cend(), static_cast<size_t>(0)); eventsPerChunk = total_events / totalChunks; // Sort banks by size size_t tmp; std::string stmp; for (size_t i = 0; i < bankn; i++) for (size_t j = 0; j < bankn - 1; j++) if (bankNumEvents[j] < bankNumEvents[j + 1]) { tmp = bankNumEvents[j]; bankNumEvents[j] = bankNumEvents[j + 1]; bankNumEvents[j + 1] = tmp; stmp = bankNames[j]; bankNames[j] = bankNames[j + 1]; bankNames[j + 1] = stmp; } int bigBanks = 0; for (size_t i = 0; i < bankn; i++) if (bankNumEvents[i] > eventsPerChunk) bigBanks++; // Each chunk is part of bank or multiple whole banks // 0.5 for last chunk of a bank with multiple chunks // 0.1 for multiple whole banks not completely filled eventsPerChunk += static_cast<size_t>((static_cast<double>(bigBanks) / static_cast<double>(totalChunks) * 0.5 + 0.05) * static_cast<double>(eventsPerChunk)); double partialChunk = 0.; firstChunkForBank = 1; for (int chunki = 1; chunki <= chunk; chunki++) { if (partialChunk > 1.) { partialChunk = 0.; firstChunkForBank = chunki; bank0 = bankn; } if (bankNumEvents[bank0] > 1) { partialChunk += static_cast<double>(eventsPerChunk) / static_cast<double>(bankNumEvents[bank0]); } if (chunki < totalChunks) bankn = bank0 + 1; else bankn = bankNames.size(); if (chunki == firstChunkForBank && partialChunk > 1.0) bankn += static_cast<size_t>(partialChunk) - 1; if (bankn > bankNames.size()) bankn = bankNames.size(); } for (size_t i = bank0; i < bankn; i++) { size_t start_event = (chunk - firstChunkForBank) * eventsPerChunk; size_t stop_event = bankNumEvents[i]; // Don't change stop_event for the final chunk if (start_event + eventsPerChunk < stop_event) stop_event = start_event + eventsPerChunk; bankNumEvents[i] = stop_event - start_event; } } return {bank0, bankn}; }
/** * Check the validity of the optional properties of the algorithm */ void LoadISISNexus2::checkOptionalProperties() { m_spec_min = getProperty("SpectrumMin"); m_spec_max = getProperty("SpectrumMax"); if( m_spec_min == 0 && m_spec_max == EMPTY_INT() ) { m_range_supplied = false; } if( m_spec_min == 0 ) { m_spec_min = 1; } if( m_spec_max == EMPTY_INT() ) { m_spec_max = m_numberOfSpectra; } // Sanity check for min/max if( m_spec_min > m_spec_max ) { g_log.error() << "Inconsistent range properties. SpectrumMin is larger than SpectrumMax." << std::endl; throw std::invalid_argument("Inconsistent range properties defined."); } if( static_cast<size_t>(m_spec_max) > m_numberOfSpectra ) { g_log.error() << "Inconsistent range property. SpectrumMax is larger than number of spectra: " << m_numberOfSpectra << std::endl; throw std::invalid_argument("Inconsistent range properties defined."); } // Check the entry number m_entrynumber = getProperty("EntryNumber"); if( static_cast<int>(m_entrynumber) > m_numberOfPeriods || m_entrynumber < 0 ) { g_log.error() << "Invalid entry number entered. File contains " << m_numberOfPeriods << " period. " << std::endl; throw std::invalid_argument("Invalid entry number."); } if( m_numberOfPeriods == 1 ) { m_entrynumber = 1; } //Check the list property m_spec_list = getProperty("SpectrumList"); if( ! m_spec_list.empty() ) { // Sort the list so that we can check it's range std::sort(m_spec_list.begin(), m_spec_list.end()); if( m_spec_list.back() > static_cast<int64_t>(m_numberOfSpectra) ) { g_log.error() << "Inconsistent SpectraList property defined for a total of " << m_numberOfSpectra << " spectra." << std::endl; throw std::invalid_argument("Inconsistent property defined"); } //Check no negative numbers have been passed std::vector<int64_t>::iterator itr = std::find_if(m_spec_list.begin(), m_spec_list.end(), std::bind2nd(std::less<int>(), 0)); if( itr != m_spec_list.end() ) { g_log.error() << "Negative SpectraList property encountered." << std::endl; throw std::invalid_argument("Inconsistent property defined."); } range_check in_range(m_spec_min, m_spec_max); if( m_range_supplied ) { m_spec_list.erase(remove_if(m_spec_list.begin(), m_spec_list.end(), in_range), m_spec_list.end()); } } else { m_range_supplied = true; } }
/** Open the event_id field and validate the contents * * @param file :: File handle for the NeXus file * @param start_event :: set to the index of the first event * @param stop_event :: set to the index of the last event + 1 * @param event_index :: (a list of size of # of pulses giving the index in *the event list for that pulse) */ void LoadBankFromDiskTask::prepareEventId( ::NeXus::File &file, int64_t &start_event, int64_t &stop_event, const std::vector<uint64_t> &event_index) { // Get the list of pixel ID's if (m_oldNexusFileNames) file.openData("event_pixel_id"); else file.openData("event_id"); // By default, use all available indices start_event = 0; ::NeXus::Info id_info = file.getInfo(); // dims[0] can be negative in ISIS meaning 2^32 + dims[0]. Take that into // account int64_t dim0 = recalculateDataSize(id_info.dims[0]); stop_event = dim0; // Handle the time filtering by changing the start/end offsets. for (size_t i = 0; i < thisBankPulseTimes->numPulses; i++) { if (thisBankPulseTimes->pulseTimes[i] >= m_loader.alg->filter_time_start) { start_event = static_cast<int64_t>(event_index[i]); break; // stop looking } } if (start_event > dim0) { // If the frame indexes are bad then we can't construct the times of the // events properly and filtering by time // will not work on this data m_loader.alg->getLogger().warning() << this->entry_name << "'s field 'event_index' seems to be invalid (start_index > than " "the number of events in the bank)." << "All events will appear in the same frame and filtering by time " "will not be possible on this data.\n"; start_event = 0; stop_event = dim0; } else { for (size_t i = 0; i < thisBankPulseTimes->numPulses; i++) { if (thisBankPulseTimes->pulseTimes[i] > m_loader.alg->filter_time_stop) { stop_event = event_index[i]; break; } } } // We are loading part - work out the event number range if (m_loader.chunk != EMPTY_INT()) { start_event = static_cast<int64_t>(m_loader.chunk - m_loader.firstChunkForBank) * static_cast<int64_t>(m_loader.eventsPerChunk); // Don't change stop_event for the final chunk if (start_event + static_cast<int64_t>(m_loader.eventsPerChunk) < stop_event) stop_event = start_event + static_cast<int64_t>(m_loader.eventsPerChunk); } // Make sure it is within range if (stop_event > dim0) stop_event = dim0; m_loader.alg->getLogger().debug() << entry_name << ": start_event " << start_event << " stop_event " << stop_event << "\n"; }
//-------------------------------------------------------------------------- // Public member functions //-------------------------------------------------------------------------- DetectorDiagnostic::DetectorDiagnostic() : API::Algorithm(), m_fracDone(0.0), m_TotalTime(RTTotal), m_parents(0), m_progStepWidth(0.0), m_minIndex(0), m_maxIndex(EMPTY_INT()), m_rangeLower(EMPTY_DBL()), m_rangeUpper(EMPTY_DBL()) { }
/** Performs asymmetry analysis on a loaded workspace * @param loadedWs :: [input] Workspace to apply analysis to * @param index :: [input] Vector index where results will be stored */ void PlotAsymmetryByLogValue::doAnalysis(Workspace_sptr loadedWs, size_t index) { // Check if workspace is a workspace group WorkspaceGroup_sptr group = boost::dynamic_pointer_cast<WorkspaceGroup>(loadedWs); // If it is not, we only have 'red' data if (!group) { MatrixWorkspace_sptr ws_red = boost::dynamic_pointer_cast<MatrixWorkspace>(loadedWs); double Y, E; calcIntAsymmetry(ws_red, Y, E); m_logValue[index] = getLogValue(*ws_red); m_redY[index] = Y; m_redE[index] = E; } else { // It is a group // Process red data MatrixWorkspace_sptr ws_red; try { ws_red = boost::dynamic_pointer_cast<MatrixWorkspace>( group->getItem(m_red - 1)); } catch (std::out_of_range &) { throw std::out_of_range("Red period out of range"); } double YR, ER; calcIntAsymmetry(ws_red, YR, ER); double logValue = getLogValue(*ws_red); m_logValue[index] = logValue; m_redY[index] = YR; m_redE[index] = ER; if (m_green != EMPTY_INT()) { // Process green period if supplied by user MatrixWorkspace_sptr ws_green; try { ws_green = boost::dynamic_pointer_cast<MatrixWorkspace>( group->getItem(m_green - 1)); } catch (std::out_of_range &) { throw std::out_of_range("Green period out of range"); } double YG, EG; calcIntAsymmetry(ws_green, YG, EG); // Red data m_redY[index] = YR; m_redE[index] = ER; // Green data m_greenY[index] = YG; m_greenE[index] = EG; // Sum m_sumY[index] = YR + YG; m_sumE[index] = sqrt(ER * ER + EG * EG); // Diff calcIntAsymmetry(ws_red, ws_green, YR, ER); m_diffY[index] = YR; m_diffE[index] = ER; } } // else loadedGroup }
/** * Process the header information. This implementation just skips it entirely. * @param file :: A reference to the file stream */ void LoadAscii::processHeader(std::ifstream & file) const { // Most files will have some sort of header. If we've haven't been told how many lines to // skip then try and guess int numToSkip = getProperty("SkipNumLines"); if( numToSkip == EMPTY_INT() ) { const int rowsToMatch(5); // Have a guess where the data starts. Basically say, when we have say "rowsToMatch" lines of pure numbers // in a row then the line that started block is the top of the data int numCols(-1), matchingRows(0), row(0); std::string line; std::vector<double> values; while( getline(file,line) ) { ++row; //int nchars = (int)line.length(); TODO dead code? boost::trim(line); if( this->skipLine(line) ) { continue; } std::list<std::string> columns; int lineCols = this->splitIntoColumns(columns, line); try { fillInputValues(values, columns); } catch(boost::bad_lexical_cast&) { continue; } if( numCols < 0 ) numCols = lineCols; if( lineCols == numCols ) { ++matchingRows; if( matchingRows == rowsToMatch ) break; } else { numCols = lineCols; matchingRows = 1; } } // Seek the file pointer back to the start. // NOTE: Originally had this as finding the stream position of the data and then moving the file pointer // back to the start of the data. This worked when a file was read on the same platform it was written // but failed when read on a different one due to underlying differences in the stream translation. file.seekg(0,std::ios::beg); // We've read the header plus the number of rowsToMatch numToSkip = row - rowsToMatch; } int i(0); std::string line; while( i < numToSkip && getline(file, line) ) { ++i; } g_log.information() << "Skipped " << numToSkip << " line(s) of header information()\n"; }