/* * Write a certain number of log entries (from beginning) to file */ void ProcessDasNexusLog::writeLogtoFile(API::MatrixWorkspace_sptr ws, std::string logname, size_t numentriesoutput, std::string outputfilename) { // 1. Get log Kernel::Property *log = ws->run().getProperty(logname); Kernel::TimeSeriesProperty<double> *tslog = dynamic_cast<Kernel::TimeSeriesProperty<double> *>(log); if (!tslog) throw std::runtime_error("Invalid time series log: it could not be cast " "(interpreted) as a time series property"); std::vector<Kernel::DateAndTime> times = tslog->timesAsVector(); std::vector<double> values = tslog->valuesAsVector(); // 2. Write out std::ofstream ofs; ofs.open(outputfilename.c_str(), std::ios::out); ofs << "# Absolute Time (nanosecond)\tPulse Time (nanosecond)\tTOF (ms)\n"; Kernel::DateAndTime prevtime(0); std::vector<double> tofs; for (size_t i = 0; i < numentriesoutput; i++) { Kernel::DateAndTime tnow = times[i]; if (tnow > prevtime) { // (a) Process previous logs std::sort(tofs.begin(), tofs.end()); for (double tof : tofs) { Kernel::DateAndTime temptime = prevtime + static_cast<int64_t>(tof * 100); ofs << temptime.totalNanoseconds() << "\t" << tnow.totalNanoseconds() << "\t" << tof * 0.1 << '\n'; } // (b) Clear tofs.clear(); // (c) Update time prevtime = tnow; } // (d) Push the current value tofs.push_back(values[i]); } // ENDFOR // Clear the last if (!tofs.empty()) { // (a) Process previous logs: note value is in unit of 100 nano-second std::sort(tofs.begin(), tofs.end()); for (double tof : tofs) { Kernel::DateAndTime temptime = prevtime + static_cast<int64_t>(tof * 100); ofs << temptime.totalNanoseconds() << "\t" << prevtime.totalNanoseconds() << "\t" << tof * 0.1 << '\n'; } } else { throw std::runtime_error("Impossible for this to happen!"); } ofs.close(); } // END Function
/* * Convert DAS log to a vector of absolute time * @param orderedtofs: tofs with abstimevec */ void ProcessDasNexusLog::convertToAbsoluteTime( API::MatrixWorkspace_sptr ws, std::string logname, std::vector<Kernel::DateAndTime> &abstimevec, std::vector<double> &orderedtofs) { // 1. Get log Kernel::Property *log = ws->run().getProperty(logname); Kernel::TimeSeriesProperty<double> *tslog = dynamic_cast<Kernel::TimeSeriesProperty<double> *>(log); if (!tslog) throw std::runtime_error("Invalid time series log: it could not be cast " "(interpreted) as a time series property"); std::vector<Kernel::DateAndTime> times = tslog->timesAsVector(); std::vector<double> values = tslog->valuesAsVector(); // 2. Get converted size_t numsamepulses = 0; std::vector<double> tofs; Kernel::DateAndTime prevtime(0); for (size_t i = 0; i < times.size(); i++) { Kernel::DateAndTime tnow = times[i]; if (tnow > prevtime) { // (a) Process previous logs std::sort(tofs.begin(), tofs.end()); for (size_t j = 0; j < tofs.size(); j++) { Kernel::DateAndTime temptime = prevtime + static_cast<int64_t>(tofs[j] * 100); abstimevec.push_back(temptime); orderedtofs.push_back(tofs[j]); } // (b) Clear tofs.clear(); // (c) Update time prevtime = tnow; } else { numsamepulses++; } // (d) Push the current value tofs.push_back(values[i]); } // ENDFOR // Clear the last if (!tofs.empty()) { // (a) Process previous logs: note value is in unit of 100 nano-second std::sort(tofs.begin(), tofs.end()); for (size_t j = 0; j < tofs.size(); j++) { Kernel::DateAndTime temptime = prevtime + static_cast<int64_t>(tofs[j] * 100); abstimevec.push_back(temptime); orderedtofs.push_back(tofs[j]); } } else { throw std::runtime_error("Impossible for this to happen!"); } return; } // END Function
void AddSinglePointTimeSeriesProperty(API::LogManager &logManager, const std::string &time, const std::string &name, const TYPE value) { // create time series property and add single value Kernel::TimeSeriesProperty<TYPE> *p = new Kernel::TimeSeriesProperty<TYPE>(name); p->addValue(time, value); // add to log manager logManager.addProperty(p); }
/* * Check log in workspace */ void ProcessDasNexusLog::checkLog(API::MatrixWorkspace_sptr ws, std::string logname) { // 1. Get log Kernel::Property *log = ws->run().getProperty(logname); if (!log) { g_log.error() << "Log " << logname << " does not exist!" << std::endl; throw std::invalid_argument("Non-exising log name"); } Kernel::TimeSeriesProperty<double> *tslog = dynamic_cast<Kernel::TimeSeriesProperty<double> *>(log); if (!tslog) { g_log.error() << "Log " << logname << " is not time series log" << std::endl; throw std::invalid_argument("Log type error!"); } // 2. Survey std::vector<Kernel::DateAndTime> times = tslog->timesAsVector(); g_log.information() << "Entries of times = " << times.size() << std::endl; size_t countsame = 0; size_t countinverse = 0; for (size_t i = 1; i < times.size(); i++) { Kernel::DateAndTime tprev = times[i - 1]; Kernel::DateAndTime tpres = times[i]; if (tprev == tpres) countsame++; else if (tprev > tpres) countinverse++; } // 3. Output Kernel::DateAndTime t0(ws->run().getProperty("run_start")->value()); Kernel::time_duration dts = times[0] - t0; Kernel::time_duration dtf = times[times.size() - 1] - t0; size_t f = times.size() - 1; g_log.information() << "Number of Equal Time Stamps = " << countsame << std::endl; g_log.information() << "Number of Inverted Time Stamps = " << countinverse << std::endl; g_log.information() << "Run Start = " << t0.totalNanoseconds() << std::endl; g_log.information() << "First Log (Absolute Time, Relative Time): " << times[0].totalNanoseconds() << ", " << Kernel::DateAndTime::nanosecondsFromDuration(dts) << std::endl; g_log.information() << "Last Log (Absolute Time, Relative Time): " << times[f].totalNanoseconds() << ", " << Kernel::DateAndTime::nanosecondsFromDuration(dtf) << std::endl; return; }
/** Creates a TimeSeriesProperty<bool> showing times when a particular period was active. * @param period :: The data period * @return the times when requested period was active */ Kernel::Property* LoadRaw::createPeriodLog(int period)const { Kernel::TimeSeriesProperty<int>* periods = dynamic_cast< Kernel::TimeSeriesProperty<int>* >(m_perioids.get()); if(!periods) return 0; std::ostringstream ostr; ostr<<period; Kernel::TimeSeriesProperty<bool>* p = new Kernel::TimeSeriesProperty<bool> ("period "+ostr.str()); std::map<Kernel::DateAndTime, int> pMap = periods->valueAsMap(); std::map<Kernel::DateAndTime, int>::const_iterator it = pMap.begin(); if (it->second != period) p->addValue(it->first,false); for(;it!=pMap.end();++it) p->addValue(it->first, (it->second == period) ); return p; }
/** Export part of designated log to an file in column format and a output file * @param logname :: name of log to export * @param numentries :: number of log entries to export * @param outputeventws :: boolean. output workspace is event workspace if * true. */ void ExportTimeSeriesLog::exportLog(string logname, int numentries, bool outputeventws) { // 1. Get log, time, and etc. std::vector<Kernel::DateAndTime> times; std::vector<double> values; if (logname.size() > 0) { // Log Kernel::TimeSeriesProperty<double> *tlog = dynamic_cast<Kernel::TimeSeriesProperty<double> *>( m_dataWS->run().getProperty(logname)); if (!tlog) { std::stringstream errmsg; errmsg << "TimeSeriesProperty Log " << logname << " does not exist in workspace " << m_dataWS->getName(); g_log.error(errmsg.str()); throw std::invalid_argument(errmsg.str()); } times = tlog->timesAsVector(); values = tlog->valuesAsVector(); } else { throw std::runtime_error("Log name cannot be left empty."); } // 2. Determine number of export log if (numentries == EMPTY_INT()) { numentries = static_cast<int>(times.size()); } else if (numentries <= 0) { stringstream errmsg; errmsg << "For Export Log, NumberEntriesExport must be greater than 0. " "Input = " << numentries; g_log.error(errmsg.str()); throw std::runtime_error(errmsg.str()); } else if (static_cast<size_t>(numentries) > times.size()) { numentries = static_cast<int>(times.size()); } // 3. Create otuput workspace if (outputeventws) { setupEventWorkspace(numentries, times, values); } else { setupWorkspace2D(numentries, times, values); } return; }
/// Run the LoadLog Child Algorithm void LoadMuonNexus1::runLoadLog(DataObjects::Workspace2D_sptr localWorkspace) { IAlgorithm_sptr loadLog = createChildAlgorithm("LoadMuonLog"); // Pass through the same input filename loadLog->setPropertyValue("Filename", m_filename); // Set the workspace property to be the same one filled above loadLog->setProperty<MatrixWorkspace_sptr>("Workspace", localWorkspace); // Now execute the Child Algorithm. Catch and log any error, but don't stop. try { loadLog->execute(); } catch (std::runtime_error &) { g_log.error("Unable to successfully run LoadLog Child Algorithm"); } catch (std::logic_error &) { g_log.error("Unable to successfully run LoadLog Child Algorithm"); } if (!loadLog->isExecuted()) g_log.error("Unable to successfully run LoadLog Child Algorithm"); NXRoot root(m_filename); try { NXChar orientation = root.openNXChar("run/instrument/detector/orientation"); // some files have no data there orientation.load(); if (orientation[0] == 't') { Kernel::TimeSeriesProperty<double> *p = new Kernel::TimeSeriesProperty<double>("fromNexus"); std::string start_time = root.getString("run/start_time"); p->addValue(start_time, -90.0); localWorkspace->mutableRun().addLogData(p); setProperty("MainFieldDirection", "Transverse"); } else { setProperty("MainFieldDirection", "Longitudinal"); } } catch (...) { setProperty("MainFieldDirection", "Longitudinal"); } auto &run = localWorkspace->mutableRun(); int n = static_cast<int>(m_numberOfPeriods); ISISRunLogs runLogs(run, n); runLogs.addStatusLog(run); }
/** Write value from a RunInfo property (i.e., log) to a stream */ void writeLogValue(std::ostream &os, const Run &runinfo, const std::string &name, const std::string &defValue = "UNKNOWN") { // Return without property exists if (!runinfo.hasProperty(name)) { os << defValue; return; } // Get handler of property Kernel::Property *prop = runinfo.getProperty(name); // Return without a valid pointer to property if (prop == NULL) { os << defValue; return; } // Get value Kernel::TimeSeriesProperty<double> *log = dynamic_cast<Kernel::TimeSeriesProperty<double> *>(prop); if (log) { // Time series to get mean os << log->getStatistics().mean; } else { // None time series os << prop->value(); } // Unit std::string units = prop->units(); if (!units.empty()) os << " " << units; return; }
/* * Merge 2 TimeSeries log together for the third one * @param ilogname1: name of log 1 to be merged * @param ilogname2: name of log 2 to be merged * @param ologname: name of the merged log to be added to workspace */ void Merge2WorkspaceLogs::mergeLogs(std::string ilogname1, std::string ilogname2, std::string ologname, bool resetlogvalue, double logvalue1, double logvalue2) { // 1. Get log Kernel::TimeSeriesProperty<double> *p1 = getTimeSeriesLog(ilogname1); Kernel::TimeSeriesProperty<double> *p2 = getTimeSeriesLog(ilogname2); std::vector<Kernel::DateAndTime> times1 = p1->timesAsVector(); std::vector<Kernel::DateAndTime> times2 = p2->timesAsVector(); Kernel::TimeSeriesProperty<double> *rp = new Kernel::TimeSeriesProperty<double>(ologname); // 2. Merge size_t index1 = 0; size_t index2 = 0; bool icont = true; Kernel::DateAndTime tmptime; double tmpvalue; bool launch1 = true; ; bool nocomparison = false; std::cout << "Merging!!" << std::endl; while (icont) { // std::cout << "index1 = " << index1 << ", index2 = " << index2 << ", // launch1 = " << launch1 << ", nocomparison = " << nocomparison << // std::endl; // i. Determine which log to work on if (!nocomparison) { if (times1[index1] < times2[index2]) { launch1 = true; } else { launch1 = false; } } // ii. Retrieve data from source log if (launch1) { // Add log1 tmptime = times1[index1]; if (resetlogvalue) { tmpvalue = logvalue1; } else { tmpvalue = p1->getSingleValue(tmptime); } } else { // Add log 2 tmptime = times2[index2]; if (resetlogvalue) { tmpvalue = logvalue2; } else { tmpvalue = p2->getSingleValue(tmptime); } } // iii. Add log rp->addValue(tmptime, tmpvalue); // iv. Increase step if (launch1) { index1++; } else { index2++; } // v. Determine status if (nocomparison) { // no comparison case: transition to terminate while if (launch1 && index1 >= times1.size()) { icont = false; } else if (!launch1 && index2 >= times2.size()) { icont = false; } } else { // still in comparison: transition to no-comparison if (launch1 && index1 >= times1.size()) { nocomparison = true; launch1 = false; } else if (!launch1 && index2 >= times2.size()) { nocomparison = true; launch1 = true; } } // ENDIFELSE nocomparison } // ENDWHILE // 3. Check and add new log int newlogsize = rp->size(); if (size_t(newlogsize) != (times1.size() + times2.size())) { g_log.error() << "Resulted log size is not equal to the sum of two source log sizes" << std::endl; throw; } matrixWS->mutableRun().addProperty(rp); return; }
/** * reads the .log stream and creates timeseries property and sets that to the run object * @param logFileStream :: The stream of the log file (data). * @param logFileName :: The name of the log file to load. * @param run :: The run information object */ void LoadLog::loadThreeColumnLogFile(std::ifstream& logFileStream, std::string logFileName, API::Run& run) { std::string str; std::string propname; Mantid::Kernel::TimeSeriesProperty<double>* logd = 0; Mantid::Kernel::TimeSeriesProperty<std::string>* logs = 0; std::map<std::string,Kernel::TimeSeriesProperty<double>*> dMap; std::map<std::string,Kernel::TimeSeriesProperty<std::string>*> sMap; typedef std::pair<std::string,Kernel::TimeSeriesProperty<double>* > dpair; typedef std::pair<std::string,Kernel::TimeSeriesProperty<std::string>* > spair; kind l_kind(LoadLog::empty); bool isNumeric(false); if (!logFileStream) { throw std::invalid_argument("Unable to open file " + m_filename); } while(Mantid::Kernel::Strings::extractToEOL(logFileStream,str)) { if ( !isDateTimeString(str) ) { throw std::invalid_argument("File" + logFileName + " is not a standard ISIS log file. Expected to be a file starting with DateTime String format."); } if (!Kernel::TimeSeriesProperty<double>::isTimeString(str) || (str[0]=='#')) { //if the line doesn't start with a time read the next line continue; } std::stringstream line(str); std::string timecolumn; line >> timecolumn; std::string blockcolumn; line >> blockcolumn; l_kind = classify(blockcolumn); if ( LoadLog::string != l_kind ) { throw std::invalid_argument("ISIS log file contains unrecognised second column entries:" + logFileName); } std::string valuecolumn; line >> valuecolumn; l_kind = classify(valuecolumn); if ( LoadLog::string != l_kind && LoadLog::number != l_kind) { continue; //no value defined, just skip this entry } // column two in .log file is called block column propname = stringToLower(blockcolumn); //check if the data is numeric std::istringstream istr(valuecolumn); double dvalue; istr >> dvalue; isNumeric = !istr.fail(); if (isNumeric) { std::map<std::string,Kernel::TimeSeriesProperty<double>*>::iterator ditr = dMap.find(propname); if(ditr != dMap.end()) { Kernel::TimeSeriesProperty<double>* prop = ditr->second; if (prop) prop->addValue(timecolumn,dvalue); } else { logd = new Kernel::TimeSeriesProperty<double>(propname); logd->addValue(timecolumn,dvalue); dMap.insert(dpair(propname,logd)); } } else { std::map<std::string,Kernel::TimeSeriesProperty<std::string>*>::iterator sitr = sMap.find(propname); if(sitr != sMap.end()) { Kernel::TimeSeriesProperty<std::string>* prop = sitr->second; if (prop) prop->addValue(timecolumn,valuecolumn); } else { logs = new Kernel::TimeSeriesProperty<std::string>(propname); logs->addValue(timecolumn,valuecolumn); sMap.insert(spair(propname,logs)); } } } try { std::map<std::string,Kernel::TimeSeriesProperty<double>*>::const_iterator itr = dMap.begin(); for(;itr != dMap.end(); ++itr) { run.addLogData(itr->second); } std::map<std::string,Kernel::TimeSeriesProperty<std::string>*>::const_iterator sitr = sMap.begin(); for(;sitr!=sMap.end();++sitr) { run.addLogData(sitr->second); } } catch(std::invalid_argument &e) { g_log.warning() << e.what(); } catch(Exception::ExistsError&e) { g_log.warning() << e.what(); } }
/** Export part of designated log to an file in column format and a output file * @brief ExportTimeSeriesLog::exportLog * @param logname :: name of log to export * @param timeunit :: unit of time for input start/stop time and output * @param starttime :: relative start time of the output time series log * @param stoptime :: relative stop time of the output time series log * @param exportepoch :: flag to output time as epoch time/absolute time * @param outputeventws :: boolean. output workspace is event workspace if * @param numentries :: number of log entries to export */ void ExportTimeSeriesLog::exportLog(const std::string &logname, const std::string timeunit, const double &starttime, const double &stoptime, const bool exportepoch, bool outputeventws, int numentries) { // Get log, time, and etc. std::vector<Kernel::DateAndTime> times; std::vector<double> values; if (logname.size() > 0) { // Log Kernel::TimeSeriesProperty<double> *tlog = dynamic_cast<Kernel::TimeSeriesProperty<double> *>( m_inputWS->run().getProperty(logname)); if (!tlog) { std::stringstream errmsg; errmsg << "TimeSeriesProperty Log " << logname << " does not exist in workspace " << m_inputWS->getName(); g_log.error(errmsg.str()); throw std::invalid_argument(errmsg.str()); } times = tlog->timesAsVector(); values = tlog->valuesAsVector(); } else { throw std::runtime_error("Log name cannot be left empty."); } // Get start time, stop time and unit factor double timeunitfactor = 1.; if (timeunit.compare("Seconds") == 0) timeunitfactor = 1.E-9; // Get index for start time size_t i_start = 0; size_t i_stop = times.size() - 1; // Rule out the case that start time is behind last log entry bool i_start_cal = false; if (starttime != EMPTY_DBL()) { int64_t timerangens = times.back().totalNanoseconds() - times.front().totalNanoseconds(); double timerange = static_cast<double>(timerangens) * timeunitfactor; g_log.debug() << "Time range is " << timerange << ", Start time is " << starttime << "\n"; if (timerange < starttime) { i_start = times.size() - 1; i_start_cal = true; } } if ((!i_start_cal) && (starttime != EMPTY_DBL() || stoptime != EMPTY_DBL())) { bool export_partial = calculateTimeSeriesRangeByTime( times, starttime, i_start, stoptime, i_stop, timeunitfactor); if (!export_partial) throw std::runtime_error( "Unable to find proton_charge for run start time. " "Failed to get partial time series."); } // Determine number of export log if (numentries == EMPTY_INT()) { numentries = static_cast<int>(times.size()); } else if (numentries <= 0) { stringstream errmsg; errmsg << "For Export Log, NumberEntriesExport must be greater than 0. " "Input = " << numentries; g_log.error(errmsg.str()); throw std::runtime_error(errmsg.str()); } else if (static_cast<size_t>(numentries) > times.size()) { numentries = static_cast<int>(times.size()); } // Create otuput workspace if (outputeventws) { setupEventWorkspace(i_start, i_stop, numentries, times, values, exportepoch); } else { setupWorkspace2D(i_start, i_stop, numentries, times, values, exportepoch, timeunitfactor); } return; }
/* * Add and check log from processed absolute time stamps */ void ProcessDasNexusLog::addLog(API::MatrixWorkspace_sptr ws, std::vector<Kernel::DateAndTime> timevec, double unifylogvalue, std::string logname, std::vector<Kernel::DateAndTime> pulsetimes, std::vector<double> orderedtofs, bool docheck) { // 1. Do some static g_log.notice() << "Vector size = " << timevec.size() << std::endl; double sum1dtms = 0.0; // sum(dt^2) double sum2dtms = 0.0; // sum(dt^2) size_t numinvert = 0; size_t numsame = 0; size_t numnormal = 0; double maxdtms = 0; double mindtms = 1.0E20; size_t numdtabove10p = 0; size_t numdtbelow10p = 0; double sampledtms = 0.00832646 * 1.0E6; double dtmsA10p = sampledtms * 1.1; double dtmsB10p = sampledtms / 1.0; for (size_t i = 1; i < timevec.size(); i++) { int64_t dtns = timevec[i].totalNanoseconds() - timevec[i - 1].totalNanoseconds(); double dtms = static_cast<double>(dtns) * 1.0E-3; sum1dtms += dtms; sum2dtms += dtms * dtms; if (dtns == 0) numsame++; else if (dtns < 0) numinvert++; else numnormal++; if (dtms > maxdtms) maxdtms = dtms; if (dtms < mindtms) mindtms = dtms; if (dtms > dtmsA10p) numdtabove10p++; else if (dtms < dtmsB10p) numdtbelow10p++; } // ENDFOR double dt = sum1dtms / static_cast<double>(timevec.size()) * 1.0E-6; double stddt = sqrt(sum2dtms / static_cast<double>(timevec.size()) * 1.0E-12 - dt * dt); g_log.notice() << "Normal dt = " << numnormal << std::endl; g_log.notice() << "Zero dt = " << numsame << std::endl; g_log.notice() << "Negative dt = " << numinvert << std::endl; g_log.notice() << "Avg d(T) = " << dt << " seconds +/- " << stddt << ", Frequency = " << 1.0 / dt << std::endl; g_log.notice() << "d(T) (unit ms) is in range [" << mindtms << ", " << maxdtms << "]" << std::endl; g_log.notice() << "Number of d(T) 10% larger than average = " << numdtabove10p << std::endl; g_log.notice() << "Number of d(T) 10% smaller than average = " << numdtbelow10p << std::endl; g_log.notice() << "Size of timevec, pulsestimes, orderedtofs = " << timevec.size() << ", " << pulsetimes.size() << ", " << orderedtofs.size() << std::endl; if (docheck) { exportErrorLog(ws, timevec, pulsetimes, orderedtofs, 1 / (0.5 * 240.1)); calDistributions(timevec, 1 / (0.5 * 240.1)); } // 2. Add log Kernel::TimeSeriesProperty<double> *newlog = new Kernel::TimeSeriesProperty<double>(logname); for (size_t i = 0; i < timevec.size(); i++) { newlog->addValue(timevec[i], unifylogvalue); } ws->mutableRun().addProperty(newlog, true); return; }
/** Executes the algorithm. Reading in the file and creating and populating * the output workspace * * @throw Exception::FileError If the Nexus file cannot be found/opened * @throw std::invalid_argument If the optional properties are set to invalid *values */ void LoadNexusLogs::exec() { std::string filename = getPropertyValue("Filename"); MatrixWorkspace_sptr workspace = getProperty("Workspace"); // Find the entry name to use (normally "entry" for SNS, "raw_data_1" for // ISIS) std::string entry_name = LoadTOFRawNexus::getEntryName(filename); ::NeXus::File file(filename); // Find the root entry try { file.openGroup(entry_name, "NXentry"); } catch (::NeXus::Exception &) { throw std::invalid_argument("Unknown NeXus file format found in file '" + filename + "'"); } /// Use frequency start for Monitor19 and Special1_19 logs with "No Time" for /// SNAP try { file.openPath("DASlogs"); try { file.openGroup("frequency", "NXlog"); try { file.openData("time"); //----- Start time is an ISO8601 string date and time. ------ try { file.getAttr("start", freqStart); } catch (::NeXus::Exception &) { // Some logs have "offset" instead of start try { file.getAttr("offset", freqStart); } catch (::NeXus::Exception &) { g_log.warning() << "Log entry has no start time indicated.\n"; file.closeData(); throw; } } file.closeData(); } catch (::NeXus::Exception &) { // No time. This is not an SNS SNAP file } file.closeGroup(); } catch (::NeXus::Exception &) { // No time. This is not an SNS frequency group } file.closeGroup(); } catch (::NeXus::Exception &) { // No time. This is not an SNS group } // print out the entry level fields std::map<std::string, std::string> entries = file.getEntries(); std::map<std::string, std::string>::const_iterator iend = entries.end(); for (std::map<std::string, std::string>::const_iterator it = entries.begin(); it != iend; ++it) { std::string group_name(it->first); std::string group_class(it->second); if (group_name == "DASlogs" || group_class == "IXrunlog" || group_class == "IXselog" || group_name == "framelog") { loadLogs(file, group_name, group_class, workspace); } if (group_class == "IXperiods") { loadNPeriods(file, workspace); } } // If there's measurement information, load that info as logs. loadAndApplyMeasurementInfo(&file, *workspace); // Freddie Akeroyd 12/10/2011 // current ISIS implementation contains an additional indirection between // collected frames via an // "event_frame_number" array in NXevent_data (which eliminates frames with no // events). // the proton_log is for all frames and so is longer than the event_index // array, so we need to // filter the proton_charge log based on event_frame_number // This difference will be removed in future for compatibility with SNS, but // the code below will allow current SANS2D files to load if (workspace->mutableRun().hasProperty("proton_log")) { std::vector<int> event_frame_number; this->getLogger().notice() << "Using old ISIS proton_log and event_frame_number indirection..." << std::endl; try { // Find the bank/name corresponding to the first event data entry, i.e. // one with type NXevent_data. file.openPath("/" + entry_name); std::map<std::string, std::string> entries = file.getEntries(); std::map<std::string, std::string>::const_iterator it = entries.begin(); std::string eventEntry; for (; it != entries.end(); ++it) { if (it->second == "NXevent_data") { eventEntry = it->first; break; } } this->getLogger().debug() << "Opening" << " /" + entry_name + "/" + eventEntry + "/event_frame_number" << " to find the event_frame_number\n"; file.openPath("/" + entry_name + "/" + eventEntry + "/event_frame_number"); file.getData(event_frame_number); } catch (const ::NeXus::Exception &) { this->getLogger().warning() << "Unable to load event_frame_number - " "filtering events by time will not work " << std::endl; } file.openPath("/" + entry_name); if (!event_frame_number.empty()) // ISIS indirection - see above comments { Kernel::TimeSeriesProperty<double> *plog = dynamic_cast<Kernel::TimeSeriesProperty<double> *>( workspace->mutableRun().getProperty("proton_log")); if (!plog) throw std::runtime_error( "Could not cast (interpret) proton_log as a time " "series property. Cannot continue."); Kernel::TimeSeriesProperty<double> *pcharge = new Kernel::TimeSeriesProperty<double>("proton_charge"); std::vector<double> pval; std::vector<Mantid::Kernel::DateAndTime> ptime; pval.reserve(event_frame_number.size()); ptime.reserve(event_frame_number.size()); std::vector<Mantid::Kernel::DateAndTime> plogt = plog->timesAsVector(); std::vector<double> plogv = plog->valuesAsVector(); for (auto number : event_frame_number) { ptime.push_back(plogt[number]); pval.push_back(plogv[number]); } pcharge->create(ptime, pval); pcharge->setUnits("uAh"); workspace->mutableRun().addProperty(pcharge, true); } } try { // Read the start and end time strings file.openData("start_time"); Kernel::DateAndTime start(file.getStrData()); file.closeData(); file.openData("end_time"); Kernel::DateAndTime end(file.getStrData()); file.closeData(); workspace->mutableRun().setStartAndEndTime(start, end); } catch (::NeXus::Exception &) { } if (!workspace->run().hasProperty("gd_prtn_chrg")) { // Try pulling it from the main proton_charge entry first try { file.openData("proton_charge"); std::vector<double> values; file.getDataCoerce(values); std::string units; file.getAttr("units", units); double charge = values.front(); if (units.find("picoCoulomb") != std::string::npos) { charge *= 1.e-06 / 3600.; } workspace->mutableRun().setProtonCharge(charge); } catch (::NeXus::Exception &) { // Try and integrate the proton logs try { // Use the DAS logs to integrate the proton charge (if any). workspace->mutableRun().getProtonCharge(); } catch (Exception::NotFoundError &) { // Ignore not found property error. } } } // Close the file file.close(); }