27#include <boost/filesystem.hpp>
28#include <boost/math/special_functions/round.hpp>
29#include <boost/math/tools/minima.hpp>
31#include <Poco/AutoPtr.h>
32#include <Poco/TemporaryFile.h>
33#include <Poco/Util/PropertyFileConfiguration.h>
46constexpr size_t HORIZONTAL_TUBES = 16;
47constexpr size_t VERTICAL_TUBES = 35;
48constexpr size_t DETECTOR_TUBES = HORIZONTAL_TUBES + VERTICAL_TUBES;
52constexpr size_t HISTO_BINS_Y_DENUMERATOR = 16;
53constexpr size_t PIXELS_PER_TUBE =
HISTO_BINS_Y / HISTO_BINS_Y_DENUMERATOR;
55constexpr size_t BM_HISTOGRAMS =
HISTO_BINS_X * PIXELS_PER_TUBE;
56constexpr size_t HISTOGRAMS = BM_HISTOGRAMS + PIXELS_PER_TUBE;
57constexpr size_t BEAM_MONITOR_BINS = 100;
58constexpr size_t PSEUDO_BM_TUBE = 55;
60constexpr size_t BM_HALF_WINDOW = 5;
70constexpr char SelectDetectorTubesStr[] =
"SelectDetectorTubes";
71constexpr char SelectDatasetStr[] =
"SelectDataset";
72constexpr char OverrideDopplerFreqStr[] =
"OverrideDopplerFrequency";
73constexpr char OverrideDopplerPhaseStr[] =
"OverrideDopplerPhase";
76constexpr char RawDopplerTimeStr[] =
"LoadAsRawDopplerTime";
77constexpr char IncludePseudoBMStr[] =
"IncludeBeamMonitor";
78constexpr char CalibrateDopplerPhaseStr[] =
"CalibrateDopplerPhase";
79constexpr char PathToBinaryStr[] =
"BinaryEventPath";
82using TimeLimits = std::pair<double, double>;
84template <
typename Type>
89 p->addValue(time,
value);
97template <
typename Type>
98Type GetNeXusValue(
const NeXus::NXEntry &entry,
const std::string &path,
const Type &defval, int32_t
index) {
103 return dataSet()[
index];
104 }
catch (std::runtime_error &) {
110double GetNeXusValue<double>(
const NeXus::NXEntry &entry,
const std::string &path,
const double &defval,
113 NeXus::NXDataSetTyped<float> dataSet = entry.openNXDataSet<
float>(path);
116 return dataSet()[
index];
117 }
catch (std::runtime_error &) {
122std::string GetNeXusValue<std::string>(
const NeXus::NXEntry &entry,
const std::string &path,
const std::string &defval,
129 return std::string(dataSet(), dataSet.dim0());
130 }
catch (std::runtime_error &) {
136void MapNeXusToProperty(NeXus::NXEntry &entry,
const std::string &path,
const T &defval, API::LogManager &logManager,
137 const std::string &name,
const T &factor, int32_t
index) {
139 T
value = GetNeXusValue<T>(entry, path, defval,
index);
140 logManager.addProperty<T>(name,
value * factor);
145void MapNeXusToProperty<std::string>(NeXus::NXEntry &entry,
const std::string &path,
const std::string &defval,
146 API::LogManager &logManager,
const std::string &name,
147 const std::string & , int32_t
index) {
149 std::string
value = GetNeXusValue<std::string>(entry, path, defval,
index);
150 logManager.addProperty<std::string>(name,
value);
154void MapNeXusToSeries(NeXus::NXEntry &entry,
const std::string &path,
const T &defval, API::LogManager &logManager,
155 const std::string &time,
const std::string &name,
const T &factor, int32_t
index) {
157 auto value = GetNeXusValue<T>(entry, path, defval,
index);
158 AddSinglePointTimeSeriesProperty<T>(logManager, time, name,
value * factor);
164template <
typename T,
typename F>
void mapRangeToIndex(
const std::string &line, std::vector<T> &result,
const F &fn) {
166 std::stringstream ss(line);
169 while (std::getline(ss, item,
',')) {
170 auto k = item.find(
'-');
173 if (k != std::string::npos) {
174 p0 = boost::lexical_cast<size_t>(item.substr(0, k));
175 p1 = boost::lexical_cast<size_t>(item.substr(k + 1, item.size() - k - 1));
177 p0 = boost::lexical_cast<size_t>(item);
181 if (p1 < result.size() && p0 <= p1) {
183 result[p0++] = fn(
index);
186 }
else if (p0 < result.size() && p1 < p0) {
188 result[p0] = fn(
index);
192 throw std::invalid_argument(
"invalid range specification");
198template <
typename F>
double invert(
double y,
const F &f,
double x0 = 0.0,
const double eps = 1e-16) {
200 double e0 = f(x0) -
y;
202 double x1 = x0 + eps;
203 double e1 = f(x1) -
y;
205 while (
fabs(e0) > eps && loop-- > 0) {
206 double x = (x1 * e0 - x0 * e1) / (e0 - e1);
223using TofData = std::tuple<double, double>;
231 const std::vector<double> &
m_L2;
233 inline double L1(
double t)
const {
return m_L0 +
m_A * sin(
m_w * t +
m_phi); }
235 inline double v1(
double t)
const {
return m_v2 -
m_A *
m_w * cos(m_w * t + m_phi); }
238 ConvertTOF(
double Amp,
double freq,
double phase,
double L1,
double v2,
const std::vector<double> &L2)
241 TofData directTOF(
size_t detID,
double tobs)
const {
244 auto tn = [=](
double t) {
return t + (L1(t) +
m_L2[detID]) / v1(t); };
246 double tsec = tobs * 1.0e-6;
247 double t0 = tsec - (
m_L0 +
m_L2[detID]) / m_v2;
248 double tinv = invert(tsec, tn, t0);
249 double tof = (
m_L0 +
m_L2[detID]) / v1(tinv);
251 return TofData(tinv * 1.0e6, tof * 1.0e6);
254 TofData analysedTOF(
size_t detID,
double tobs)
const {
256 auto tn = [=](
double t) {
return t + L1(t) / v1(t) +
m_L2[detID] /
m_v2; };
258 double tsec = tobs * 1.0e-6;
259 double t0 = tsec - (
m_L0 +
m_L2[detID]) / m_v2;
260 double t = invert(tsec, tn, t0);
263 return TofData(t * 1.0e6, tof * 1.0e6);
268double maskedMean(
const std::vector<double> &vec,
const std::vector<bool> &mask) {
269 if (vec.size() == 0 || vec.size() != mask.size())
270 throw std::runtime_error(
"masked mean of empty or mismatched vectors");
273 for (
size_t i = 0; i != vec.size(); i++) {
280 throw std::runtime_error(
"mean of empty vector");
281 return sum /
static_cast<double>(
count);
285double maskedStdev(
const std::vector<double> &vec,
const std::vector<bool> &mask) {
287 auto avg = maskedMean(vec, mask);
290 for (
size_t i = 0; i != vec.size(); i++) {
293 sum += (vec[i] - avg) * (vec[i] - avg);
296 return std::sqrt(sum /
static_cast<double>(
count));
308std::vector<double> runningAverage(
const std::vector<size_t> &data,
size_t halfWindow) {
309 const auto N = data.size();
310 const size_t totalWindow = 2 * halfWindow + 1;
315 size_t startIndex = N - halfWindow;
316 for (
size_t i = 0; i < totalWindow; i++) {
317 size_t ix = (startIndex + i) % N;
323 std::vector<double> filtered(N, 0);
324 for (
size_t i = 0; i < N; i++) {
326 filtered[i] =
static_cast<double>(sum) /
static_cast<double>(totalWindow);
328 sum -= data[startIndex];
329 sum += data[(startIndex + totalWindow) % N];
330 startIndex = (startIndex + 1) % N;
341 explicit FileLoader(
const char *filename) :
_ifs(filename,
std::ios::binary |
std::ios::in) {
343 throw std::runtime_error(
"unable to open file");
350 bool read(
char *s, std::streamsize
n) {
return static_cast<bool>(
_ifs.read(s,
n)); }
352 size_t size() {
return _size; }
356 size_t selected_position() {
return _ifs.tellg(); }
399 EventProcessor(
const std::vector<bool> &roi,
const std::vector<size_t> &mapIndex,
const size_t stride,
400 const double framePeriod,
const double gatePeriod, TimeLimits timeBoundary, TimeLimits directLimits,
401 TimeLimits analysedLimits,
bool includeBM)
425 return static_cast<int64_t
>(start * 1.0e3);
428 void addEvent(
size_t x,
size_t p,
double tdop,
double taux) {
435 auto y =
static_cast<size_t>(p / HISTO_BINS_Y_DENUMERATOR);
439 size_t id = BM_HISTOGRAMS +
y;
458 xid = xid + DETECTOR_TUBES;
463 if (
id >=
m_roi.size())
489 EventCounter(
const std::vector<bool> &roi,
const std::vector<size_t> &mapIndex,
const size_t stride,
490 const double framePeriod,
const double gatePeriod,
const TimeLimits &timeBoundary,
491 const TimeLimits &directLimits,
const TimeLimits &analysedLimits, std::vector<size_t> &eventCounts,
493 :
EventProcessor(roi, mapIndex, stride, framePeriod, gatePeriod, timeBoundary, directLimits, analysedLimits,
523 if (
x < DETECTOR_TUBES)
524 std::tie(pulse, tof) =
m_convertTOF.analysedTOF(
id, tobs);
526 std::tie(pulse, tof) =
m_convertTOF.directTOF(
id, tobs);
527 offset +=
static_cast<int64_t
>(pulse * 1e3);
535 auto ev = Types::Event::TofEvent(tof, Types::Core::DateAndTime(offset));
543 auto ev = Types::Event::TofEvent(tobs, Types::Core::DateAndTime(offset));
553 EventAssigner(
const std::vector<bool> &roi,
const std::vector<size_t> &mapIndex,
const size_t stride,
554 const double framePeriod,
const double gatePeriod,
const TimeLimits &timeBoundary,
555 const TimeLimits &directLimits,
const TimeLimits &analysedLimits, ConvertTOF &convert,
556 std::vector<EventVector_pt> &eventVectors, int64_t startTime,
bool saveAsTOF,
bool includeBM)
557 :
EventProcessor(roi, mapIndex, stride, framePeriod, gatePeriod, timeBoundary, directLimits, analysedLimits,
567 size_t numBins()
const {
return BEAM_MONITOR_BINS; }
571template <
typename EP>
574 using namespace ANSTO;
578 FileLoader loader(eventFile.c_str());
583 ReadEventFile(loader, eventProcessor, progTracker, 100,
false);
593 std::vector<std::string> exts;
599 exts.emplace_back(
".hdf");
601 exts.emplace_back(
".tar");
603 "The input filename of the stored data");
606 Base::declareProperty(PathToBinaryStr,
"",
607 "Relative or absolute path to the compressed binary\n"
608 "event file linked to the HDF file, eg /storage/data/");
613 exts.emplace_back(
".xml");
615 "The input filename of the mask data");
617 Base::declareProperty(SelectDetectorTubesStr,
"",
618 "Comma separated range of detectors tubes to be loaded,\n"
621 Base::declareProperty(
625 Base::declareProperty(SelectDatasetStr, 0,
"Select the index for the dataset to be loaded.");
628 Base::declareProperty(OverrideDopplerFreqStr,
EMPTY_DBL(),
"Override the Doppler frequency, in Hertz.");
630 Base::declareProperty(OverrideDopplerPhaseStr,
EMPTY_DBL(),
"Override the Doppler phase, in degrees.");
632 Base::declareProperty(CalibrateDopplerPhaseStr,
false,
633 "Calibrate the Doppler phase prior to TOF conversion,\n"
634 "ignored if imported as Doppler time or phase entered");
636 Base::declareProperty(RawDopplerTimeStr,
false,
637 "Import file as observed time relative the Doppler\n"
638 "drive, in microsecs.");
640 Base::declareProperty(IncludePseudoBMStr,
false,
"Include the individual beam monitor events as spectra.");
643 "Only include events after the provided start time, in "
644 "seconds (relative to the start of the run).");
647 "Only include events before the provided stop time, in "
648 "seconds (relative to the start of the run).");
650 std::string grpOptional =
"Filters";
659 m_localWorkspace = std::make_shared<DataObjects::EventWorkspace>();
660 m_localWorkspace->initialize(HISTOGRAMS, 2, 1);
664 m_localWorkspace->setYUnit(
"Counts");
667 m_localWorkspace->setTitle(title);
678template <
typename FD>
void LoadEMU<FD>::exec(
const std::string &hdfFile,
const std::string &eventFile) {
680 namespace fs = boost::filesystem;
684 fs::path p = hdfFile;
685 for (; !p.extension().empty();)
687 std::string title = p.generic_string();
694 logManager.
addProperty(SelectDatasetStr, m_datasetIndex);
695 loadParameters(hdfFile, logManager);
696 prog.
doReport(
"creating instrument");
701 std::string maskfile = Base::getPropertyValue(
MaskStr);
702 std::string seltubes = Base::getPropertyValue(SelectDetectorTubesStr);
703 logManager.
addProperty(SelectDetectorTubesStr, seltubes);
706 std::vector<bool> roi = createRoiVector(seltubes, maskfile);
708 if (Base::isEmpty(timeMaxBoundary))
709 timeMaxBoundary = std::numeric_limits<double>::infinity();
713 auto instr = m_localWorkspace->getInstrument();
714 auto iparam = [&instr](
const std::string &tag) {
return instr->getNumberParameter(tag)[0]; };
720 double sampleAnalyser = iparam(
"SampleAnalyser");
721 auto endID =
static_cast<detid_t>(DETECTOR_TUBES * PIXELS_PER_TUBE);
722 for (
detid_t detID = 0; detID < endID; ++detID)
723 updateNeutronicPostions(detID, sampleAnalyser);
727 std::string dmapStr = instr->getParameterAsString(
"DetectorMap");
728 std::vector<size_t> detMapIndex = std::vector<size_t>(DETECTOR_TUBES, 0);
729 mapRangeToIndex(dmapStr, detMapIndex, [](
size_t n) {
return n; });
734 loadDetectorL2Values();
735 loadDopplerParameters(logManager);
736 double v2 = iparam(
"AnalysedV2");
737 double framePeriod = 1.0e6 / m_dopplerFreq;
738 double sourceSample = iparam(
"SourceSample");
739 ConvertTOF convertTOF(m_dopplerAmpl * m_dopplerRun, m_dopplerFreq, m_dopplerPhase, sourceSample, v2, m_detectorL2);
747 size_t numberHistograms = m_localWorkspace->getNumberHistograms();
748 std::vector<EventVector_pt> eventVectors(numberHistograms,
nullptr);
749 std::vector<size_t> eventCounts(numberHistograms, 0);
755 TimeLimits directLimits(1000.0 * iparam(
"DirectTauxMin"), 1000.0 * iparam(
"DirectTauxMax"));
756 TimeLimits analysedLimits(1000.0 * iparam(
"AnalysedTauxMin"), 1000.0 * iparam(
"AnalysedTauxMax"));
762 bool includeBM = Base::getProperty(IncludePseudoBMStr);
763 EMU::EventCounter eventCounter(roi, detMapIndex, PIXELS_PER_TUBE, framePeriod, gatePeriod, timeBoundary, directLimits,
764 analysedLimits, eventCounts, includeBM);
765 EMU::loadEvents(prog,
"loading neutron counts", eventFile, eventCounter);
767 prepareEventStorage(progTracker, eventCounts, eventVectors);
772 Types::Core::DateAndTime startTime(m_startRun);
773 auto start_nanosec = startTime.totalNanoseconds();
774 bool saveAsTOF = !Base::getProperty(RawDopplerTimeStr);
775 bool loadAsTOF = !m_calibrateDoppler && saveAsTOF;
776 EMU::EventAssigner eventAssigner(roi, detMapIndex, PIXELS_PER_TUBE, framePeriod, gatePeriod, timeBoundary,
777 directLimits, analysedLimits, convertTOF, eventVectors, start_nanosec, loadAsTOF,
779 EMU::loadEvents(prog,
"loading neutron events (TOF)", eventFile, eventAssigner);
782 auto filteredBM = runningAverage(eventAssigner.
beamMonitorCounts(), BM_HALF_WINDOW);
783 auto res = std::minmax_element(filteredBM.begin(), filteredBM.end());
784 auto ratePerSec =
static_cast<double>(eventAssigner.
numBins()) / eventCounter.
duration();
785 auto minBM = *res.first * ratePerSec;
786 auto maxBM = *res.second * ratePerSec;
787 AddSinglePointTimeSeriesProperty<double>(logManager, m_startRun,
"BeamMonitorBkgRate", minBM);
788 AddSinglePointTimeSeriesProperty<double>(logManager, m_startRun,
"BeamMonitorRate", maxBM);
789 AddSinglePointTimeSeriesProperty<int>(logManager, m_startRun,
"MonitorCounts",
790 static_cast<int>(eventAssigner.
bmCounts()));
794 auto minTOF = eventAssigner.
tofMin();
795 auto maxTOF = eventAssigner.
tofMax();
796 if (m_calibrateDoppler) {
797 calibrateDopplerPhase(eventCounts, eventVectors);
799 dopplerTimeToTOF(eventVectors, minTOF, maxTOF);
802 AddSinglePointTimeSeriesProperty<double>(logManager, m_startRun,
"DopplerPhase", m_dopplerPhase);
805 m_localWorkspace->setAllX(HistogramData::BinEdges{std::max(0.0, floor(minTOF)), maxTOF + 1});
806 setupDetectorMasks(roi);
809 auto frame_count = eventCounter.
numFrames();
810 AddSinglePointTimeSeriesProperty<int>(logManager, m_startRun,
"frame_count",
static_cast<int>(frame_count));
813 auto scan_period =
static_cast<double>(frame_count + 1) / m_dopplerFreq;
814 AddSinglePointTimeSeriesProperty<double>(logManager, m_startRun,
"ScanPeriod", scan_period);
816 std::string filename = Base::getPropertyValue(
FilenameStr);
819 Types::Core::time_duration duration =
820 boost::posix_time::microseconds(
static_cast<boost::int64_t
>(eventCounter.
duration() * 1.0e6));
821 Types::Core::DateAndTime endTime(startTime + duration);
822 logManager.
addProperty(
"start_time", startTime.toISO8601String());
823 logManager.
addProperty(
"end_time", endTime.toISO8601String());
827 loadEnvironParameters(hdfFile, logManager);
829 Base::setProperty(
"OutputWorkspace", m_localWorkspace);
836 size_t maskedBins = 0;
837 for (
size_t i = 0; i != roi.size(); i++)
841 if (maskedBins > 0) {
843 std::vector<size_t> maskIndexList(maskedBins);
844 size_t maskIndex = 0;
846 for (
size_t i = 0; i != roi.size(); i++)
848 maskIndexList[maskIndex++] = i;
850 auto maskingAlg = Base::createChildAlgorithm(
"MaskDetectors");
851 maskingAlg->setProperty(
"Workspace", m_localWorkspace);
852 maskingAlg->setProperty(
"WorkspaceIndexList", maskIndexList);
853 maskingAlg->executeAsChildAlg();
859template <
typename FD>
861 std::vector<EventVector_pt> &eventVectors) {
863 size_t numberHistograms = eventCounts.size();
864 for (
size_t i = 0; i != numberHistograms; ++i) {
868 eventList.
reserve(eventCounts[i]);
883 auto instr = m_localWorkspace->getInstrument();
888 m_dopplerFreq = Base::getProperty(OverrideDopplerFreqStr);
889 if (Base::isEmpty(m_dopplerFreq)) {
891 m_dopplerFreq = 0.5 * doppVel / (M_PI * m_dopplerAmpl);
893 AddSinglePointTimeSeriesProperty<double>(logm, m_startRun,
"DopplerFrequency", m_dopplerFreq);
895 m_dopplerPhase = Base::getProperty(OverrideDopplerPhaseStr);
896 m_calibrateDoppler = Base::getProperty(CalibrateDopplerPhaseStr) && Base::isEmpty(m_dopplerPhase);
897 if (Base::isEmpty(m_dopplerPhase)) {
899 double doppThreshold = instr->getNumberParameter(
"DopplerReferenceThreshold")[0];
900 double doppDelay = instr->getNumberParameter(
"DopplerReferenceDelay")[0];
901 m_dopplerPhase = 180.0 - asin(0.001 * doppThreshold / m_dopplerAmpl) * 180.0 / M_PI + doppDelay * m_dopplerFreq;
905 int32_t calPhase = (m_calibrateDoppler ? 1 : 0);
911template <
typename FD>
913 const std::vector<EventVector_pt> &eventVectors) {
916 auto instr = m_localWorkspace->getInstrument();
917 double v2 = instr->getNumberParameter(
"AnalysedV2")[0];
918 double l1 = instr->getNumberParameter(
"SourceSample")[0];
921 auto startID =
static_cast<size_t>(HORIZONTAL_TUBES * PIXELS_PER_TUBE);
922 auto endID =
static_cast<size_t>(DETECTOR_TUBES * PIXELS_PER_TUBE);
924 for (
size_t i = startID; i < endID; i++)
927 throw std::runtime_error(
"no analysed events for phase calibration");
931 constexpr size_t NHIST = 100;
932 std::vector<int> histogram(NHIST + 1, 0);
935 auto costFn = [&,
this](
double phase) {
936 ConvertTOF convTOF(m_dopplerAmpl * m_dopplerRun, m_dopplerFreq, phase, l1, v2, m_detectorL2);
941 for (
size_t i = startID; i < endID; i++) {
942 for (
auto const &
x : *eventVectors[i]) {
943 std::tie(pulse, tof) = convTOF.analysedTOF(i,
x.tof());
944 auto tof1 = 1e-6 * tof - m_detectorL2[i] / v2;
945 nVel[ix++] = l1 / tof1;
950 auto ixlim = std::minmax_element(nVel.begin(), nVel.end());
951 auto vmin = nVel[ixlim.first - nVel.begin()];
952 auto vmax = nVel[ixlim.second - nVel.begin()];
954 std::fill(histogram.begin(), histogram.end(), 0);
955 auto delta = (vmax - vmin) / NHIST;
958 auto j =
static_cast<size_t>(std::floor((v - vmin) /
delta));
960 if (histogram[j] > maxHist)
961 maxHist = histogram[j];
966 auto minLevel =
static_cast<int>(maxHist / 4);
968 nCnd[i] = (histogram[nMap[i]] >= minLevel ? true :
false);
972 auto cost = maskedStdev(nVel, nCnd);
978 int bits = std::numeric_limits<double>::digits;
979 boost::uintmax_t itn = 30;
980 using boost::math::tools::brent_find_minima;
981 auto minPhase = m_dopplerPhase - 5.0;
982 auto maxPhase = m_dopplerPhase + 5.0;
983 auto r = brent_find_minima(costFn, minPhase, maxPhase, bits, itn);
984 m_dopplerPhase = r.first;
989template <
typename FD>
993 auto instr = m_localWorkspace->getInstrument();
994 double v2 = instr->getNumberParameter(
"AnalysedV2")[0];
995 double l1 = instr->getNumberParameter(
"SourceSample")[0];
996 ConvertTOF convTOF(m_dopplerAmpl * m_dopplerRun, m_dopplerFreq, m_dopplerPhase, l1, v2, m_detectorL2);
1001 auto directID =
static_cast<size_t>(DETECTOR_TUBES * PIXELS_PER_TUBE);
1002 for (
size_t id = 0;
id < eventVectors.size();
id++) {
1003 for (
auto &
x : *eventVectors[
id]) {
1006 std::tie(pulse, tof) = convTOF.analysedTOF(
id,
x.tof());
1008 std::tie(pulse, tof) = convTOF.directTOF(
id,
x.tof());
1011 int64_t pulseTime =
x.pulseTime().totalNanoseconds();
1012 pulseTime +=
static_cast<int64_t
>(pulse * 1000);
1013 x = Types::Event::TofEvent(tof, Types::Core::DateAndTime(pulseTime));
1016 minTOF = maxTOF =
x.tof();
1019 minTOF = std::min(minTOF,
x.tof());
1020 maxTOF = std::max(maxTOF,
x.tof());
1029 m_detectorL2 = std::vector<double>(HISTOGRAMS);
1030 const auto &detectorInfo = m_localWorkspace->detectorInfo();
1031 auto detIDs = detectorInfo.detectorIDs();
1032 for (
const auto detID : detIDs) {
1033 auto ix = detectorInfo.indexOf(detID);
1034 double l2 = detectorInfo.l2(ix);
1035 m_detectorL2[detID] =
l2;
1044 auto &compInfo = m_localWorkspace->mutableComponentInfo();
1047 auto component = instrument->getDetector(detID);
1048 double rho, theta, phi;
1052 double scale = -(2 * sampleAnalyser +
rho) /
rho;
1055 const auto componentIndex = compInfo.indexOf(component->getComponentID());
1056 compInfo.setPosition(componentIndex,
position);
1057 }
catch (
const std::runtime_error &) {
1064template <
typename FD>
1067 std::vector<bool> result(HISTOGRAMS,
true);
1070 if (!selected.empty()) {
1072 mapRangeToIndex(selected, tubes, [](
size_t) {
return true; });
1074 if (tubes[i] ==
false) {
1075 for (
size_t j = 0; j < PIXELS_PER_TUBE; j++) {
1076 result[i * PIXELS_PER_TUBE + j] =
false;
1082 if (maskfile.length() == 0)
1085 std::ifstream input(maskfile.c_str());
1087 throw std::invalid_argument(
"invalid mask file");
1090 while (std::getline(input, line)) {
1091 auto i0 = line.find(
"<detids>");
1092 auto iN = line.find(
"</detids>");
1094 if ((i0 != std::string::npos) && (iN != std::string::npos) && (i0 < iN)) {
1095 line = line.substr(i0 + 8, iN - i0 - 8);
1096 mapRangeToIndex(line, result, [](
size_t) {
return false; });
1109 MapNeXusToProperty<std::string>(entry,
"sample/name",
"unknown", logm,
"SampleName",
"", 0);
1110 MapNeXusToProperty<std::string>(entry,
"sample/description",
"unknown", logm,
"SampleDescription",
"", 0);
1113 Types::Core::DateAndTime startTime(GetNeXusValue<std::string>(entry,
"start_time",
"2000-01-01T00:00:00", 0));
1114 if (m_datasetIndex > 0) {
1115 auto baseTime = GetNeXusValue<int32_t>(entry,
"instrument/detector/start_time", 0, 0);
1116 auto nthTime = GetNeXusValue<int32_t>(entry,
"instrument/detector/start_time", 0, m_datasetIndex);
1118 Types::Core::time_duration duration =
1119 boost::posix_time::microseconds(
static_cast<boost::int64_t
>((nthTime - baseTime) * 1.0e6));
1120 Types::Core::DateAndTime startDataset(startTime + duration);
1121 m_startRun = startDataset.toISO8601String();
1123 m_startRun = startTime.toISO8601String();
1126 MapNeXusToSeries<double>(entry,
"instrument/doppler/ctrl/amplitude", 75.0, logm, m_startRun,
"DopplerAmplitude",
1127 0.001, m_datasetIndex);
1128 MapNeXusToSeries<double>(entry,
"instrument/doppler/ctrl/velocity", 4.7, logm, m_startRun,
"DopplerVelocity", 1,
1130 MapNeXusToSeries<int>(entry,
"instrument/doppler/ctrl/run_cmd", 1, logm, m_startRun,
"DopplerRun", 1, m_datasetIndex);
1132 MapNeXusToSeries<double>(entry,
"instrument/chpr/background/actspeed", 1272.8, logm, m_startRun,
1133 "BackgroundChopperFrequency", 1.0 / 60, 0);
1134 MapNeXusToSeries<double>(entry,
"instrument/chpr/graphite/actspeed", 2545.6, logm, m_startRun,
1135 "GraphiteChopperFrequency", 1.0 / 60, 0);
1137 MapNeXusToSeries<double>(entry,
"instrument/hztubegap", 0.02, logm, m_startRun,
"horizontal_tubes_gap", 1.0, 0);
1139 MapNeXusToSeries<double>(entry,
"instrument/source/power", 20.0, logm, m_startRun,
"ReactorPower", 1.0,
1142 MapNeXusToProperty<double>(entry,
"instrument/doppler/tosource", 2.035, logm,
"SourceSample", 1.0, 0);
1154 std::vector<std::string> tags = {
"P01PS03",
"P01PSP03",
"T01S00",
"T01S05",
"T01S06",
"T01SP00",
"T01SP06",
1155 "T02S00",
"T02S04",
"T02S05",
"T02S06",
"T02SP00",
"T02SP06",
"T3S1",
1156 "T3S2",
"T3S3",
"T3S4",
"T3SP1",
"T3SP2",
"T3SP3",
"T3SP4"};
1158 for (
const auto &tag : tags) {
1159 MapNeXusToSeries<double>(entry,
"data/" + tag, 0.0, logm, time_str,
"env_" + tag, 1.0, m_datasetIndex);
1167 auto loadInstrumentAlg = Base::createChildAlgorithm(
"LoadInstrument");
1168 loadInstrumentAlg->setProperty(
"Workspace", m_localWorkspace);
1169 loadInstrumentAlg->setPropertyValue(
"InstrumentName",
"EMUau");
1171 loadInstrumentAlg->executeAsChildAlg();
1194const std::string
LoadEMUHdf::summary()
const {
return "Loads an EMU Hdf and linked event file into a workspace."; }
1202 if (descriptor.
pathExists(
"/entry1/site_name") && descriptor.
pathExists(
"/entry1/instrument/doppler/ctrl/velocity") &&
1203 descriptor.
pathExists(
"/entry1/instrument/doppler/ctrl/amplitude") &&
1204 descriptor.
pathExists(
"/entry1/instrument/detector/daq_dirname") &&
1205 descriptor.
pathExists(
"/entry1/instrument/detector/dataset_number") &&
1206 descriptor.
pathExists(
"/entry1/data/hmm_total_t_ds0") && descriptor.
pathExists(
"/entry1/data/hmm_total_t_ds1") &&
1207 descriptor.
pathExists(
"/entry1/data/hmm_total_xt_ds0") &&
1208 descriptor.
pathExists(
"/entry1/data/hmm_total_xt_ds1")) {
1224 namespace fs = boost::filesystem;
1229 if (evtPath.empty())
1233 if (evtPath.rfind(
"./") == 0 || evtPath.rfind(
"../") == 0) {
1234 fs::path hp = hdfFile;
1235 evtPath = fs::canonical(evtPath, hp.parent_path()).generic_string();
1242 if (fs::is_directory(evtPath)) {
1245 auto eventDir = GetNeXusValue<std::string>(entry,
"instrument/detector/daq_dirname",
"./", 0);
1246 auto dataset = GetNeXusValue<int32_t>(entry,
"instrument/detector/dataset_number", 0,
m_datasetIndex);
1251 char buffer[255] = {};
1252 snprintf(buffer,
sizeof(buffer),
"%s/DATASET_%d/EOS.bin", eventDir.c_str(), dataset);
1253 fs::path path = evtPath;
1255 path = fs::absolute(path);
1256 evtPath = path.generic_string();
1260 if (!fs::is_regular_file(evtPath)) {
1261 std::string msg =
"Check path, cannot open binary event file: " + evtPath;
1262 throw std::runtime_error(msg);
1283 return "Loads an EMU tar file, containing the Hdf and event file, into a "
1297 size_t hdfFiles = 0;
1298 size_t binFiles = 0;
1299 const std::vector<std::string> &subFiles = file.
files();
1300 for (
const auto &subFile : subFiles) {
1301 auto len = subFile.length();
1302 if ((len > 4) && (subFile.find_first_of(
"\\/", 0, 2) == std::string::npos)) {
1303 if ((subFile.rfind(
".hdf") == len - 4) && (subFile.compare(0, 3,
"EMU") == 0))
1305 else if (subFile.rfind(
".bin") == len - 4)
1310 return (hdfFiles == 1) && (binFiles == 1) ? 50 : 0;
1325 if (!tarFile.
good())
1326 throw std::invalid_argument(
"invalid EMU tar file");
1333 const std::vector<std::string> &files = tarFile.
files();
1334 auto selectFile = [&](
const std::string &ext) {
1335 auto itf = std::find_if(files.cbegin(), files.cend(),
1336 [&ext](
const std::string &file) { return file.rfind(ext) == file.length() - 4; });
1337 if (itf == files.end())
1338 throw std::runtime_error(
"missing tar file data");
1340 tarFile.
select(itf->c_str());
1342 auto extractFile = [&](Poco::TemporaryFile &tfile) {
1343 std::shared_ptr<FILE> handle(fopen(tfile.path().c_str(),
"wb"), fclose);
1348 while (0 != (bytesRead = tarFile.
read(buffer,
sizeof(buffer))))
1349 fwrite(buffer, bytesRead, 1, handle.get());
1356 Poco::TemporaryFile hdfFile;
1357 extractFile(hdfFile);
1361 Poco::TemporaryFile eventFile;
1362 extractFile(eventFile);
double value
The value of the point.
std::map< DeltaEMode::Type, std::string > index
const std::vector< double > & m_L2
#define DECLARE_NEXUS_FILELOADER_ALGORITHM(classname)
DECLARE_NEXUS_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM macro wh...
#define DECLARE_FILELOADER_ALGORITHM(classname)
DECLARE_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM macro when wri...
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 void init()=0
Virtual method - must be overridden by concrete algorithm.
virtual void exec()=0
Virtual method - must be overridden by concrete algorithm.
@ 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 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)
size_t read(void *dst, size_t size)
bool select(const char *file)
const std::vector< std::string > & files() const
std::vector< EventVector_pt > & m_eventVectors
const std::vector< size_t > & beamMonitorCounts() const
EventAssigner(const std::vector< bool > &roi, const std::vector< size_t > &mapIndex, const size_t stride, const double framePeriod, const double gatePeriod, const TimeLimits &timeBoundary, const TimeLimits &directLimits, const TimeLimits &analysedLimits, ConvertTOF &convert, std::vector< EventVector_pt > &eventVectors, int64_t startTime, bool saveAsTOF, bool includeBM)
void addEventImpl(size_t id, size_t x, size_t, double tobs) override
std::vector< size_t > m_bmCounts
void addPseudoBMEventImpl(size_t id, double tobs) override
const ConvertTOF & m_convertTOF
EventCounter(const std::vector< bool > &roi, const std::vector< size_t > &mapIndex, const size_t stride, const double framePeriod, const double gatePeriod, const TimeLimits &timeBoundary, const TimeLimits &directLimits, const TimeLimits &analysedLimits, std::vector< size_t > &eventCounts, bool includeBM)
void addEventImpl(size_t id, size_t, size_t, double) override
void addPseudoBMEventImpl(size_t id, double) override
std::vector< size_t > & m_eventCounts
const double m_framePeriod
const std::vector< bool > & m_roi
const TimeLimits m_directTaux
void addEvent(size_t x, size_t p, double tdop, double taux)
const std::vector< size_t > & m_mapIndex
virtual void addEventImpl(size_t id, size_t x, size_t y, double tof)=0
const double m_gatePeriod
int64_t frameStart() const
EventProcessor(const std::vector< bool > &roi, const std::vector< size_t > &mapIndex, const size_t stride, const double framePeriod, const double gatePeriod, TimeLimits timeBoundary, TimeLimits directLimits, TimeLimits analysedLimits, bool includeBM)
virtual void addPseudoBMEventImpl(size_t id, double tobs)=0
const TimeLimits m_analysedTaux
const TimeLimits m_timeBoundary
LoadEMUHdf : Loads an ANSTO EMU Hdf and linked event file into a workspace.
const std::vector< std::string > seeAlso() const override
Similar algorithms.
void exec() override
Execute the algorithm.
int version() const override
Algorithm's version for identification.
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
const std::string name() const override
Algorithms name for identification.
const std::string category() const override
Algorithm's category for identification.
void init() override
Initialise the algorithm and declare the properties for the nexus descriptor.
int confidence(Kernel::NexusDescriptor &descriptor) const override
Return the confidence as an integer value that this algorithm can load the file descriptor.
LoadEMUTar : Loads a merged ANSTO EMU Hdf and event file into a workspace.
int version() const override
Algorithm's version for identification.
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
const std::string name() const override
Algorithms name for identification.
int confidence(Kernel::FileDescriptor &descriptor) const override
Return the confidence as an integer value that this algorithm can load the file descriptor.
const std::string category() const override
Algorithm's category for identification.
void exec() override
Execute the algorithm.
const std::vector< std::string > seeAlso() const override
Similar algorithms.
void init() override
Initialise the algorithm and declare the standard properties for the general file descriptor.
void prepareEventStorage(ANSTO::ProgressTracker &prog, const std::vector< size_t > &eventCounts, std::vector< EventVector_pt > &eventVectors)
Allocate space for the event storage in eventVectors after the eventCounts have been determined.
void calibrateDopplerPhase(const std::vector< size_t > &eventCounts, const std::vector< EventVector_pt > &eventVectors)
Calibrate the doppler phase based on the analysed events using the eventCounts and eventVectors.
std::vector< bool > createRoiVector(const std::string &seltubes, const std::string &maskfile)
Region of interest is defined by the selected detectors and the maskfile.
void loadInstrument()
Load the instrument definition.
void loadParameters(const std::string &hdfFile, API::LogManager &logm)
Load parameters from input hdfFile and save to the log manager, logm.
void dopplerTimeToTOF(std::vector< EventVector_pt > &eventVectors, double &minTOF, double &maxTOF)
Convert the doppler time to TOF for all the events in eventVectors and time of flight range as minTOF...
void loadDetectorL2Values()
Recovers the L2 neutronic distance for each detector.
void setupDetectorMasks(const std::vector< bool > &roi)
Set up the detector masks to the region of interest roi.
void updateNeutronicPostions(detid_t detID, double sampleAnalyser)
Update the neutronic position for the detID using the distance from the source and the sample to anal...
void loadDopplerParameters(API::LogManager &logm)
Get the Doppler parameters and record to the log manager, logm.
void createWorkspace(const std::string &title)
Creates an event workspace and sets the title.
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,...
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.
Defines a wrapper around an open file.
const std::string & filename() const
Access the filename.
const std::string & extension() const
Access the file extension.
Defines a wrapper around a file whose internal structure can be accessed using the NeXus API.
const std::string & extension() const
Access the file extension.
bool pathExists(const std::string &path) const
Query if a path exists.
OptionalBool : Tri-state bool.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
A specialised Property class for holding a series of time-value pairs.
NXDataSetTyped< T > openNXDataSet(const std::string &name) const
Templated method for creating datasets.
Templated class implementation of NXDataSet.
void load(const int blocksize=1, int i=-1, int j=-1, int k=-1, int l=-1) override
Implementation of the virtual NXDataSet::load(...) method.
Implements NXentry Nexus class.
Implements NXroot Nexus class.
NXEntry openFirstEntry()
Open the first NXentry in the file.
std::shared_ptr< T > createWorkspace(InitArgs... args)
void loadEvents(API::Progress &prog, const char *progMsg, const std::string &eventFile, EP &eventProcessor)
static char const *const FilenameStr
static const size_t HISTO_BINS_X
static const size_t HISTO_BINS_Y
static const size_t Progress_LoadBinFile
void AddSinglePointTimeSeriesProperty(API::LogManager &logManager, const std::string &time, const std::string &name, const TYPE value)
std::size_t numEvents(::NeXus::File &file, bool &hasTotalCounts, bool &oldNeXusFileNames, const std::string &prefix, const NexusHDF5Descriptor &descriptor)
Get the number of events in the currently opened group.
static char const *const MaskStr
static char const *const FilterByTimeStartStr
static const size_t Progress_Total
static char const *const FilterByTimeStopStr
static const size_t Progress_ReserveMemory
DLLExport void getEventsFrom(EventList &el, std::vector< Types::Event::TofEvent > *&events)
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
NXDataSetTyped< char > NXChar
The char dataset type.
int32_t detid_t
Typedef for a detector ID.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
@ Output
An output workspace.