/** Executes the algorithm.
   *
   *  @throw runtime_error Thrown if algorithm cannot execute
   */
  void SaveNexusProcessed::exec()
  {
    //TODO: Remove?
    NXMEnableErrorReporting();

    Workspace_sptr inputWorkspace = getProperty("InputWorkspace");

    // Retrieve the filename from the properties
    m_filename = getPropertyValue("Filename");
    //m_entryname = getPropertyValue("EntryName");
    m_title = getPropertyValue("Title");
    // Do we prserve events?
    bool PreserveEvents = getProperty("PreserveEvents");

    MatrixWorkspace_const_sptr matrixWorkspace = boost::dynamic_pointer_cast<const MatrixWorkspace>(inputWorkspace);
    ITableWorkspace_const_sptr tableWorkspace = boost::dynamic_pointer_cast<const ITableWorkspace>(inputWorkspace);
    PeaksWorkspace_const_sptr peaksWorkspace = boost::dynamic_pointer_cast<const PeaksWorkspace>(inputWorkspace);
    OffsetsWorkspace_const_sptr offsetsWorkspace = boost::dynamic_pointer_cast<const OffsetsWorkspace>(inputWorkspace);
    if(peaksWorkspace) g_log.debug("We have a peaks workspace");
    // check if inputWorkspace is something we know how to save
    if (!matrixWorkspace && !tableWorkspace) {
      g_log.debug() << "Workspace "  << m_title << " not saved because it is not of a type we can presently save.\n";
      return;
    }
    m_eventWorkspace = boost::dynamic_pointer_cast<const EventWorkspace>(matrixWorkspace);
    const std::string workspaceID = inputWorkspace->id();
    if ((workspaceID.find("Workspace2D") == std::string::npos) &&
      (workspaceID.find("RebinnedOutput") == std::string::npos) &&
      !m_eventWorkspace && !tableWorkspace && !offsetsWorkspace)
      throw Exception::NotImplementedError("SaveNexusProcessed passed invalid workspaces. Must be Workspace2D, EventWorkspace, ITableWorkspace, or OffsetsWorkspace.");

    // Create progress object for initial part - depends on whether events are processed
    if( PreserveEvents && m_eventWorkspace)
    {
       m_timeProgInit = 0.07; // Events processed 0.05 to 1.0
    }
    else
    {
      m_timeProgInit = 1.0; // All work is done in the initial part
    }
    Progress prog_init(this, 0.0, m_timeProgInit, 7);

    // If no title's been given, use the workspace title field
    if (m_title.empty()) 
      m_title = inputWorkspace->getTitle();

    // If we don't want to append then remove the file if it already exists
    bool append_to_file = getProperty("Append");
    if( !append_to_file )
    {
      Poco::File file(m_filename);
      if( file.exists() )
        file.remove();
    }
	// Then immediately open the file
    Mantid::NeXus::NexusFileIO *nexusFile= new Mantid::NeXus::NexusFileIO( &prog_init );

    nexusFile->openNexusWrite( m_filename );

    // Equivalent C++ API handle
    ::NeXus::File * cppFile = new ::NeXus::File(nexusFile->fileID);

    prog_init.reportIncrement(1, "Opening file");
    if( nexusFile->writeNexusProcessedHeader( m_title ) != 0 )
      throw Exception::FileError("Failed to write to file", m_filename);

    prog_init.reportIncrement(1, "Writing header");

    // write instrument data, if present and writer enabled
    if (matrixWorkspace) 
    { 
      // Save the instrument names, ParameterMap, sample, run
      matrixWorkspace->saveExperimentInfoNexus(cppFile);
      prog_init.reportIncrement(1, "Writing sample and instrument");

      // check if all X() are in fact the same array
      const bool uniformSpectra = API::WorkspaceHelpers::commonBoundaries(matrixWorkspace);

      // Retrieve the workspace indices (from params)
      std::vector<int> spec;
      this->getSpectrumList(spec, matrixWorkspace);

      prog_init.reportIncrement(1, "Writing data");
      // Write out the data (2D or event)
      if (m_eventWorkspace && PreserveEvents)
      {
        this->execEvent(nexusFile,uniformSpectra,spec);
      }
      else if (offsetsWorkspace)
      {
        g_log.warning() << "Writing SpecialWorkspace2D ID=" << workspaceID << "\n";
        nexusFile->writeNexusProcessedData2D(matrixWorkspace,uniformSpectra,spec, "offsets_workspace", true);
      }
      else
      {
        nexusFile->writeNexusProcessedData2D(matrixWorkspace,uniformSpectra,spec, "workspace", true);
      }

      // MW 27/10/10 - don't try and save the spectra-detector map if there isn't one
      if ( matrixWorkspace->getAxis(1)->isSpectra() )
      {
        cppFile->openGroup("instrument", "NXinstrument");
        matrixWorkspace->saveSpectraMapNexus(cppFile, spec, ::NeXus::LZW);
        cppFile->closeGroup();
      }

    }  // finish matrix workspace specifics 



    if (peaksWorkspace) 
    {
      // Save the instrument names, ParameterMap, sample, run
      peaksWorkspace->saveExperimentInfoNexus(cppFile);
      prog_init.reportIncrement(1, "Writing sample and instrument");
    }


    // peaks workspace specifics
    if (peaksWorkspace)
    {
      //	g_log.information("Peaks Workspace saving to Nexus would be done");
      //	int pNum = peaksWorkspace->getNumberPeaks();
      peaksWorkspace->saveNexus( cppFile );



    } // finish peaks workspace specifics
    else if (tableWorkspace) // Table workspace specifics 
    {
      nexusFile->writeNexusTableWorkspace(tableWorkspace,"table_workspace");
    }  // finish table workspace specifics

    // Switch to the Cpp API for the algorithm history
	  inputWorkspace->getHistory().saveNexus(cppFile);

    nexusFile->closeNexusFile();

    delete nexusFile;

    return;
  }
Exemple #2
0
void SaveNexusProcessed::doExec(Workspace_sptr inputWorkspace,
                                Mantid::NeXus::NexusFileIO_sptr &nexusFile,
                                const bool keepFile,
                                optional_size_t entryNumber) {
  // TODO: Remove?
  NXMEnableErrorReporting();

  // Retrieve the filename from the properties
  m_filename = getPropertyValue("Filename");
  // m_entryname = getPropertyValue("EntryName");
  m_title = getPropertyValue("Title");
  // Do we prserve events?
  bool PreserveEvents = getProperty("PreserveEvents");

  MatrixWorkspace_const_sptr matrixWorkspace =
      boost::dynamic_pointer_cast<const MatrixWorkspace>(inputWorkspace);
  ITableWorkspace_const_sptr tableWorkspace =
      boost::dynamic_pointer_cast<const ITableWorkspace>(inputWorkspace);
  PeaksWorkspace_const_sptr peaksWorkspace =
      boost::dynamic_pointer_cast<const PeaksWorkspace>(inputWorkspace);
  OffsetsWorkspace_const_sptr offsetsWorkspace =
      boost::dynamic_pointer_cast<const OffsetsWorkspace>(inputWorkspace);
  if (peaksWorkspace)
    g_log.debug("We have a peaks workspace");
  // check if inputWorkspace is something we know how to save
  if (!matrixWorkspace && !tableWorkspace) {
    // get the workspace name for the error message
    std::string name = getProperty("InputWorkspace");

    // md workspaces should be saved using SaveMD
    if (bool(boost::dynamic_pointer_cast<const IMDEventWorkspace>(
            inputWorkspace)) ||
        bool(boost::dynamic_pointer_cast<const IMDHistoWorkspace>(
            inputWorkspace)))
      g_log.warning() << name << " can be saved using SaveMD\n";

    // standard error message
    std::stringstream msg;
    msg << "Workspace \"" << name
        << "\" not saved because it is not of a type we can presently save.";

    throw std::runtime_error(msg.str());
  }
  m_eventWorkspace =
      boost::dynamic_pointer_cast<const EventWorkspace>(matrixWorkspace);
  const std::string workspaceID = inputWorkspace->id();
  if ((workspaceID.find("Workspace2D") == std::string::npos) &&
      (workspaceID.find("RebinnedOutput") == std::string::npos) &&
      !m_eventWorkspace && !tableWorkspace && !offsetsWorkspace)
    throw Exception::NotImplementedError(
        "SaveNexusProcessed passed invalid workspaces. Must be Workspace2D, "
        "EventWorkspace, ITableWorkspace, or OffsetsWorkspace.");

  // Create progress object for initial part - depends on whether events are
  // processed
  if (PreserveEvents && m_eventWorkspace) {
    m_timeProgInit = 0.07; // Events processed 0.05 to 1.0
  } else {
    m_timeProgInit = 1.0; // All work is done in the initial part
  }
  Progress prog_init(this, 0.0, m_timeProgInit, 7);

  // If no title's been given, use the workspace title field
  if (m_title.empty())
    m_title = inputWorkspace->getTitle();

  // get the workspace name to write to file
  std::string wsName = inputWorkspace->getName();

  // If we don't want to append then remove the file if it already exists
  bool append_to_file = getProperty("Append");
  if (!append_to_file && !keepFile) {
    Poco::File file(m_filename);
    if (file.exists())
      file.remove();
  }

  nexusFile->resetProgress(&prog_init);
  nexusFile->openNexusWrite(m_filename, entryNumber);

  // Equivalent C++ API handle
  auto cppFile = new ::NeXus::File(nexusFile->fileID);

  prog_init.reportIncrement(1, "Opening file");
  if (nexusFile->writeNexusProcessedHeader(m_title, wsName) != 0)
    throw Exception::FileError("Failed to write to file", m_filename);

  prog_init.reportIncrement(1, "Writing header");

  // write instrument data, if present and writer enabled
  if (matrixWorkspace) {
    // Save the instrument names, ParameterMap, sample, run
    matrixWorkspace->saveExperimentInfoNexus(cppFile);
    prog_init.reportIncrement(1, "Writing sample and instrument");

    // check if all X() are in fact the same array
    const bool uniformSpectra =
        API::WorkspaceHelpers::commonBoundaries(*matrixWorkspace);

    // Retrieve the workspace indices (from params)
    std::vector<int> spec;
    this->getSpectrumList(spec, matrixWorkspace);

    prog_init.reportIncrement(1, "Writing data");
    // Write out the data (2D or event)
    if (m_eventWorkspace && PreserveEvents) {
      this->execEvent(nexusFile.get(), uniformSpectra, spec);
    } else if (offsetsWorkspace) {
      g_log.warning() << "Writing SpecialWorkspace2D ID=" << workspaceID
                      << "\n";
      nexusFile->writeNexusProcessedData2D(matrixWorkspace, uniformSpectra,
                                           spec, "offsets_workspace", true);
    } else {
      nexusFile->writeNexusProcessedData2D(matrixWorkspace, uniformSpectra,
                                           spec, "workspace", true);
    }

    cppFile->openGroup("instrument", "NXinstrument");
    matrixWorkspace->saveSpectraMapNexus(cppFile, spec, ::NeXus::LZW);
    cppFile->closeGroup();

  } // finish matrix workspace specifics

  if (peaksWorkspace) {
    // Save the instrument names, ParameterMap, sample, run
    peaksWorkspace->saveExperimentInfoNexus(cppFile);
    prog_init.reportIncrement(1, "Writing sample and instrument");
  }

  // peaks workspace specifics
  if (peaksWorkspace) {
    //  g_log.information("Peaks Workspace saving to Nexus would be done");
    //  int pNum = peaksWorkspace->getNumberPeaks();
    peaksWorkspace->saveNexus(cppFile);

  }                        // finish peaks workspace specifics
  else if (tableWorkspace) // Table workspace specifics
  {
    nexusFile->writeNexusTableWorkspace(tableWorkspace, "table_workspace");
  } // finish table workspace specifics

  // Switch to the Cpp API for the algorithm history
  if (trackingHistory()) {
    m_history->fillAlgorithmHistory(
        this, Mantid::Kernel::DateAndTime::getCurrentTime(), 0,
        Algorithm::g_execCount);
    if (!isChild()) {
      inputWorkspace->history().addHistory(m_history);
    }
    // this is a child algorithm, but we still want to keep the history.
    else if (isRecordingHistoryForChild() && m_parentHistory) {
      m_parentHistory->addChildHistory(m_history);
    }
  }

  inputWorkspace->history().saveNexus(cppFile);
  nexusFile->closeGroup();
}