32using namespace Kernel;
52constexpr char MaskStr[] =
"Mask";
57constexpr char PathToBinaryStr[] =
"BinaryEventPath";
58constexpr char TOFBiasStr[] =
"TimeOfFlightBias";
65template <
typename Type>
69 auto p =
new Kernel::TimeSeriesProperty<Type>(
name);
70 p->addValue(time,
value);
73 logManager.addProperty(p);
78template <
typename Type>
79Type
GetNeXusValue(
const Nexus::NXEntry &entry,
const std::string &address,
const Type &defval, int32_t
index) {
81 Nexus::NXDataSetTyped<Type> dataSet = entry.openNXDataSet<Type>(address);
84 return dataSet()[
index];
85 }
catch (std::runtime_error &) {
92double GetNeXusValue<double>(
const Nexus::NXEntry &entry,
const std::string &address,
const double &defval,
98 return dataSet()[
index];
99 }
catch (std::runtime_error &) {
106 const std::string &defval, int32_t ) {
109 return entry.getString(address);
110 }
catch (std::runtime_error &) {
116void MapNeXusToProperty(
const Nexus::NXEntry &entry,
const std::string &address,
const T &defval,
117 API::LogManager &logManager,
const std::string &
name,
const T &factor, int32_t
index) {
119 T
value = GetNeXusValue<T>(entry, address, defval,
index);
120 logManager.addProperty<T>(
name,
value * factor);
126 API::LogManager &logManager,
const std::string &
name,
127 const std::string & , int32_t
index) {
130 logManager.addProperty<std::string>(
name,
value);
134void MapNeXusToSeries(
const Nexus::NXEntry &entry,
const std::string &address,
const T &defval,
135 API::LogManager &logManager,
const std::string &time,
const std::string &
name,
const T &factor,
138 auto value = GetNeXusValue<T>(entry, address, defval,
index);
139 AddSinglePointTimeSeriesProperty<T>(logManager, time,
name,
value * factor);
145template <
typename T,
typename F>
void mapRangeToIndex(
const std::string &line, std::vector<T> &result,
const F &fn) {
147 std::stringstream ss(line);
150 while (std::getline(ss, item,
',')) {
151 auto const k = item.find(
'-');
154 if (k != std::string::npos) {
155 p0 = boost::lexical_cast<size_t>(item.substr(0, k));
156 p1 = boost::lexical_cast<size_t>(item.substr(k + 1, item.size() - k - 1));
158 p0 = boost::lexical_cast<size_t>(item);
162 if (p1 < result.size() && p0 <= p1) {
164 result[p0++] = fn(
index);
167 }
else if (p0 < result.size() && p1 < p0) {
169 result[p0] = fn(
index);
173 throw std::invalid_argument(
"invalid range specification");
183 explicit FileLoader(
const char *filename) :
_ifs(filename,
std::ios::binary |
std::ios::in) {
185 throw std::runtime_error(
"unable to open file");
192 bool read(
char *s, std::streamsize
n) {
return static_cast<bool>(
_ifs.read(s,
n)); }
194 size_t size()
const {
return _size; }
198 size_t selected_position() {
return _ifs.tellg(); }
219 m_M = (
static_cast<double>(N) / (maxVal - minVal));
225 inline double ival(
double val)
const {
return m_M * val +
m_B; }
227 inline double xval(
double ix)
const {
return (ix -
m_B) /
m_M; }
229 inline void add(
double val) {
230 auto ix =
static_cast<size_t>(std::floor(
ival(val)));
268 EventProcessor(
const std::vector<bool> &roi,
const std::vector<size_t> &mapIndex,
const double framePeriod,
269 const double gatePeriod,
const TimeLimits &timeBoundary,
size_t maxEvents)
295 return static_cast<int64_t
>(start * 1.0e3);
304 void addEvent(
size_t x,
size_t p,
double tof,
double ) {
321 if (
id >=
m_roi.size())
350 const std::vector<double> &
m_L2;
356 double deltaT = 1.0e6 * (
m_L1 +
m_L2[id]) /
m_V0 - tobs;
362 EventCounter(
const std::vector<bool> &roi,
const std::vector<size_t> &mapIndex,
const double framePeriod,
363 const double gatePeriod,
const TimeLimits &timeBoundary, std::vector<size_t> &eventCounts,
364 const double L1,
const double V0,
const std::vector<double> &vecL2,
size_t maxEvents)
376 for (
size_t i = 0; i < hvec.size(); i++) {
377 if (hvec[i] >= minLevel) {
378 auto ix =
static_cast<double>(i);
384 return (
count > 0 ? sum /
static_cast<double>(
count) : 0.0);
414 auto ev = Types::Event::TofEvent(tof, Types::Core::DateAndTime(offset));
419 EventAssigner(
const std::vector<bool> &roi,
const std::vector<size_t> &mapIndex,
const double framePeriod,
420 const double gatePeriod,
const TimeLimits &timeBoundary, std::vector<EventVector_pt> &eventVectors,
421 int64_t startTime,
double tofCorrection,
double sampleTime,
size_t maxEvents)
430template <
typename EP>
433 using namespace ANSTO;
437 FileLoader loader(eventFile.c_str());
442 ReadEventFile(loader, eventProcessor, progTracker, 100,
false);
451 std::vector<std::string> exts;
456 exts.emplace_back(
".hdf");
458 "The input filename of the stored data");
461 "Relative or absolute path to the compressed binary\n"
462 "event file linked to the HDF file, eg /storage/data/");
466 exts.emplace_back(
".xml");
468 "The input filename of the mask data");
471 "Comma separated range of detectors tubes to be loaded,\n"
486 "Only include events after the provided start time, in "
487 "seconds (relative to the start of the run).");
490 "Only include events before the provided stop time, in "
491 "seconds (relative to the start of the run).");
493 std::string grpOptional =
"Filters";
506 m_localWorkspace->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create(
"TOF");
521void LoadPLN::exec(
const std::string &hdfFile,
const std::string &eventFile) {
523 namespace fs = std::filesystem;
527 fs::path p = hdfFile;
528 for (; !p.extension().empty();)
530 std::string title = p.generic_string();
538 prog.
doReport(
"creating instrument");
550 timeMaxBoundary = std::numeric_limits<double>::infinity();
555 std::string dmapStr = instr->getParameterAsString(
"DetectorMap");
556 std::vector<size_t> detMapIndex = std::vector<size_t>(
HISTO_BINS_X, 0);
562 std::vector<EventVector_pt> eventVectors(numberHistograms,
nullptr);
563 std::vector<size_t> eventCounts(numberHistograms, 0);
567 double framePeriod = 1.0e6 / masterRpm;
571 double gatePeriod = (std::round(masterRpm / slaveRpm) == 1.0 ? 0.5 * framePeriod : framePeriod);
572 AddSinglePointTimeSeriesProperty<double>(logManager,
m_startRun,
"GatePeriod", gatePeriod);
575 size_t hdfCounts =
static_cast<size_t>(logManager.
getTimeSeriesProperty<
int>(
"TotalCounts")->firstValue());
577 double sourceSample =
fabs(instr->getSource()->getPos().Z());
580 double sampleTime = 1.0e6 * sourceSample / velocity;
581 PLN::EventCounter eventCounter(roi, detMapIndex, framePeriod, gatePeriod, timeBoundary, eventCounts, sourceSample,
583 PLN::loadEvents(prog,
"loading neutron counts", eventFile, eventCounter);
597 Types::Core::DateAndTime startTime(
m_startRun);
598 auto const start_nanosec = startTime.totalNanoseconds();
604 logManager.
addProperty(
"CalibrateTOF", (calibrateTOF ? 1 : 0));
605 AddSinglePointTimeSeriesProperty<double>(logManager,
m_startRun,
"TOFCorrection", tofCorrection);
606 PLN::EventAssigner eventAssigner(roi, detMapIndex, framePeriod, gatePeriod, timeBoundary, eventVectors, start_nanosec,
607 tofCorrection, sampleTime, hdfCounts);
608 PLN::loadEvents(prog,
"loading neutron events (TOF)", eventFile, eventAssigner);
612 auto minTOF = eventAssigner.
tofMin();
613 auto maxTOF = eventAssigner.
tofMax();
616 m_localWorkspace->setAllX(HistogramData::BinEdges{std::max(0.0, floor(minTOF)), maxTOF + 1});
620 auto frame_count =
static_cast<int>(eventCounter.
numFrames());
621 AddSinglePointTimeSeriesProperty<int>(logManager,
m_startRun,
"frame_count", frame_count);
626 Types::Core::time_duration duration =
627 boost::posix_time::microseconds(
static_cast<boost::int64_t
>(eventCounter.
duration() * 1.0e6));
628 Types::Core::DateAndTime endTime(startTime + duration);
629 logManager.
addProperty(
"start_time", startTime.toISO8601String());
630 logManager.
addProperty(
"end_time", endTime.toISO8601String());
644 auto detIDs = detectorInfo.detectorIDs();
645 for (
const auto detID : detIDs) {
646 auto ix = detectorInfo.indexOf(detID);
647 double l2 = detectorInfo.l2(ix);
656 const size_t maskedBins = std::count_if(roi.cbegin(), roi.cend(), [](
bool v) { return !v; });
658 if (maskedBins > 0) {
660 std::vector<size_t> maskIndexList(maskedBins);
661 size_t maskIndex = 0;
663 for (
size_t i = 0; i != roi.size(); i++)
665 maskIndexList[maskIndex++] = i;
669 maskingAlg->setProperty(
"WorkspaceIndexList", maskIndexList);
670 maskingAlg->executeAsChildAlg();
677 std::vector<EventVector_pt> &eventVectors) {
679 size_t numberHistograms = eventCounts.size();
680 for (
size_t i = 0; i != numberHistograms; ++i) {
684 eventList.
reserve(eventCounts[i]);
703 if (!selected.empty()) {
707 if (tubes[i] ==
false) {
713 for (
size_t i = 0; i <
MONITORS; i++) {
718 if (maskfile.length() == 0)
721 std::ifstream input(maskfile.c_str());
723 throw std::invalid_argument(
"invalid mask file");
726 while (std::getline(input, line)) {
727 auto i0 = line.find(
"<detids>");
728 auto iN = line.find(
"</detids>");
730 if ((i0 != std::string::npos) && (iN != std::string::npos) && (i0 < iN)) {
731 line = line.substr(i0 + 8, iN - i0 - 8);
748 auto baseTime = GetNeXusValue<int32_t>(entry,
"instrument/detector/start_time", 0,
m_datasetIndex);
749 uint64_t baseTimeNSec =
static_cast<uint64_t
>(baseTime) * 1'000'000'000;
757 double lambdaFactor = (lambdaOnTwoMode ? 0.5 : 1.0);
758 logm.
addProperty(
"LambdaOnTwoMode", (lambdaOnTwoMode ? 1 : 0));
760 MapNeXusToSeries<double>(entry,
"instrument/fermi_chopper/mchs", 0.0, logm,
m_startRun,
"FermiChopperFreq", 1.0 / 60,
762 MapNeXusToSeries<double>(entry,
"instrument/fermi_chopper/schs", 0.0, logm,
m_startRun,
"OverlapChopperFreq",
764 MapNeXusToSeries<double>(entry,
"instrument/crystal/wavelength", 0.0, logm,
m_startRun,
"Wavelength", lambdaFactor,
766 MapNeXusToSeries<double>(entry,
"instrument/detector/stth", 0.0, logm,
m_startRun,
"DetectorTankAngle", 1.0,
784 for (
const auto &tag : tags) {
785 MapNeXusToSeries<double>(entry,
"data/" + tag, 0.0, logm, time_str,
"env_" + tag, 1.0,
m_datasetIndex);
795 loadInstrumentAlg->setPropertyValue(
"InstrumentName",
"PELICAN");
797 loadInstrumentAlg->executeAsChildAlg();
812const std::string
LoadPLN::summary()
const {
return "Loads a PLN Hdf and linked event file into a workspace."; }
820 if (descriptor.
isEntry(
"/entry1/site_name") && descriptor.
isEntry(
"/entry1/instrument/fermi_chopper") &&
821 descriptor.
isEntry(
"/entry1/instrument/aperture/sh1") &&
822 descriptor.
isEntry(
"/entry1/instrument/ag1010/MEAS/Temperature") &&
823 descriptor.
isEntry(
"/entry1/instrument/detector/daq_dirname") &&
824 descriptor.
isEntry(
"/entry1/instrument/detector/dataset_number") && descriptor.
isEntry(
"/entry1/data/hmm") &&
825 descriptor.
isEntry(
"/entry1/data/time_of_flight") && descriptor.
isEntry(
"/entry1/data/total_counts")) {
837 namespace fs = std::filesystem;
846 if (evtPath.rfind(
"./") == 0 || evtPath.rfind(
"../") == 0) {
847 fs::path hp(hdfFile);
848 evtPath = fs::canonical(hp.parent_path() / evtPath).string();
854 std::string message(
"Negative dataset index provided, reset to zero!");
862 if (fs::is_directory(evtPath)) {
866 auto dataset = GetNeXusValue<int32_t>(entry,
"instrument/detector/dataset_number", 0,
m_datasetIndex);
868 std::string message(
"Negative dataset index recorded in HDF, reset to zero!");
876 std::stringstream buffer;
877 buffer << eventDir.c_str() <<
"/DATASET_" << dataset <<
"/EOS.bin";
878 fs::path filePath = evtPath;
879 filePath /= buffer.str();
880 filePath = fs::absolute(filePath);
881 std::string nomPath = filePath.generic_string();
882 if (fs::is_regular_file(nomPath)) {
885 fs::path hp = hdfFile;
888 buffer << hp.stem().generic_string().c_str() <<
".bin";
889 fs::path path = evtPath;
890 path /= buffer.str();
891 path = fs::absolute(path);
892 evtPath = path.generic_string();
897 if (!fs::is_regular_file(evtPath)) {
898 std::string msg =
"Check path, cannot open binary event file: " + evtPath;
899 throw std::runtime_error(msg);
902 exec(hdfFile, evtPath);
double value
The value of the point.
std::map< DeltaEMode::Type, std::string > index
#define DECLARE_NEXUS_FILELOADER_ALGORITHM(classname)
DECLARE_NEXUS_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM macro wh...
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
@ OptionalLoad
to specify a file to read but the file doesn't have to exist
@ Load
allowed here which will be passed to the algorithm
void setDetectorID(const detid_t detID)
Clear the list of detector IDs, then add one.
void setSpectrumNo(specnum_t num)
Sets the spectrum number of this spectrum.
This class contains the information about the log entries.
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
HeldType getPropertyValueAsType(const std::string &name) const
Get the value of a property as the given TYPE.
Kernel::TimeSeriesProperty< T > * getTimeSeriesProperty(const std::string &name) const
Returns a property as a time series property.
Helper class for reporting progress from algorithms.
void doReport(const std::string &msg="") override
Actually do the reporting, without changing the loop counter.
A property class for workspaces.
helper class to keep track of progress
void update(int64_t position)
LoadPLN : Loads an ANSTO PLN Hdf and linked event file into a workspace.
std::vector< double > m_detectorL2
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
const std::vector< std::string > seeAlso() const override
Similar algorithms.
void prepareEventStorage(ANSTO::ProgressTracker &prog, std::vector< size_t > &eventCounts, std::vector< EventVector_pt > &eventVectors)
Allocate space for the event storage in eventVectors after the eventCounts have been determined.
int version() const override
Algorithm's version for identification.
void setupDetectorMasks(const std::vector< bool > &roi)
Set up the detector masks to the region of interest roi.
void loadEnvironParameters(const std::string &hdfFile, API::LogManager &logm)
Load the environment variables from the hdfFile and save as time series to the log manager,...
DataObjects::EventWorkspace_sptr m_localWorkspace
void init() override
Initialise the algorithm and declare the properties for the nexus descriptor.
void createWorkspace(const std::string &title)
Creates an event workspace and sets the title.
void loadParameters(const std::string &hdfFile, API::LogManager &logm)
Load parameters from input hdfFile and save to the log manager, logm.
void loadDetectorL2Values()
Recovers the L2 neutronic distance for each detector.
void loadInstrument()
Load the instrument definition.
std::vector< bool > createRoiVector(const std::string &seltubes, const std::string &maskfile)
Region of interest is defined by the selected detectors and the maskfile.
const std::string name() const override
Algorithms name for identification.
int confidence(Nexus::NexusDescriptorLazy &descriptor) const override
Return the confidence as an integer value that this algorithm can load the file descriptor.
void exec() override
Execute the algorithm.
const std::string category() const override
Algorithm's category for identification.
EventAssigner(const std::vector< bool > &roi, const std::vector< size_t > &mapIndex, const double framePeriod, const double gatePeriod, const TimeLimits &timeBoundary, std::vector< EventVector_pt > &eventVectors, int64_t startTime, double tofCorrection, double sampleTime, size_t maxEvents)
std::vector< EventVector_pt > & m_eventVectors
void addEventImpl(size_t id, size_t, size_t, double tobs) override
std::vector< size_t > & m_eventCounts
EventCounter(const std::vector< bool > &roi, const std::vector< size_t > &mapIndex, const double framePeriod, const double gatePeriod, const TimeLimits &timeBoundary, std::vector< size_t > &eventCounts, const double L1, const double V0, const std::vector< double > &vecL2, size_t maxEvents)
void addEventImpl(size_t id, size_t, size_t, double tobs) override
const std::vector< double > & m_L2
const std::vector< bool > & m_roi
void addEvent(size_t x, size_t p, double tof, double)
const std::vector< size_t > & m_mapIndex
size_t availableEvents() const
const double m_framePeriod
const TimeLimits m_timeBoundary
virtual void addEventImpl(size_t id, size_t x, size_t y, double tof)=0
int64_t frameStart() const
const double m_gatePeriod
size_t processedEvents() const
EventProcessor(const std::vector< bool > &roi, const std::vector< size_t > &mapIndex, const double framePeriod, const double gatePeriod, const TimeLimits &timeBoundary, size_t maxEvents)
double ival(double val) const
std::vector< size_t > m_hist
double xval(double ix) const
SimpleHist(size_t N, double minVal, double maxVal)
const std::vector< size_t > & histogram() const
void setSortOrder(const EventSortType order) const
Manually set the event list sort order value.
void reserve(size_t num) override
Reserve a certain number of entries in event list of the specified eventType.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertyGroup(const std::string &name, const std::string &group)
Set the group for a given property.
void error(const std::string &msg)
Logs at error level.
void warning(const std::string &msg)
Logs at warning level.
Validator to check that a property is not left empty.
OptionalBool : Tri-state bool.
Implements NXentry Nexus class.
Implements NXroot Nexus class.
NXEntry openFirstEntry()
Open the first NXentry in the file.
std::string const & extension() const noexcept
Access the file extension.
bool isEntry(std::string const &entryName, std::string const &groupClass) const
Checks if a full-address entry exists for a particular groupClass in a Nexus dataset.
int64_t epochRelDateTimeBase(int64_t epochInNanoSeconds)
void ReadEventFile(IReader &loader, IEventHandler &handler, IProgress &progress, int32_t def_clock_scale, bool use_tx_chopper)
std::vector< std::string > filterDatasets(const Nexus::NXEntry &entry, const std::string &groupAddress, const std::string ®exFilter)
extract datasets from a group that match a regex filter
void loadEvents(API::Progress &prog, const char *progMsg, const std::string &eventFile, EP &eventProcessor)
void MapNeXusToProperty(const Nexus::NXEntry &entry, const std::string &address, const T &defval, API::LogManager &logManager, const std::string &name, const T &factor, int32_t index)
constexpr size_t DETECTOR_TUBES
Type GetNeXusValue(const Nexus::NXEntry &entry, const std::string &address, const Type &defval, int32_t index)
constexpr char SelectDetectorTubesStr[]
constexpr size_t HISTO_BINS_Y_DENUMERATOR
static const size_t Progress_LoadBinFile
std::string GetNeXusValue< std::string >(const Nexus::NXEntry &entry, const std::string &address, const std::string &defval, int32_t)
constexpr size_t DETECTOR_SPECTRA
static char const *const FilterByTimeStopStr
static char const *const MaskStr
static char const *const FilenameStr
constexpr char CalibrateTOFStr[]
constexpr char SelectDatasetStr[]
static const size_t HISTO_BINS_X
void AddSinglePointTimeSeriesProperty(API::LogManager &logManager, const std::string &time, const std::string &name, const TYPE value)
constexpr char LambdaOnTwoStr[]
static char const *const FilterByTimeStartStr
void MapNeXusToSeries(const Nexus::NXEntry &entry, const std::string &nxsPath, uint64_t startTime, uint64_t endTime, Anxs::ScanLog valueOption, const T &defval, API::LogManager &logManager, const std::string &logName, const T &factor)
void MapNeXusToProperty< std::string >(const Nexus::NXEntry &entry, const std::string &address, const std::string &defval, API::LogManager &logManager, const std::string &name, const std::string &, int32_t index)
static const size_t Progress_ReserveMemory
constexpr size_t MONITORS
constexpr size_t PIXELS_PER_TUBE
constexpr size_t HISTOGRAMS
static const size_t Progress_Total
std::pair< double, double > TimeLimits
double GetNeXusValue< double >(const Nexus::NXEntry &entry, const std::string &address, const double &defval, int32_t index)
constexpr char TOFBiasStr[]
void mapRangeToIndex(const std::string &line, std::vector< T > &result, const F &fn)
DLLExport void getEventsFrom(EventList &el, std::vector< Types::Event::TofEvent > *&events)
NXDataSetTyped< float > NXFloat
The float dataset type.
static constexpr double NeutronMass
Mass of the neutron in kg.
static constexpr double h
Planck constant in J*s.
int32_t detid_t
Typedef for a detector ID.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Output
An output workspace.