Exemplo n.º 1
0
/**
 * Attempts to load a grouping information referenced by IDF.
 * @param instrument :: Intrument which we went the grouping for
 * @param mainFieldDirection :: (MUSR) orientation of the instrument
 * @return Grouping information
 */
boost::shared_ptr<Grouping> getGroupingFromIDF(Instrument_const_sptr instrument,
                                               const std::string& mainFieldDirection)
{
  std::string parameterName = "Default grouping file";

  // Special case for MUSR, because it has two possible groupings
  if (instrument->getName() == "MUSR")
  {
    parameterName.append(" - " + mainFieldDirection);
  }

  std::vector<std::string> groupingFiles = instrument->getStringParameter(parameterName);

  if ( groupingFiles.size() == 1 )
  {
    const std::string groupingFile = groupingFiles[0];

    // Get search directory for XML instrument definition files (IDFs)
    std::string directoryName = ConfigService::Instance().getInstrumentDirectory();

    auto loadedGrouping = boost::make_shared<Grouping>();
    loadGroupingFromXML(directoryName + groupingFile, *loadedGrouping);

    return loadedGrouping;
  }
  else
  {
    throw std::runtime_error("Multiple groupings specified for the instrument");
  }
}
Exemplo n.º 2
0
  /** Executes the algorithm
   *
   *  @throw Exception::FileError If the grouping file cannot be opened or read successfully
   *  @throw runtime_error If unable to run one of the Child Algorithms successfully
   */
  void ReadGroupsFromFile::exec()
  {
    MatrixWorkspace_const_sptr ws = getProperty("InstrumentWorkspace");

    // Get the instrument.
    Instrument_const_sptr inst = ws->getInstrument();

    // Create a copy (without the data) of the workspace - it will contain the
    Workspace2D_sptr localWorkspace =
        boost::dynamic_pointer_cast<Workspace2D>(WorkspaceFactory::Instance().create(ws, ws->getNumberHistograms(), 2, 1));
    if (!localWorkspace)
      throw std::runtime_error("Failed when creating a Workspace2D from the input!");

    const std::string groupfile=getProperty("GroupingFilename");

    if ( ! groupfile.empty() )
    {
      std::string filename(groupfile);
      std::transform(filename.begin(), filename.end(), filename.begin(), tolower);
      if ( filename.find(".xml") != std::string::npos )
      {
        readXMLGroupingFile(groupfile);
      }
      else
      {
        readGroupingFile(groupfile);
      }
    }

    // Get the instrument.
    const int64_t nHist=localWorkspace->getNumberHistograms();

    // Determine whether the user wants to see unselected detectors or not
    const std::string su=getProperty("ShowUnselected");
    bool showunselected=(!su.compare("True"));
    bool success=false;

    for (int64_t i=0;i<nHist;i++)
    {
      ISpectrum * spec = localWorkspace->getSpectrum(i);
      const std::set<detid_t> & dets = spec->getDetectorIDs();
      if (dets.empty()) // Nothing
      {
        spec->dataY()[0]=0.0;
        continue;
      }
      // Find the first detector ID in the list
      calmap::const_iterator it=calibration.find(*dets.begin());
      if (it==calibration.end()) //Could not find the detector
      {
        spec->dataY()[0]=0.0;
        continue;
      }
      if (showunselected)
      {
        if (((*it).second).second==0)
          spec->dataY()[0]=0.0;
        else
          spec->dataY()[0]=static_cast<double>(((*it).second).first);
      }
      else
        spec->dataY()[0]=static_cast<double>(((*it).second).first);
      if (!success) success=true; //At least one detector is found in the cal file

    }
    progress(1);

    calibration.clear();
    if (!success) //Do some cleanup
    {
      localWorkspace.reset();
      throw std::runtime_error("Fail to found a detector in "+groupfile+" existing in instrument "+inst->getName());
    }
    setProperty("OutputWorkspace",localWorkspace);
    return;
  }
/** Execute the algorithm.
 */
void CreateChunkingFromInstrument::exec() {
  // get the instrument
  Instrument_const_sptr inst = this->getInstrument();

  // setup the output workspace
  ITableWorkspace_sptr strategy =
      WorkspaceFactory::Instance().createTable("TableWorkspace");
  strategy->addColumn("str", "BankName");
  this->setProperty("OutputWorkspace", strategy);

  // get the correct level of grouping
  string groupLevel = this->getPropertyValue(PARAM_CHUNK_BY);
  vector<string> groupNames =
      getGroupNames(this->getPropertyValue(PARAM_CHUNK_NAMES));
  if (groupLevel.compare("All") == 0) {
    return; // nothing to do
  } else if (inst->getName().compare("SNAP") == 0 &&
             groupLevel.compare("Group") == 0) {
    groupNames.clear();
    groupNames.push_back("East");
    groupNames.push_back("West");
  }

  // set up a progress bar with the "correct" number of steps
  int maxBankNum = this->getProperty(PARAM_MAX_BANK_NUM);
  Progress progress(this, .2, 1., maxBankNum);

  // search the instrument for the bank names
  int maxRecurseDepth = this->getProperty(PARAM_MAX_RECURSE);
  map<string, vector<string>> grouping;
  // cppcheck-suppress syntaxError
    PRAGMA_OMP(parallel for schedule(dynamic, 1) )
    for (int num = 0; num < maxBankNum; ++num) {
      PARALLEL_START_INTERUPT_REGION
      ostringstream mess;
      mess << "bank" << num;
      IComponent_const_sptr comp =
          inst->getComponentByName(mess.str(), maxRecurseDepth);
      PARALLEL_CRITICAL(grouping)
      if (comp) {
        // get the name of the correct parent
        string parent;
        if (groupNames.empty()) {
          parent = parentName(comp, groupLevel);
        } else {
          parent = parentName(comp, groupNames);
        }

        // add it to the correct chunk
        if (!parent.empty()) {
          if (grouping.count(parent) == 0)
            grouping[parent] = vector<string>();

          grouping[parent].push_back(comp->getName());
        }
      }
      progress.report();
      PARALLEL_END_INTERUPT_REGION
    }
    PARALLEL_CHECK_INTERUPT_REGION

    // check to see that something happened
    if (grouping.empty())
      throw std::runtime_error("Failed to find any banks in the instrument");

    // fill in the table workspace
    for (auto group = grouping.begin(); group != grouping.end(); ++group) {
      stringstream banks;
      for (auto bank = group->second.begin(); bank != group->second.end();
           ++bank)
        banks << (*bank) << ",";

      // remove the trailing comma
      string banksStr = banks.str();
      banksStr = banksStr.substr(0, banksStr.size() - 1);

      // add it to the table
      TableRow row = strategy->appendRow();
      row << banksStr;
    }
}
Exemplo n.º 4
0
/** Executes the algorithm
 *
 *  @throw Exception::FileError If the grouping file cannot be opened or read successfully
 *  @throw runtime_error If unable to run one of the Child Algorithms successfully
 */
void CreateDummyCalFile::exec()
{
    // Get the input workspace
    MatrixWorkspace_const_sptr inputW = getProperty("InputWorkspace");
    if (!inputW)
        throw std::invalid_argument("No InputWorkspace");

    //Get some stuff from the input workspace
    Instrument_const_sptr inst = inputW->getInstrument();
    std::string instname = inst->getName();

    // Check that the instrument is in store
    // Get only the first 3 letters
    std::string instshort=instname;
    std::transform(instshort.begin(),instshort.end(),instshort.begin(),toupper);
    instshort=instshort+"_Definition.xml";
    // Determine the search directory for XML instrument definition files (IDFs)
    std::string directoryName = Kernel::ConfigService::Instance().getInstrumentDirectory();

    // Set up the DOM parser and parse xml file
    DOMParser pParser;
    Document* pDoc;
    try
    {
        pDoc = pParser.parse(directoryName+instshort);
    }
    catch(...)
    {
        g_log.error("Unable to parse file " + m_filename);
        throw Kernel::Exception::FileError("Unable to parse File:" , m_filename);
    }
    // Get pointer to root element
    Element* pRootElem = pDoc->documentElement();
    if ( !pRootElem->hasChildNodes() )
    {
        g_log.error("XML file: " + m_filename + "contains no root element.");
        throw Kernel::Exception::InstrumentDefinitionError("No root element in XML instrument file", m_filename);
    }

    // Handle used in the singleton constructor for instrument file should append the value
    // of the last-modified tag inside the file to determine if it is already in memory so that
    // changes to the instrument file will cause file to be reloaded.
    auto temp = instshort + pRootElem->getAttribute("last-modified");// Generate the mangled name by hand (old-style)

    // If instrument not in store, insult the user
    if (!API::InstrumentDataService::Instance().doesExist(temp))
    {
        Mantid::Geometry::IDFObject idf(directoryName+instshort);
        temp = idf.getMangledName(); // new style.
        if (!API::InstrumentDataService::Instance().doesExist(temp))
        {
            g_log.error("Instrument "+instshort+" is not present in data store.");
            throw std::runtime_error("Instrument "+instshort+" is not present in data store.");
        }
    }

    // Get the names of groups
    groups=instname;

    // Split the names of the group and insert in a vector, throw if group empty
    std::vector<std::string> vgroups;
    boost::split( vgroups, instname, boost::algorithm::detail::is_any_ofF<char>(",/*"));
    if (vgroups.empty())
    {
        g_log.error("Could not determine group names. Group names should be separated by / or ,");
        throw std::runtime_error("Could not determine group names. Group names should be separated by / or ,");
    }

    // Assign incremental number to each group
    std::map<std::string,int> group_map;
    int index=0;
    for (std::vector<std::string>::const_iterator it=vgroups.begin(); it!=vgroups.end(); ++it)
        group_map[(*it)]=++index;

    // Not needed anymore
    vgroups.clear();

    // Find Detectors that belong to groups
    typedef boost::shared_ptr<const Geometry::ICompAssembly> sptr_ICompAss;
    typedef boost::shared_ptr<const Geometry::IComponent> sptr_IComp;
    typedef boost::shared_ptr<const Geometry::IDetector> sptr_IDet;
    std::queue< std::pair<sptr_ICompAss,int> > assemblies;
    sptr_ICompAss current=boost::dynamic_pointer_cast<const Geometry::ICompAssembly>(inst);
    sptr_IDet currentDet;
    sptr_IComp currentIComp;
    sptr_ICompAss currentchild;

    int top_group, child_group;

    if (current.get())
    {
        top_group=group_map[current->getName()]; // Return 0 if not in map
        assemblies.push(std::make_pair(current,top_group));
    }

    std::string filename=getProperty("CalFilename");

    // Plan to overwrite file, so do not check if it exists
    bool overwrite=false;

    int number=0;
    Progress prog(this,0.0,0.8,assemblies.size());
    while(!assemblies.empty()) //Travel the tree from the instrument point
    {
        current=assemblies.front().first;
        top_group=assemblies.front().second;
        assemblies.pop();
        int nchilds=current->nelements();
        if (nchilds!=0)
        {
            for (int i=0; i<nchilds; ++i)
            {
                currentIComp=(*(current.get()))[i]; // Get child
                currentDet=boost::dynamic_pointer_cast<const Geometry::IDetector>(currentIComp);
                if (currentDet.get())// Is detector
                {
                    if (overwrite) // Map will contains udet as the key
                        instrcalib[currentDet->getID()]=std::make_pair(number++,top_group);
                    else          // Map will contains the entry number as the key
                        instrcalib[number++]=std::make_pair(currentDet->getID(),top_group);
                }
                else // Is an assembly, push in the queue
                {
                    currentchild=boost::dynamic_pointer_cast<const Geometry::ICompAssembly>(currentIComp);
                    if (currentchild.get())
                    {
                        child_group=group_map[currentchild->getName()];
                        if (child_group==0)
                            child_group=top_group;
                        assemblies.push(std::make_pair(currentchild,child_group));
                    }
                }
            }
        }
        prog.report();
    }
    // Write the results in a file
    saveGroupingFile(filename,overwrite);
    progress(0.2);
    return;
}
Exemplo n.º 5
0
  /** 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();
//    }


  }
Exemplo n.º 6
0
/** Reads the calibration file.
 *
 * @param calFileName :: path to the old .cal file
 * @param groupWS :: optional, GroupingWorkspace to save. Will be 0 if not specified.
 * @param offsetsWS :: optional, OffsetsWorkspace to save. Will be 0.0 if not specified.
 * @param maskWS :: optional, masking-type workspace to save. Will be 1 (selected) if not specified.
 */
void SaveCalFile::saveCalFile(const std::string& calFileName,
                              GroupingWorkspace_sptr groupWS, OffsetsWorkspace_sptr offsetsWS, MaskWorkspace_sptr maskWS)
{
    Instrument_const_sptr inst;

    bool doGroup = false;
    if (groupWS)
    {
        doGroup = true;
        inst = groupWS->getInstrument();
    }

    bool doOffsets = false;
    if (offsetsWS) {
        doOffsets = true;
        inst = offsetsWS->getInstrument();
    }

    bool doMask = false;
    if (maskWS)
    {
        doMask = true;
        inst = maskWS->getInstrument();
        if (!inst)
            g_log.warning() << "Mask workspace " << maskWS->name() << " has no instrument associated with." << "\n";
    }

    g_log.information() << "Status: doGroup = " << doGroup << " doOffsets = " << doOffsets
                        << " doMask = " << doMask << "\n";

    if (!inst)
        throw std::invalid_argument("You must give at least one of the grouping, offsets or masking workspaces.");

    // Header of the file
    std::ofstream fout(calFileName.c_str());
    fout <<"# Calibration file for instrument " << inst->getName() << " written on "
         << DateAndTime::getCurrentTime().toISO8601String() << ".\n";
    fout <<"# Format: number    UDET         offset    select    group\n";

    // Get all the detectors
    detid2det_map allDetectors;
    inst->getDetectors(allDetectors);
    int64_t number=0;

    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;

        //Find the offset, if any
        double offset = 0.0;
        if (doOffsets)
            offset = offsetsWS->getValue(detectorID, 0.0);

        //Find the group, if any
        int64_t group = 1;
        if (doGroup)
            group = static_cast<int64_t>(groupWS->getValue(detectorID, 0.0));

        // Find the selection, if any
        int selected = 1;
        if (doMask && (maskWS->isMasked(detectorID)))
            selected = 0;

        //if(group > 0)
        fout << std::fixed << std::setw(9) << number <<
             std::fixed << std::setw(15) << detectorID <<
             std::fixed << std::setprecision(7) << std::setw(15)<< offset <<
             std::fixed << std::setw(8) << selected <<
             std::fixed << std::setw(8) << group  << "\n";

        number++;
    }

}
Exemplo n.º 7
0
/**
 * 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;
}
Exemplo n.º 8
0
/** Execute the algorithm.
 */
void CreateGroupingWorkspace::exec() {
  MatrixWorkspace_sptr inWS = getProperty("InputWorkspace");
  std::string InstrumentName = getPropertyValue("InstrumentName");
  std::string InstrumentFilename = getPropertyValue("InstrumentFilename");
  std::string OldCalFilename = getPropertyValue("OldCalFilename");
  std::string GroupNames = getPropertyValue("GroupNames");
  std::string grouping = getPropertyValue("GroupDetectorsBy");
  int numGroups = getProperty("FixedGroupCount");
  std::string componentName = getPropertyValue("ComponentName");

  // Some validation
  int numParams = 0;
  if (inWS)
    numParams++;
  if (!InstrumentName.empty())
    numParams++;
  if (!InstrumentFilename.empty())
    numParams++;

  if (numParams > 1)
    throw std::invalid_argument("You must specify exactly ONE way to get an "
                                "instrument (workspace, instrument name, or "
                                "IDF file). You specified more than one.");
  if (numParams == 0)
    throw std::invalid_argument("You must specify exactly ONE way to get an "
                                "instrument (workspace, instrument name, or "
                                "IDF file). You specified none.");

  if (!OldCalFilename.empty() && !GroupNames.empty())
    throw std::invalid_argument("You must specify either to use the "
                                "OldCalFilename parameter OR GroupNames but "
                                "not both!");

  bool sortnames = false;

  // ---------- Get the instrument one of 3 ways ---------------------------
  Instrument_const_sptr inst;
  if (inWS) {
    inst = inWS->getInstrument();
  } else {
    Algorithm_sptr childAlg = createChildAlgorithm("LoadInstrument", 0.0, 0.2);
    MatrixWorkspace_sptr tempWS = boost::make_shared<Workspace2D>();
    childAlg->setProperty<MatrixWorkspace_sptr>("Workspace", tempWS);
    childAlg->setPropertyValue("Filename", InstrumentFilename);
    childAlg->setProperty("RewriteSpectraMap",
                          Mantid::Kernel::OptionalBool(true));
    childAlg->setPropertyValue("InstrumentName", InstrumentName);
    childAlg->executeAsChildAlg();
    inst = tempWS->getInstrument();
  }

  if (GroupNames.empty() && OldCalFilename.empty()) {
    if (grouping.compare("All") == 0) {
      GroupNames = inst->getName();
    } else if (inst->getName().compare("SNAP") == 0 &&
               grouping.compare("Group") == 0) {
      GroupNames = "East,West";
    } else {
      sortnames = true;
      GroupNames = "";
      int maxRecurseDepth = this->getProperty("MaxRecursionDepth");

      // cppcheck-suppress syntaxError
          PRAGMA_OMP(parallel for schedule(dynamic, 1) )
          for (int num = 0; num < 300; ++num) {
            PARALLEL_START_INTERUPT_REGION
            std::ostringstream mess;
            mess << grouping << num;
            IComponent_const_sptr comp =
                inst->getComponentByName(mess.str(), maxRecurseDepth);
            PARALLEL_CRITICAL(GroupNames)
            if (comp)
              GroupNames += mess.str() + ",";
            PARALLEL_END_INTERUPT_REGION
          }
          PARALLEL_CHECK_INTERUPT_REGION
    }
  }

  // --------------------------- Create the output --------------------------
  auto outWS = boost::make_shared<GroupingWorkspace>(inst);
  this->setProperty("OutputWorkspace", outWS);

  // This will get the grouping
  std::map<detid_t, int> detIDtoGroup;

  Progress prog(this, 0.2, 1.0, outWS->getNumberHistograms());
  // Make the grouping one of three ways:
  if (!GroupNames.empty())
    detIDtoGroup = makeGroupingByNames(GroupNames, inst, prog, sortnames);
  else if (!OldCalFilename.empty())
    detIDtoGroup = readGroupingFile(OldCalFilename, prog);
  else if ((numGroups > 0) && !componentName.empty())
    detIDtoGroup =
        makeGroupingByNumGroups(componentName, numGroups, inst, prog);

  g_log.information() << detIDtoGroup.size()
                      << " entries in the detectorID-to-group map.\n";
  setProperty("NumberGroupedSpectraResult",
              static_cast<int>(detIDtoGroup.size()));

  if (detIDtoGroup.empty()) {
    g_log.warning() << "Creating empty group workspace\n";
    setProperty("NumberGroupsResult", static_cast<int>(0));
  } else {
    size_t numNotFound = 0;

    // Make the groups, if any
    std::map<detid_t, int>::const_iterator it_end = detIDtoGroup.end();
    std::map<detid_t, int>::const_iterator it;
    std::unordered_set<int> groupCount;
    for (it = detIDtoGroup.begin(); it != it_end; ++it) {
      int detID = it->first;
      int group = it->second;
      groupCount.insert(group);
      try {
        outWS->setValue(detID, double(group));
      } catch (std::invalid_argument &) {
        numNotFound++;
      }
    }
    setProperty("NumberGroupsResult", static_cast<int>(groupCount.size()));

    if (numNotFound > 0)
      g_log.warning() << numNotFound << " detector IDs (out of "
                      << detIDtoGroup.size()
                      << ") were not found in the instrument\n.";
  }
}