/** Set up corrections with customized TOF correction input * The first column must be either DetectorID or Spectrum (from 0... as * workspace index) * The second column must be Correction or CorrectFactor, a number between 0 * and 1, i.e, [0, 1] * The third column is optional as shift in unit of second */ void FilterEvents::setupCustomizedTOFCorrection() { // Check input workspace vector<string> colnames = m_detCorrectWorkspace->getColumnNames(); bool hasshift = false; if (colnames.size() < 2) throw runtime_error("Input table workspace is not valide."); else if (colnames.size() >= 3) hasshift = true; bool usedetid; if (colnames[0].compare("DetectorID") == 0) usedetid = true; else if (colnames[0].compare("Spectrum") == 0) usedetid = false; else { usedetid = false; stringstream errss; errss << "First column must be either DetectorID or Spectrum. " << colnames[0] << " is not supported. "; throw runtime_error(errss.str()); } // Parse detector and its TOF correction (i.e., offset factor and tof shift) // to a map map<detid_t, double> toffactormap; map<detid_t, double> tofshiftmap; size_t numrows = m_detCorrectWorkspace->rowCount(); for (size_t i = 0; i < numrows; ++i) { TableRow row = m_detCorrectWorkspace->getRow(i); // Parse to map detid_t detid; double offset_factor; row >> detid >> offset_factor; if (offset_factor >= 0 && offset_factor <= 1) { // Valid offset (factor value) toffactormap.emplace(detid, offset_factor); } else { // Error, throw! stringstream errss; errss << "Correction (i.e., offset) equal to " << offset_factor << " of row " << "is out of range [0, 1]."; throw runtime_error(errss.str()); } // Shift if (hasshift) { double shift; row >> shift; tofshiftmap.emplace(detid, shift); } } // ENDFOR(row i) // Check size of TOF correction map size_t numhist = m_eventWS->getNumberHistograms(); if (toffactormap.size() > numhist) { g_log.warning() << "Input correction table workspace has more detectors (" << toffactormap.size() << ") than input workspace " << m_eventWS->name() << "'s spectra number (" << numhist << ".\n"; } else if (toffactormap.size() < numhist) { stringstream errss; errss << "Input correction table workspace has more detectors (" << toffactormap.size() << ") than input workspace " << m_eventWS->name() << "'s spectra number (" << numhist << ".\n"; throw runtime_error(errss.str()); } // Apply to m_detTofOffsets and m_detTofShifts if (usedetid) { // Get vector IDs vector<detid_t> vecDetIDs(numhist, 0); // Set up the detector IDs to vecDetIDs and set up the initial value for (size_t i = 0; i < numhist; ++i) { // It is assumed that there is one detector per spectra. // If there are more than 1 spectrum, it is very likely to have problem // with correction factor const DataObjects::EventList events = m_eventWS->getEventList(i); auto detids = events.getDetectorIDs(); if (detids.size() != 1) { // Check whether there are more than 1 detector per spectra. stringstream errss; errss << "The assumption is that one spectrum has one and only one " "detector. " << "Error is found at spectrum " << i << ". It has " << detids.size() << " detectors."; throw runtime_error(errss.str()); } vecDetIDs[i] = *detids.begin(); } // Map correction map to list map<detid_t, double>::iterator fiter; for (size_t i = 0; i < numhist; ++i) { detid_t detid = vecDetIDs[i]; // correction (factor) map fiter = toffactormap.find(detid); if (fiter != toffactormap.end()) m_detTofFactors[i] = fiter->second; else { stringstream errss; errss << "Detector " << "w/ ID << " << detid << " of spectrum " << i << " in Eventworkspace " << m_eventWS->name() << " cannot be found in input TOF calibration workspace. "; throw runtime_error(errss.str()); } // correction shift map fiter = tofshiftmap.find(detid); if (fiter != tofshiftmap.end()) m_detTofOffsets[i] = fiter->second; } // ENDFOR (each spectrum i) } else { // It is spectrum Number already map<detid_t, double>::iterator fiter; // correction factor for (fiter = toffactormap.begin(); fiter != toffactormap.end(); ++fiter) { size_t wsindex = static_cast<size_t>(fiter->first); if (wsindex < numhist) m_detTofFactors[wsindex] = fiter->second; else { stringstream errss; errss << "Workspace index " << wsindex << " is out of range."; throw runtime_error(errss.str()); } } // correction shift for (fiter = tofshiftmap.begin(); fiter != tofshiftmap.end(); ++fiter) { size_t wsindex = static_cast<size_t>(fiter->first); if (wsindex < numhist) m_detTofOffsets[wsindex] = fiter->second; else { stringstream errss; errss << "Workspace index " << wsindex << " is out of range."; throw runtime_error(errss.str()); } } } return; }
/** Write out an event list into an already-opened group * @param el :: reference to the EventList to write. * @param group_name :: group_name to create. * */ int NexusFileIO::writeEventList( const DataObjects::EventList & el, std::string group_name) const { //write data entry NXstatus status=NXmakegroup(fileID, group_name.c_str(), "NXdata"); if(status==NX_ERROR) return(2); NXopengroup(fileID, group_name.c_str(), "NXdata"); // Copy the detector IDs to an array. const std::set<detid_t>& dets = el.getDetectorIDs(); // Write out the detector IDs if (!dets.empty()) { std::vector<detid_t> detectorIDs(dets.begin(),dets.end()); int dims_array[1]; NXwritedata("detector_IDs", NX_INT64, 1, dims_array, (void*)(detectorIDs.data()), false ); } std::string eventType("UNKNOWN"); size_t num = el.getNumberEvents(); switch (el.getEventType()) { case TOF: eventType = "TOF"; writeEventListData( el.getEvents(), true, true, false, false ); break; case WEIGHTED: eventType = "WEIGHTED"; writeEventListData( el.getWeightedEvents(), true, true, true, true ); break; case WEIGHTED_NOTIME: eventType = "WEIGHTED_NOTIME"; writeEventListData( el.getWeightedEventsNoTime(), true, false, true, true ); break; } // --- Save the type of sorting ----- std::string sortType; switch (el.getSortType()) { case TOF_SORT: sortType = "TOF_SORT"; break; case PULSETIME_SORT: sortType = "PULSETIME_SORT"; break; case UNSORTED: default: sortType = "UNSORTED"; break; } NXputattr (fileID, "sort_type", reinterpret_cast<void*>(const_cast<char*>(sortType.c_str())), static_cast<int>(sortType.size()), NX_CHAR); // Save an attribute with the type of each event. NXputattr (fileID, "event_type", reinterpret_cast<void*>(const_cast<char*>(eventType.c_str())), static_cast<int>(eventType.size()), NX_CHAR); // Save an attribute with the number of events NXputattr (fileID, "num_events", (void*)(&num), 1, NX_INT64); // Close it up! status=NXclosegroup(fileID); return((status==NX_ERROR)?3:0); }