Skip to content
Snippets Groups Projects
LoadISISNexus2.cpp 46.3 KiB
Newer Older
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidDataHandling/LoadISISNexus2.h"
#include "MantidDataHandling/LoadEventNexus.h"
#include "MantidDataHandling/LoadRawHelper.h"
#include "MantidKernel/ArrayProperty.h"
#include "MantidKernel/BoundedValidator.h"
#include "MantidKernel/ConfigService.h"
#include "MantidKernel/ListValidator.h"
#include "MantidKernel/LogParser.h"
#include "MantidKernel/LogFilter.h"
#include "MantidKernel/TimeSeriesProperty.h"
#include "MantidKernel/UnitFactory.h"

#include "MantidAPI/RegisterFileLoader.h"
#include "MantidGeometry/Instrument/Detector.h"
#include <nexus/NeXusFile.hpp>
#include <nexus/NeXusException.hpp>
#include <Poco/Path.h>
#include <Poco/DateTimeFormatter.h>
#include <Poco/DateTimeParser.h>
#include <Poco/DateTimeFormat.h>
#include <cmath>
#include <vector>
#include <sstream>
#include <cctype>
    DECLARE_NEXUS_FILELOADER_ALGORITHM(LoadISISNexus2);
    using namespace Kernel;
    using namespace API;
Peterson, Peter's avatar
Peterson, Peter committed
    using std::size_t;
    /// Empty default constructor
    LoadISISNexus2::LoadISISNexus2() : 
      m_filename(), m_instrument_name(), m_samplename(),
      m_detBlockInfo(),m_monBlockInfo(),m_loadBlockInfo(),
      m_have_detector(false),
      m_load_selected_spectra(false),m_specInd2specNum_map(),m_spec2det_map(),
      m_entrynumber(0), m_tof_data(), m_proton_charge(0.),
      m_spec(), m_monitors(), m_logCreator(), m_progress()
    * Return the confidence criteria for this algorithm can load the file
    * @param descriptor A descriptor for the file
    * @returns An integer specifying the confidence level. 0 indicates it will not be used
    */
    int LoadISISNexus2::confidence(Kernel::NexusDescriptor & descriptor) const
    {
      if(descriptor.pathOfTypeExists("/raw_data_1","NXentry")) return 80;
      return 0;
    }

    /// Initialization method.
      exts.push_back(".nxs");
      exts.push_back(".n*");
      declareProperty(new FileProperty("Filename", "", FileProperty::Load, exts),
        "The name of the Nexus file to load" );
      declareProperty(new WorkspaceProperty<Workspace>("OutputWorkspace","",Direction::Output));

      auto mustBePositive = boost::make_shared<BoundedValidator<int64_t> >();
      declareProperty("SpectrumMin",(int64_t)0, mustBePositive);
      declareProperty("SpectrumMax",(int64_t)EMPTY_INT(), mustBePositive);
      declareProperty(new ArrayProperty<int64_t>("SpectrumList"));
      declareProperty("EntryNumber", (int64_t)0, mustBePositive,
        "The particular entry number to read (default: Load all workspaces and creates a workspace group)");

      std::vector<std::string> monitorOptions;
      monitorOptions.push_back("Include");
      monitorOptions.push_back("Exclude");
      monitorOptions.push_back("Separate");
      std::map<std::string,std::string> monitorOptionsAliases;
      monitorOptionsAliases["1"] = "Separate";
      monitorOptionsAliases["0"] = "Exclude";
      declareProperty("LoadMonitors","Include", boost::make_shared<Kernel::StringListValidator>(monitorOptions,monitorOptionsAliases),
        "Option to control the loading of monitors.\n"
        "Allowed options are Include,Exclude, Separate.\n"
        "Include:The default is Include option would load monitors with the workspace if monitors spectra are within the range of loaded detectors.\n"
        "If the time binning for the monitors is different from the\n"
        "binning of the detectors this option is equivalent to the Separate option\n"
        "Exclude:Exclude option excludes monitors from the output workspace.\n"
        "Separate:Separate option loads monitors into a separate workspace called: OutputWorkspace_monitors.\n"
        "Defined aliases:\n"
        "1:  Equivalent to Separate.\n"
        "0:  Equivalent to Exclude.\n");
    /** Executes the algorithm. Reading in the file and creating and populating
    *  the output workspace
    * 
    *  @throw Exception::FileError If the Nexus file cannot be found/opened
    *  @throw std::invalid_argument If the optional properties are set to invalid values
    */
    void LoadISISNexus2::exec()

      //**********************************************************************
      // process load monitor options request
      bool bincludeMonitors,bseparateMonitors, bexcludeMonitors;
      LoadRawHelper::ProcessLoadMonitorOptions(bincludeMonitors,bseparateMonitors, bexcludeMonitors,this);
      //**********************************************************************
      m_filename = getPropertyValue("Filename");
      // Create the root Nexus class
      NXRoot root(m_filename);

      // "Open" the same file but with the C++ interface
      m_cppFile.reset( new ::NeXus::File(root.m_fileID));
      // Open the raw data group 'raw_data_1'
      NXEntry entry = root.openEntry("raw_data_1");

      // Read in the instrument name from the Nexus file
      m_instrument_name = entry.getString("name");

      //Test if we have a detector block
Peterson, Peter's avatar
Peterson, Peter committed
      size_t ndets(0);
        NXClass det_class = entry.openNXGroup("detector_1");
        NXInt spectrum_index = det_class.openNXInt("spectrum_index");
        spectrum_index.load();
        ndets = spectrum_index.dim0();
        // We assume that this spectrum list increases monotonically
        m_spec = spectrum_index.sharedBuffer();
        m_spec_end = m_spec.get() + ndets;
        m_have_detector = true;
      }
      catch(std::runtime_error &)
      {
        ndets = 0;
      NXInt nsp1 = entry.openNXInt("isis_vms_compat/NSP1");
      NXInt udet = entry.openNXInt("isis_vms_compat/UDET");
      NXInt spec = entry.openNXInt("isis_vms_compat/SPEC");
Peterson, Peter's avatar
Peterson, Peter committed
      size_t nmons(0);

      //Pull out the monitor blocks, if any exist
      for(std::vector<NXClassInfo>::const_iterator it = entry.groups().begin(); 
        it != entry.groups().end(); ++it) 
        if (it->nxclass == "NXmonitor") // Count monitors
          NXInt index = entry.openNXInt(std::string(it->nxname) + "/spectrum_index");
          index.load();
          int64_t ind = *index();
          m_monitors[ind ] = it->nxname;
        if (bexcludeMonitors)
          g_log.warning() << "Nothing to do. No detectors found and no monitor loading requested";
          return;
        }
        else
        {
          g_log.error() << "Invalid NeXus structure, cannot find detector or monitor blocks.";
          throw std::runtime_error("Inconsistent NeXus file structure.");
      std::set<specid_t>  ExcluedMonitorsSpectra;
      bseparateMonitors=findSpectraDetRangeInFile(entry,m_spec,ndets,nsp1[0],m_monitors,bexcludeMonitors,bseparateMonitors,ExcluedMonitorsSpectra);
      const size_t x_length = m_detBlockInfo.numberOfChannels + 1;
      // Check input is consistent with the file, throwing if not, exclude spectra selected at findSpectraDetRangeInFile;
Loading
Loading full blame...