33using namespace Kernel;
42constexpr char MaskStr[] =
"Mask";
56 {
"end", Anxs::ScanLog::End}, {
"mean", Anxs::ScanLog::Mean}, {
"start", Anxs::ScanLog::Start}};
84template <
typename Type>
89 p->addValue(time,
value);
99 AddSinglePointTimeSeriesProperty<T>(logManager, strEventTime,
name,
value);
104template <
typename Type>
110 return dataSet()[
index];
111 }
catch (std::runtime_error &) {
124 return dataSet()[
index];
125 }
catch (std::runtime_error &) {
132 const std::string &defval, int32_t ) {
136 }
catch (std::runtime_error &) {
145 T
value = GetNeXusValue<T>(entry, address, defval,
index);
153 const std::string & , int32_t
index) {
162 const std::string &logName,
const T &factor) {
165 uint64_t eventTime{0};
169 eventTime = startTime;
172 AddSinglePointTimeSeriesProperty<T>(logManager, strEventTime, logName, eventValue * factor);
178template <
typename T,
typename F>
void mapRangeToIndex(
const std::string &line, std::vector<T> &result,
const F &fn) {
180 std::stringstream ss(line);
183 while (std::getline(ss, item,
',')) {
184 auto const k = item.find(
'-');
187 if (k != std::string::npos) {
188 p0 = boost::lexical_cast<size_t>(item.substr(0, k));
189 p1 = boost::lexical_cast<size_t>(item.substr(k + 1, item.size() - k - 1));
191 p0 = boost::lexical_cast<size_t>(item);
195 if (p1 < result.size() && p0 <= p1) {
197 result[p0++] = fn(
index);
200 }
else if (p0 < result.size() && p1 < p0) {
202 result[p0] = fn(
index);
206 throw std::invalid_argument(
"invalid range specification");
211 const Nexus::NXEntry &entry, uint64_t start_nsec, uint64_t end_nsec) {
218 const std::string neutronPath{
"instrument/detector_events"};
232 throw std::runtime_error(
"unable to open file");
239 bool read(
char *s, std::streamsize
n) {
return static_cast<bool>(
_ifs.read(s,
n)); }
262 m_M = (
static_cast<double>(N) / (maxVal - minVal));
268 inline double ival(
double val)
const {
return m_M * val +
m_B; }
270 inline double xval(
double ix)
const {
return (ix -
m_B) /
m_M; }
272 inline void add(
double val) {
273 auto ix =
static_cast<size_t>(std::floor(
ival(val)));
311 EventProcessor(
const std::vector<bool> &roi,
const std::vector<size_t> &mapIndex,
const double framePeriod,
312 const double gatePeriod,
const TimeLimits &timeBoundary,
size_t maxEvents)
338 return static_cast<int64_t
>(start * 1.0e3);
347 void addEvent(
size_t x,
size_t p,
double tof)
override {
364 if (
id >=
m_roi.size())
393 const std::vector<double> &
m_L2;
399 double deltaT = 1.0e6 * (
m_L1 +
m_L2[id]) /
m_V0 - tobs;
405 EventCounter(
const std::vector<bool> &roi,
const std::vector<size_t> &mapIndex,
const double framePeriod,
406 const double gatePeriod,
const TimeLimits &timeBoundary, std::vector<size_t> &eventCounts,
407 const double L1,
const double V0,
const std::vector<double> &vecL2,
size_t maxEvents)
419 for (
size_t i = 0; i < hvec.size(); i++) {
420 if (hvec[i] >= minLevel) {
421 auto ix =
static_cast<double>(i);
427 return (
count > 0 ? sum /
static_cast<double>(
count) : 0.0);
457 auto ev = Types::Event::TofEvent(tof, Types::Core::DateAndTime(offset));
462 EventAssigner(
const std::vector<bool> &roi,
const std::vector<size_t> &mapIndex,
const double framePeriod,
463 const double gatePeriod,
const TimeLimits &timeBoundary, std::vector<EventVector_pt> &eventVectors,
464 int64_t startTime,
double tofCorrection,
double sampleTime,
size_t maxEvents)
480 std::vector<std::string> exts;
485 exts.emplace_back(
".nxs");
487 "The input filename of the stored data");
491 exts.emplace_back(
".xml");
493 "The input filename of the mask data");
496 "Comma separated range of detectors tubes to be loaded,\n"
511 "Only include events after the provided start time, in "
512 "seconds (relative to the start of the run).");
515 "Only include events before the provided stop time, in "
516 "seconds (relative to the start of the run).");
520 std::string grpOptional =
"Filters";
533 m_localWorkspace->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create(
"TOF");
545 namespace fs = std::filesystem;
549 if (API::AnalysisDataService::Instance().doesExist(outName))
550 API::AnalysisDataService::Instance().remove(outName);
563 uint64_t startTime, endTime;
568 if (startTime >= endTime) {
569 g_log.
error() <<
"Invalid time window from hmscan" <<
"\n";
570 throw std::runtime_error(
"LoadPLNnxs: invalid or missing scan time range.");
582 prog.
doReport(
"creating instrument");
594 timeMaxBoundary = std::numeric_limits<double>::infinity();
599 std::string dmapStr = instr->getParameterAsString(
"DetectorMap");
600 std::vector<size_t> detMapIndex = std::vector<size_t>(
HISTO_BINS_X, 0);
606 std::vector<EventVector_pt> eventVectors(numberHistograms,
nullptr);
607 std::vector<size_t> eventCounts(numberHistograms, 0);
611 double framePeriod = 1.0e6 / masterRpm;
615 double gatePeriod = (std::round(masterRpm / slaveRpm) == 1.0 ? 0.5 * framePeriod : framePeriod);
616 AddSinglePointTimeSeriesProperty<double>(logManager,
m_startRun,
"GatePeriod", gatePeriod);
621 double sourceSample =
fabs(instr->getSource()->getPos().Z());
624 double sampleTime = 1.0e6 * sourceSample / velocity;
625 PLN2::EventCounter eventCounter(roi, detMapIndex, framePeriod, gatePeriod, timeBoundary, eventCounts, sourceSample,
627 loadEvents(prog,
"loading neutron counts", &eventCounter, nxsEntry, startTime, endTime);
636 Types::Core::DateAndTime startDateTime(
m_startRun);
637 auto const start_nanosec = startDateTime.totalNanoseconds();
643 logManager.
addProperty(
"CalibrateTOF", (calibrateTOF ? 1 : 0));
644 AddSinglePointTimeSeriesProperty<double>(logManager,
m_startRun,
"TOFCorrection", tofCorrection);
645 PLN2::EventAssigner eventAssigner(roi, detMapIndex, framePeriod, gatePeriod, timeBoundary, eventVectors,
646 start_nanosec, tofCorrection, sampleTime, 0);
647 loadEvents(prog,
"loading neutron events (TOF)", &eventAssigner, nxsEntry, startTime, endTime);
651 auto minTOF = eventAssigner.
tofMin();
652 auto maxTOF = eventAssigner.
tofMax();
655 m_localWorkspace->setAllX(HistogramData::BinEdges{std::max(0.0, floor(minTOF)), maxTOF + 1});
659 auto frame_count =
static_cast<int>(eventCounter.
numFrames());
660 AddSinglePointTimeSeriesProperty<int>(logManager,
m_startRun,
"frame_count", frame_count);
665 Types::Core::time_duration duration =
666 boost::posix_time::microseconds(
static_cast<boost::int64_t
>(eventCounter.
duration() * 1.0e6));
667 Types::Core::DateAndTime endDateTime(startDateTime + duration);
668 logManager.
addProperty(
"start_time", startDateTime.toISO8601String());
669 logManager.
addProperty(
"end_time", endDateTime.toISO8601String());
683 auto detIDs = detectorInfo.detectorIDs();
684 for (
const auto detID : detIDs) {
685 auto ix = detectorInfo.indexOf(detID);
686 double l2 = detectorInfo.l2(ix);
695 size_t maskedBins = std::count(roi.begin(), roi.end(),
false);
697 if (maskedBins > 0) {
699 std::vector<size_t> maskIndexList(maskedBins);
700 size_t maskIndex = 0;
702 for (
size_t i = 0; i != roi.size(); i++)
704 maskIndexList[maskIndex++] = i;
708 maskingAlg->setProperty(
"WorkspaceIndexList", maskIndexList);
709 maskingAlg->executeAsChildAlg();
716 std::vector<EventVector_pt> &eventVectors) {
718 size_t numberHistograms = eventCounts.size();
719 for (
size_t i = 0; i != numberHistograms; ++i) {
723 eventList.
reserve(eventCounts[i]);
742 if (!selected.empty()) {
746 if (tubes[i] ==
false) {
752 for (
size_t i = 0; i <
MONITORS; i++) {
757 if (maskfile.length() == 0)
760 std::ifstream input(maskfile.c_str());
762 throw std::invalid_argument(
"invalid mask file");
765 while (std::getline(input, line)) {
766 auto i0 = line.find(
"<detids>");
767 auto iN = line.find(
"</detids>");
769 if ((i0 != std::string::npos) && (iN != std::string::npos) && (i0 < iN)) {
770 line = line.substr(i0 + 8, iN - i0 - 8);
790 double lambdaFactor = (lambdaOnTwoMode ? 0.5 : 1.0);
791 logm.
addProperty(
"LambdaOnTwoMode", (lambdaOnTwoMode ? 1 : 0));
793 MapNeXusToSeries<double>(entry,
"instrument/fermi_chopper/mchs", startTime, endTime, Anxs::ScanLog::End, 0.0, logm,
794 "FermiChopperFreq", 1.0 / 60);
795 MapNeXusToSeries<double>(entry,
"instrument/fermi_chopper/schs", startTime, endTime, Anxs::ScanLog::End, 0.0, logm,
796 "OverlapChopperFreq", 1.0 / 60);
797 MapNeXusToSeries<double>(entry,
"instrument/crystal/wavelength", startTime, endTime, Anxs::ScanLog::End, 0.0, logm,
798 "Wavelength", lambdaFactor);
799 MapNeXusToSeries<double>(entry,
"instrument/detector/stth", startTime, endTime, Anxs::ScanLog::End, 0.0, logm,
800 "DetectorTankAngle", 1.0);
801 MapNeXusToSeries<int64_t>(entry,
"monitor/bm1_counts", startTime, endTime, Anxs::ScanLog::End, 0, logm,
803 MapNeXusToSeries<double>(entry,
"instrument/detector/tofw", startTime, endTime, Anxs::ScanLog::End, 5.0, logm,
805 MapNeXusToSeries<double>(entry,
"sample/mscor", startTime, endTime, Anxs::ScanLog::End, 0.0, logm,
"SampleRotation",
815 auto tags =
ANSTO::filterGroups(entry,
"control/",
"^[A-Z]{1,3}[0-9]{1,3}[A-Za-z]{1,9}[0-9]{0,3}$");
816 for (
const auto &tag : tags) {
817 MapNeXusToSeries<double>(entry,
"control/" + tag, startTime, endTime, Anxs::ScanLog::End, 0.0, logm,
"env_" + tag,
828 loadInstrumentAlg->setPropertyValue(
"InstrumentName",
"PELICAN");
830 loadInstrumentAlg->executeAsChildAlg();
845const std::string
LoadPLNnxs::summary()
const {
return "Loads a PLN2 Hdf and linked event file into a workspace."; }
853 if (descriptor.
isEntry(
"/entry1/instrument/fermi_chopper/schs/value") &&
854 descriptor.
isEntry(
"/entry1/instrument/aperture/sh1/value") &&
855 descriptor.
isEntry(
"/entry1/instrument/ag1010/MEAS/Temperature/value") &&
856 descriptor.
isEntry(
"/entry1/instrument/detector/stth/value") &&
857 descriptor.
isEntry(
"/entry1/instrument/detector_events/event_id") &&
858 descriptor.
isEntry(
"/entry1/scan_dataset/time") && descriptor.
isEntry(
"/entry1/scan_dataset/value")) {
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.
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.
abstract base class for processing events as they are read from the file
helper class to keep track of progress
void update(int64_t position)
LoadPLNnxs : Loads an ANSTO PLN nxs and linked event file into a workspace.
int confidence(Nexus::NexusDescriptorLazy &descriptor) const override
Return the confidence as an integer value that this algorithm can load the file descriptor.
void loadInstrument()
Load the instrument definition.
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.
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 loadDetectorL2Values()
Recovers the L2 neutronic distance for each detector.
void createWorkspace(const std::string &title)
Creates an event workspace and sets the title.
void loadEnvironParameters(const Nexus::NXEntry &entry, uint64_t startTime, uint64_t endTime, API::LogManager &logm)
Load the environment variables from the nxsFile and save as time series to the log manager,...
void setupDetectorMasks(const std::vector< bool > &roi)
Set up the detector masks to the region of interest roi.
void exec() override
Execute the algorithm.
int version() const override
Algorithm's version for identification.
const std::string category() const override
Algorithm's category for identification.
const std::string name() const override
Algorithms name for identification.
DataObjects::EventWorkspace_sptr m_localWorkspace
void loadParameters(const Nexus::NXEntry &entry, uint64_t startTime, uint64_t endTime, API::LogManager &logm)
Load parameters from input nxsFile and save to the log manager, logm.
std::vector< bool > createRoiVector(const std::string &seltubes, const std::string &maskfile)
Region of interest is defined by the selected detectors and the maskfile.
std::vector< double > m_detectorL2
void init() override
Initialise the algorithm and declare the properties for the nexus descriptor.
void addEventImpl(size_t id, size_t, size_t, double tobs) override
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
std::vector< size_t > & m_eventCounts
void addEventImpl(size_t id, size_t, size_t, double tobs) override
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)
const std::vector< double > & m_L2
const double m_gatePeriod
size_t processedEvents() const
const std::vector< bool > & m_roi
EventProcessor(const std::vector< bool > &roi, const std::vector< size_t > &mapIndex, const double framePeriod, const double gatePeriod, const TimeLimits &timeBoundary, size_t maxEvents)
virtual void addEventImpl(size_t id, size_t x, size_t y, double tof)=0
const std::vector< size_t > & m_mapIndex
const double m_framePeriod
const TimeLimits m_timeBoundary
int64_t frameStart() const
void addEvent(size_t x, size_t p, double tof) override
size_t availableEvents() const
bool read(char *s, std::streamsize n)
size_t selected_position()
FileLoader(const char *filename)
const std::vector< size_t > & histogram() const
double ival(double val) const
double xval(double ix) const
std::vector< size_t > m_hist
SimpleHist(size_t N, double minVal, double maxVal)
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.
OptionalBool : Tri-state bool.
A specialised Property class for holding a series of time-value pairs.
std::string getString(const std::string &name) const
Returns a string.
NXDataSetTyped< T > openNXDataSet(const std::string &name) const
Templated method for creating datasets.
Templated class implementation of NXDataSet.
void load()
Read all of the datablock in.
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.
std::string extractWorkspaceTitle(const std::string &nxsFile)
int64_t epochRelDateTimeBase(int64_t epochInNanoSeconds)
std::pair< uint64_t, uint64_t > getHMScanLimits(const Nexus::NXEntry &entry, int datasetIx)
uint64_t extractTimedDataSet(const Nexus::NXEntry &entry, const std::string &path, uint64_t startTime, uint64_t endTime, std::vector< uint64_t > ×, std::vector< T > &events, std::string &units)
void ReadEventData(ProgressTracker &prog, const Nexus::NXEntry &entry, BaseEventProcessor *handler, uint64_t start_nsec, uint64_t end_nsec, const std::string &neutron_path, int tube_resolution=1024)
std::pair< uint64_t, uint64_t > getTimeScanLimits(const Nexus::NXEntry &entry, int datasetIx)
std::vector< Types::Event::TofEvent > * EventVector_pt
pointer to the vector of events
std::vector< std::string > filterGroups(const Nexus::NXEntry &entry, const std::string &groupAddress, const std::string ®exFilter)
extract groups from a group that match a regex filter
constexpr size_t TUBE_DETECTOR_RESOLUTION
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[]
void loadEvents(API::Progress &prog, const char *progMsg, EP &eventProcessor, const Nexus::NXEntry &entry, uint64_t start_nsec, uint64_t end_nsec)
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 UseHMScanTimeStr
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
static const std::map< std::string, Anxs::ScanLog > ScanLogMap
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)
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.
DatasetTime(int32_t index, int64_t start, int64_t end)
@ Output
An output workspace.