/** Gets the distances between the source and detectors whose IDs you pass to it * @param WS :: the input workspace * @param mon0Spec :: Spectrum number of the output from the first monitor * @param mon1Spec :: Spectrum number of the output from the second monitor * @param monitor0Dist :: the calculated distance to the detector whose ID was passed to this function first * @param monitor1Dist :: calculated distance to the detector whose ID was passed to this function second * @throw NotFoundError if no detector is found for the detector ID given * @throw runtime_error if there is a problem with the SpectraDetectorMap */ void GetEi::getGeometry(API::MatrixWorkspace_const_sptr WS, specid_t mon0Spec, specid_t mon1Spec, double &monitor0Dist, double &monitor1Dist) const { const IObjComponent_const_sptr source = WS->getInstrument()->getSource(); // retrieve a pointer to the first detector and get its distance size_t monWI = 0; try { monWI = WS->getIndexFromSpectrumNumber(mon0Spec); } catch (std::runtime_error &) { g_log.error() << "Could not find the workspace index for the monitor at spectrum " << mon0Spec << "\n"; g_log.error() << "Error retrieving data for the first monitor" << std::endl; throw std::bad_cast(); } const std::set<detid_t> & dets = WS->getSpectrum(monWI)->getDetectorIDs(); if ( dets.size() != 1 ) { g_log.error() << "The detector for spectrum number " << mon0Spec << " was either not found or is a group, grouped monitors are not supported by this algorithm\n"; g_log.error() << "Error retrieving data for the first monitor" << std::endl; throw std::bad_cast(); } IDetector_const_sptr det = WS->getInstrument()->getDetector(*dets.begin()); monitor0Dist = det->getDistance(*(source.get())); // repeat for the second detector try { monWI = WS->getIndexFromSpectrumNumber(mon0Spec); } catch (std::runtime_error &) { g_log.error() << "Could not find the workspace index for the monitor at spectrum " << mon0Spec << "\n"; g_log.error() << "Error retrieving data for the second monitor\n"; throw std::bad_cast(); } const std::set<detid_t> & dets2 = WS->getSpectrum(monWI)->getDetectorIDs(); if ( dets2.size() != 1 ) { g_log.error() << "The detector for spectrum number " << mon1Spec << " was either not found or is a group, grouped monitors are not supported by this algorithm\n"; g_log.error() << "Error retrieving data for the second monitor\n"; throw std::bad_cast(); } det = WS->getInstrument()->getDetector(*dets2.begin()); monitor1Dist = det->getDistance(*(source.get())); }
/** * Cache frequently accessed values * @param instrument : The instrument for this run * @param detID : The det ID for this observation */ void CachedExperimentInfo::initCaches( const Geometry::Instrument_const_sptr &instrument, const detid_t detID) { // Throws if detector does not exist // Takes into account possible detector mapping IDetector_const_sptr det = m_exptInfo.getDetectorByID(detID); // Instrument distances boost::shared_ptr<const ReferenceFrame> refFrame = instrument->getReferenceFrame(); m_beam = refFrame->pointingAlongBeam(); m_up = refFrame->pointingUp(); m_horiz = refFrame->pointingHorizontal(); IComponent_const_sptr source = instrument->getSource(); IComponent_const_sptr sample = instrument->getSample(); IComponent_const_sptr aperture = instrument->getComponentByName("aperture", 1); if (!aperture) { throw std::invalid_argument( "No component named \"aperture\" found in instrument."); } IObjComponent_const_sptr firstChopper = instrument->getChopperPoint(0); const Kernel::V3D samplePos = sample->getPos(); const Kernel::V3D beamDir = samplePos - source->getPos(); // Cache m_twoTheta = det->getTwoTheta(samplePos, beamDir); m_phi = det->getPhi(); m_modToChop = firstChopper->getDistance(*source); m_apertureToChop = firstChopper->getDistance(*aperture); m_chopToSample = sample->getDistance(*firstChopper); m_sampleToDet = det->getDistance(*sample); // Aperture Geometry::BoundingBox apertureBox; aperture->getBoundingBox(apertureBox); if (apertureBox.isNull()) { throw std::invalid_argument("CachedExperimentInfo::initCaches - Aperture " "has no bounding box, cannot sample from it"); } m_apertureSize.first = apertureBox.maxPoint()[0] - apertureBox.minPoint()[0]; m_apertureSize.second = apertureBox.maxPoint()[1] - apertureBox.minPoint()[1]; // Sample volume const API::Sample &sampleDescription = m_exptInfo.sample(); const Geometry::Object &shape = sampleDescription.getShape(); m_sampleWidths = shape.getBoundingBox().width(); // Detector volume // Make sure it encompasses all possible detectors det->getBoundingBox(m_detBox); if (m_detBox.isNull()) { throw std::invalid_argument("CachedExperimentInfo::initCaches - Detector " "has no bounding box, cannot sample from it. " "ID:" + boost::lexical_cast<std::string>(det->getID())); } const double rad2deg = 180. / M_PI; const double thetaInDegs = twoTheta() * rad2deg; const double phiInDegs = phi() * rad2deg; m_gonimeter = new Goniometer; m_gonimeter->makeUniversalGoniometer(); m_gonimeter->setRotationAngle("phi", thetaInDegs); m_gonimeter->setRotationAngle("chi", phiInDegs); m_sampleToDetMatrix = m_exptInfo.sample().getOrientedLattice().getU() * m_gonimeter->getR(); // EFixed m_efixed = m_exptInfo.getEFixed(det); }
/** Executes the algorithm * * @throw runtime_error Thrown if algorithm cannot execute */ void DiffractionEventCalibrateDetectors::exec() { // Try to retrieve optional properties const int maxIterations = getProperty("MaxIterations"); const double peakOpt = getProperty("LocationOfPeakToOptimize"); // Get the input workspace EventWorkspace_const_sptr inputW = getProperty("InputWorkspace"); // retrieve the properties const std::string rb_params=getProperty("Params"); //Get some stuff from the input workspace Instrument_const_sptr inst = inputW->getInstrument(); //Build a list of Rectangular Detectors std::vector<boost::shared_ptr<RectangularDetector> > detList; // --------- Loading only one bank ---------------------------------- std::string onebank = getProperty("BankName"); bool doOneBank = (onebank != ""); for (int i=0; i < inst->nelements(); i++) { boost::shared_ptr<RectangularDetector> det; boost::shared_ptr<ICompAssembly> assem; boost::shared_ptr<ICompAssembly> assem2; det = boost::dynamic_pointer_cast<RectangularDetector>( (*inst)[i] ); if (det) { if (det->getName().compare(onebank) == 0) detList.push_back(det); if (!doOneBank) detList.push_back(det); } else { //Also, look in the first sub-level for RectangularDetectors (e.g. PG3). // We are not doing a full recursive search since that will be very long for lots of pixels. assem = boost::dynamic_pointer_cast<ICompAssembly>( (*inst)[i] ); if (assem) { for (int j=0; j < assem->nelements(); j++) { det = boost::dynamic_pointer_cast<RectangularDetector>( (*assem)[j] ); if (det) { if (det->getName().compare(onebank) == 0) detList.push_back(det); if (!doOneBank) detList.push_back(det); } else { //Also, look in the second sub-level for RectangularDetectors (e.g. PG3). // We are not doing a full recursive search since that will be very long for lots of pixels. assem2 = boost::dynamic_pointer_cast<ICompAssembly>( (*assem)[j] ); if (assem2) { for (int k=0; k < assem2->nelements(); k++) { det = boost::dynamic_pointer_cast<RectangularDetector>( (*assem2)[k] ); if (det) { if (det->getName().compare(onebank) == 0) detList.push_back(det); if (!doOneBank) detList.push_back(det); } } } } } } } } // set-up minimizer std::string inname = getProperty("InputWorkspace"); std::string outname = inname+"2"; //getProperty("OutputWorkspace"); IAlgorithm_sptr algS = createSubAlgorithm("SortEvents"); algS->setPropertyValue("InputWorkspace",inname); algS->setPropertyValue("SortBy", "X Value"); algS->executeAsSubAlg(); inputW=algS->getProperty("InputWorkspace"); //Write DetCal File double baseX,baseY,baseZ,upX,upY,upZ; std::string filename=getProperty("DetCalFilename"); std::fstream outfile; outfile.open(filename.c_str(), std::ios::out); if(detList.size() > 1) { outfile << "#\n"; outfile << "# Mantid Optimized .DetCal file for SNAP with TWO detector panels\n"; outfile << "# Old Panel, nominal size and distance at -90 degrees.\n"; outfile << "# New Panel, nominal size and distance at +90 degrees.\n"; outfile << "#\n"; outfile << "# Lengths are in centimeters.\n"; outfile << "# Base and up give directions of unit vectors for a local\n"; outfile << "# x,y coordinate system on the face of the detector.\n"; outfile << "#\n"; std::time_t current_t = DateAndTime::get_current_time().to_time_t() ; std::tm * current = gmtime( ¤t_t ); outfile << "# "<<asctime (current) <<"\n"; outfile << "#\n"; outfile << "6 L1 T0_SHIFT\n"; IObjComponent_const_sptr source = inst->getSource(); IObjComponent_const_sptr sample = inst->getSample(); outfile << "7 "<<source->getDistance(*sample)*100<<" 0\n"; outfile << "4 DETNUM NROWS NCOLS WIDTH HEIGHT DEPTH DETD CenterX CenterY CenterZ BaseX BaseY BaseZ UpX UpY UpZ\n"; } Progress prog(this,0.0,1.0,detList.size()); for (int det=0; det < static_cast<int>(detList.size()); det++) { std::string par[6]; par[0]=detList[det]->getName(); par[1]=inname; par[2]=outname; std::ostringstream strpeakOpt; strpeakOpt<<peakOpt; par[3]=strpeakOpt.str(); par[4]=rb_params; // --- Create a GroupingWorkspace for this detector name ------ CPUTimer tim; IAlgorithm_sptr alg2 = AlgorithmFactory::Instance().create("CreateGroupingWorkspace", 1); alg2->initialize(); alg2->setPropertyValue("InputWorkspace", getPropertyValue("InputWorkspace")); alg2->setPropertyValue("GroupNames", detList[det]->getName()); std::string groupWSName = "group_" + detList[det]->getName(); alg2->setPropertyValue("OutputWorkspace", groupWSName); alg2->executeAsSubAlg(); par[5] = groupWSName; std::cout << tim << " to CreateGroupingWorkspace" << std::endl; const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex; gsl_multimin_fminimizer *s = NULL; gsl_vector *ss, *x; gsl_multimin_function minex_func; // finally do the fitting int nopt = 6; int iter = 0; int status = 0; double size; /* Starting point */ x = gsl_vector_alloc (nopt); gsl_vector_set (x, 0, 0.0); gsl_vector_set (x, 1, 0.0); gsl_vector_set (x, 2, 0.0); gsl_vector_set (x, 3, 0.0); gsl_vector_set (x, 4, 0.0); gsl_vector_set (x, 5, 0.0); /* Set initial step sizes to 0.1 */ ss = gsl_vector_alloc (nopt); gsl_vector_set_all (ss, 0.1); /* Initialize method and iterate */ minex_func.n = nopt; minex_func.f = &Mantid::Algorithms::gsl_costFunction; minex_func.params = ∥ s = gsl_multimin_fminimizer_alloc (T, nopt); gsl_multimin_fminimizer_set (s, &minex_func, x, ss); do { iter++; status = gsl_multimin_fminimizer_iterate(s); if (status) break; size = gsl_multimin_fminimizer_size (s); status = gsl_multimin_test_size (size, 1e-2); } while (status == GSL_CONTINUE && iter < maxIterations && s->fval != -0.000 ); // Output summary to log file if (s->fval != -0.000) movedetector(gsl_vector_get (s->x, 0), gsl_vector_get (s->x, 1), gsl_vector_get (s->x, 2), gsl_vector_get (s->x, 3), gsl_vector_get (s->x, 4), gsl_vector_get (s->x, 5), par[0], getProperty("InputWorkspace")); else { gsl_vector_set (s->x, 0, 0.0); gsl_vector_set (s->x, 1, 0.0); gsl_vector_set (s->x, 2, 0.0); gsl_vector_set (s->x, 3, 0.0); gsl_vector_set (s->x, 4, 0.0); gsl_vector_set (s->x, 5, 0.0); } std::string reportOfDiffractionEventCalibrateDetectors = gsl_strerror(status); if (s->fval == -0.000) reportOfDiffractionEventCalibrateDetectors = "No events"; g_log.information() << "Detector = " << det << "\n" << "Method used = " << "Simplex" << "\n" << "Iteration = " << iter << "\n" << "Status = " << reportOfDiffractionEventCalibrateDetectors << "\n" << "Minimize PeakLoc-" << peakOpt << " = " << s->fval << "\n"; //Move in cm for small shifts g_log.information() << "Move (X) = " << gsl_vector_get (s->x, 0)*0.01 << " \n"; g_log.information() << "Move (Y) = " << gsl_vector_get (s->x, 1)*0.01 << " \n"; g_log.information() << "Move (Z) = " << gsl_vector_get (s->x, 2)*0.01 << " \n"; g_log.information() << "Rotate (X) = " << gsl_vector_get (s->x, 3) << " \n"; g_log.information() << "Rotate (Y) = " << gsl_vector_get (s->x, 4) << " \n"; g_log.information() << "Rotate (Z) = " << gsl_vector_get (s->x, 5) << " \n"; Kernel::V3D CalCenter=V3D(gsl_vector_get (s->x, 0)*0.01, gsl_vector_get (s->x, 1)*0.01, gsl_vector_get (s->x, 2)*0.01); Kernel::V3D Center=detList[det]->getPos()+CalCenter; int pixmax = detList[det]->xpixels()-1; int pixmid = (detList[det]->ypixels()-1)/2; BoundingBox box; detList[det]->getAtXY(pixmax, pixmid)->getBoundingBox(box); baseX = box.xMax(); baseY = box.yMax(); baseZ = box.zMax(); Kernel::V3D Base=V3D(baseX,baseY,baseZ)+CalCenter; pixmid = (detList[det]->xpixels()-1)/2; pixmax = detList[det]->ypixels()-1; detList[det]->getAtXY(pixmid, pixmax)->getBoundingBox(box); upX = box.xMax(); upY = box.yMax(); upZ = box.zMax(); Kernel::V3D Up=V3D(upX,upY,upZ)+CalCenter; Base-=Center; Up-=Center; //Rotate around x baseX = Base[0]; baseY = Base[1]; baseZ = Base[2]; double deg2rad=M_PI/180.0; double angle = gsl_vector_get (s->x, 3)*deg2rad; Base=V3D(baseX,baseY*cos(angle)-baseZ*sin(angle), baseY*sin(angle)+baseZ*cos(angle)); upX = Up[0]; upY = Up[1]; upZ = Up[2]; Up=V3D(upX,upY*cos(angle)-upZ*sin(angle), upY*sin(angle)+upZ*cos(angle)); //Rotate around y baseX = Base[0]; baseY = Base[1]; baseZ = Base[2]; angle = gsl_vector_get (s->x, 4)*deg2rad; Base=V3D(baseZ*sin(angle)+baseX*cos(angle), baseY,baseZ*cos(angle)-baseX*sin(angle)); upX = Up[0]; upY = Up[1]; upZ = Up[2]; Up=V3D(upZ*cos(angle)-upX*sin(angle),upY, upZ*sin(angle)+upX*cos(angle)); //Rotate around z baseX = Base[0]; baseY = Base[1]; baseZ = Base[2]; angle = gsl_vector_get (s->x, 5)*deg2rad; Base=V3D(baseX*cos(angle)-baseY*sin(angle), baseX*sin(angle)+baseY*cos(angle),baseZ); upX = Up[0]; upY = Up[1]; upZ = Up[2]; Up=V3D(upX*cos(angle)-upY*sin(angle), upX*sin(angle)+upY*cos(angle),upZ); Base.normalize(); Up.normalize(); Center*=100.0; // << det+1 << " " outfile << "5 " << detList[det]->getName().substr(4) << " " << detList[det]->xpixels() << " " << detList[det]->ypixels() << " " << 100.0*detList[det]->xsize() << " " << 100.0*detList[det]->ysize() << " " << "0.2000" << " " << Center.norm() << " " ; Center.write(outfile); outfile << " "; Base.write(outfile); outfile << " "; Up.write(outfile); outfile << "\n"; // clean up dynamically allocated gsl stuff gsl_vector_free(x); gsl_vector_free(ss); gsl_multimin_fminimizer_free (s); // Remove the now-unneeded grouping workspace AnalysisDataService::Instance().remove(groupWSName); prog.report(detList[det]->getName()); } // Closing outfile.close(); return; }