/** Load the pulse times, if needed. This sets * thisBankPulseTimes to the right pointer. * */ void LoadBankFromDiskTask::loadPulseTimes(::NeXus::File &file) { try { // First, get info about the event_time_zero field in this bank file.openData("event_time_zero"); } catch (::NeXus::Exception &) { // Field not found error is most likely. // Use the "proton_charge" das logs. thisBankPulseTimes = m_loader.alg->m_allBanksPulseTimes; return; } std::string thisStartTime; size_t thisNumPulses = 0; file.getAttr("offset", thisStartTime); if (!file.getInfo().dims.empty()) thisNumPulses = file.getInfo().dims[0]; file.closeData(); // Now, we look through existing ones to see if it is already loaded // thisBankPulseTimes = NULL; for (auto &bankPulseTime : m_loader.m_bankPulseTimes) { if (bankPulseTime->equals(thisNumPulses, thisStartTime)) { thisBankPulseTimes = bankPulseTime; return; } } // Not found? Need to load and add it thisBankPulseTimes = boost::make_shared<BankPulseTimes>(boost::ref(file), m_framePeriodNumbers); m_loader.m_bankPulseTimes.push_back(thisBankPulseTimes); }
/** Try to load the "Veto_pulse" field in DASLogs * and convert it to a sample log. * * @param file :: open nexus file at the DASLogs group * @param workspace :: workspace to add to. */ void LoadNexusLogs::loadVetoPulses( ::NeXus::File &file, boost::shared_ptr<API::MatrixWorkspace> workspace) const { try { file.openGroup("Veto_pulse", "NXgroup"); } catch (::NeXus::Exception &) { // No group. This is common in older files return; } file.openData("veto_pulse_time"); // Load the start date/time as ISO8601 string. std::string start_time; file.getAttr("start_time", start_time); DateAndTime start(start_time); // Read the offsets std::vector<double> time_double; file.getData(time_double); // Fake values with zeroes. std::vector<double> values(time_double.size(), 0.0); TimeSeriesProperty<double> *tsp = new TimeSeriesProperty<double>("veto_pulse_time"); tsp->create(start, time_double, values); tsp->setUnits(""); // Add the log workspace->mutableRun().addProperty(tsp); file.closeData(); file.closeGroup(); }
/** Open and load the times-of-flight data */ void LoadBankFromDiskTask::loadTof(::NeXus::File &file) { // Allocate the array auto temp = new float[m_loadSize[0]]; delete[] m_event_time_of_flight; m_event_time_of_flight = temp; // Get the list of event_time_of_flight's if (!m_oldNexusFileNames) file.openData("event_time_offset"); else file.openData("event_time_of_flight"); // Check that the required space is there in the file. ::NeXus::Info tof_info = file.getInfo(); int64_t tof_dim0 = recalculateDataSize(tof_info.dims[0]); if (tof_dim0 < m_loadSize[0] + m_loadStart[0]) { m_loader.alg->getLogger().warning() << "Entry " << entry_name << "'s event_time_offset field is too small " "to load the desired data.\n"; m_loadError = true; } // Check that the type is what it is supposed to be if (tof_info.type == ::NeXus::FLOAT32) file.getSlab(m_event_time_of_flight, m_loadStart, m_loadSize); else { m_loader.alg->getLogger().warning() << "Entry " << entry_name << "'s event_time_offset field is not FLOAT32! It will be skipped.\n"; m_loadError = true; } if (!m_loadError) { std::string units; file.getAttr("units", units); if (units != "microsecond") { m_loader.alg->getLogger().warning() << "Entry " << entry_name << "'s event_time_offset field's units are " "not microsecond. It will be skipped.\n"; m_loadError = true; } file.closeData(); } // no error }
/** Open and load the times-of-flight data * @param file An NeXus::File object opened at the correct group * @returns A new array containing the time of flights for this bank */ std::unique_ptr<float[]> LoadBankFromDiskTask::loadTof(::NeXus::File &file) { // Allocate the array auto event_time_of_flight = Mantid::Kernel::make_unique<float[]>(m_loadSize[0]); // Get the list of event_time_of_flight's std::string key, tof_unit; if (!m_oldNexusFileNames) key = "event_time_offset"; else key = "event_time_of_flight"; file.openData(key); // Check that the required space is there in the file. ::NeXus::Info tof_info = file.getInfo(); int64_t tof_dim0 = recalculateDataSize(tof_info.dims[0]); if (tof_dim0 < m_loadSize[0] + m_loadStart[0]) { m_loader.alg->getLogger().warning() << "Entry " << entry_name << "'s event_time_offset field is too small " "to load the desired data.\n"; m_loadError = true; } // The Nexus standard does not specify if event_time_offset should be float or // integer, so we use the NeXusIOHelper to perform the conversion to float on // the fly. If the data field already contains floats, the conversion is // skipped. auto vec = NeXus::NeXusIOHelper::readNexusSlab<float>(file, key, m_loadStart, m_loadSize); file.getAttr("units", tof_unit); file.closeData(); // Convert Tof to microseconds Kernel::Units::timeConversionVector(vec, tof_unit, "microseconds"); std::copy(vec.begin(), vec.end(), event_time_of_flight.get()); return event_time_of_flight; }
/** Loads an entry from a previously-open NXS file as a log entry * in the workspace's run. * * @param file: NXS file handle. MUST BE PASSED BY REFERENCE otherwise there * occurs a segfault. * @param entry_name, entry_class: name and class of NXlog to open. */ void LoadLogsFromSNSNexus::loadSampleLog(::NeXus::File& file, std::string entry_name, std::string entry_class) { // whether or not to overwrite logs on workspace bool overwritelogs = this->getProperty("OverwriteLogs"); file.openGroup(entry_name, entry_class); // Validate the NX log class. map<string, string> entries = file.getEntries(); if ((entries.find("value") == entries.end()) || (entries.find("time") == entries.end()) ) { g_log.warning() << "Invalid NXlog entry " << entry_name << " found. Did not contain 'value' and 'time'.\n"; file.closeGroup(); return; } ::NeXus::Info info; //Two possible types of properties: vector<double> values; vector<int> values_int; bool isTimeSeries = false; bool isInt = false; file.openData("value"); //Get the units of the property std::string units(""); try { file.getAttr("units", units); } catch (::NeXus::Exception &) { //Ignore missing units field. units = ""; } //If there is more than one entry, it is a timeseries info = file.getInfo(); //isTimeSeries = (info.dims[0] > 1); isTimeSeries = true; Timer timer1; try { //Get the data (convert types if necessary) if (file.isDataInt()) { isInt = true; file.getDataCoerce(values_int); // if (values_int.size() == 1) // { // WS->mutableRun().addProperty(entry_name, values_int[0], units); // } } else { //Try to get as doubles. file.getDataCoerce(values); // if (values.size() == 1) // { // WS->mutableRun().addProperty(entry_name, values[0], units); // } } } catch (::NeXus::Exception &e) { g_log.warning() << "NXlog entry " << entry_name << " gave an error when loading 'value' data:'" << e.what() << "'.\n"; file.closeData(); file.closeGroup(); return; } if (VERBOSE) std::cout << "getDataCoerce took " << timer1.elapsed() << " sec.\n"; file.closeData(); if (isTimeSeries) { // --- Time series property --- //Get the times vector<double> time_double; vector<DateAndTime> times; try { file.openData("time"); } catch (::NeXus::Exception &e) { g_log.warning() << "NXlog entry " << entry_name << " gave an error when opening the time field '" << e.what() << "'.\n"; file.closeGroup(); return; } //----- Start time is an ISO8601 string date and time. ------ std::string start; try { file.getAttr("start", start); } catch (::NeXus::Exception &) { //Some logs have "offset" instead of start try { file.getAttr("offset", start); } catch (::NeXus::Exception &) { g_log.warning() << "NXlog entry " << entry_name << " has no start time indicated.\n"; file.closeData(); file.closeGroup(); return; } } //Convert to date and time Kernel::DateAndTime start_time = Kernel::DateAndTime(start); std::string time_units; file.getAttr("units", time_units); if (time_units != "second") { g_log.warning() << "NXlog entry " << entry_name << " has time units of '" << time_units << "', which are unsupported. 'second' is the only supported time unit.\n"; file.closeData(); file.closeGroup(); return; } Timer timer2; //--- Load the seconds into a double array --- try { file.getDataCoerce(time_double); } catch (::NeXus::Exception &e) { g_log.warning() << "NXlog entry " << entry_name << "'s time field could not be loaded: '" << e.what() << "'.\n"; file.closeData(); file.closeGroup(); return; } file.closeData(); if (VERBOSE) std::cout << "getDataCoerce for the seconds field took " << timer2.elapsed() << " sec.\n"; if (isInt) { //Make an int TSP TimeSeriesProperty<int> * tsp = new TimeSeriesProperty<int>(entry_name); tsp->create(start_time, time_double, values_int); tsp->setUnits( units ); WS->mutableRun().addProperty( tsp, overwritelogs ); } else { //Make a double TSP TimeSeriesProperty<double> * tsp = new TimeSeriesProperty<double>(entry_name); Timer timer3; tsp->create(start_time, time_double, values); if (VERBOSE) std::cout << "creating a TSP took " << timer3.elapsed() << " sec.\n"; tsp->setUnits( units ); WS->mutableRun().addProperty( tsp, overwritelogs ); // Trick to free memory? std::vector<double>().swap(time_double); std::vector<double>().swap(values); } } file.closeGroup(); }
/** * Read histogram data * @param histogramEntries map of the file entries that have histogram * @param outputGroup pointer to the workspace group * @param nxFile Reads data from inside first first top entry */ void LoadMcStas::readHistogramData( const std::map<std::string, std::string> &histogramEntries, WorkspaceGroup_sptr &outputGroup, ::NeXus::File &nxFile) { std::string nameAttrValueYLABEL; for (const auto &histogramEntry : histogramEntries) { const std::string &dataName = histogramEntry.first; const std::string &dataType = histogramEntry.second; // open second level entry nxFile.openGroup(dataName, dataType); // grap title to use to e.g. create workspace name std::string nameAttrValueTITLE; nxFile.getAttr("filename", nameAttrValueTITLE); if (nxFile.hasAttr("ylabel")) { nxFile.getAttr("ylabel", nameAttrValueYLABEL); } // Find the axis names auto nxdataEntries = nxFile.getEntries(); std::string axis1Name, axis2Name; for (auto &nxdataEntry : nxdataEntries) { if (nxdataEntry.second == "NXparameters") continue; if (nxdataEntry.first == "ncount") continue; nxFile.openData(nxdataEntry.first); if (nxFile.hasAttr("axis")) { int axisNo(0); nxFile.getAttr("axis", axisNo); if (axisNo == 1) axis1Name = nxdataEntry.first; else if (axisNo == 2) axis2Name = nxdataEntry.first; else throw std::invalid_argument("Unknown axis number"); } nxFile.closeData(); } std::vector<double> axis1Values, axis2Values; nxFile.readData<double>(axis1Name, axis1Values); if (axis2Name.length() == 0) { axis2Name = nameAttrValueYLABEL; axis2Values.push_back(0.0); } else { nxFile.readData<double>(axis2Name, axis2Values); } const size_t axis1Length = axis1Values.size(); const size_t axis2Length = axis2Values.size(); g_log.debug() << "Axis lengths=" << axis1Length << " " << axis2Length << '\n'; // Require "data" field std::vector<double> data; nxFile.readData<double>("data", data); // Optional errors field std::vector<double> errors; try { nxFile.readData<double>("errors", errors); } catch (::NeXus::Exception &) { g_log.information() << "Field " << dataName << " contains no error information.\n"; } // close second level entry nxFile.closeGroup(); MatrixWorkspace_sptr ws = WorkspaceFactory::Instance().create( "Workspace2D", axis2Length, axis1Length, axis1Length); Axis *axis1 = ws->getAxis(0); axis1->title() = axis1Name; // Set caption auto lblUnit = boost::make_shared<Units::Label>(); lblUnit->setLabel(axis1Name, ""); axis1->unit() = lblUnit; Axis *axis2 = new NumericAxis(axis2Length); axis2->title() = axis2Name; // Set caption lblUnit = boost::make_shared<Units::Label>(); lblUnit->setLabel(axis2Name, ""); axis2->unit() = lblUnit; ws->setYUnit(axis2Name); ws->replaceAxis(1, axis2); for (size_t wsIndex = 0; wsIndex < axis2Length; ++wsIndex) { auto &dataY = ws->dataY(wsIndex); auto &dataE = ws->dataE(wsIndex); auto &dataX = ws->dataX(wsIndex); for (size_t j = 0; j < axis1Length; ++j) { // Data is stored in column-major order so we are translating to // row major for Mantid const size_t fileDataIndex = j * axis2Length + wsIndex; dataY[j] = data[fileDataIndex]; dataX[j] = axis1Values[j]; if (!errors.empty()) dataE[j] = errors[fileDataIndex]; } axis2->setValue(wsIndex, axis2Values[wsIndex]); } // set the workspace title ws->setTitle(nameAttrValueTITLE); // use the workspace title to create the workspace name std::replace(nameAttrValueTITLE.begin(), nameAttrValueTITLE.end(), ' ', '_'); // ensure that specified name is given to workspace (eventWS) when added to // outputGroup std::string nameOfGroupWS = getProperty("OutputWorkspace"); std::string nameUserSee = nameAttrValueTITLE + "_" + nameOfGroupWS; std::string extraProperty = "Outputworkspace_dummy_" + std::to_string(m_countNumWorkspaceAdded); declareProperty(Kernel::make_unique<WorkspaceProperty<Workspace>>( extraProperty, nameUserSee, Direction::Output)); setProperty(extraProperty, boost::static_pointer_cast<Workspace>(ws)); m_countNumWorkspaceAdded++; // need to increment to ensure extraProperty are // unique // Make Mantid store the workspace in the group outputGroup->addWorkspace(ws); } nxFile.closeGroup(); } // finish