/** Get the list of banks, given the settings * * @return map with key = bank number; value = pointer to the rectangular *detector */ std::map<int, RectangularDetector_const_sptr> ConvertToDetectorFaceMD::getBanks() { Instrument_const_sptr inst = in_ws->getInstrument(); std::vector<int> bankNums = this->getProperty("BankNumbers"); std::sort(bankNums.begin(), bankNums.end()); std::map<int, RectangularDetector_const_sptr> banks; if (bankNums.empty()) { // --- Find all rectangular detectors ---- // Get all children std::vector<IComponent_const_sptr> comps; inst->getChildren(comps, true); for (auto &comp : comps) { // Retrieve it RectangularDetector_const_sptr det = boost::dynamic_pointer_cast<const RectangularDetector>(comp); if (det) { std::string name = det->getName(); if (name.size() < 5) continue; std::string bank = name.substr(4, name.size() - 4); int bankNum; if (Mantid::Kernel::Strings::convert(bank, bankNum)) banks[bankNum] = det; g_log.debug() << "Found bank " << bank << ".\n"; } } } else { // -- Find detectors using the numbers given --- for (auto &bankNum : bankNums) { std::string bankName = "bank" + Mantid::Kernel::Strings::toString(bankNum); IComponent_const_sptr comp = inst->getComponentByName(bankName); RectangularDetector_const_sptr det = boost::dynamic_pointer_cast<const RectangularDetector>(comp); if (det) banks[bankNum] = det; } } for (auto &bank : banks) { RectangularDetector_const_sptr det = bank.second; // Track the largest detector if (det->xpixels() > m_numXPixels) m_numXPixels = det->xpixels(); if (det->ypixels() > m_numYPixels) m_numYPixels = det->ypixels(); } if (banks.empty()) throw std::runtime_error("No RectangularDetectors with a name like " "'bankXX' found in the instrument."); return banks; }
/** Execute the algorithm. */ void SaveIsawPeaks::exec() { // Section header std::string header = "2 SEQN H K L COL ROW CHAN L2 2_THETA AZ WL D IPK INTI SIGI RFLG"; std::string filename = getPropertyValue("Filename"); PeaksWorkspace_sptr ws = getProperty("InputWorkspace"); std::vector<Peak> peaks = ws->getPeaks(); // We must sort the peaks first by run, then bank #, and save the list of workspace indices of it typedef std::map<int, std::vector<size_t> > bankMap_t; typedef std::map<int, bankMap_t> runMap_t; std::set<int> uniqueBanks; runMap_t runMap; for (size_t i=0; i < peaks.size(); ++i) { Peak & p = peaks[i]; int run = p.getRunNumber(); int bank = 0; std::string bankName = p.getBankName(); if (bankName.size() <= 4) { g_log.information() << "Could not interpret bank number of peak " << i << "(" << bankName << ")\n"; continue; } // Take out the "bank" part of the bank name and convert to an int bankName = bankName.substr(4, bankName.size()-4); Strings::convert(bankName, bank); // Save in the map runMap[run][bank].push_back(i); // Track unique bank numbers uniqueBanks.insert(bank); } Instrument_const_sptr inst = ws->getInstrument(); if (!inst) throw std::runtime_error("No instrument in PeaksWorkspace. Cannot save peaks file."); double l1; V3D beamline; double beamline_norm; V3D samplePos; inst->getInstrumentParameters(l1, beamline, beamline_norm, samplePos); std::ofstream out; bool append = getProperty("AppendFile"); if (append) { out.open( filename.c_str(), std::ios::app); } else { out.open( filename.c_str()); out << "Version: 2.0 Facility: SNS " ; out << " Instrument: " << inst->getName() << " Date: " ; //TODO: The experiment date might be more useful than the instrument date. // For now, this allows the proper instrument to be loaded back after saving. Kernel::DateAndTime expDate = inst->getValidFromDate() + 1.0; out << expDate.to_ISO8601_string() << std::endl; out << "6 L1 T0_SHIFT" << std::endl; out << "7 "<< std::setw( 10 ) ; out << std::setprecision( 4 ) << std::fixed << ( l1*100 ) ; out << std::setw( 12 ) << std::setprecision( 3 ) << std::fixed ; // Time offset of 0.00 for now out << "0.000" << std::endl; // ============================== Save .detcal info ========================================= if (true) { out << "4 DETNUM NROWS NCOLS WIDTH HEIGHT DEPTH DETD CenterX CenterY CenterZ BaseX BaseY BaseZ UpX UpY UpZ" << std::endl; // Here would save each detector... std::set<int>::iterator it; for (it = uniqueBanks.begin(); it != uniqueBanks.end(); it++) { // Build up the bank name int bank = *it; std::ostringstream mess; mess << "bank" << bank; std::string bankName = mess.str(); // Retrieve it RectangularDetector_const_sptr det = boost::dynamic_pointer_cast<const RectangularDetector>(inst->getComponentByName(bankName)); if (det) { // Center of the detector V3D center = det->getPos(); // Distance to center of detector double detd = (center - inst->getSample()->getPos()).norm(); // Base unit vector (along the horizontal, X axis) V3D base = det->getAtXY(det->xpixels()-1,0)->getPos() - det->getAtXY(0,0)->getPos(); base.normalize(); // Up unit vector (along the vertical, Y axis) V3D up = det->getAtXY(0,det->ypixels()-1)->getPos() - det->getAtXY(0,0)->getPos(); up.normalize(); // Write the line out << "5 " << std::setw(6) << std::right << bank << " " << std::setw(6) << std::right << det->xpixels() << " " << std::setw(6) << std::right << det->ypixels() << " " << std::setw(7) << std::right << std::fixed << std::setprecision(4) << 100.0*det->xsize() << " " << std::setw(7) << std::right << std::fixed << std::setprecision(4) << 100.0*det->ysize() << " " << " 0.2000 " << std::setw(6) << std::right << std::fixed << std::setprecision(2) << 100.0*detd << " " << std::setw(9) << std::right << std::fixed << std::setprecision(4) << 100.0*center.X() << " " << std::setw(9) << std::right << std::fixed << std::setprecision(4) << 100.0*center.Y() << " " << std::setw(9) << std::right << std::fixed << std::setprecision(4) << 100.0*center.Z() << " " << std::setw(8) << std::right << std::fixed << std::setprecision(5) << base.X() << " " << std::setw(8) << std::right << std::fixed << std::setprecision(5) << base.Y() << " " << std::setw(8) << std::right << std::fixed << std::setprecision(5) << base.Z() << " " << std::setw(8) << std::right << std::fixed << std::setprecision(5) << up.X() << " " << std::setw(8) << std::right << std::fixed << std::setprecision(5) << up.Y() << " " << std::setw(8) << std::right << std::fixed << std::setprecision(5) << up.Z() << " " << std::endl; } } } } // ============================== Save all Peaks ========================================= // Sequence number int seqNum = 1; // Go in order of run numbers runMap_t::iterator runMap_it; for (runMap_it = runMap.begin(); runMap_it != runMap.end(); runMap_it++) { // Start of a new run int run = runMap_it->first; bankMap_t & bankMap = runMap_it->second; bankMap_t::iterator bankMap_it; for (bankMap_it = bankMap.begin(); bankMap_it != bankMap.end(); bankMap_it++) { // Start of a new bank. int bank = bankMap_it->first; std::vector<size_t> & ids = bankMap_it->second; if (ids.size() > 0) { // Write the bank header out << "0 NRUN DETNUM CHI PHI OMEGA MONCNT" << std::endl; out << "1" << std::setw( 5 ) << run << std::setw( 7 ) << std::right << bank; // Determine goniometer angles by calculating from the goniometer matrix of a peak in the list Goniometer gon(peaks[ids[0]].getGoniometerMatrix()); std::vector<double> angles = gon.getEulerAngles("yzy"); double phi = angles[2]; double chi = angles[1]; double omega = angles[0]; out << std::setw( 7 ) << std::fixed << std::setprecision( 2 ) << chi << " "; out << std::setw( 7 ) << std::fixed << std::setprecision( 2 ) << phi << " "; out << std::setw( 7 ) << std::fixed << std::setprecision( 2 ) << omega << " "; out << std::setw( 7 ) << (int)( 0 ) << std::endl; out << header << std::endl; // Go through each peak at this run / bank for (size_t i=0; i < ids.size(); i++) { size_t wi = ids[i]; Peak & p = peaks[wi]; // Sequence (run) number out << "3" << std::setw( 7 ) << seqNum; // HKL is flipped by -1 due to different q convention in ISAW vs mantid. out << std::setw( 5 ) << Utils::round(-p.getH()) << std::setw( 5 ) << Utils::round(-p.getK()) << std::setw( 5 ) << Utils::round(-p.getL()); // Row/column out << std::setw( 8 ) << std::fixed << std::setprecision( 2 ) << static_cast<double>(p.getCol()) << " "; out << std::setw( 8 ) << std::fixed << std::setprecision( 2 ) << static_cast<double>(p.getRow()) << " "; out << std::setw( 8 ) << std::fixed << std::setprecision( 0 ) << p.getTOF() << " "; out << std::setw( 9 ) << std::fixed << std::setprecision( 3 ) << (p.getL2()*100.0) << " "; // This is the scattered beam direction V3D dir = p.getDetPos() - inst->getSample()->getPos(); double scattering, azimuth; // Two-theta = polar angle = scattering angle = between +Z vector and the scattered beam scattering = dir.angle( V3D(0.0, 0.0, 1.0) ); // "Azimuthal" angle: project the beam onto the XY plane, and measure the angle between that and the +X axis (right-handed) azimuth = atan2( dir.Y(), dir.X() ); out << std::setw( 9 ) << std::fixed << std::setprecision( 5 ) << scattering << " "; //two-theta scattering out << std::setw( 9 ) << std::fixed << std::setprecision( 5 ) << azimuth << " "; out << std::setw( 10 ) << std::fixed << std::setprecision( 6 ) << p.getWavelength() << " "; out << std::setw( 9 ) << std::fixed << std::setprecision( 4 ) << p.getDSpacing() << " "; out << std::setw( 8 ) << std::fixed << int(p.getBinCount()) << std::setw( 10 ) << " " << std::fixed << std::setprecision( 2 ) << p.getIntensity() << " "; out << std::setw( 7 ) << std::fixed << std::setprecision( 2 ) << p.getSigmaIntensity() << " "; int thisReflag = 310; out << std::setw( 5 ) << thisReflag; out << std::endl; // Count the sequence seqNum++; } } } } out.flush(); out.close(); // //REMOVE: // std::string line; // std::ifstream myfile (filename.c_str()); // if (myfile.is_open()) // { // while ( myfile.good() ) // { // getline (myfile,line); // std::cout << line << std::endl; // } // myfile.close(); // } }
/** Execute the algorithm. */ void ConvertToDetectorFaceMD::exec() { // TODO convert matrix to event as needed MatrixWorkspace_sptr mws = this->getProperty("InputWorkspace"); in_ws = boost::dynamic_pointer_cast<EventWorkspace>(mws); if (!in_ws) throw std::runtime_error("InputWorkspace is not an EventWorkspace"); // Fill the map, throw if there are grouped pixels. m_detID_to_WI = in_ws->getDetectorIDToWorkspaceIndexVector(m_detID_to_WI_offset, true); // Get the map of the banks we'll display std::map<int, RectangularDetector_const_sptr> banks = this->getBanks(); // Find the size in the TOF dimension double tof_min, tof_max; Axis *ax0 = in_ws->getAxis(0); in_ws->getXMinMax(tof_min, tof_max); if (ax0->getValue(0) < tof_min) tof_min = ax0->getValue(0); if (ax0->getValue(ax0->length() - 1) > tof_max) tof_max = ax0->getValue(ax0->length() - 1); // Get MDFrame of General Frame type Mantid::Geometry::GeneralFrame framePixel( Mantid::Geometry::GeneralFrame::GeneralFrameName, "pixel"); Mantid::Geometry::GeneralFrame frameTOF( Mantid::Geometry::GeneralFrame::GeneralFrameName, ax0->unit()->label()); // ------------------ Build all the dimensions ---------------------------- MDHistoDimension_sptr dimX( new MDHistoDimension("x", "x", framePixel, static_cast<coord_t>(0), static_cast<coord_t>(m_numXPixels), m_numXPixels)); MDHistoDimension_sptr dimY( new MDHistoDimension("y", "y", framePixel, static_cast<coord_t>(0), static_cast<coord_t>(m_numYPixels), m_numYPixels)); std::string TOFname = ax0->title(); if (TOFname.empty()) TOFname = ax0->unit()->unitID(); MDHistoDimension_sptr dimTOF(new MDHistoDimension( TOFname, TOFname, frameTOF, static_cast<coord_t>(tof_min), static_cast<coord_t>(tof_max), ax0->length())); std::vector<IMDDimension_sptr> dims{dimX, dimY, dimTOF}; if (banks.size() > 1) { Mantid::Geometry::GeneralFrame frameNumber( Mantid::Geometry::GeneralFrame::GeneralFrameName, "number"); int min = banks.begin()->first; int max = banks.rbegin()->first + 1; MDHistoDimension_sptr dimBanks(new MDHistoDimension( "bank", "bank", frameNumber, static_cast<coord_t>(min), static_cast<coord_t>(max), max - min)); dims.push_back(dimBanks); } // --------- Create the workspace with the right number of dimensions // ---------- size_t nd = dims.size(); IMDEventWorkspace_sptr outWS = MDEventFactory::CreateMDWorkspace(nd, "MDEvent"); outWS->initGeometry(dims); outWS->initialize(); this->setBoxController(outWS->getBoxController(), mws->getInstrument()); outWS->splitBox(); MDEventWorkspace3::sptr outWS3 = boost::dynamic_pointer_cast<MDEventWorkspace3>(outWS); MDEventWorkspace4::sptr outWS4 = boost::dynamic_pointer_cast<MDEventWorkspace4>(outWS); // Copy ExperimentInfo (instrument, run, sample) to the output WS ExperimentInfo_sptr ei(in_ws->cloneExperimentInfo()); uint16_t runIndex = outWS->addExperimentInfo(ei); // ---------------- Convert each bank -------------------------------------- for (auto &bank : banks) { int bankNum = bank.first; RectangularDetector_const_sptr det = bank.second; for (int x = 0; x < det->xpixels(); x++) for (int y = 0; y < det->ypixels(); y++) { // Find the workspace index for this pixel coordinate detid_t detID = det->getDetectorIDAtXY(x, y); size_t wi = m_detID_to_WI[detID + m_detID_to_WI_offset]; if (wi >= in_ws->getNumberHistograms()) throw std::runtime_error("Invalid workspace index found in bank " + det->getName() + "!"); coord_t xPos = static_cast<coord_t>(x); coord_t yPos = static_cast<coord_t>(y); coord_t bankPos = static_cast<coord_t>(bankNum); EventList &el = in_ws->getSpectrum(wi); // We want to bind to the right templated function, so we have to know // the type of TofEvent contained in the EventList. boost::function<void()> func; switch (el.getEventType()) { case TOF: if (nd == 3) this->convertEventList<TofEvent, MDEvent<3>, 3>( outWS3, wi, xPos, yPos, bankPos, runIndex, detID); else if (nd == 4) this->convertEventList<TofEvent, MDEvent<4>, 4>( outWS4, wi, xPos, yPos, bankPos, runIndex, detID); break; case WEIGHTED: if (nd == 3) this->convertEventList<WeightedEvent, MDEvent<3>, 3>( outWS3, wi, xPos, yPos, bankPos, runIndex, detID); else if (nd == 4) this->convertEventList<WeightedEvent, MDEvent<4>, 4>( outWS4, wi, xPos, yPos, bankPos, runIndex, detID); break; case WEIGHTED_NOTIME: if (nd == 3) this->convertEventList<WeightedEventNoTime, MDEvent<3>, 3>( outWS3, wi, xPos, yPos, bankPos, runIndex, detID); else if (nd == 4) this->convertEventList<WeightedEventNoTime, MDEvent<4>, 4>( outWS4, wi, xPos, yPos, bankPos, runIndex, detID); break; default: throw std::runtime_error("EventList had an unexpected data type!"); } } } // ---------------------- Perform all box splitting --------------- ThreadScheduler *ts = new ThreadSchedulerLargestCost(); ThreadPool tp(ts); outWS->splitAllIfNeeded(ts); tp.joinAll(); outWS->refreshCache(); // Save the output workspace this->setProperty("OutputWorkspace", outWS); }
/** Write the group labeled "data" * * @param bank :: name of the bank * @param is_definition * @return error code */ int SaveToSNSHistogramNexus::WriteDataGroup(std::string bank, int is_definition) { int dataType, dataRank, dataDimensions[NX_MAXRANK]; NXname name; void *dataBuffer; if (NXgetinfo(inId, &dataRank, dataDimensions, &dataType) != NX_OK) return NX_ERROR; // Get the rectangular detector IComponent_const_sptr det_comp = inputWorkspace->getInstrument()->getComponentByName(std::string(bank)); RectangularDetector_const_sptr det = boost::dynamic_pointer_cast<const RectangularDetector>(det_comp); if (!det) { g_log.information() << "Detector '" + bank + "' not found, or it is not a rectangular detector!\n"; // Just copy that then. if (NXmalloc(&dataBuffer, dataRank, dataDimensions, dataType) != NX_OK) return NX_ERROR; if (NXgetdata(inId, dataBuffer) != NX_OK) return NX_ERROR; if (NXcompmakedata(outId, name, dataType, dataRank, dataDimensions, NX_COMP_LZW, dataDimensions) != NX_OK) return NX_ERROR; if (NXopendata(outId, name) != NX_OK) return NX_ERROR; if (WriteAttributes(is_definition) != NX_OK) return NX_ERROR; if (NXputdata(outId, dataBuffer) != NX_OK) return NX_ERROR; if (NXfree(&dataBuffer) != NX_OK) return NX_ERROR; if (NXclosedata(outId) != NX_OK) return NX_ERROR; } else { // YES it is a rectangular detector. // --- Memory requirements ---- size_t memory_required = size_t(det->xpixels() * det->ypixels()) * size_t(inputWorkspace->blocksize()) * 2 * sizeof(float); Kernel::MemoryStats mem; mem.update(); size_t memory_available = mem.availMem() * 1024; std::cout << "Memory available: " << memory_available / 1024 << " kb. "; std::cout << "Memory required: " << memory_required / 1024 << " kb. "; // Give a 50% margin of error in allocating the memory memory_available = memory_available / 2; if (memory_available > static_cast<size_t>(5e9)) memory_available = static_cast<size_t>(5e9); if (memory_available < memory_required) { // Compute how large of a slab you can still use. int x_slab; x_slab = static_cast<int>( memory_available / (det->ypixels() * inputWorkspace->blocksize() * 2 * sizeof(float))); if (x_slab <= 0) x_slab = 1; // Look for a slab size that evenly divides the # of pixels. while (x_slab > 1) { if ((det->xpixels() % x_slab) == 0) break; x_slab--; } std::cout << "Saving in slabs of " << x_slab << " X pixels.\n"; if (this->WriteOutDataOrErrors(det, x_slab, "data", "data_errors", false, false, is_definition, bank) != NX_OK) return NX_ERROR; if (this->WriteOutDataOrErrors(det, x_slab, "errors", "", true, false, is_definition, bank) != NX_OK) return NX_ERROR; } else { std::cout << "Saving in one block.\n"; if (this->WriteOutDataOrErrors(det, det->xpixels(), "data", "data_errors", false, true, is_definition, bank) != NX_OK) return NX_ERROR; } } return NX_OK; }