20#include "MantidHistogramData/Histogram.h"
29#include <boost/algorithm/string.hpp>
30#include <boost/filesystem.hpp>
40const std::map<std::string, std::string> MONTHS{{
"JAN",
"01"}, {
"FEB",
"02"}, {
"MAR",
"03"}, {
"APR",
"04"},
41 {
"MAY",
"05"}, {
"JUN",
"06"}, {
"JUL",
"07"}, {
"AUG",
"08"},
42 {
"SEP",
"09"}, {
"OCT",
"10"}, {
"NOV",
"11"}, {
"DEC",
"12"}};
43const std::vector<std::string> PSI_MONTHS{
"JAN",
"FEB",
"MAR",
"APR",
"MAY",
"JUN",
44 "JUL",
"AUG",
"SEP",
"OCT",
"NOV",
"DEC"};
45constexpr int TEMPERATURE_FILE_MAX_SEARCH_DEPTH = 3;
46constexpr auto TEMPERATURE_FILE_EXT =
".mon";
58 return "Loads a data file that is in PSI Muon Binary format into a "
59 "workspace (Workspace2D class).";
66 auto &stream = descriptor.
data();
68 std::string fileFormat;
69 streamReader.
read(fileFormat, 2);
70 if (fileFormat !=
"1N") {
81 const std::vector<std::string> exts{
".bin"};
83 "The name of the Bin file to load");
85 const std::vector<std::string> extsTemps{
".mon"};
86 declareProperty(std::make_unique<Mantid::API::FileProperty>(
"TemperatureFilename",
"",
88 "The name of the temperature file to be loaded, this is optional as it "
89 "will be automatically searched for if not provided.");
93 "An output workspace.");
96 "If no temp file has been given decide whether the algorithm "
97 "will search for the temperature file.");
107 "This property should only be set in the GUI and is present to work with "
108 "the Muon GUI preprocessor.");
110 declareProperty(
"MainFieldDirection", 0,
"The field direction of the magnetic field on the instrument",
114 "A vector of time zero values");
118 "TableWorkspace of time zeros for each spectra");
120 declareProperty(
"CorrectTime",
true,
"Boolean flag controlling whether time should be corrected by timezero.",
125 "Table or a group of tables with information about the "
126 "detector grouping stored in the file (if any).");
127 auto mustBePositive = std::make_shared<Kernel::BoundedValidator<specnum_t>>();
128 mustBePositive->setLower(0);
130 "Index number of the first spectrum to read\n");
132 "Index of last spectrum to read\n"
133 "(default the last spectrum)");
138 if (
sizeof(
float) != 4) {
142 throw std::runtime_error(
"A float on this machine is not 32 bits");
147 std::ifstream binFile(binFilename, std::ios::in | std::ios::binary);
151 std::string fileFormat;
152 streamReader.
read(fileFormat, 2);
153 if (fileFormat !=
"1N") {
154 throw std::runtime_error(
"Loaded file is not of PSIMuonBin type (First 2 bytes != 1N)");
168 Mantid::HistogramData::Histogram(Mantid::HistogramData::BinEdges(sizeOfXForHistograms)));
170 for (
auto specNum = 0u; specNum <
m_histograms.size(); ++specNum) {
171 outputWorkspace->mutableX(specNum) =
m_xAxis;
172 outputWorkspace->mutableY(specNum) =
m_histograms[specNum];
173 outputWorkspace->mutableE(specNum) =
m_eAxis[specNum];
174 outputWorkspace->getSpectrum(specNum).setDetectorID(specNum + 1);
183 auto largestBinValue = outputWorkspace->x(0)[outputWorkspace->x(0).size() - 1];
188 setProperty(
"LastGoodData", outputWorkspace->x(0)[lastGoodDataSpecIndex]);
190 double timeZero = 0.0;
191 std::vector<double> timeZeroList;
203 double absTimeZero = timeZero;
204 std::vector<double> correctedTimeZeroList;
205 if (timeZero > largestBinValue) {
206 absTimeZero = outputWorkspace->x(0)[
static_cast<int>(std::floor(timeZero))];
207 std::transform(timeZeroList.cbegin(), timeZeroList.cend(), std::back_inserter(correctedTimeZeroList),
208 [&outputWorkspace](
const auto timeZeroValue) {
209 return outputWorkspace->x(0)[static_cast<int>(std::floor(timeZeroValue))];
212 correctedTimeZeroList = timeZeroList;
216 setProperty(
"TimeZeroList", correctedTimeZeroList);
226 setProperty(
"FirstGoodData", outputWorkspace->x(0)[firstGoodDataSpecIndex]);
233 for (
auto specNum = 0u; specNum <
m_histograms.size(); ++specNum) {
234 auto &xData = outputWorkspace->mutableX(specNum);
235 std::transform(xData.cbegin(), xData.cend(), xData.begin(),
236 [absTimeZero](
const auto &xValue) { return xValue - absTimeZero; });
249 std::dynamic_pointer_cast<Mantid::DataObjects::TableWorkspace>(
251 detectorTable->addColumn(
"vector_int",
"detector");
252 for (
size_t i = 0; i < numSpec; i++) {
253 std::vector<int> dets{
static_cast<int>(i) + 1};
257 setProperty(
"DetectorGroupingTable", detectorTable);
264 std::dynamic_pointer_cast<Mantid::DataObjects::TableWorkspace>(
266 assert(deadTimeTable);
267 deadTimeTable->addColumn(
"int",
"spectrum");
268 deadTimeTable->addColumn(
"double",
"dead-time");
270 for (
size_t i = 0; i < numSpec; i++) {
272 row << static_cast<int>(i) + 1 << 0.0;
279 if (date.size() == 11) {
280 year = date.substr(7, 4);
282 year =
"20" + date.substr(7, 2);
284 return year +
"-" + MONTHS.find(date.substr(3, 3))->second +
"-" + date.substr(0, 2) +
"T" + time;
314 static_cast<float>((625.E-6) / 8. * pow(
static_cast<float>(2.),
static_cast<float>(
m_header.
tdcResolution)));
387 for (
auto i = 0u; i <= 5; ++i) {
395 for (
auto i = 6u; i < 18; ++i) {
403 for (
auto i = 0u; i <= 15; ++i) {
420 for (
auto i = 0u; i < 4; ++i) {
442 constexpr auto sizeInt32_t =
sizeof(int32_t);
443 const auto headerSize = 1024;
447 std::vector<double> &nextHistogram =
m_histograms[histogramIndex];
451 int32_t nextReadValue;
452 streamReader >> nextReadValue;
453 nextHistogram.emplace_back(nextReadValue);
461 for (
auto xIndex = 0u; xIndex <=
m_histograms[0].size(); ++xIndex) {
467 std::vector<double> newEAxis;
468 for (
auto eIndex = 0u; eIndex <
m_histograms[0].size(); ++eIndex) {
469 newEAxis.emplace_back(sqrt(histogram[eIndex]));
471 m_eAxis.emplace_back(newEAxis);
477 logAlg->setProperty(
"Workspace", ws);
483 alg->setProperty(
"InputWorkspace", ws);
484 alg->setProperty(
"OutputWorkspace",
"not_used");
487 alg->executeAsChildAlg();
488 return alg->getProperty(
"OutputWorkspace");
494 alg->setProperty(
"LogType",
"String");
495 alg->setProperty(
"LogName", logName);
496 alg->setProperty(
"LogText", logText);
497 alg->executeAsChildAlg();
503 alg->setProperty(
"LogType",
"Number");
504 alg->setProperty(
"NumberType",
"Double");
505 alg->setProperty(
"LogName", logName);
507 alg->executeAsChildAlg();
513 alg->setProperty(
"LogType",
"Number");
514 alg->setProperty(
"NumberType",
"Int");
515 alg->setProperty(
"LogName", logName);
517 alg->executeAsChildAlg();
526 outputWorkspace->mutableRun().addProperty(
"run_number",
static_cast<int>(
m_header.
numberOfRuns));
529 outputWorkspace->setYUnit(
"Counts");
530 std::shared_ptr<Kernel::Units::Label> lblUnit =
533 outputWorkspace->getAxis(0)->unit() = lblUnit;
539 Mantid::Types::Core::DateAndTime start(startDate);
540 Mantid::Types::Core::DateAndTime end(endDate);
541 outputWorkspace->mutableRun().setStartAndEndTime(start, end);
542 }
catch (
const std::logic_error &) {
543 Mantid::Types::Core::DateAndTime start;
544 Mantid::Types::Core::DateAndTime end;
545 outputWorkspace->mutableRun().setStartAndEndTime(start, end);
562 }
catch (std::invalid_argument &) {
563 g_log.
warning(
"The \"sample_temp\" could not be converted to a number for "
564 "the sample log so has been added as a string");
570 for (
auto tempNum = 1u; tempNum < sizeOfTemps + 1; ++tempNum) {
592 }
catch (std::invalid_argument &) {
593 g_log.
warning(
"The \"Field\" could not be converted to a number for "
594 "the sample log so has been added as a string");
600 for (
auto i = 0u; i < sizeOfScalars; ++i) {
609 for (
auto i = 0u; i < sizeOfLabels; ++i) {
616 const bool isSpace =
name.find_first_not_of(
" ") == std::string::npos;
626 for (
size_t i = 0; i < sizeOfFirstGood; ++i) {
646 for (
auto i = 0u; i < sizeOfMonLow; ++i) {
659 for (
auto i = 0u; i < 16; ++i) {
668 for (
auto i = 0u; i < 16; ++i) {
678 }
catch (std::invalid_argument &e) {
679 g_log.
warning(
"Temperature file was not be loaded: " + std::string(e.what()));
680 }
catch (std::runtime_error &e) {
681 g_log.
warning(
"Temperature file was not be loaded:" + std::string(e.what()));
686std::string findTitlesFromLine(
const std::string &line) {
687 bool titlesFound =
false;
688 std::string foundTitles =
"";
689 for (
const auto &charecter : line) {
690 if (charecter ==
':') {
692 }
else if (titlesFound) {
693 foundTitles += charecter;
701 auto foundTitles = findTitlesFromLine(line);
702 boost::trim(foundTitles);
703 if (foundTitles.find(
"\\") == std::string::npos) {
717 auto date = line.substr(2, 11);
718 auto _time = line.substr(14, 8);
723 if (line.find(
"Title") != std::string::npos) {
726 }
else if (std::find(std::begin(PSI_MONTHS), std::end(PSI_MONTHS), line.substr(5, 3)) != std::end(PSI_MONTHS)) {
735 const int uselessLines = 6;
737 std::string line =
"";
738 for (
const auto charecter : contents) {
739 if (charecter ==
'\n') {
740 if (line.empty() || line[0] !=
'!') {
742 }
else if (lineNo > uselessLines) {
754 std::vector<std::string> segments;
755 boost::split(segments, line, boost::is_any_of(
"\\"));
758 if (segments.size() != 5) {
759 throw std::runtime_error(
"Line does not have 5 segments delimited by \\: '" + line +
"'");
761 const auto recordTime = segments[0];
762 const auto numValues = std::stoi(segments[1]);
763 std::vector<std::string> firstValues;
764 boost::split(firstValues, segments[2], boost::is_any_of(
" "));
765 std::vector<std::string> secondValues;
766 boost::split(secondValues, segments[3], boost::is_any_of(
" "));
770 double secondsInRecordTime = (std::stoi(recordTime.substr(0, 2)) * 60 * 60) +
771 (std::stoi(recordTime.substr(3, 2)) * 60) +
772 (std::stoi(recordTime.substr(6, 2)));
776 logAlg->setProperty(
"Workspace", ws);
777 logAlg->setProperty(
"Time", timeLog);
779 for (
auto i = 0; i < numValues; ++i) {
781 logAlg->setProperty(
"Type",
"double");
782 logAlg->setProperty(
"Value", firstValues[i]);
783 logAlg->executeAsChildAlg();
787 logAlg->setProperty(
"Type",
"double");
788 logAlg->setProperty(
"Value", firstValues[0]);
789 logAlg->executeAsChildAlg();
792 logAlg->setProperty(
"Type",
"double");
793 logAlg->setProperty(
"Value", secondValues[0]);
794 logAlg->executeAsChildAlg();
803 namespace fs = boost::filesystem;
804 const fs::path searchDir{fs::path{
getPropertyValue(
"Filename")}.parent_path()};
806 std::deque<fs::path> queue{fs::path{searchDir}};
807 while (!queue.empty()) {
808 const auto first = queue.front();
810 for (fs::directory_iterator dirIter{first}; dirIter != fs::directory_iterator(); ++dirIter) {
811 const auto &entry{dirIter->path()};
813 if (fs::is_directory(entry)) {
814 const auto relPath{entry.lexically_relative(searchDir)};
815 if (std::distance(relPath.begin(), relPath.end()) < TEMPERATURE_FILE_MAX_SEARCH_DEPTH) {
818 queue.push_back(entry);
820 }
else if (entry.extension() == TEMPERATURE_FILE_EXT &&
822 return entry.string();
832 const bool searchForTempFile =
getProperty(
"SearchForTempFile");
833 if (fileName ==
"" && searchForTempFile) {
837 if (fileName ==
"") {
838 throw std::invalid_argument(
"No temperature file could be found/was provided");
841 g_log.
notice(
"Temperature file in use by LoadPSIMuonBin: '" + fileName +
"'");
843 std::ifstream in(fileName, std::ios::in);
844 std::string contents;
845 in.seekg(0, std::ios::end);
846 contents.resize(in.tellg());
847 in.seekg(0, std::ios::beg);
848 in.read(&contents[0], contents.size());
853 std::string line =
"";
854 for (
const auto &character : contents) {
855 if (character ==
'\n') {
856 if (!line.empty() && line[0] ==
'!') {
#define DECLARE_FILELOADER_ALGORITHM(classname)
DECLARE_FILELOADER_ALGORITHM should be used in place of the standard DECLARE_ALGORITHM macro when wri...
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.
@ 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
TableRow represents a row in a TableWorkspace.
A property class for workspaces.
std::vector< std::vector< double > > m_eAxis
bool loadMutipleAsOne() override
Returns a value indicating whether or not loader wants to load multiple files into a single workspace...
void readInHeader(Mantid::Kernel::BinaryStreamReader &streamReader)
int version() const override
function to return a version of the algorithm, must be overridden in all algorithms
void exec() override
Virtual method - must be overridden by concrete algorithm.
void readArrayVariables(Mantid::Kernel::BinaryStreamReader &streamReader)
void readInTemperatureFileHeader(const std::string &contents)
void processDateHeaderLine(const std::string &line)
struct headerData m_header
struct temperatureHeaderData m_tempHeader
const std::string summary() const override
function returns a summary message that will be displayed in the default GUI, and in the help.
void readInHistograms(Mantid::Kernel::BinaryStreamReader &streamReader)
void readInTemperatureFile(DataObjects::Workspace2D_sptr &ws)
void init() override
Virtual method - must be overridden by concrete algorithm.
std::vector< std::vector< double > > m_histograms
void processLine(const std::string &line, DataObjects::Workspace2D_sptr &ws)
void readSingleVariables(Mantid::Kernel::BinaryStreamReader &streamReader)
void processTitleHeaderLine(const std::string &line)
Mantid::API::Algorithm_sptr createSampleLogAlgorithm(DataObjects::Workspace2D_sptr &ws)
void processHeaderLine(const std::string &line)
void assignOutputWorkspaceParticulars(DataObjects::Workspace2D_sptr &outputWorkspace)
int confidence(Kernel::FileDescriptor &descriptor) const override
Returns a confidence value that this algorithm can load a file.
void generateUnknownAxis()
const std::string category() const override
function to return a category of the algorithm.
std::string detectTempFile()
void makeDeadTimeTable(const size_t &numSpec)
API::MatrixWorkspace_sptr extractSpectra(DataObjects::Workspace2D_sptr &ws)
void addToSampleLog(const std::string &logName, const std::string &logText, DataObjects::Workspace2D_sptr &ws)
const std::string name() const override
function to return a name of the algorithm, must be overridden in all algorithms
void setDetectorGroupingTable(const size_t &numSpec)
std::vector< double > m_xAxis
std::string getFormattedDateTime(const std::string &date, const std::string &time)
void readStringVariables(Mantid::Kernel::BinaryStreamReader &streamReader)
Support for a property that holds an array of values.
Assists with reading a binary file by providing standard overloads for the istream operators (>>) to ...
BinaryStreamReader & read(std::vector< int16_t > &value, const size_t nvals)
Read an array of int16_t into the given vector.
void moveStreamToPosition(size_t nbytes)
Move the stream to nbytes past the beginning of the file.
Defines a wrapper around an open file.
std::istream & data()
Access the open file stream.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void notice(const std::string &msg)
Logs at notice level.
void warning(const std::string &msg)
Logs at warning level.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
static const UnitLabel Microsecond
Microsecond.
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
DataObjects::TableWorkspace_sptr createTimeZeroTable(const size_t numSpec, const std::vector< double > &timeZeros)
Creates a timezero table for the loaded detectors.
std::shared_ptr< Workspace2D > Workspace2D_sptr
shared pointer to Mantid::DataObjects::Workspace2D
std::shared_ptr< TableWorkspace > TableWorkspace_sptr
shared pointer to Mantid::DataObjects::TableWorkspace
std::unique_ptr< T > create(const P &parent, const IndexArg &indexArg, const HistArg &histArg)
This is the create() method that all the other create() methods call.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
int32_t specnum_t
Typedef for a spectrum Number.
std::string to_string(const wide_integer< Bits, Signed > &n)
int16_t numberOfDataRecordsHistogram
int16_t lengthOfDataRecordsBin
std::string labels_scalars[18]
float temperatureDeviation[4]
int16_t lengthOfHistograms
int16_t numberOfHistograms
std::string labelsOfHistograms[16]
int16_t numberOfHistogramsPerRecord
int32_t monNumberOfevents
int16_t numberOfDataRecordsFile
bool delimeterOfTitlesIsBackSlash
std::string startDateTime
std::vector< std::string > titles
@ Input
An input workspace.
@ Output
An output workspace.