Skip to content
Snippets Groups Projects
LoadISISNexus2.cpp 46.3 KiB
Newer Older
      alg->setPropertyValue("Filename", this->getProperty("Filename"));
      alg->setProperty<MatrixWorkspace_sptr>("Workspace", ws);
      try
        alg->executeAsChildAlg();
        g_log.warning() << "Unable to load run logs. There will be no log "
          << "data associated with this workspace\n";
      // For ISIS Nexus only, fabricate an additional log containing an array of proton charge information from the periods group.
      try
      {
        NXClass protonChargeClass = entry.openNXGroup("periods");
        NXFloat periodsCharge = protonChargeClass.openNXFloat("proton_charge");
        periodsCharge.load();
        size_t nperiods = periodsCharge.dim0();
        std::vector<double> chargesVector(nperiods);
        std::copy(periodsCharge(), periodsCharge() + nperiods, chargesVector.begin());
        ArrayProperty<double>* protonLogData = new ArrayProperty<double>("proton_charge_by_period", chargesVector);
        ws->mutableRun().addProperty(protonLogData);  
      }
      catch(std::runtime_error&)
      {
        this->g_log.debug("Cannot read periods information from the nexus file. This group may be absent.");
      }
      // Populate the instrument parameters.

      // Make log creator object and add the run status log
      m_logCreator.reset(new ISISRunLogs(ws->run(), m_detBlockInfo.numberOfPeriods));
      m_logCreator->addStatusLog(ws->mutableRun());
    double LoadISISNexus2::dblSqrt(double in)
    {
      return sqrt(in);
    }
    /**Method takes input parameters which describe  monitor loading and analyze them against spectra/monitor block information in the file. 
    * The result is the option if monitors can  be loaded together with spectra or mast be treated separately 
    * and additional information on how to treat monitor spectra.
    *
    *@param entry                :: entry to the NeXus file, opened at root folder
    *@param spectrum_index       :: array of spectra indexes of the data present in the file
    *@param ndets                :: size of the spectrum index array
    *@param n_vms_compat_spectra :: number of data entries containing common time bins (e.g. all spectra, or all spectra and monitors or some spectra (this is not fully supported)
    *@param monitors             :: map connecting monitor spectra ID against monitor group name in the file. 
    *@param excludeMonitors      :: input property indicating if it is requested to exclude monitors from the target workspace
    *@param separateMonitors     :: input property indicating if it is requested to load monitors separately (and exclude them from target data workspace this way)
    *
    *@param OvelapMonitorSpectra :: output property containing the list of monitors ID for monitors, which are also included with spectra. 
    *@return excludeMonitors     :: indicator if monitors should or mast be excluded from the main data workspace if they can not be loaded with the data
    *                               (contain different number of time channels)
    *
    bool LoadISISNexus2::findSpectraDetRangeInFile(NXEntry &entry,boost::shared_array<int>  &spectrum_index,int64_t ndets,int64_t n_vms_compat_spectra,
      std::map<int64_t,std::string> &monitors,bool excludeMonitors,bool separateMonitors,std::set<specid_t> &OvelapMonitorSpectra)
      OvelapMonitorSpectra.clear();
      size_t nmons = monitors.size();

      if (nmons>0)
      {
        NXInt chans = entry.openNXInt(m_monitors.begin()->second + "/data");
        m_monBlockInfo    = DataBlock(chans);
        m_monBlockInfo.numberOfSpectra = nmons; // each monitor is in separate group so number of spectra is equal to number of groups.

        // identify monitor ID range.
        for(auto it = monitors.begin(); it!=monitors.end(); it++)
        {
          int64_t mon_id = static_cast<int64_t>(it->first);
          if(m_monBlockInfo.spectraID_min>mon_id )m_monBlockInfo.spectraID_min=mon_id;
          if(m_monBlockInfo.spectraID_max<mon_id )m_monBlockInfo.spectraID_max=mon_id;
        }
        if(m_monBlockInfo.spectraID_max-m_monBlockInfo.spectraID_min+1!=static_cast<int64_t>(nmons))
        {
          g_log.warning()<<" non-consequent monitor ID-s in the monitor block. Unexpected situation for the loader\n";
        }
        // at this stage we assume that the only going to load monitors
        m_loadBlockInfo =  m_monBlockInfo;

        separateMonitors = false; // only monitors in the main workspace. No detectors. Will be loaded in the main workspace
        return separateMonitors;
      }

      // detectors are present in the file
      NXData nxData = entry.openNXData("detector_1");
      NXInt data = nxData.openIntData();

      m_detBlockInfo    = DataBlock(data);
      // We assume again that this spectrum list ID increase monotonically
      m_detBlockInfo.spectraID_min = spectrum_index[0];
      m_detBlockInfo.spectraID_max = spectrum_index[ndets-1];
      if(m_detBlockInfo.spectraID_max-m_detBlockInfo.spectraID_min+1!=static_cast<int64_t>(m_detBlockInfo.numberOfSpectra))
      {
        g_log.warning()<<" non-consequent spectra ID-s in the detectors block. Unexpected situation for the loader\n";
      }


      m_loadBlockInfo   = m_detBlockInfo;  


      // now we are analyzing what is actually going or can be loaded

      bool removeMonitors = excludeMonitors || separateMonitors;
      if (((m_detBlockInfo.numberOfPeriods!=m_monBlockInfo.numberOfPeriods) || (m_detBlockInfo.numberOfChannels!=m_monBlockInfo.numberOfChannels)) && nmons>0)
        // detectors and monitors have different characteristics. Can be loaded only to separate workspaces.
        if(!removeMonitors)
        {
          g_log.warning()<<" Performing separate loading as can not load spectra and monitors in the single workspace:\n" ;
          g_log.warning()<<" Monitors data contain :"<<m_monBlockInfo.numberOfChannels<<" time channels and: "<<m_monBlockInfo.numberOfPeriods<<" period(s)\n";
          g_log.warning()<<" Spectra  data contain :"<<m_detBlockInfo.numberOfChannels<<" time channels and: "<<m_detBlockInfo.numberOfPeriods<<" period(s)\n";
        }
        separateMonitors = true;
        removeMonitors  = true;
      int64_t spectraID_min  = std::min(m_monBlockInfo.spectraID_min,m_detBlockInfo.spectraID_min);
      int64_t spectraID_max  = std::max(m_monBlockInfo.spectraID_max,m_detBlockInfo.spectraID_max);
      size_t  totNumOfSpectra= m_monBlockInfo.numberOfSpectra+m_detBlockInfo.numberOfSpectra;
        m_loadBlockInfo.numberOfSpectra =totNumOfSpectra;
        m_loadBlockInfo.spectraID_min = spectraID_min;
        m_loadBlockInfo.spectraID_max = spectraID_max;
      }
      if (separateMonitors)
        m_loadBlockInfo = m_detBlockInfo;


      // verify integrity of the monitor and detector information

      if((totNumOfSpectra ==static_cast<size_t>( n_vms_compat_spectra )) && (spectraID_max-spectraID_min+1 ==static_cast<int64_t>(n_vms_compat_spectra)))
      {
        // all information written in the file is correct, there are no spurious spectra and detectors & monitors form continuous block on HDD
        return separateMonitors;
      // something is wrong and we need to analyze spectra map.  Currently we can identify and manage the case when all monitor's spectra are written together with detectors
      //make settings for this situation
      m_detBlockInfo.numberOfSpectra -= m_monBlockInfo.numberOfSpectra; 
      m_loadBlockInfo.numberOfSpectra-=  m_monBlockInfo.numberOfSpectra;
      std::map<int64_t,std::string> remaining_monitors;
        for(auto it = monitors.begin(); it!=monitors.end(); it++)
          if(it->first>=m_detBlockInfo.spectraID_min && it->first <=m_detBlockInfo.spectraID_max)
          {   //monitors ID-s are included with spectra ID-s -- let's try not to load it twice. 
            OvelapMonitorSpectra.insert(static_cast<specid_t>(it->first));
        }
      }
      monitors.swap(remaining_monitors);
} // namespace Mantid