void CalculateDIFC::calculate() { Instrument_const_sptr instrument = m_inputWS->getInstrument(); SpecialWorkspace2D_sptr localWS = boost::dynamic_pointer_cast<SpecialWorkspace2D>(m_outputWS); double l1; Kernel::V3D beamline, samplePos; double beamline_norm; instrument->getInstrumentParameters(l1, beamline, beamline_norm, samplePos); // To get all the detector ID's detid2det_map allDetectors; instrument->getDetectors(allDetectors); // Now go through all detid2det_map::const_iterator it = allDetectors.begin(); for (; it != allDetectors.end(); ++it) { Geometry::IDetector_const_sptr det = it->second; if ((!det->isMasked()) && (!det->isMonitor())) { const detid_t detID = it->first; double offset = 0.; if (m_offsetsWS) offset = m_offsetsWS->getValue(detID, 0.); double difc = Geometry::Instrument::calcConversion( l1, beamline, beamline_norm, samplePos, det, offset); difc = 1. / difc; // calcConversion gives 1/DIFC localWS->setValue(detID, difc); } } }
/** * Make a map of the conversion factors between tof and D-spacing * for all pixel IDs in a workspace. * * @param DFileName name of dspacemap file * @param offsetsWS :: OffsetsWorkspace with instrument and offsets */ void SaveDspacemap::CalculateDspaceFromCal(Mantid::DataObjects::OffsetsWorkspace_sptr offsetsWS, std::string DFileName) { const char * filename = DFileName.c_str(); // Get a pointer to the instrument contained in the workspace Instrument_const_sptr instrument = offsetsWS->getInstrument(); double l1; Kernel::V3D beamline,samplePos; double beamline_norm; instrument->getInstrumentParameters(l1,beamline,beamline_norm, samplePos); //To get all the detector ID's detid2det_map allDetectors; instrument->getDetectors(allDetectors); detid2det_map::const_iterator it; detid_t maxdetID = 0; for (it = allDetectors.begin(); it != allDetectors.end(); it++) { detid_t detectorID = it->first; if(detectorID > maxdetID) maxdetID = detectorID; } detid_t paddetID = detid_t(getProperty("PadDetID")); if (maxdetID < paddetID)maxdetID = paddetID; // Now write the POWGEN-style Dspace mapping file std::ofstream fout(filename, std::ios_base::out|std::ios_base::binary); Progress prog(this,0.0,1.0,maxdetID); for (detid_t i = 0; i != maxdetID; i++) { //Compute the factor double factor; Geometry::IDetector_const_sptr det; // Find the detector with that detector id it = allDetectors.find(i); if (it != allDetectors.end()) { det = it->second; factor = Instrument::calcConversion(l1, beamline, beamline_norm, samplePos, det, offsetsWS->getValue(i, 0.0)); //Factor of 10 between ISAW and Mantid factor *= 0.1 ; if(factor<0)factor = 0.0; fout.write( reinterpret_cast<char*>( &factor ), sizeof(double) ); } else { factor = 0; fout.write( reinterpret_cast<char*>( &factor ), sizeof(double) ); } //Report progress prog.report(); } fout.close(); }
/** * Make a map of the conversion factors between tof and D-spacing * for all pixel IDs in a workspace. * * @param DFileName :: name of dspacemap file * @param offsetsWS :: OffsetsWorkspace to be filled. */ void LoadDspacemap::CalculateOffsetsFromDSpacemapFile( const std::string DFileName, Mantid::DataObjects::OffsetsWorkspace_sptr offsetsWS) { // Get a pointer to the instrument contained in the workspace Instrument_const_sptr instrument = offsetsWS->getInstrument(); double l1; Kernel::V3D beamline, samplePos; double beamline_norm; instrument->getInstrumentParameters(l1, beamline, beamline_norm, samplePos); // To get all the detector ID's detid2det_map allDetectors; instrument->getDetectors(allDetectors); // Read in the POWGEN-style Dspace mapping file const char *filename = DFileName.c_str(); std::ifstream fin(filename, std::ios_base::in | std::ios_base::binary); std::vector<double> dspace; double read; while (!fin.eof()) { fin.read(reinterpret_cast<char *>(&read), sizeof read); // Factor of 10 between ISAW and Mantid read *= 10.; dspace.push_back(read); } detid2det_map::const_iterator it; for (it = allDetectors.begin(); it != allDetectors.end(); ++it) { detid_t detectorID = it->first; Geometry::IDetector_const_sptr det = it->second; // Compute the factor double offset = 0.0; double factor = Instrument::calcConversion(l1, beamline, beamline_norm, samplePos, det, offset); offset = dspace[detectorID] / factor - 1.0; // Save in the map try { offsetsWS->setValue(detectorID, offset); } catch (std::invalid_argument &) { } } }
/** * @param offsetsWS * @param index * @return The offset adjusted value of DIFC */ double calculateDIFC(OffsetsWorkspace_const_sptr offsetsWS, const size_t index) { Instrument_const_sptr instrument = offsetsWS->getInstrument(); const detid_t detid = getDetID(offsetsWS, index); const double offset = getOffset(offsetsWS, detid); double l1; Kernel::V3D beamline, samplePos; double beamline_norm; instrument->getInstrumentParameters(l1, beamline, beamline_norm, samplePos); Geometry::IDetector_const_sptr detector = instrument->getDetector(detid); // the factor returned is what is needed to convert TOF->d-spacing // the table is supposed to be filled with DIFC which goes the other way const double factor = Instrument::calcConversion(l1, beamline, beamline_norm, samplePos, detector, offset); return 1./factor; }
/** 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(); // } }
/** * Make a map of the conversion factors between tof and D-spacing * for all pixel IDs in a workspace. * map vulcan should contain the module/module and stack/stack offset * * @param vulcan :: map between detector ID and vulcan correction factor. * @param offsetsWS :: OffsetsWorkspace to be filled. */ void LoadDspacemap::CalculateOffsetsFromVulcanFactors( std::map<detid_t, double> &vulcan, Mantid::DataObjects::OffsetsWorkspace_sptr offsetsWS) { // Get a pointer to the instrument contained in the workspace // At this point, instrument VULCAN has been created? Instrument_const_sptr instrument = offsetsWS->getInstrument(); g_log.notice() << "Name of instrument = " << instrument->getName() << std::endl; g_log.notice() << "Input map (dict): size = " << vulcan.size() << std::endl; // To get all the detector ID's detid2det_map allDetectors; instrument->getDetectors(allDetectors); detid2det_map::const_iterator it; int numfinds = 0; g_log.notice() << "Input number of detectors = " << allDetectors.size() << std::endl; // Get detector information double l1, beamline_norm; Kernel::V3D beamline, samplePos; instrument->getInstrumentParameters(l1, beamline, beamline_norm, samplePos); /*** A survey of parent detector std::map<detid_t, bool> parents; for (it = allDetectors.begin(); it != allDetectors.end(); it++){ int32_t detid = it->first; // def boost::shared_ptr<const Mantid::Geometry::IDetector> IDetector_const_sptr; std::string parentname = it->second->getParent()->getComponentID()->getName(); g_log.notice() << "Name = " << parentname << std::endl; // parents.insert(parentid, true); } ***/ /*** Here some special configuration for VULCAN is hard-coded here! * Including (1) Super-Parent Information ***/ Kernel::V3D referencePos; detid_t anydetinrefmodule = 21 * 1250 + 5; std::map<detid_t, Geometry::IDetector_const_sptr>::iterator det_iter = allDetectors.find(anydetinrefmodule); if (det_iter == allDetectors.end()) { throw std::invalid_argument("Any Detector ID is Instrument's detector"); } referencePos = det_iter->second->getParent()->getPos(); double refl2 = referencePos.norm(); double halfcosTwoThetaRef = referencePos.scalar_prod(beamline) / (refl2 * beamline_norm); double sinThetaRef = sqrt(0.5 - halfcosTwoThetaRef); double difcRef = sinThetaRef * (l1 + refl2) / CONSTANT; // Loop over all detectors in instrument to find the offset for (it = allDetectors.begin(); it != allDetectors.end(); ++it) { int detectorID = it->first; Geometry::IDetector_const_sptr det = it->second; double offset = 0.0; // Find the vulcan factor; double vulcan_factor = 0.0; std::map<detid_t, double>::const_iterator vulcan_iter = vulcan.find(detectorID); if (vulcan_iter != vulcan.end()) { vulcan_factor = vulcan_iter->second; numfinds++; } // g_log.notice() << "Selected Detector with ID = " << detectorID << " ID2 // = " << id2 << std::endl; proved to be same double intermoduleoffset = 0; double interstackoffset = 0; detid_t intermoduleid = detid_t(detectorID / 1250) * 1250 + 1250 - 2; vulcan_iter = vulcan.find(intermoduleid); if (vulcan_iter == vulcan.end()) { g_log.error() << "Cannot find inter-module offset ID = " << intermoduleid << std::endl; } else { intermoduleoffset = vulcan_iter->second; } detid_t interstackid = detid_t(detectorID / 1250) * 1250 + 1250 - 1; vulcan_iter = vulcan.find(interstackid); if (vulcan_iter == vulcan.end()) { g_log.error() << "Cannot find inter-module offset ID = " << intermoduleid << std::endl; } else { interstackoffset = vulcan_iter->second; } /*** This is the previous way to correct upon DIFC[module center pixel] // The actual factor is 10^(-value_in_the_file) vulcan_factor = pow(10.0,-vulcan_factor); // At this point, tof_corrected = vulcan_factor * tof_input // So this is the offset offset = vulcan_factor - 1.0; ***/ /*** New approach to correct based on DIFC of each pixel * Equation: offset = DIFC^(pixel)/DIFC^(parent)*(1+vulcan_offset)-1 * offset should be close to 0 ***/ // 1. calculate DIFC Kernel::V3D detPos; detPos = det->getPos(); // Now detPos will be set with respect to samplePos detPos -= samplePos; double l2 = detPos.norm(); double halfcosTwoTheta = detPos.scalar_prod(beamline) / (l2 * beamline_norm); double sinTheta = sqrt(0.5 - halfcosTwoTheta); double difc_pixel = sinTheta * (l1 + l2) / CONSTANT; // Kernel::V3D parentPos = det->getParent()->getPos(); // parentPos -= samplePos; // double l2parent = parentPos.norm(); // double halfcosTwoThetaParent = parentPos.scalar_prod(beamline)/(l2 * // beamline_norm); // double sinThetaParent = sqrt(0.5 - halfcosTwoThetaParent); // double difc_parent = sinThetaParent*(l1+l2parent)/CONSTANT; /*** Offset Replicate Previous Result offset = difc_pixel/difc_parent*(pow(10.0, -vulcan_factor))-1.0; ***/ offset = difc_pixel / difcRef * (pow(10.0, -(vulcan_factor + intermoduleoffset + interstackoffset))) - 1.0; // Save in the map try { offsetsWS->setValue(detectorID, offset); if (intermoduleid != 27498 && intermoduleid != 28748 && intermoduleid != 29998 && intermoduleid != 33748 && intermoduleid != 34998 && intermoduleid != 36248) { g_log.error() << "Detector ID = " << detectorID << " Inter-Module ID = " << intermoduleid << std::endl; throw std::invalid_argument("Indexing error!"); } } catch (std::invalid_argument &) { g_log.notice() << "Misses Detector ID = " << detectorID << std::endl; } } // for g_log.notice() << "Number of matched detectors =" << numfinds << std::endl; }