void LoadSINQFocus::loadRunDetails(NXEntry & entry) { API::Run & runDetails = m_localWorkspace->mutableRun(); // int runNum = entry.getInt("run_number"); // std::string run_num = boost::lexical_cast<std::string>(runNum); // runDetails.addProperty("run_number", run_num); std::string start_time = entry.getString("start_time"); //start_time = getDateTimeInIsoFormat(start_time); runDetails.addProperty("run_start", start_time); std::string end_time = entry.getString("end_time"); //end_time = getDateTimeInIsoFormat(end_time); runDetails.addProperty("run_end", end_time); double wavelength = entry.getFloat(m_instrumentPath + "/monochromator/lambda"); runDetails.addProperty<double>("wavelength", wavelength); double energy = entry.getFloat(m_instrumentPath + "/monochromator/energy"); runDetails.addProperty<double>("Ei", energy, true); //overwrite std::string title = entry.getString("title"); runDetails.addProperty("title", title); m_localWorkspace->setTitle(title); }
void LoadLLB::loadRunDetails(NXEntry &entry) { API::Run &runDetails = m_localWorkspace->mutableRun(); // int runNum = entry.getInt("run_number"); // std::string run_num = boost::lexical_cast<std::string>(runNum); // runDetails.addProperty("run_number", run_num); std::string start_time = entry.getString("start_time"); // start_time = getDateTimeInIsoFormat(start_time); runDetails.addProperty("run_start", start_time); std::string end_time = entry.getString("end_time"); // end_time = getDateTimeInIsoFormat(end_time); runDetails.addProperty("run_end", end_time); double wavelength = entry.getFloat("nxbeam/incident_wavelength"); runDetails.addProperty<double>("wavelength", wavelength); double energy = m_loader.calculateEnergy(wavelength); runDetails.addProperty<double>("Ei", energy, true); // overwrite std::string title = entry.getString("title"); runDetails.addProperty("title", title); m_localWorkspace->setTitle(title); }
/** * Loads the mapping between index -> set of detector IDs * * If "detector_index", "detector_count" and "detector_list" are all present, * use these to get the mapping, otherwise spectrum number = detector ID * (one-to-one) * * The spectrum spectrum_index[i] maps to detector_count[i] detectors, whose * detector IDs are in detector_list starting at the index detector_index[i] * * @returns :: map of index -> detector IDs * @throws std::runtime_error if fails to read data from file */ std::map<int, std::set<int>> LoadMuonNexus2::loadDetectorMapping(const Mantid::NeXus::NXInt &spectrumIndex) { std::map<int, std::set<int>> mapping; const int nSpectra = spectrumIndex.dim0(); // Find and open the data group NXRoot root(getPropertyValue("Filename")); NXEntry entry = root.openEntry(m_entry_name); const std::string detectorName = [&entry]() { // Only the first NXdata found for (auto &group : entry.groups()) { std::string className = group.nxclass; if (className == "NXdata") { return group.nxname; } } throw std::runtime_error("No NXdata found in file"); }(); NXData dataGroup = entry.openNXData(detectorName); // Usually for muon data, detector id = spectrum number // If not, the optional groups "detector_index", "detector_list" and // "detector_count" will be present to map one to the other const bool hasDetectorMapping = dataGroup.containsDataSet("detector_index") && dataGroup.containsDataSet("detector_list") && dataGroup.containsDataSet("detector_count"); if (hasDetectorMapping) { // Read detector IDs try { const auto detIndex = dataGroup.openNXInt("detector_index"); const auto detCount = dataGroup.openNXInt("detector_count"); const auto detList = dataGroup.openNXInt("detector_list"); const int nSpectra = detIndex.dim0(); for (int i = 0; i < nSpectra; ++i) { const int start = detIndex[i]; const int nDetectors = detCount[i]; std::set<int> detIDs; for (int jDet = 0; jDet < nDetectors; ++jDet) { detIDs.insert(detList[start + jDet]); } mapping[i] = detIDs; } } catch (const ::NeXus::Exception &err) { // Throw a more user-friendly message std::ostringstream message; message << "Failed to read detector mapping: " << err.what(); throw std::runtime_error(message.str()); } } else { for (int i = 0; i < nSpectra; ++i) { mapping[i] = std::set<int>{spectrumIndex[i]}; } } return mapping; }
/** Execute the algorithm. */ void LoadILLReflectometry::exec() { // Retrieve filename std::string filenameData = getPropertyValue("Filename"); // open the root node NeXus::NXRoot dataRoot(filenameData); NXEntry firstEntry = dataRoot.openFirstEntry(); // Load Monitor details: n. monitors x monitor contents std::vector<std::vector<int>> monitorsData = loadMonitors(firstEntry); // Load Data details (number of tubes, channels, etc) loadDataDetails(firstEntry); std::string instrumentPath = m_loader.findInstrumentNexusPath(firstEntry); setInstrumentName(firstEntry, instrumentPath); initWorkSpace(firstEntry, monitorsData); g_log.debug("Building properties..."); loadNexusEntriesIntoProperties(filenameData); g_log.debug("Loading data..."); loadDataIntoTheWorkSpace(firstEntry, monitorsData); // load the instrument from the IDF if it exists g_log.debug("Loading instrument definition..."); runLoadInstrument(); // 1) Move // Get distance and tilt angle stored in nexus file // Mantid way //// auto angleProp = /// dynamic_cast<PropertyWithValue<double>*>(m_localWorkspace->run().getProperty("dan.value")); // Nexus way double angle = firstEntry.getFloat("instrument/dan/value"); // detector angle in degrees double distance = firstEntry.getFloat( "instrument/det/value"); // detector distance in millimeter distance /= 1000.0; // convert to meter g_log.debug() << "Moving detector at angle " << angle << " and distance " << distance << std::endl; placeDetector(distance, angle); // Set the channel width property auto channel_width = dynamic_cast<PropertyWithValue<double> *>( m_localWorkspace->run().getProperty("monitor1.time_of_flight_0")); m_localWorkspace->mutableRun().addProperty<double>( "channel_width", *channel_width, true); // overwrite // Set the output workspace property setProperty("OutputWorkspace", m_localWorkspace); }
/** Log the run details from the file * @param localWorkspace :: The workspace details to use */ void LoadMuonNexus1::loadRunDetails(DataObjects::Workspace2D_sptr localWorkspace) { API::Run &runDetails = localWorkspace->mutableRun(); runDetails.addProperty("run_title", localWorkspace->getTitle(), true); int numSpectra = static_cast<int>(localWorkspace->getNumberHistograms()); runDetails.addProperty("nspectra", numSpectra); NXRoot root(m_filename); try { std::string start_time = root.getString("run/start_time"); runDetails.addProperty("run_start", start_time); } catch (std::runtime_error &) { g_log.warning("run/start_time is not available, run_start log not added."); } try { std::string stop_time = root.getString("run/stop_time"); runDetails.addProperty("run_end", stop_time); } catch (std::runtime_error &) { g_log.warning("run/stop_time is not available, run_end log not added."); } try { std::string dur = root.getString("run/duration"); runDetails.addProperty("dur", dur); runDetails.addProperty("durunits", 1); // 1 means second here runDetails.addProperty("dur_secs", dur); } catch (std::runtime_error &) { g_log.warning("run/duration is not available, dur log not added."); } // Get sample parameters NXEntry runSample = root.openEntry("run/sample"); if (runSample.containsDataSet("temperature")) { float temperature = runSample.getFloat("temperature"); runDetails.addProperty("sample_temp", static_cast<double>(temperature)); } if (runSample.containsDataSet("magnetic_field")) { float magn_field = runSample.getFloat("magnetic_field"); runDetails.addProperty("sample_magn_field", static_cast<double>(magn_field)); } }
/* * Load data about the Experiment. * * TODO: This is very incomplete. In ISIS they much more info in the nexus file than ILL. * * @param entry :: The Nexus entry */ void LoadSINQFocus::loadExperimentDetails(NXEntry & entry) { std::string name = boost::lexical_cast<std::string>( entry.getFloat("sample/name")); m_localWorkspace->mutableSample().setName(name); }
/** * Load data about the sample * @param local_workspace :: The workspace to load the logs to. * @param entry :: The Nexus entry */ void LoadISISNexus2::loadSampleData(DataObjects::Workspace2D_sptr local_workspace, NXEntry & entry) { /// Sample geometry NXInt spb = entry.openNXInt("isis_vms_compat/SPB"); // Just load the index we need, not the whole block. The flag is the third value in spb.load(1, 2); int geom_id = spb[0]; local_workspace->mutableSample().setGeometryFlag(spb[0]); NXFloat rspb = entry.openNXFloat("isis_vms_compat/RSPB"); // Just load the indices we need, not the whole block. The values start from the 4th onward rspb.load(3, 3); double thick(rspb[0]), height(rspb[1]), width(rspb[2]); local_workspace->mutableSample().setThickness(thick); local_workspace->mutableSample().setHeight(height); local_workspace->mutableSample().setWidth(width); g_log.debug() << "Sample geometry - ID: " << geom_id << ", thickness: " << thick << ", height: " << height << ", width: " << width << "\n"; }
/** Load logs from Nexus file. Logs are expected to be in * /run/sample group of the file. * @param ws :: The workspace to load the logs to. * @param entry :: The Nexus entry * @param period :: The period of this workspace */ void LoadMuonNexus2::loadLogs(API::MatrixWorkspace_sptr ws, NXEntry &entry, int period) { // Avoid compiler warning (void)period; std::string start_time = entry.getString("start_time"); std::string sampleName = entry.getString("sample/name"); NXMainClass runlogs = entry.openNXClass<NXMainClass>("sample"); ws->mutableSample().setName(sampleName); for (std::vector<NXClassInfo>::const_iterator it = runlogs.groups().begin(); it != runlogs.groups().end(); ++it) { NXLog nxLog = runlogs.openNXLog(it->nxname); Kernel::Property *logv = nxLog.createTimeSeries(start_time); if (!logv) continue; ws->mutableRun().addLogData(logv); } ws->setTitle(entry.getString("title")); if (entry.containsDataSet("notes")) { ws->setComment(entry.getString("notes")); } std::string run_num = std::to_string(entry.getInt("run_number")); // The sample is left to delete the property ws->mutableRun().addLogData( new PropertyWithValue<std::string>("run_number", run_num)); ws->populateInstrumentParameters(); }
/** Log the run details from the file * @param localWorkspace :: The workspace details to use */ void LoadMuonNexus2::loadRunDetails( DataObjects::Workspace2D_sptr localWorkspace) { API::Run &runDetails = localWorkspace->mutableRun(); runDetails.addProperty("run_title", localWorkspace->getTitle(), true); int numSpectra = static_cast<int>(localWorkspace->getNumberHistograms()); runDetails.addProperty("nspectra", numSpectra); m_filename = getPropertyValue("Filename"); NXRoot root(m_filename); NXEntry entry = root.openEntry(m_entry_name); std::string start_time = entry.getString("start_time"); runDetails.addProperty("run_start", start_time); std::string stop_time = entry.getString("end_time"); runDetails.addProperty("run_end", stop_time); if (entry.containsGroup("run")) { NXClass runRun = entry.openNXGroup("run"); if (runRun.containsDataSet("good_total_frames")) { int dum = runRun.getInt("good_total_frames"); runDetails.addProperty("goodfrm", dum); } if (runRun.containsDataSet("number_periods")) { int dum = runRun.getInt("number_periods"); runDetails.addProperty("nperiods", dum); } } { // Duration taken to be stop_time minus stat_time auto start = createFromSanitizedISO8601(start_time); auto end = createFromSanitizedISO8601(stop_time); double duration_in_secs = DateAndTime::secondsFromDuration(end - start); runDetails.addProperty("dur_secs", duration_in_secs); } }
/** Load logs from Nexus file. Logs are expected to be in * /raw_data_1/runlog group of the file. Call to this method must be done * within /raw_data_1 group. * @param ws :: The workspace to load the logs to. * @param entry :: Nexus entry */ void LoadISISNexus2::loadLogs(DataObjects::Workspace2D_sptr ws, NXEntry & entry) { IAlgorithm_sptr alg = createChildAlgorithm("LoadNexusLogs", 0.0, 0.5); alg->setPropertyValue("Filename", this->getProperty("Filename")); alg->setProperty<MatrixWorkspace_sptr>("Workspace", ws); try { alg->executeAsChildAlg(); } catch(std::runtime_error&) { g_log.warning() << "Unable to load run logs. There will be no log " << "data associated with this workspace\n"; return; } // For ISIS Nexus only, fabricate an addtional log containing an array of proton charge information from the periods group. try { NXClass protonChargeClass = entry.openNXGroup("periods"); NXFloat periodsCharge = protonChargeClass.openNXFloat("proton_charge"); periodsCharge.load(); size_t nperiods = periodsCharge.dim0(); std::vector<double> chargesVector(nperiods); std::copy(periodsCharge(), periodsCharge() + nperiods, chargesVector.begin()); ArrayProperty<double>* protonLogData = new ArrayProperty<double>("proton_charge_by_period", chargesVector); ws->mutableRun().addProperty(protonLogData); } catch(std::runtime_error&) { this->g_log.debug("Cannot read periods information from the nexus file. This group may be absent."); } // Populate the instrument parameters. ws->populateInstrumentParameters(); // Make log creator object and add the run status log m_logCreator.reset(new ISISRunLogs(ws->run(), m_numberOfPeriods)); m_logCreator->addStatusLog(ws->mutableRun()); }
/** * Read the instrument group * @param mtd_entry :: The node for the current workspace * @param local_workspace :: The workspace to attach the instrument */ void LoadNexusProcessed::readInstrumentGroup(NXEntry & mtd_entry, API::MatrixWorkspace_sptr local_workspace) { //Instrument information NXInstrument inst = mtd_entry.openNXInstrument("instrument"); if ( ! inst.containsGroup("detector") ) { g_log.information() << "Detector block not found. The workspace will not contain any detector information.\n"; return; } //Populate the spectra-detector map NXDetector detgroup = inst.openNXDetector("detector"); //Read necessary arrays from the file // Detector list contains a list of all of the detector numbers. If it not present then we can't update the spectra // map int ndets(-1); boost::shared_array<int> det_list(NULL); try { NXInt detlist_group = detgroup.openNXInt("detector_list"); ndets = detlist_group.dim0(); detlist_group.load(); det_list.swap(detlist_group.sharedBuffer()); } catch(std::runtime_error &) { g_log.information() << "detector_list block not found. The workspace will not contain any detector information." << std::endl; return; } //Detector count contains the number of detectors associated with each spectra NXInt det_count = detgroup.openNXInt("detector_count"); det_count.load(); //Detector index - contains the index of the detector in the workspace NXInt det_index = detgroup.openNXInt("detector_index"); det_index.load(); int nspectra = det_index.dim0(); //Spectra block - Contains spectrum numbers for each workspace index // This might not exist so wrap and check. If it doesn't exist create a default mapping bool have_spectra(true); boost::shared_array<int> spectra(NULL); try { NXInt spectra_block = detgroup.openNXInt("spectra"); spectra_block.load(); spectra.swap(spectra_block.sharedBuffer()); } catch(std::runtime_error &) { have_spectra = false; } //Now build the spectra list int *spectra_list = new int[ndets]; API::Axis *axis1 = local_workspace->getAxis(1); int index=0; for(int i = 1; i <= nspectra; ++i) { int spectrum(-1); if( have_spectra ) spectrum = spectra[i-1]; else spectrum = i+1 ; if ((i >= m_spec_min && i < m_spec_max )||(m_list && find(m_spec_list.begin(), m_spec_list.end(), i) != m_spec_list.end())) { if( m_axis1vals.empty() ) { axis1->spectraNo(index) = spectrum; } else { axis1->setValue(index, m_axis1vals[i-1]); } ++index; } int offset = det_index[i-1]; int detcount = det_count[i-1]; for(int j = 0; j < detcount; j++) { spectra_list[offset + j] = spectrum; } } local_workspace->replaceSpectraMap(new SpectraDetectorMap(spectra_list, det_list.get(), ndets)); delete[] spectra_list; }
/** * Load a table */ API::Workspace_sptr LoadNexusProcessed::loadTableEntry(NXEntry & entry) { API::ITableWorkspace_sptr workspace; workspace = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace"); NXData nx_tw = entry.openNXData("table_workspace"); std::vector<double> values; bool hasNumberOfRowBeenSet = false; //int numberOfRows = 0; int columnNumber = 1; do { std::string str = "column_" + boost::lexical_cast<std::string>(columnNumber); NXInfo info = nx_tw.getDataSetInfo(str.c_str()); if (info.stat == NX_ERROR) { break; } if ( info.type == NX_FLOAT64 ) { NXDouble nxDouble = nx_tw.openNXDouble(str.c_str()); std::string columnTitle = nxDouble.attributes("name"); if (!columnTitle.empty()) { workspace->addColumn("double", columnTitle); nxDouble.load(); int length = nxDouble.dim0(); if ( !hasNumberOfRowBeenSet ) { workspace->setRowCount(length); hasNumberOfRowBeenSet = true; } for (int i = 0; i < length; i++) workspace->cell<double>(i,columnNumber-1) = *(nxDouble() + i); } } else if ( info.type == NX_CHAR ) { NXChar data = nx_tw.openNXChar(str.c_str()); std::string columnTitle = data.attributes("name"); if (!columnTitle.empty()) { workspace->addColumn("str", columnTitle); int nRows = info.dims[0]; if ( !hasNumberOfRowBeenSet ) { workspace->setRowCount(nRows); hasNumberOfRowBeenSet = true; } int maxStr = info.dims[1]; std::string fromCrap(maxStr,' '); data.load(); for (int iR = 0; iR < nRows; iR++) { for (int i = 0; i < maxStr; i++) fromCrap[i] = *(data()+i+maxStr*iR); workspace->cell<std::string>(iR,columnNumber-1) = fromCrap; } } } columnNumber++; } while ( 1 ); return boost::static_pointer_cast<API::Workspace>(workspace); }
/** * Load data about the run * @param local_workspace :: The workspace to load the run information in to * @param entry :: The Nexus entry */ void LoadISISNexus2::loadRunDetails(DataObjects::Workspace2D_sptr local_workspace, NXEntry & entry) { API::Run & runDetails = local_workspace->mutableRun(); // Charge is stored as a float m_proton_charge = static_cast<double>(entry.getFloat("proton_charge")); runDetails.setProtonCharge(m_proton_charge); std::string run_num = boost::lexical_cast<std::string>(entry.getInt("run_number")); runDetails.addProperty("run_number", run_num); // // Some details are only stored in the VMS compatability block so we'll pull everything from there // for consistency NXClass vms_compat = entry.openNXGroup("isis_vms_compat"); // Run header NXChar char_data = vms_compat.openNXChar("HDR"); char_data.load(); runDetails.addProperty("run_header", std::string(char_data(),80)); // Data details on run not the workspace runDetails.addProperty("nspectra", static_cast<int>(m_numberOfSpectraInFile)); runDetails.addProperty("nchannels", static_cast<int>(m_numberOfChannelsInFile)); runDetails.addProperty("nperiods", static_cast<int>(m_numberOfPeriodsInFile)); // RPB struct info NXInt rpb_int = vms_compat.openNXInt("IRPB"); rpb_int.load(); runDetails.addProperty("dur", rpb_int[0]); // actual run duration runDetails.addProperty("durunits", rpb_int[1]); // scaler for above (1=seconds) runDetails.addProperty("dur_freq", rpb_int[2]); // testinterval for above (seconds) runDetails.addProperty("dmp", rpb_int[3]); // dump interval runDetails.addProperty("dmp_units", rpb_int[4]); // scaler for above runDetails.addProperty("dmp_freq", rpb_int[5]); // interval for above runDetails.addProperty("freq", rpb_int[6]); // 2**k where source frequency = 50 / 2**k // Now double data NXFloat rpb_dbl = vms_compat.openNXFloat("RRPB"); rpb_dbl.load(); runDetails.addProperty("gd_prtn_chrg", static_cast<double>(rpb_dbl[7])); // good proton charge (uA.hour) runDetails.addProperty("tot_prtn_chrg", static_cast<double>(rpb_dbl[8])); // total proton charge (uA.hour) runDetails.addProperty("goodfrm",rpb_int[9]); // good frames runDetails.addProperty("rawfrm", rpb_int[10]); // raw frames runDetails.addProperty("dur_wanted", rpb_int[11]); // requested run duration (units as for "duration" above) runDetails.addProperty("dur_secs", rpb_int[12]); // actual run duration in seconds runDetails.addProperty("mon_sum1", rpb_int[13]); // monitor sum 1 runDetails.addProperty("mon_sum2", rpb_int[14]); // monitor sum 2 runDetails.addProperty("mon_sum3",rpb_int[15]); // monitor sum 3 // End date and time is stored separately in ISO format in the "raw_data1/endtime" class char_data = entry.openNXChar("end_time"); char_data.load(); std::string end_time_iso = std::string(char_data(), 19); runDetails.addProperty("run_end", end_time_iso); char_data = entry.openNXChar("start_time"); char_data.load(); std::string start_time_iso = std::string(char_data(), 19); runDetails.addProperty("run_start", start_time_iso); runDetails.addProperty("rb_proposal",rpb_int[21]); // RB (proposal) number vms_compat.close(); }
/** * Load a given period into the workspace * @param period :: The period number to load (starting from 1) * @param entry :: The opened root entry node for accessing the monitor and data nodes * @param local_workspace :: The workspace to place the data in */ void LoadISISNexus2::loadPeriodData(int64_t period, NXEntry & entry, DataObjects::Workspace2D_sptr local_workspace) { int64_t hist_index = 0; int64_t period_index(period - 1); int64_t first_monitor_spectrum = 0; if( !m_monitors.empty() ) { first_monitor_spectrum = m_monitors.begin()->first; hist_index = first_monitor_spectrum - 1; for(std::map<int64_t,std::string>::const_iterator it = m_monitors.begin(); it != m_monitors.end(); ++it) { NXData monitor = entry.openNXData(it->second); NXInt mondata = monitor.openIntData(); m_progress->report("Loading monitor"); mondata.load(1,static_cast<int>(period-1)); // TODO this is just wrong MantidVec& Y = local_workspace->dataY(hist_index); Y.assign(mondata(),mondata() + m_numberOfChannels); MantidVec& E = local_workspace->dataE(hist_index); std::transform(Y.begin(), Y.end(), E.begin(), dblSqrt); local_workspace->getAxis(1)->spectraNo(hist_index) = static_cast<specid_t>(it->first); NXFloat timeBins = monitor.openNXFloat("time_of_flight"); timeBins.load(); local_workspace->dataX(hist_index).assign(timeBins(),timeBins() + timeBins.dim0()); hist_index++; } if (first_monitor_spectrum > 1) { hist_index = 0; } } if( m_have_detector ) { NXData nxdata = entry.openNXData("detector_1"); NXDataSetTyped<int> data = nxdata.openIntData(); data.open(); //Start with thelist members that are lower than the required spectrum const int * const spec_begin = m_spec.get(); std::vector<int64_t>::iterator min_end = m_spec_list.end(); if( !m_spec_list.empty() ) { // If we have a list, by now it is ordered so first pull in the range below the starting block range // Note the reverse iteration as we want the last one if( m_range_supplied ) { min_end = std::find_if(m_spec_list.begin(), m_spec_list.end(), std::bind2nd(std::greater<int>(), m_spec_min)); } for( std::vector<int64_t>::iterator itr = m_spec_list.begin(); itr < min_end; ++itr ) { // Load each int64_t spectra_no = (*itr); // For this to work correctly, we assume that the spectrum list increases monotonically int64_t filestart = std::lower_bound(spec_begin,m_spec_end,spectra_no) - spec_begin; m_progress->report("Loading data"); loadBlock(data, static_cast<int64_t>(1), period_index, filestart, hist_index, spectra_no, local_workspace); } } if( m_range_supplied ) { // When reading in blocks we need to be careful that the range is exactly divisible by the blocksize // and if not have an extra read of the left overs const int64_t blocksize = 8; const int64_t rangesize = (m_spec_max - m_spec_min + 1) - m_monitors.size(); const int64_t fullblocks = rangesize / blocksize; int64_t read_stop = 0; int64_t spectra_no = m_spec_min; if (first_monitor_spectrum == 1) {// this if crudely checks whether the monitors are at the begining or end of the spectra spectra_no += static_cast<int>(m_monitors.size()); } // For this to work correctly, we assume that the spectrum list increases monotonically int64_t filestart = std::lower_bound(spec_begin,m_spec_end,spectra_no) - spec_begin; if( fullblocks > 0 ) { read_stop = (fullblocks * blocksize);// + m_monitors.size(); //RNT: I think monitors are excluded from the data //for( ; hist_index < read_stop; ) for(int64_t i = 0; i < fullblocks; ++i) { loadBlock(data, blocksize, period_index, filestart, hist_index, spectra_no, local_workspace); filestart += blocksize; } } int64_t finalblock = rangesize - (fullblocks * blocksize); if( finalblock > 0 ) { loadBlock(data, finalblock, period_index, filestart, hist_index, spectra_no, local_workspace); } } //Load in the last of the list indices for( std::vector<int64_t>::iterator itr = min_end; itr < m_spec_list.end(); ++itr ) { // Load each int64_t spectra_no = (*itr); // For this to work correctly, we assume that the spectrum list increases monotonically int64_t filestart = std::lower_bound(spec_begin,m_spec_end,spectra_no) - spec_begin; loadBlock(data, 1, period_index, filestart, hist_index, spectra_no, local_workspace); } } try { const std::string title = entry.getString("title"); local_workspace->setTitle(title); // write the title into the log file (run object) local_workspace->mutableRun().addProperty("run_title", title, true); } catch (std::runtime_error &) { g_log.debug() << "No title was found in the input file, " << getPropertyValue("Filename") << std::endl; } }
/** * Load data about the run * @param local_workspace :: The workspace to load the run information in to * @param entry :: The Nexus entry */ void LoadISISNexus2::loadRunDetails(DataObjects::Workspace2D_sptr &local_workspace, NXEntry &entry) { API::Run &runDetails = local_workspace->mutableRun(); // Charge is stored as a float m_proton_charge = static_cast<double>(entry.getFloat("proton_charge")); runDetails.setProtonCharge(m_proton_charge); std::string run_num = boost::lexical_cast<std::string>(entry.getInt("run_number")); runDetails.addProperty("run_number", run_num); // // Some details are only stored in the VMS comparability block so we'll pull // everything from there // for consistency NXClass vms_compat = entry.openNXGroup("isis_vms_compat"); // Run header NXChar char_data = vms_compat.openNXChar("HDR"); char_data.load(); // Space-separate the fields char *nxsHdr = char_data(); char header[86] = {}; const size_t byte = sizeof(char); const char fieldSep(' '); size_t fieldWidths[7] = {3, 5, 20, 24, 12, 8, 8}; char *srcStart = nxsHdr; char *destStart = header; for (size_t i = 0; i < 7; ++i) { size_t width = fieldWidths[i]; memcpy(destStart, srcStart, width * byte); if (i < 6) // no space after last field { srcStart += width; destStart += width; memset(destStart, fieldSep, byte); // insert separator destStart += 1; } } runDetails.addProperty("run_header", std::string(header, header + 86)); // Data details on run not the workspace runDetails.addProperty("nspectra", static_cast<int>(m_loadBlockInfo.numberOfSpectra)); runDetails.addProperty("nchannels", static_cast<int>(m_loadBlockInfo.numberOfChannels)); runDetails.addProperty("nperiods", static_cast<int>(m_loadBlockInfo.numberOfPeriods)); // RPB struct info NXInt rpb_int = vms_compat.openNXInt("IRPB"); rpb_int.load(); runDetails.addProperty("dur", rpb_int[0]); // actual run duration runDetails.addProperty("durunits", rpb_int[1]); // scaler for above (1=seconds) runDetails.addProperty("dur_freq", rpb_int[2]); // testinterval for above (seconds) runDetails.addProperty("dmp", rpb_int[3]); // dump interval runDetails.addProperty("dmp_units", rpb_int[4]); // scaler for above runDetails.addProperty("dmp_freq", rpb_int[5]); // interval for above runDetails.addProperty("freq", rpb_int[6]); // 2**k where source frequency = 50 / 2**k // Now double data NXFloat rpb_dbl = vms_compat.openNXFloat("RRPB"); rpb_dbl.load(); runDetails.addProperty( "gd_prtn_chrg", static_cast<double>(rpb_dbl[7])); // good proton charge (uA.hour) runDetails.addProperty( "tot_prtn_chrg", static_cast<double>(rpb_dbl[8])); // total proton charge (uA.hour) runDetails.addProperty("goodfrm", rpb_int[9]); // good frames runDetails.addProperty("rawfrm", rpb_int[10]); // raw frames runDetails.addProperty( "dur_wanted", rpb_int[11]); // requested run duration (units as for "duration" above) runDetails.addProperty("dur_secs", rpb_int[12]); // actual run duration in seconds runDetails.addProperty("mon_sum1", rpb_int[13]); // monitor sum 1 runDetails.addProperty("mon_sum2", rpb_int[14]); // monitor sum 2 runDetails.addProperty("mon_sum3", rpb_int[15]); // monitor sum 3 // End date and time is stored separately in ISO format in the // "raw_data1/endtime" class char_data = entry.openNXChar("end_time"); char_data.load(); std::string end_time_iso = std::string(char_data(), 19); runDetails.addProperty("run_end", end_time_iso); char_data = entry.openNXChar("start_time"); char_data.load(); std::string start_time_iso = std::string(char_data(), 19); runDetails.addProperty("run_start", start_time_iso); runDetails.addProperty("rb_proposal", rpb_int[21]); // RB (proposal) number vms_compat.close(); }
/** * Load a given period into the workspace * @param period :: The period number to load (starting from 1) * @param entry :: The opened root entry node for accessing the monitor and data * nodes * @param local_workspace :: The workspace to place the data in * @param update_spectra2det_mapping :: reset spectra-detector map to the one * calculated earlier. (Warning! -- this map has to be calculated correctly!) */ void LoadISISNexus2::loadPeriodData(int64_t period, NXEntry &entry, DataObjects::Workspace2D_sptr &local_workspace, bool update_spectra2det_mapping) { int64_t hist_index = 0; int64_t period_index(period - 1); // int64_t first_monitor_spectrum = 0; for (auto block = m_spectraBlocks.begin(); block != m_spectraBlocks.end(); ++block) { if (block->isMonitor) { NXData monitor = entry.openNXData(block->monName); NXInt mondata = monitor.openIntData(); m_progress->report("Loading monitor"); mondata.load(1, static_cast<int>(period - 1)); // TODO this is just wrong MantidVec &Y = local_workspace->dataY(hist_index); Y.assign(mondata(), mondata() + m_monBlockInfo.numberOfChannels); MantidVec &E = local_workspace->dataE(hist_index); std::transform(Y.begin(), Y.end(), E.begin(), dblSqrt); if (update_spectra2det_mapping) { // local_workspace->getAxis(1)->setValue(hist_index, // static_cast<specid_t>(it->first)); auto spec = local_workspace->getSpectrum(hist_index); specid_t specID = m_specInd2specNum_map.at(hist_index); spec->setDetectorIDs( m_spec2det_map.getDetectorIDsForSpectrumNo(specID)); spec->setSpectrumNo(specID); } NXFloat timeBins = monitor.openNXFloat("time_of_flight"); timeBins.load(); local_workspace->dataX(hist_index) .assign(timeBins(), timeBins() + timeBins.dim0()); hist_index++; } else if (m_have_detector) { NXData nxdata = entry.openNXData("detector_1"); NXDataSetTyped<int> data = nxdata.openIntData(); data.open(); // Start with the list members that are lower than the required spectrum const int *const spec_begin = m_spec.get(); // When reading in blocks we need to be careful that the range is exactly // divisible by the block-size // and if not have an extra read of the left overs const int64_t blocksize = 8; const int64_t rangesize = block->last - block->first + 1; const int64_t fullblocks = rangesize / blocksize; int64_t spectra_no = block->first; // For this to work correctly, we assume that the spectrum list increases // monotonically int64_t filestart = std::lower_bound(spec_begin, m_spec_end, spectra_no) - spec_begin; if (fullblocks > 0) { for (int64_t i = 0; i < fullblocks; ++i) { loadBlock(data, blocksize, period_index, filestart, hist_index, spectra_no, local_workspace); filestart += blocksize; } } int64_t finalblock = rangesize - (fullblocks * blocksize); if (finalblock > 0) { loadBlock(data, finalblock, period_index, filestart, hist_index, spectra_no, local_workspace); } } } try { const std::string title = entry.getString("title"); local_workspace->setTitle(title); // write the title into the log file (run object) local_workspace->mutableRun().addProperty("run_title", title, true); } catch (std::runtime_error &) { g_log.debug() << "No title was found in the input file, " << getPropertyValue("Filename") << std::endl; } }
/**Method takes input parameters which describe monitor loading and analyze *them against spectra/monitor block information in the file. * The result is the option if monitors can be loaded together with spectra or *mast be treated separately * and additional information on how to treat monitor spectra. * *@param entry :: entry to the NeXus file, opened at root folder *@param spectrum_index :: array of spectra indexes of the data present in *the file *@param ndets :: size of the spectrum index array *@param n_vms_compat_spectra :: number of data entries containing common time *bins (e.g. all spectra, or all spectra and monitors or some spectra (this is *not fully supported) *@param monitors :: map connecting monitor spectra ID against *monitor group name in the file. *@param excludeMonitors :: input property indicating if it is requested to *exclude monitors from the target workspace *@param separateMonitors :: input property indicating if it is requested to *load monitors separately (and exclude them from target data workspace this way) * *@param OvelapMonitors :: output property containing the list of monitors *ID for monitors, which are also included with spectra. *@return excludeMonitors :: indicator if monitors should or mast be excluded *from the main data workspace if they can not be loaded with the data * (contain different number of time channels) * */ bool LoadISISNexus2::findSpectraDetRangeInFile( NXEntry &entry, boost::shared_array<int> &spectrum_index, int64_t ndets, int64_t n_vms_compat_spectra, std::map<int64_t, std::string> &monitors, bool excludeMonitors, bool separateMonitors, std::map<int64_t, std::string> &OvelapMonitors) { OvelapMonitors.clear(); size_t nmons = monitors.size(); if (nmons > 0) { NXInt chans = entry.openNXInt(m_monitors.begin()->second + "/data"); m_monBlockInfo = DataBlock(chans); m_monBlockInfo.numberOfSpectra = nmons; // each monitor is in separate group // so number of spectra is equal to // number of groups. // identify monitor ID range. for (auto it = monitors.begin(); it != monitors.end(); it++) { int64_t mon_id = static_cast<int64_t>(it->first); if (m_monBlockInfo.spectraID_min > mon_id) m_monBlockInfo.spectraID_min = mon_id; if (m_monBlockInfo.spectraID_max < mon_id) m_monBlockInfo.spectraID_max = mon_id; } if (m_monBlockInfo.spectraID_max - m_monBlockInfo.spectraID_min + 1 != static_cast<int64_t>(nmons)) { g_log.warning() << "When trying to find the range of monitor spectra: " "non-consequent monitor ID-s in the monitor block. " "Unexpected situation for the loader\n"; } // at this stage we assume that the only going to load monitors m_loadBlockInfo = m_monBlockInfo; } if (ndets == 0) { separateMonitors = false; // only monitors in the main workspace. No // detectors. Will be loaded in the main workspace // Possible function exit point return separateMonitors; } // detectors are present in the file NXData nxData = entry.openNXData("detector_1"); NXInt data = nxData.openIntData(); m_detBlockInfo = DataBlock(data); // We assume again that this spectrum list ID increase monotonically m_detBlockInfo.spectraID_min = spectrum_index[0]; m_detBlockInfo.spectraID_max = spectrum_index[ndets - 1]; if (m_detBlockInfo.spectraID_max - m_detBlockInfo.spectraID_min + 1 != static_cast<int64_t>(m_detBlockInfo.numberOfSpectra)) { g_log.warning() << "When trying to find the range of monitor spectra: " "non-consequent spectra ID-s in the detectors block. " "Unexpected situation for the loader\n"; } m_loadBlockInfo = m_detBlockInfo; // now we are analyzing what is actually going or can be loaded bool removeMonitors = excludeMonitors || separateMonitors; if (((m_detBlockInfo.numberOfPeriods != m_monBlockInfo.numberOfPeriods) || (m_detBlockInfo.numberOfChannels != m_monBlockInfo.numberOfChannels)) && nmons > 0) { // detectors and monitors have different characteristics. Can be loaded only // to separate workspaces. if (!removeMonitors) { g_log.warning() << " Performing separate loading as can not load spectra " "and monitors in the single workspace:\n"; g_log.warning() << " Monitors data contain :" << m_monBlockInfo.numberOfChannels << " time channels and: " << m_monBlockInfo.numberOfPeriods << " period(s)\n"; g_log.warning() << " Spectra data contain :" << m_detBlockInfo.numberOfChannels << " time channels and: " << m_detBlockInfo.numberOfPeriods << " period(s)\n"; } separateMonitors = true; removeMonitors = true; } int64_t spectraID_min = std::min(m_monBlockInfo.spectraID_min, m_detBlockInfo.spectraID_min); int64_t spectraID_max = std::max(m_monBlockInfo.spectraID_max, m_detBlockInfo.spectraID_max); size_t totNumOfSpectra = m_monBlockInfo.numberOfSpectra + m_detBlockInfo.numberOfSpectra; if (!removeMonitors) { m_loadBlockInfo.numberOfSpectra = totNumOfSpectra; m_loadBlockInfo.spectraID_min = spectraID_min; m_loadBlockInfo.spectraID_max = spectraID_max; } if (separateMonitors) m_loadBlockInfo = m_detBlockInfo; // verify integrity of the monitor and detector information if ((totNumOfSpectra == static_cast<size_t>(n_vms_compat_spectra)) && (spectraID_max - spectraID_min + 1 == static_cast<int64_t>(n_vms_compat_spectra))) { // all information written in the file is correct, there are no spurious // spectra and detectors & monitors form continuous block on HDD return separateMonitors; } // something is wrong and we need to analyze spectra map. Currently we can // identify and manage the case when all monitor's spectra are written // together with detectors // make settings for this situation m_detBlockInfo.numberOfSpectra -= m_monBlockInfo.numberOfSpectra; m_loadBlockInfo.numberOfSpectra -= m_monBlockInfo.numberOfSpectra; std::map<int64_t, std::string> remaining_monitors; if (removeMonitors) { for (auto it = monitors.begin(); it != monitors.end(); it++) { if (it->first >= m_detBlockInfo.spectraID_min && it->first <= m_detBlockInfo.spectraID_max) { // monitors ID-s are // included with spectra // ID-s -- let's try not // to load it twice. OvelapMonitors.insert(*it); } else { remaining_monitors.insert(*it); } } } monitors.swap(remaining_monitors); return separateMonitors; }