/** Convert a SPICE 2D Det MatrixWorkspace to MDEvents and append to an
 * MDEventWorkspace
 * It is optional to use a virtual instrument or copy from input data workspace
 * @brief ConvertCWSDExpToMomentum::convertSpiceMatrixToMomentumMDEvents
 * @param dataws :: data matrix workspace
 * @param usevirtual :: boolean flag to use virtual instrument
 * @param startdetid :: starting detid for detectors from this workspace mapping
 * to virtual instrument in MDEventWorkspace
 * @param scannumber :: scan number
 * @param runnumber :: run number for all MDEvents created from this matrix
 * @param measuretime :: duration (time) to measure this point
 * @param monitor_counts :: monitor counts; add to ExpInfo
 * workspace
 */
void ConvertCWSDExpToMomentum::convertSpiceMatrixToMomentumMDEvents(
    MatrixWorkspace_sptr dataws, bool usevirtual, const detid_t &startdetid,
    const int scannumber, const int runnumber, double measuretime,
    int monitor_counts) {
  // Create transformation matrix from which the transformation is
  Kernel::DblMatrix rotationMatrix;
  setupTransferMatrix(dataws, rotationMatrix);

  g_log.information() << "Before insert new event, output workspace has "
                      << m_outputWS->getNEvents() << "Events.\n";

  // Creates a new instance of the MDEventInserte to output workspace
  MDEventWorkspace<MDEvent<3>, 3>::sptr mdws_mdevt_3 =
      boost::dynamic_pointer_cast<MDEventWorkspace<MDEvent<3>, 3>>(m_outputWS);
  MDEventInserter<MDEventWorkspace<MDEvent<3>, 3>::sptr> inserter(mdws_mdevt_3);

  // Calcualte k_i: it is assumed that all k_i are same for one Pt.
  // number, i.e., one 2D XML file
  Kernel::V3D sourcePos = dataws->getInstrument()->getSource()->getPos();
  Kernel::V3D samplePos = dataws->getInstrument()->getSample()->getPos();
  if (dataws->readX(0).size() != 2)
    throw std::runtime_error(
        "Input matrix workspace has wrong dimension in X-axis.");
  double momentum = 0.5 * (dataws->readX(0)[0] + dataws->readX(0)[1]);
  Kernel::V3D ki = (samplePos - sourcePos) * (momentum / sourcePos.norm());

  g_log.debug() << "Source at " << sourcePos.toString()
                << ", Norm = " << sourcePos.norm()
                << ", momentum = " << momentum << "\n"
                << "k_i = " << ki.toString() << "\n";

  // Go though each spectrum to conver to MDEvent
  size_t numspec = dataws->getNumberHistograms();
  double maxsignal = 0;
  size_t nummdevents = 0;
  for (size_t iws = 0; iws < numspec; ++iws) {
    // Get detector positions and signal
    double signal = dataws->readY(iws)[0];
    // Skip event with 0 signal
    if (fabs(signal) < 0.001)
      continue;
    double error = sqrt(fabs(signal));
    Kernel::V3D detpos = dataws->getDetector(iws)->getPos();
    std::vector<Mantid::coord_t> q_sample(3);

    // Calculate Q-sample and new detector ID in virtual instrument.
    Kernel::V3D qlab = convertToQSample(samplePos, ki, detpos, momentum,
                                        q_sample, rotationMatrix);
    detid_t native_detid = dataws->getDetector(iws)->getID();
    detid_t detid = native_detid + startdetid;

    // Insert
    inserter.insertMDEvent(
        static_cast<float>(signal), static_cast<float>(error * error),
        static_cast<uint16_t>(runnumber), detid, q_sample.data());
    updateQRange(q_sample);

    g_log.debug() << "Q-lab = " << qlab.toString() << "\n";
    g_log.debug() << "Insert DetID " << detid << ", signal = " << signal
                  << ", with q_sample = " << q_sample[0] << ", " << q_sample[1]
                  << ", " << q_sample[2] << "\n";

    // Update some statistical inforamtion
    if (signal > maxsignal)
      maxsignal = signal;
    ++nummdevents;
  }

  g_log.information() << "Imported Matrixworkspace of run number " << runnumber
                      << ": Max. Signal = " << maxsignal << ", Add "
                      << nummdevents << " MDEvents "
                      << "\n";

  // Add experiment info including instrument, goniometer and run number
  ExperimentInfo_sptr expinfo = boost::make_shared<ExperimentInfo>();
  if (usevirtual)
    expinfo->setInstrument(m_virtualInstrument);
  else {
    Geometry::Instrument_const_sptr tmp_inst = dataws->getInstrument();
    expinfo->setInstrument(tmp_inst);
  }
  expinfo->mutableRun().setGoniometer(dataws->run().getGoniometer(), false);
  int scan_run_number = scannumber * 1000 + runnumber;
  expinfo->mutableRun().addProperty("run_number", scan_run_number);
  expinfo->mutableRun().addProperty("duration", measuretime);
  expinfo->mutableRun().addProperty("monitor", monitor_counts);
  // Add all the other propertys from original data workspace
  const std::vector<Kernel::Property *> vec_property =
      dataws->run().getProperties();
  for (auto property : vec_property) {
    expinfo->mutableRun().addProperty(property->clone());
  }

  m_outputWS->addExperimentInfo(expinfo);
}
Exemple #2
0
/**
* Copy over the metadata from the input matrix workspace to output
*MDEventWorkspace
* @param mdEventWS :: The output MDEventWorkspace where metadata are copied to.
*The source of the metadata is the input matrix workspace
*
*/
void ConvertToMD::copyMetaData(API::IMDEventWorkspace_sptr &mdEventWS) const {

  // found detector which is not a monitor to get proper bin boundaries.
  size_t spectra_index(0);
  bool dector_found(false);
  for (size_t i = 0; i < m_InWS2D->getNumberHistograms(); ++i) {
    try {
      auto det = m_InWS2D->getDetector(i);
      if (!det->isMonitor()) {
        spectra_index = i;
        dector_found = true;
        g_log.debug() << "Using spectra N " << i << " as the source of the bin "
                                                    "boundaries for the "
                                                    "resolution corrections \n";
        break;
      }
    } catch (...) {
    }
  }
  if (!dector_found)
    g_log.warning() << "No detectors in the workspace are associated with "
                       "spectra. Using spectrum 0 trying to retrieve the bin "
                       "boundaries \n";

  // retrieve representative bin boundaries
  MantidVec binBoundaries = m_InWS2D->readX(spectra_index);
  // check if the boundaries transformation is necessary
  if (m_Convertor->getUnitConversionHelper().isUnitConverted()) {

    if (!dynamic_cast<DataObjects::EventWorkspace *>(m_InWS2D.get())) {
      g_log.information() << " ConvertToMD converts input workspace units, but "
                             "the bin boundaries are copied from the first "
                             "workspace spectra. The resolution estimates can "
                             "be incorrect if unit conversion depends on "
                             "spectra number.\n";

      UnitsConversionHelper &unitConv = m_Convertor->getUnitConversionHelper();
      unitConv.updateConversion(spectra_index);
      for (double &binBoundarie : binBoundaries) {
        binBoundarie = unitConv.convertUnits(binBoundarie);
      }
    }
    // sort bin boundaries in case if unit transformation have swapped them.
    if (binBoundaries[0] > binBoundaries.back()) {
      g_log.information() << "Bin boundaries are not arranged monotonously. "
                             "Sorting performed\n";
      std::sort(binBoundaries.begin(), binBoundaries.end());
    }
  }

  // Replacement for SpectraDetectorMap::createIDGroupsMap using the ISpectrum
  // objects instead
  auto mapping = boost::make_shared<det2group_map>();
  for (size_t i = 0; i < m_InWS2D->getNumberHistograms(); ++i) {
    const auto &dets = m_InWS2D->getSpectrum(i).getDetectorIDs();
    if (!dets.empty()) {
      mapping->emplace(*dets.begin(),
                       std::vector<detid_t>(dets.begin(), dets.end()));
    }
  }

  // The last experiment info should always be the one that refers
  // to latest converting workspace. All others should have had this
  // information set already
  uint16_t nexpts = mdEventWS->getNumExperimentInfo();
  if (nexpts > 0) {
    ExperimentInfo_sptr expt =
        mdEventWS->getExperimentInfo(static_cast<uint16_t>(nexpts - 1));
    expt->mutableRun().storeHistogramBinBoundaries(binBoundaries);
    expt->cacheDetectorGroupings(*mapping);
  }
}
Exemple #3
0
void LoadFlexiNexus::addMetaData(NeXus::File *fin, Workspace_sptr ws,
                                 ExperimentInfo_sptr info) {
  std::map<std::string, std::string>::const_iterator it;

  // assign a title
  if ((it = dictionary.find("title")) == dictionary.end()) {
    const std::string title("No title found");
    ws->setTitle(title);
  } else {
    if (it->second.find('/') == it->second.npos) {
      const std::string title(it->second);
      ws->setTitle(title);
    } else {
      if (safeOpenpath(fin, it->second)) {
        const std::string title = fin->getStrData();
        ws->setTitle(title);
      }
    }
  }

  // assign a sample name
  std::string sample;
  if ((it = dictionary.find("sample")) == dictionary.end()) {
    sample = "No sample found";
  } else {
    if (it->second.find('/') == it->second.npos) {
      sample = it->second;
    } else {
      if (safeOpenpath(fin, it->second)) {
        sample = fin->getStrData();
      } else {
        sample = "Sampe plath not found";
      }
    }
  }
  info->mutableSample().setName(sample);

  /**
  * load all the extras into the Run information
  */
  Run &r = info->mutableRun();
  auto specialMap = populateSpecialMap();
  for (it = dictionary.begin(); it != dictionary.end(); ++it) {
    if (specialMap.find(it->first) == specialMap.end()) {
      // not in specials!
      if (it->second.find('/') == it->second.npos) {
        r.addProperty(it->first, it->second, true);
      } else {
        if (safeOpenpath(fin, it->second)) {
          NeXus::Info inf = fin->getInfo();
          if (inf.type == ::NeXus::CHAR) {
            std::string data = fin->getStrData();
            r.addProperty(it->first, data, true);
          } else if (inf.type == ::NeXus::FLOAT32 ||
                     inf.type == ::NeXus::FLOAT64) {
            std::vector<double> data;
            fin->getDataCoerce(data);
            r.addProperty(it->first, data, true);
          } else {
            std::vector<int> data;
            fin->getDataCoerce(data);
            r.addProperty(it->first, data, true);
          }
        }
      }
    }
  }
}
Exemple #4
0
/** Execute the algorithm.
 */
void LoadDNSSCD::exec() {
  MultipleFileProperty *multiFileProp =
      dynamic_cast<MultipleFileProperty *>(getPointerToProperty("Filenames"));
  if (!multiFileProp) {
    throw std::logic_error(
        "Filenames property must have MultipleFileProperty type.");
  }
  std::vector<std::string> filenames =
      VectorHelper::flattenVector(multiFileProp->operator()());
  if (filenames.empty())
    throw std::invalid_argument("Must specify at least one filename.");

  // set type of normalization
  std::string normtype = getProperty("Normalization");
  if (normtype == "monitor") {
    m_normtype = "Monitor";
    m_normfactor = 1.0;
  } else {
    m_normtype = "Timer";
    m_normfactor = 0.0; // error for time should be 0
  }

  g_log.notice() << "The normalization workspace will contain " << m_normtype
                 << ".\n";

  ExperimentInfo_sptr expinfo = boost::make_shared<ExperimentInfo>();
  API::Run &run = expinfo->mutableRun();
  for (auto fname : filenames) {
    std::map<std::string, std::string> str_metadata;
    std::map<std::string, double> num_metadata;
    try {
      read_data(fname, str_metadata, num_metadata);
      // if no stop_time, take file_save_time
      std::string time(str_metadata["stop_time"]);
      if (time.empty()) {
        g_log.warning()
            << "stop_time is empty! File save time will be used instead."
            << std::endl;
        time = str_metadata["file_save_time"];
      }
      updateProperties<std::string>(run, str_metadata, time);
      updateProperties<double>(run, num_metadata, time);
    } catch (...) {
      g_log.warning() << "Failed to read file " << fname;
      g_log.warning() << ". This file will be ignored. " << std::endl;
      g_log.debug() << boost::current_exception_diagnostic_information()
                    << std::endl;
    }
  }

  if (m_data.empty())
    throw std::runtime_error(
        "No valid DNS files have been provided. Nothing to load.");

  m_OutWS = MDEventFactory::CreateMDWorkspace(m_nDims, "MDEvent");

  m_OutWS->addExperimentInfo(expinfo);

  // load huber angles from a table workspace if given
  ITableWorkspace_sptr huberWS = getProperty("LoadHuberFrom");
  if (huberWS) {
    g_log.notice() << "Huber angles will be loaded from " << huberWS->getName()
                   << std::endl;
    loadHuber(huberWS);
  }

  // get wavelength
  TimeSeriesProperty<double> *wlprop =
      dynamic_cast<TimeSeriesProperty<double> *>(
          expinfo->run().getProperty("Lambda"));
  // assume, that lambda is in nm
  double wavelength =
      wlprop->minValue() * 10.0; // needed to estimate extents => minValue
  run.addProperty("wavelength", wavelength);
  run.getProperty("wavelength")->setUnits("Angstrom");

  fillOutputWorkspace(wavelength);

  std::string saveHuberTableWS = getProperty("SaveHuberTo");
  if (!saveHuberTableWS.empty()) {
    Mantid::API::ITableWorkspace_sptr huber_table = saveHuber();
    setProperty("SaveHuberTo", huber_table);
  }
  setProperty("OutputWorkspace", m_OutWS);
}