/**Calculates the distance a neutron coming from the sample will have deviated * from a * straight tragetory before hitting a detector. If calling this function many * times * for the same detector you can call this function once, with waveLength=1, and * use * the fact drop is proportional to wave length squared .This function has no * knowledge * of which axis is vertical for a given instrument * @param ws :: workspace * @param det :: the detector that the neutron entered * @param waveLength :: the neutrons wave length in meters * @param extraLength :: additional length * @return the deviation in meters */ double GravitySANSHelper::gravitationalDrop(API::MatrixWorkspace_const_sptr ws, Geometry::IDetector_const_sptr det, const double waveLength, const double extraLength) const { using namespace PhysicalConstants; /// Pre-factor in gravity calculation: gm^2/2h^2 static const double gm2_OVER_2h2 = g * NeutronMass * NeutronMass / (2.0 * h * h); const V3D samplePos = ws->getInstrument()->getSample()->getPos(); const double pathLength = det->getPos().distance(samplePos) + extraLength; // Want L2 (sample-pixel distance) squared, times the prefactor g^2/h^2 const double L2 = gm2_OVER_2h2 * std::pow(pathLength, 2); return waveLength * waveLength * L2; }
/** * Set the new detector position given the r,theta and phi. * @param det :: A pointer to the detector * @param l2 :: A single l2 * @param theta :: A single theta * @param phi :: A single phi */ void UpdateInstrumentFromFile::setDetectorPosition(const Geometry::IDetector_const_sptr & det, const float l2, const float theta, const float phi) { if( m_ignoreMonitors && det->isMonitor() ) return; Geometry::ParameterMap & pmap = m_workspace->instrumentParameters(); Kernel::V3D pos; if (!m_ignorePhi) { pos.spherical(l2, theta, phi); } else { double r,t,p; det->getPos().getSpherical(r,t,p); pos.spherical(l2, theta, p); } Geometry::ComponentHelper::moveComponent(*det, pmap, pos, Geometry::ComponentHelper::Absolute); }
std::pair<double, double> LoadILLSANS::calculateQMaxQMin() { double min = std::numeric_limits<double>::max(), max = std::numeric_limits<double>::min(); g_log.debug("Calculating Qmin Qmax..."); std::size_t nHist = m_localWorkspace->getNumberHistograms(); for (std::size_t i = 0; i < nHist; ++i) { Geometry::IDetector_const_sptr det = m_localWorkspace->getDetector(i); if (!det->isMonitor()) { const MantidVec &lambdaBinning = m_localWorkspace->readX(i); Kernel::V3D detPos = det->getPos(); double r, theta, phi; detPos.getSpherical(r, theta, phi); double v1 = calculateQ(*(lambdaBinning.begin()), theta); double v2 = calculateQ(*(lambdaBinning.end() - 1), theta); // std::cout << "i=" << i << " theta="<<theta << " lambda_i=" << // *(lambdaBinning.begin()) << " lambda_f=" << *(lambdaBinning.end()-1) << // " v1=" << v1 << " v2=" << v2 << '\n'; if (i == 0) { min = v1; max = v1; } if (v1 < min) { min = v1; } if (v2 < min) { min = v2; } if (v1 > max) { max = v1; } if (v2 > max) { max = v2; } } else g_log.debug() << "Detector " << i << " is a Monitor : " << det->getID() << '\n'; } g_log.debug() << "Calculating Qmin Qmax. Done : [" << min << "," << max << "]\n"; return std::pair<double, double>(min, max); }
/** * This function calculates the exponential contribution to the He3 tube * efficiency. * @param spectraIndex :: the current index to calculate * @param idet :: the current detector pointer * @throw out_of_range if twice tube thickness is greater than tube diameter * @return the exponential contribution for the given detector */ double He3TubeEfficiency::calculateExponential(std::size_t spectraIndex, Geometry::IDetector_const_sptr idet) { // Get the parameters for the current associated tube double pressure = this->getParameter("TubePressure", spectraIndex, "tube_pressure", idet); double tubethickness = this->getParameter("TubeThickness", spectraIndex, "tube_thickness", idet); double temperature = this->getParameter("TubeTemperature", spectraIndex, "tube_temperature", idet); double detRadius(0.0); Kernel::V3D detAxis; this->getDetectorGeometry(idet, detRadius, detAxis); double detDiameter = 2.0 * detRadius; double twiceTubeThickness = 2.0 * tubethickness; // now get the sin of the angle, it's the magnitude of the cross product of // unit vector along the detector tube axis and a unit vector directed from // the sample to the detector center Kernel::V3D vectorFromSample = idet->getPos() - this->samplePos; vectorFromSample.normalize(); Kernel::Quat rot = idet->getRotation(); // rotate the original cylinder object axis to get the detector axis in the // actual instrument rot.rotate(detAxis); detAxis.normalize(); // Scalar product is quicker than cross product double cosTheta = detAxis.scalar_prod(vectorFromSample); double sinTheta = std::sqrt(1.0 - cosTheta * cosTheta); const double straight_path = detDiameter - twiceTubeThickness; if (std::fabs(straight_path - 0.0) < TOL) { throw std::out_of_range("Twice tube thickness cannot be greater than "\ "or equal to the tube diameter"); } const double pathlength = straight_path / sinTheta; return EXP_SCALAR_CONST * (pressure / temperature) * pathlength; }
/**Calculates the distance a neutron coming from the sample will have deviated * from a * straight tragetory before hitting a detector. If calling this function many * times * for the same detector you can call this function once, with waveLength=1, and * use * the fact drop is proportional to wave length squared .This function has no * knowledge * of which axis is vertical for a given instrument * @param ws :: workspace * @param det :: the detector that the neutron entered * @param waveLength :: the neutrons wave length in meters * @param extraLength :: additional length * @return the deviation in meters */ double GravitySANSHelper::gravitationalDrop(API::MatrixWorkspace_const_sptr ws, Geometry::IDetector_const_sptr det, const double waveLength, const double extraLength) const { using namespace PhysicalConstants; /// Pre-factor in gravity calculation: gm^2/2h^2 static const double gm2_OVER_2h2 = g * NeutronMass * NeutronMass / (2.0 * h * h); const V3D samplePos = ws->getInstrument()->getSample()->getPos(); // Perform a path length correction if an Lextra is specified. // The correction is Lcorr^2 = (L + Lextra)^2 -(LExtra)^2 const auto pathLengthWithExtraLength = det->getPos().distance(samplePos) + extraLength; const auto pathLengthSquared = std::pow(pathLengthWithExtraLength, 2) - std::pow(extraLength, 2); // Want L2 (sample-pixel distance) squared, times the prefactor g^2/h^2 const double L2 = gm2_OVER_2h2 * pathLengthSquared; return waveLength * waveLength * L2; }
/** method to cacluate the detectors parameters and add them to the detectors *averages *@param spDet -- shared pointer to the Mantid Detector *@param Observer -- sample position or the centre of the polar system of *coordinates to calculate detector's parameters. */ void AvrgDetector::addDetInfo(const Geometry::IDetector_const_sptr &spDet, const Kernel::V3D &Observer) { m_nComponents++; Kernel::V3D detPos = spDet->getPos(); Kernel::V3D toDet = (detPos - Observer); double dist2Det, Polar, Azimut, ringPolar, ringAzim; // identify the detector' position in the beam coordinate system: toDet.getSpherical(dist2Det, Polar, Azimut); if (m_nComponents <= 1) { m_FlightPathSum = dist2Det; m_PolarSum = Polar; m_AzimutSum = Azimut; m_AzimBase = Polar; m_PolarBase = Azimut; ringPolar = Polar; ringAzim = Azimut; } else { ringPolar = nearAngle(m_AzimBase, Polar); ringAzim = nearAngle(m_PolarBase, Azimut); m_FlightPathSum += dist2Det; m_PolarSum += ringPolar; m_AzimutSum += ringAzim; } // centre of the azimuthal ring (the ring detectors form around the beam) Kernel::V3D ringCentre(0, 0, toDet.Z()); // Get the bounding box Geometry::BoundingBox bbox; std::vector<Kernel::V3D> coord(3); Kernel::V3D er(0, 1, 0), e_th, ez(0, 0, 1); // ez along beamline, which is always oz; if (dist2Det) er = toDet / dist2Det; // direction to the detector Kernel::V3D e_tg = er.cross_prod(ez); // tangential to the ring and anticloakwise; e_tg.normalize(); // make orthogonal -- projections are calculated in this coordinate system ez = e_tg.cross_prod(er); coord[0] = er; // new X coord[1] = ez; // new y coord[2] = e_tg; // new z bbox.setBoxAlignment(ringCentre, coord); spDet->getBoundingBox(bbox); // linear extensions of the bounding box orientied tangentially to the equal // scattering angle circle double azimMin = bbox.zMin(); double azimMax = bbox.zMax(); double polarMin = bbox.yMin(); // bounding box has been rotated according to // coord above, so z is along e_tg double polarMax = bbox.yMax(); if (m_useSphericalSizes) { if (dist2Det == 0) dist2Det = 1; // convert to angular units double polarHalfSize = rad2deg * atan2(0.5 * (polarMax - polarMin), dist2Det); double azimHalfSize = rad2deg * atan2(0.5 * (azimMax - azimMin), dist2Det); polarMin = ringPolar - polarHalfSize; polarMax = ringPolar + polarHalfSize; azimMin = ringAzim - azimHalfSize; azimMax = ringAzim + azimHalfSize; } if (m_AzimMin > azimMin) m_AzimMin = azimMin; if (m_AzimMax < azimMax) m_AzimMax = azimMax; if (m_PolarMin > polarMin) m_PolarMin = polarMin; if (m_PolarMax < polarMax) m_PolarMax = polarMax; }
/** * 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; }
/** Execute the algorithm. */ void ModifyDetectorDotDatFile::exec() { std::string inputFilename = getPropertyValue("InputFilename"); std::string outputFilename = getPropertyValue("OutputFilename"); Workspace_sptr ws1 = getProperty("InputWorkspace"); ExperimentInfo_sptr ws = boost::dynamic_pointer_cast<ExperimentInfo>(ws1); // Check instrument Instrument_const_sptr inst = ws->getInstrument(); if (!inst) throw std::runtime_error("No instrument in the Workspace. Cannot modify detector dot dat file"); // Open files std::ifstream in; in.open( inputFilename.c_str()); if(!in) { throw Exception::FileError("Can't open input file", inputFilename); } std::ofstream out; out.open( outputFilename.c_str()); if(!out) { in.close(); throw Exception::FileError("Can't open output file", outputFilename); } // Read first line, modify it and put into output file std::string str; getline( in, str ); out << str << " and modified by MANTID algorithm ModifyDetectorDotDatFile \n"; // Read second line to check number of detectors and columns int detectorCount, numColumns; getline( in, str ); std::istringstream header2(str); header2 >> detectorCount >> numColumns; out << str << "\n"; // check that we have at least 1 detector and six columns if( detectorCount < 1 || numColumns < 6) { out.close(); in.close(); throw Exception::FileError("Incompatible file format found when reading line 2 in the input file", inputFilename); } // Copy column title line getline( in, str ); out << str << "\n"; int i=0; // Format details int pOffset = 3; // Precision of Offset int pOther = 5; // Precision of Other floats int wDet = 9; // Field width of Detector ID int wOff = 8; // Field width of Offset int wRad = 10; // Field width of Radius int wCode = 6; // Field width of Code int wAng = 12; // Field width of angles // Read input file line by line, modify line as necessary and put line into output file while( getline( in, str ) ){ std::istringstream istr(str); detid_t detID; double offset; int code; float dump; // ignored data if (str.empty() || str[0] == '#') { // comments and empty lines are allowed and just copied out << str << "\n"; continue; } // First six columns in the file, the detector ID and a code for the type of detector CODE = 3 (psd gas tube) istr >> detID >> offset >> dump >> code >> dump >> dump; if( code == 3 ){ // This is detector will look for it in workspace and if found use its position Geometry::IDetector_const_sptr det = ws->getDetectorByID( detID ); if( det ) { V3D pos = det->getPos(); double l2; double theta; double phi; pos.getSpherical ( l2, theta, phi ); std::streampos width = istr.tellg(); // Amount of string to replace // Some experimenting with line manipulation std::ostringstream oss; oss << std::fixed << std::right ; oss.precision(pOffset); oss << std::setw(wDet) << detID << std::setw(wOff) << offset; oss.precision(pOther); oss << std::setw(wRad) << l2 << std::setw(wCode) << code << std::setw(wAng) << theta << std::setw(wAng) << phi ; std::string prefix = oss.str(); std::string suffix = str.substr( width, std::string::npos ); out << prefix << suffix << "\n"; i++; } else { // Detector not found, don't modify out << str << "\n"; } } else { // We do not modify any other type of line out << str << "\n"; } } out.close(); in.close(); }
/** * Updates from a more generic ascii file * @param filename :: The input filename */ void UpdateInstrumentFromFile::updateFromAscii(const std::string & filename) { AsciiFileHeader header; const bool isSpectrum = parseAsciiHeader(header); Geometry::Instrument_const_sptr inst = m_workspace->getInstrument(); // Throws for multiple detectors const spec2index_map specToIndex(m_workspace->getSpectrumToWorkspaceIndexMap()); std::ifstream datfile(filename.c_str(), std::ios_base::in); const int skipNLines = getProperty("SkipFirstNLines"); std::string line; int lineCount(0); while(lineCount < skipNLines) { std::getline(datfile,line); ++lineCount; } std::vector<double> colValues(header.colCount - 1, 0.0); while(std::getline(datfile,line)) { boost::trim(line); std::istringstream is(line); // Column 0 should be ID/spectrum number int32_t detOrSpec(-1000); is >> detOrSpec; // If first thing read is not a number then skip the line if(is.fail()) { g_log.debug() << "Skipping \"" << line << "\". Cannot interpret as list of numbers.\n"; continue; } Geometry::IDetector_const_sptr det; try { if(isSpectrum) { auto it = specToIndex.find(detOrSpec); if(it != specToIndex.end()) { const size_t wsIndex = it->second; det = m_workspace->getDetector(wsIndex); } else { g_log.debug() << "Skipping \"" << line << "\". Spectrum is not in workspace.\n"; continue; } } else { det = inst->getDetector(detOrSpec); } } catch(Kernel::Exception::NotFoundError&) { g_log.debug() << "Skipping \"" << line << "\". Spectrum in workspace but cannot find associated detector.\n"; continue; } // Special cases for detector r,t,p. Everything else is // attached as an detector parameter double R(0.0),theta(0.0), phi(0.0); for(size_t i = 1; i < header.colCount; ++i) { double value(0.0); is >> value; if(i < header.colCount - 1 && is.eof()) { //If stringstream is at EOF & we are not at the last column then // there aren't enought columns in the file throw std::runtime_error("UpdateInstrumentFromFile::updateFromAscii - " "File contains fewer than expected number of columns, check AsciiHeader property."); } if(i == header.rColIdx) R = value; else if(i == header.thetaColIdx) theta = value; else if(i == header.phiColIdx) phi = value; else if(header.detParCols.count(i) == 1) { Geometry::ParameterMap & pmap = m_workspace->instrumentParameters(); pmap.addDouble(det->getComponentID(), header.colToName[i],value); } } // Check stream state. stringstream::EOF should have been reached, if not then there is still more to // read and the file has more columns than the header indicated if(!is.eof()) { throw std::runtime_error("UpdateInstrumentFromFile::updateFromAscii - " "File contains more than expected number of columns, check AsciiHeader property."); } // If not supplied use current values double r,t,p; det->getPos().getSpherical(r,t,p); if(header.rColIdx == 0) R = r; if(header.thetaColIdx == 0) theta = t; if(header.phiColIdx == 0) phi = p; setDetectorPosition(det, static_cast<float>(R), static_cast<float>(theta), static_cast<float>(phi)); } }
/** Read the scaling information from a file (e.g. merlin_detector.sca) or from * the RAW file (.raw) * @param scalingFile :: Name of scaling file .sca * @param truepos :: V3D vector of actual positions as read from the file * @return False if unable to open file, True otherwise */ bool SetScalingPSD::processScalingFile(const std::string &scalingFile, std::vector<Kernel::V3D> &truepos) { // Read the scaling information from a text file (.sca extension) or from a // raw file (.raw) // This is really corrected positions as (r,theta,phi) for each detector // Compare these with the instrument values to determine the change in // position and the scaling // which may be necessary for each pixel if in a tube. // movePos is used to updated positions std::map<int, Kernel::V3D> posMap; std::map<int, double> scaleMap; std::map<int, double>::iterator its; Instrument_const_sptr instrument = m_workspace->getInstrument(); if (scalingFile.find(".sca") != std::string::npos || scalingFile.find(".SCA") != std::string::npos) { // read a .sca text format file // format consists of a short header followed by one line per detector std::ifstream sFile(scalingFile.c_str()); if (!sFile) { g_log.error() << "Unable to open scaling file " << scalingFile << std::endl; return false; } std::string str; getline(sFile, str); // skip header line should be <filename> generated by <prog> int detectorCount; getline(sFile, str); // get detector count line std::istringstream istr(str); istr >> detectorCount; if (detectorCount < 1) { g_log.error("Bad detector count in scaling file"); throw std::runtime_error("Bad detector count in scaling file"); } truepos.reserve(detectorCount); getline(sFile, str); // skip title line int detIdLast = -10; Kernel::V3D truPosLast, detPosLast; Progress prog(this, 0.0, 0.5, detectorCount); // Now loop through lines, one for each detector/monitor. The latter are // ignored. while (getline(sFile, str)) { if (str.empty() || str[0] == '#') continue; std::istringstream istr(str); // read 6 values from the line to get the 3 (l2,theta,phi) of interest int detIndex, code; double l2, theta, phi, offset; istr >> detIndex >> offset >> l2 >> code >> theta >> phi; // sanity check on angles - l2 should be +ve but sample file has a few -ve // values // on monitors if (theta > 181.0 || theta < -1 || phi < -181 || phi > 181) { g_log.error("Position angle data out of range in .sca file"); throw std::runtime_error( "Position angle data out of range in .sca file"); } Kernel::V3D truPos; // use abs as correction file has -ve l2 for first few detectors truPos.spherical(fabs(l2), theta, phi); truepos.push_back(truPos); // Geometry::IDetector_const_sptr det; try { det = instrument->getDetector(detIndex); } catch (Kernel::Exception::NotFoundError &) { continue; } Kernel::V3D detPos = det->getPos(); Kernel::V3D shift = truPos - detPos; // scaling applied to dets that are not monitors and have sequential IDs if (detIdLast == detIndex - 1 && !det->isMonitor()) { Kernel::V3D diffI = detPos - detPosLast; Kernel::V3D diffT = truPos - truPosLast; double scale = diffT.norm() / diffI.norm(); Kernel::V3D scaleDir = diffT / diffT.norm(); // Wish to store the scaling in a map, if we already have a scaling // for this detector (i.e. from the other side) we average the two // values. End of tube detectors only have one scaling estimate. scaleMap[detIndex] = scale; its = scaleMap.find(detIndex - 1); if (its == scaleMap.end()) scaleMap[detIndex - 1] = scale; else its->second = 0.5 * (its->second + scale); // std::cout << detIndex << scale << scaleDir << std::endl; } detIdLast = detIndex; detPosLast = detPos; truPosLast = truPos; posMap[detIndex] = shift; // prog.report(); } } else if (scalingFile.find(".raw") != std::string::npos ||