From 801a4890e7a9bc5cfab837c413e031fa77fd03a1 Mon Sep 17 00:00:00 2001 From: Owen Arnold <owen.arnold@stfc.ac.uk> Date: Mon, 29 Jun 2015 12:49:05 +0100 Subject: [PATCH] refs #12776. Write individual period logs. --- .../inc/MantidDataHandling/LoadEventNexus.h | 8 +- .../DataHandling/src/LoadEventNexus.cpp | 74 ++++++++++--------- .../DataHandling/src/LoadNexusLogs.cpp | 4 + .../DataHandling/src/LoadTOFRawNexus.cpp | 5 +- .../DataHandling/test/LoadEventNexusTest.h | 10 +++ .../DataHandling/test/LoadNexusLogsTest.h | 28 ++++++- 6 files changed, 85 insertions(+), 44 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadEventNexus.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadEventNexus.h index 383ae1bf6c6..eee8e2f5621 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadEventNexus.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadEventNexus.h @@ -11,6 +11,7 @@ #include "MantidDataObjects/Events.h" #include "MantidAPI/WorkspaceGroup.h" #include "MantidKernel/TimeSeriesProperty.h" +#include <memory> namespace Mantid { @@ -58,7 +59,7 @@ private: public: - void setNPeriods(size_t nPeriods); + void setNPeriods(size_t nPeriods, std::unique_ptr<const Kernel::TimeSeriesProperty<int> >& periodLog); void reserveEventListAt(size_t wi, size_t size){ for(size_t i = 0; i < m_WsVec.size(); ++i){ @@ -252,7 +253,7 @@ public: static boost::shared_ptr<BankPulseTimes> runLoadNexusLogs(const std::string &nexusfilename, API::MatrixWorkspace_sptr localWorkspace, Algorithm &alg, - bool returnpulsetimes, int& size_t); + bool returnpulsetimes, int& size_t, std::unique_ptr<const Kernel::TimeSeriesProperty<int> >& periodLog); static void loadEntryMetadata(const std::string &nexusfilename, Mantid::API::MatrixWorkspace_sptr WS, @@ -430,9 +431,6 @@ private: /// to open the nexus file with specific exception handling/message void safeOpenFile(const std::string fname); - /// Fetch the periods corresponding to the frame - std::vector<int> fetchFramePeriods(); - /// Was the instrument loaded? bool m_instrument_loaded_correctly; diff --git a/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp b/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp index 645dd5e6735..d6403d34432 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadEventNexus.cpp @@ -1424,33 +1424,6 @@ void LoadEventNexus::createWorkspaceIndexMaps(const bool monitors, pixelID_to_wi_offset, true); } -/** - * Fetch the period numbers corresponding to each frame. - * @return vector of period numbers, should have as many as we have frames. Indexes correspond to period numbers. - */ -std::vector<int> LoadEventNexus::fetchFramePeriods() -{ - std::vector<int> periodLog(1, BankPulseTimes::FirstPeriod); // One entry, all period 1. in call any of the below is missing. - try { - m_file->openGroup(m_top_entry_name, "NXentry"); - m_file->openGroup("framelog", "NXcollection"); - try { - m_file->openGroup("period_log", "NXlog"); - m_file->openData("value"); - std::vector<int> temp; - m_file->getData(temp); - periodLog = temp; - m_file->closeData(); - m_file->closeGroup(); - } catch (::NeXus::Exception &) { - } - m_file->closeGroup(); - m_file->closeGroup(); - } catch (::NeXus::Exception & ex) { - } - return periodLog; -} - //----------------------------------------------------------------------------- /** * Load events from the file. @@ -1473,11 +1446,12 @@ void LoadEventNexus::loadEvents(API::Progress *const prog, // Initialize the counter of bad TOFs bad_tofs = 0; int nPeriods = 1; + std::unique_ptr<const TimeSeriesProperty<int> > periodLog(new const TimeSeriesProperty<int>("period_log")); if (!m_logs_loaded_correctly) { if (loadlogs) { prog->doReport("Loading DAS logs"); - m_allBanksPulseTimes = runLoadNexusLogs(m_filename, m_ws, *this, true, nPeriods); + m_allBanksPulseTimes = runLoadNexusLogs(m_filename, m_ws, *this, true, nPeriods, periodLog); run_start = m_ws->getFirstPulseTime(); m_logs_loaded_correctly = true; @@ -1496,7 +1470,7 @@ void LoadEventNexus::loadEvents(API::Progress *const prog, true); } } - m_ws->setNPeriods(nPeriods); // This is how many workspaces we are going to make. + m_ws->setNPeriods(nPeriods, periodLog); // This is how many workspaces we are going to make. // Make sure you have a non-NULL m_allBanksPulseTimes if (m_allBanksPulseTimes == NULL) { @@ -1786,14 +1760,14 @@ void LoadEventNexus::loadEvents(API::Progress *const prog, numProg += bankNames.size() * 3; // 3 = second proc task Progress *prog2 = new Progress(this, 0.3, 1.0, numProg); - const std::vector<int> periodLog = fetchFramePeriods(); + const std::vector<int> periodLogVec = periodLog->valuesAsVector(); for (size_t i = bank0; i < bankn; i++) { // We make tasks for loading if (bankNumEvents[i] > 0) pool.schedule(new LoadBankFromDiskTask( this, bankNames[i], classType, bankNumEvents[i], oldNeXusFileNames, - prog2, diskIOMutex, scheduler, periodLog)); + prog2, diskIOMutex, scheduler, periodLogVec)); } // Start and end all threads pool.joinAll(); @@ -1850,15 +1824,35 @@ EventWorkspace_sptr DecoratorWorkspace::createEmptyEventWorkspace() const { return eventWS; } -void DecoratorWorkspace::setNPeriods(size_t nPeriods) { +void DecoratorWorkspace::setNPeriods(size_t nPeriods, std::unique_ptr<const TimeSeriesProperty<int> >& periodLog) { // Create vector where size is the number of periods and initialize workspaces in each. auto temp = m_WsVec[0]; m_WsVec = std::vector<DataObjects::EventWorkspace_sptr>( nPeriods); + std::vector<int> periodNumbers = periodLog->valuesAsVector(); + std::set<int> uniquePeriods(periodNumbers.begin(), periodNumbers.end()); + const bool addBoolTimeSeries = (uniquePeriods.size() == nPeriods); + for (size_t i = 0; i < m_WsVec.size(); ++i) { + const int periodNumber = int(i+1); m_WsVec[i] = createEmptyEventWorkspace(); + if(addBoolTimeSeries) { + std::stringstream buffer; + buffer << "period " << periodNumber; + auto * periodBoolLog = new Kernel::TimeSeriesProperty<bool>(buffer.str()); + for(int j = 0; j < int(periodLog->size()); ++j){ + periodBoolLog->addValue(periodLog->nthTime(j), periodNumber == periodLog->nthValue(j)); + } + Run& mutableRun = m_WsVec[i]->mutableRun(); + mutableRun.addProperty(periodBoolLog); + + Kernel::PropertyWithValue<int> *currentPeriodProperty = + new Kernel::PropertyWithValue<int>("current_period", periodNumber); + mutableRun.addProperty(currentPeriodProperty); + } + copyLogs(temp, m_WsVec[i]); // Copy all logs from dummy workspace to period workspaces. m_WsVec[i]->setInstrument(temp->getInstrument()); } @@ -2935,13 +2929,15 @@ void LoadEventNexus::filterDuringPause(API::MatrixWorkspace_sptr workspace) { * @param alg :: Handle of the algorithm * @param returnpulsetimes :: flag to return shared pointer for BankPulseTimes, *otherwise NULL. +* @param nPeriods : Number of periods (write to) +* @param periodLog : Period logs DateAndTime to int map. * * @return Pulse times given in the DAS logs */ boost::shared_ptr<BankPulseTimes> LoadEventNexus::runLoadNexusLogs(const std::string &nexusfilename, API::MatrixWorkspace_sptr localWorkspace, - API::Algorithm &alg, bool returnpulsetimes, int& nPeriods) { + API::Algorithm &alg, bool returnpulsetimes, int& nPeriods, std::unique_ptr<const TimeSeriesProperty<int> >& periodLog) { // --------------------- Load DAS Logs ----------------- // The pulse times will be empty if not specified in the DAS logs. // BankPulseTimes * out = NULL; @@ -2957,10 +2953,16 @@ LoadEventNexus::runLoadNexusLogs(const std::string &nexusfilename, localWorkspace); loadLogs->execute(); - if(localWorkspace->run().hasProperty("nperiods")){ - nPeriods = localWorkspace->run().getPropertyValueAsType<int>("nperiods"); + const Run& run = localWorkspace->run(); + // Get the number of periods + if(run.hasProperty("nperiods")){ + nPeriods = run.getPropertyValueAsType<int>("nperiods"); + } + // Get the period log. Map of DateAndTime to Period int values. + if(run.hasProperty("period_log")){ + auto* temp = run.getProperty("period_log"); + periodLog.reset(dynamic_cast<TimeSeriesProperty<int>*>(temp->clone())); } - // If successful, we can try to load the pulse times Kernel::TimeSeriesProperty<double> *log = diff --git a/Code/Mantid/Framework/DataHandling/src/LoadNexusLogs.cpp b/Code/Mantid/Framework/DataHandling/src/LoadNexusLogs.cpp index 4188589f3c0..d20d6326ae8 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadNexusLogs.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadNexusLogs.cpp @@ -315,6 +315,10 @@ void LoadNexusLogs::loadLogs( } else if (log_class == "IXseblock") { loadSELog(file, itr->first, workspace); } + else if(log_class == "NXcollection"){ + int jj = 0; + ++jj; + } } loadVetoPulses(file, workspace); diff --git a/Code/Mantid/Framework/DataHandling/src/LoadTOFRawNexus.cpp b/Code/Mantid/Framework/DataHandling/src/LoadTOFRawNexus.cpp index 51aee612360..72748a24ce7 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadTOFRawNexus.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadTOFRawNexus.cpp @@ -518,8 +518,9 @@ void LoadTOFRawNexus::exec() { prog->doReport("Loading DAS logs"); g_log.debug() << "Loading DAS logs" << std::endl; - int nPeriods = 1; - LoadEventNexus::runLoadNexusLogs(filename, WS, *this, false, nPeriods); + int nPeriods = 1; // Unused + std::unique_ptr<const TimeSeriesProperty<int> > periodLog(new const TimeSeriesProperty<int>("period_log")); // Unused + LoadEventNexus::runLoadNexusLogs(filename, WS, *this, false, nPeriods, periodLog); // Load the instrument prog->report("Loading instrument"); diff --git a/Code/Mantid/Framework/DataHandling/test/LoadEventNexusTest.h b/Code/Mantid/Framework/DataHandling/test/LoadEventNexusTest.h index 631a751229d..2c5224e30a4 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadEventNexusTest.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadEventNexusTest.h @@ -633,6 +633,16 @@ void test_extract_nperiod_data() { EventWorkspace_sptr ws = boost::dynamic_pointer_cast<EventWorkspace>(outGroup->getItem(i)); TS_ASSERT(ws); TSM_ASSERT("Non-zero events in each period", ws->getNumberEvents() > 0); + + std::stringstream buffer; + buffer << "period " << i+1; + std::string periodBoolLog = buffer.str(); + + const int currentPeriod = ws->run().getPropertyValueAsType<int>("current_period"); + + TSM_ASSERT("Each period should have a boolean array for masking period numbers", ws->run().hasProperty(periodBoolLog)); + TSM_ASSERT_EQUALS("Current period is not what was expected.", currentPeriod, i+1); + } } diff --git a/Code/Mantid/Framework/DataHandling/test/LoadNexusLogsTest.h b/Code/Mantid/Framework/DataHandling/test/LoadNexusLogsTest.h index 508365f3962..a7aef732b8f 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadNexusLogsTest.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadNexusLogsTest.h @@ -108,7 +108,7 @@ public: TS_ASSERT_EQUALS(dlog->size(),172); } - void test_extract_nperiod_log(){ + void test_extract_nperiod_log_from_event_nexus(){ auto testWS = createTestWorkspace(); auto run = testWS->run(); @@ -131,6 +131,32 @@ public: } + void test_extract_periods_log_from_event_nexus(){ + + auto testWS = createTestWorkspace(); + auto run = testWS->run(); + TSM_ASSERT("Should not have nperiods until we run LoadNexusLogs", !run.hasProperty("nperiods")); + LoadNexusLogs loader; + + loader.setChild(true); + loader.initialize(); + loader.setProperty("Workspace", testWS); + loader.setPropertyValue("Filename", "LARMOR00003368.nxs"); + loader.execute(); + run = testWS->run(); + + const bool hasPeriods = run.hasProperty("period_log"); + TSM_ASSERT("Should have period_log now we have run LoadNexusLogs", hasPeriods); + + auto* temp = run.getProperty("period_log"); + auto * periodLog = dynamic_cast<TimeSeriesProperty<int>*>(temp); + TSM_ASSERT("Period log should be an int time series property", periodLog); + + std::vector<int> periodValues = periodLog->valuesAsVector(); + std::set<int> uniquePeriods(periodValues.begin(), periodValues.end()); + TSM_ASSERT_EQUALS("Should have 4 periods in total", 4, uniquePeriods.size()); + } + private: API::MatrixWorkspace_sptr createTestWorkspace() -- GitLab