Beispiel #1
0
//----------------------------------------------------------------------------------------------
void LoadPDFgetNFile::setUnit(Workspace2D_sptr ws) {
  // 1. Set X
  string xcolname = mColumnNames[0];

  if (xcolname.compare("Q") == 0) {
    string unit = "MomentumTransfer";
    ws->getAxis(0)->setUnit(unit);
  } else if (xcolname.compare("r") == 0) {
    ws->getAxis(0)->unit() = UnitFactory::Instance().create("Label");
    Unit_sptr unit = ws->getAxis(0)->unit();
    boost::shared_ptr<Units::Label> label =
        boost::dynamic_pointer_cast<Units::Label>(unit);
    label->setLabel("AtomicDistance", "Angstrom");
  } else {
    stringstream errss;
    errss << "X axis " << xcolname << " is not supported for unit. " << endl;
    g_log.warning() << errss.str() << endl;
  }

  // 2. Set Y
  string ycolname = mColumnNames[1];
  string ylabel("");
  if (ycolname.compare("G(r)") == 0) {
    ylabel = "PDF";
  } else if (ycolname.compare("S") == 0) {
    ylabel = "S";
  } else {
    ylabel = "Intensity";
  }
  ws->setYUnitLabel(ylabel);

  return;
}
void MDHistoToWorkspace2D::recurseData(IMDHistoWorkspace_sptr inWS,
                                       Workspace2D_sptr outWS,
                                       size_t currentDim, coord_t *pos) {
  boost::shared_ptr<const IMDDimension> dim = inWS->getDimension(currentDim);
  if (currentDim == rank - 1) {
    MantidVec &Y = outWS->dataY(currentSpectra);
    for (unsigned int j = 0; j < dim->getNBins(); j++) {
      pos[currentDim] = dim->getX(j);
      Y[j] = inWS->getSignalAtCoord(
          pos, static_cast<Mantid::API::MDNormalization>(0));
    }
    MantidVec &E = outWS->dataE(currentSpectra);
    // MSVC compiler can't figure out the correct overload with out the function
    // cast on sqrt
    std::transform(Y.begin(), Y.end(), E.begin(),
                   (double (*)(double))std::sqrt);
    std::vector<double> xData;
    for (unsigned int i = 0; i < dim->getNBins(); i++) {
      xData.push_back(dim->getX(i));
    }
    outWS->setX(currentSpectra, xData);
    outWS->getSpectrum(currentSpectra)
        ->setSpectrumNo(static_cast<specid_t>(currentSpectra));
    currentSpectra++;
  } else {
    // recurse deeper
    for (int i = 0; i < static_cast<int>(dim->getNBins()); i++) {
      pos[currentDim] = dim->getX(i);
      recurseData(inWS, outWS, currentDim + 1, pos);
    }
  }
}
Beispiel #3
0
/** Remove peaks from a input workspace
  */
Workspace2D_sptr
RemovePeaks::removePeaks(API::MatrixWorkspace_const_sptr dataws, int wsindex,
                         double numfwhm) {
  // Check
  if (m_vecPeakCentre.empty())
    throw runtime_error("RemovePeaks has not been setup yet. ");

  // Initialize vectors
  const MantidVec &vecX = dataws->readX(wsindex);
  const MantidVec &vecY = dataws->readY(wsindex);
  const MantidVec &vecE = dataws->readE(wsindex);

  size_t sizex = vecX.size();
  vector<bool> vec_useX(sizex, true);

  // Exclude regions
  size_t numbkgdpoints =
      excludePeaks(vecX, vec_useX, m_vecPeakCentre, m_vecPeakFWHM, numfwhm);
  size_t numbkgdpointsy = numbkgdpoints;
  size_t sizey = vecY.size();
  if (sizex > sizey)
    --numbkgdpointsy;

  // Construct output workspace
  Workspace2D_sptr outws = boost::dynamic_pointer_cast<Workspace2D>(
      WorkspaceFactory::Instance().create("Workspace2D", 1, numbkgdpoints,
                                          numbkgdpointsy));
  outws->getAxis(0)->setUnit(dataws->getAxis(0)->unit()->unitID());
  MantidVec &outX = outws->dataX(0);
  MantidVec &outY = outws->dataY(0);
  MantidVec &outE = outws->dataE(0);
  size_t index = 0;
  for (size_t i = 0; i < sizex; ++i) {
    if (vec_useX[i]) {
      if (index >= numbkgdpoints)
        throw runtime_error("Programming logic error (1)");
      outX[index] = vecX[i];
      ++index;
    }
  }
  index = 0;
  for (size_t i = 0; i < sizey; ++i) {
    if (vec_useX[i]) {
      if (index >= numbkgdpointsy)
        throw runtime_error("Programming logic error (2)");
      outY[index] = vecY[i];
      outE[index] = vecE[i];
      ++index;
    }
  }

  return outws;
}
  /** Fit function
    * Minimizer: "Levenberg-MarquardtMD"/"Simplex"
   */
  bool RefinePowderInstrumentParameters2::doFitFunction(IFunction_sptr function, Workspace2D_sptr dataws, int wsindex,
                                                        string minimizer, int numiters, double& chi2, string& fitstatus)
  {
    // 0. Debug output
    stringstream outss;
    outss << "Fit function: " << m_positionFunc->asString() << endl << "Data To Fit: \n";
    for (size_t i = 0; i < dataws->readX(0).size(); ++i)
      outss << dataws->readX(wsindex)[i] << "\t\t" << dataws->readY(wsindex)[i] << "\t\t"
            << dataws->readE(wsindex)[i] << "\n";
    g_log.information() << outss.str();

    // 1. Create and setup fit algorithm
    API::IAlgorithm_sptr fitalg = createChildAlgorithm("Fit", 0.0, 0.2, true);
    fitalg->initialize();

    fitalg->setProperty("Function", function);
    fitalg->setProperty("InputWorkspace", dataws);
    fitalg->setProperty("WorkspaceIndex", wsindex);
    fitalg->setProperty("Minimizer", minimizer);
    fitalg->setProperty("CostFunction", "Least squares");
    fitalg->setProperty("MaxIterations", numiters);
    fitalg->setProperty("CalcErrors", true);

    // 2. Fit
    bool successfulfit = fitalg->execute();
    if (!fitalg->isExecuted() || ! successfulfit)
    {
      // Early return due to bad fit
      g_log.warning("Fitting to instrument geometry function failed. ");
      chi2 = DBL_MAX;
      fitstatus = "Minimizer throws exception.";
      return false;
    }

    // 3. Understand solution
    chi2 = fitalg->getProperty("OutputChi2overDoF");
    string tempfitstatus = fitalg->getProperty("OutputStatus");
    fitstatus = tempfitstatus;

    bool goodfit = fitstatus.compare("success") == 0;

    stringstream dbss;
    dbss << "Fit Result (GSL):  Chi^2 = " << chi2
         << "; Fit Status = " << fitstatus << ", Return Bool = " << goodfit << std::endl;
    vector<string> funcparnames = function->getParameterNames();
    for (size_t i = 0; i < funcparnames.size(); ++i)
      dbss << funcparnames[i] << " = " << setw(20) << function->getParameter(funcparnames[i])
           << " +/- " << function->getError(i) << "\n";
    g_log.debug() << dbss.str();

    return goodfit;
  }
Beispiel #5
0
/**
 * Reads the data (FITS matrix) from a single FITS file into a
 * workspace (directly into the spectra, using one spectrum per image
 * row).
 *
 * @param fileInfo information on the FITS file to load, including its path
 * @param cmpp centimeters per pixel, to scale/normalize values
 * @param ws workspace with the required dimensions
 * @param buffer pre-allocated buffer to read from file
 *
 * @throws std::runtime_error if there are file input issues
 */
void LoadFITS::readDataToWorkspace(const FITSInfo &fileInfo, double cmpp,
                                   Workspace2D_sptr ws,
                                   std::vector<char> &buffer) {
  const size_t bytespp = (fileInfo.bitsPerPixel / 8);
  const size_t len = m_pixelCount * bytespp;
  readInBuffer(fileInfo, buffer, len);

  const size_t nrows(fileInfo.axisPixelLengths[1]),
      ncols(fileInfo.axisPixelLengths[0]);
  // Treat buffer as a series of bytes
  uint8_t *buffer8 = reinterpret_cast<uint8_t *>(buffer.data());

  PARALLEL_FOR_NO_WSP_CHECK()
  for (int i = 0; i < static_cast<int>(nrows); ++i) {
    auto &xVals = ws->mutableX(i);
    auto &yVals = ws->mutableY(i);
    auto &eVals = ws->mutableE(i);
    xVals = static_cast<double>(i) * cmpp;

    for (size_t j = 0; j < ncols; ++j) {
      // Map from 2D->1D index
      const size_t start = ((i * (bytespp)) * nrows) + (j * (bytespp));
      uint8_t const *const buffer8Start = buffer8 + start;
      // Reverse byte order of current value. Make sure we allocate enough
      // enough space to hold the size
      uint8_t byteValue[g_maxBytesPP];
      std::reverse_copy(buffer8Start, buffer8Start + bytespp, byteValue);

      double val = 0;
      if (fileInfo.bitsPerPixel == 8) {
        val = toDouble<uint8_t>(byteValue);
      } else if (fileInfo.bitsPerPixel == 16) {
        val = toDouble<uint16_t>(byteValue);
      } else if (fileInfo.bitsPerPixel == 32 && !fileInfo.isFloat) {
        val = toDouble<uint32_t>(byteValue);
      } else if (fileInfo.bitsPerPixel == 64 && !fileInfo.isFloat) {
        val = toDouble<uint32_t>(byteValue);
      } else if (fileInfo.bitsPerPixel == 32 && fileInfo.isFloat) {
        val = toDouble<float>(byteValue);
      } else if (fileInfo.bitsPerPixel == 64 && fileInfo.isFloat) {
        val = toDouble<double>(byteValue);
      }

      val = fileInfo.scale * val - fileInfo.offset;
      yVals[j] = val;
      eVals[j] = sqrt(val);
    }
  }
}
Beispiel #6
0
/** Sets error of workspace to specified value
  *
  * Since an estimation of the error is calculated from background counts, this
  *value is assigned to the workspace via this method.
  *
  * @param correlationWorkspace :: Workspace containing the correlation spectrum
  *on which the peak search was performed.
  * @param error :: Error that is set on the workspace.
  */
void
PoldiPeakSearch::setErrorsOnWorkspace(Workspace2D_sptr correlationWorkspace,
                                      double error) const {
  MantidVec &errors = correlationWorkspace->dataE(0);

  std::fill(errors.begin(), errors.end(), error);
}
/*
 * Generate a SANS test workspace, with instrument geometry.
 * The geometry is the SANSTEST geometry, with a 30x30 pixel 2D detector.
 *
 * @param workspace: name of the workspace to be created.
 */
Workspace2D_sptr SANSInstrumentCreationHelper::createSANSInstrumentWorkspace(
    std::string workspace) {
  // Create a test workspace with test data with a well defined peak
  // The test instrument has two monitor channels
  Workspace2D_sptr ws = WorkspaceCreationHelper::create2DWorkspace123(
      nBins * nBins + nMonitors, 1, 1);
  AnalysisDataService::Instance().addOrReplace(workspace, ws);
  ws->getAxis(0)->unit() =
      Mantid::Kernel::UnitFactory::Instance().create("Wavelength");
  ws->setYUnit("");

  // Load instrument geometry
  runLoadInstrument("SANSTEST", ws);
  runLoadMappingTable(ws, nBins, nBins);

  return ws;
}
Beispiel #8
0
/**
 * Writes a single workspace into the file
 * @param workspace the workspace to get data from
 * @param nxFile the nexus file to save data into
 */
void SaveNXTomo::writeSingleWorkspace(const Workspace2D_sptr workspace,
                                      ::NeXus::File &nxFile) {
  try {
    nxFile.openPath("/entry1/tomo_entry/data");
  } catch (...) {
    throw std::runtime_error("Unable to create a valid NXTomo file");
  }

  int numFiles = 0;
  nxFile.getAttr<int>("NumFiles", numFiles);

  // Change slab start to after last data position
  m_slabStart[0] = numFiles;
  m_slabSize[0] = 1;

  // Set the rotation value for this WS
  std::vector<double> rotValue;
  rotValue.push_back(0);

  if (workspace->run().hasProperty("Rotation")) {
    std::string tmpVal = workspace->run().getLogData("Rotation")->value();
    try {
      rotValue[0] = boost::lexical_cast<double>(tmpVal);
    } catch (...) {
    }
    // Invalid Cast is handled below
  }

  nxFile.openData("rotation_angle");
  nxFile.putSlab(rotValue, numFiles, 1);
  nxFile.closeData();

  // Copy data out, remake data with dimension of old size plus new elements.
  // Insert previous data.
  nxFile.openData("data");

  double *dataArr = new double[m_spectraCount];

  for (int64_t i = 0; i < m_dimensions[1]; ++i) {
    for (int64_t j = 0; j < m_dimensions[2]; ++j) {
      dataArr[i * m_dimensions[1] + j] =
          workspace->dataY(i * m_dimensions[1] + j)[0];
    }
  }

  nxFile.putSlab(dataArr, m_slabStart, m_slabSize);

  nxFile.closeData();

  nxFile.putAttr("NumFiles", numFiles + 1);

  nxFile.closeGroup();

  // Write additional log information, intensity and image key
  writeLogValues(workspace, nxFile, numFiles);
  writeIntensityValue(workspace, nxFile, numFiles);
  writeImageKeyValue(workspace, nxFile, numFiles);

  ++numFiles;

  delete[] dataArr;
}
Beispiel #9
0
/** Filter non-background data points out and create a background workspace
  */
Workspace2D_sptr
ProcessBackground::filterForBackground(BackgroundFunction_sptr bkgdfunction) {
  double posnoisetolerance = getProperty("NoiseTolerance");
  double negnoisetolerance = getProperty("NegativeNoiseTolerance");
  if (isEmpty(negnoisetolerance))
    negnoisetolerance = posnoisetolerance;

  // Calcualte theoretical values
  const std::vector<double> x = m_dataWS->readX(m_wsIndex);
  API::FunctionDomain1DVector domain(x);
  API::FunctionValues values(domain);
  bkgdfunction->function(domain, values);

  g_log.information() << "Function used to select background points : "
                      << bkgdfunction->asString() << "\n";

  // Optional output
  string userbkgdwsname = getPropertyValue("UserBackgroundWorkspace");
  if (userbkgdwsname.size() == 0)
    throw runtime_error("In mode SelectBackgroundPoints, "
                        "UserBackgroundWorkspace must be given!");

  size_t sizex = domain.size();
  size_t sizey = values.size();
  MatrixWorkspace_sptr visualws = boost::dynamic_pointer_cast<MatrixWorkspace>(
      WorkspaceFactory::Instance().create("Workspace2D", 4, sizex, sizey));
  for (size_t i = 0; i < sizex; ++i) {
    for (size_t j = 0; j < 4; ++j) {
      visualws->dataX(j)[i] = domain[i];
    }
  }
  for (size_t i = 0; i < sizey; ++i) {
    visualws->dataY(0)[i] = values[i];
    visualws->dataY(1)[i] = m_dataWS->readY(m_wsIndex)[i] - values[i];
    visualws->dataY(2)[i] = posnoisetolerance;
    visualws->dataY(3)[i] = -negnoisetolerance;
  }
  setProperty("UserBackgroundWorkspace", visualws);

  // Filter for background
  std::vector<double> vecx, vecy, vece;
  for (size_t i = 0; i < domain.size(); ++i) {
    // double y = m_dataWS->readY(m_wsIndex)[i];
    // double theoryy = values[i]; y-theoryy
    double purey = visualws->readY(1)[i];
    if (purey < posnoisetolerance && purey > -negnoisetolerance) {
      // Selected
      double x = domain[i];
      double y = m_dataWS->readY(m_wsIndex)[i];
      double e = m_dataWS->readE(m_wsIndex)[i];
      vecx.push_back(x);
      vecy.push_back(y);
      vece.push_back(e);
    }
  }
  g_log.information() << "Found " << vecx.size() << " background points out of "
                      << m_dataWS->readX(m_wsIndex).size()
                      << " total data points. "
                      << "\n";

  // Build new workspace for OutputWorkspace
  size_t nspec = 3;
  Workspace2D_sptr outws =
      boost::dynamic_pointer_cast<DataObjects::Workspace2D>(
          API::WorkspaceFactory::Instance().create("Workspace2D", nspec,
                                                   vecx.size(), vecy.size()));
  for (size_t i = 0; i < vecx.size(); ++i) {
    for (size_t j = 0; j < nspec; ++j)
      outws->dataX(j)[i] = vecx[i];
    outws->dataY(0)[i] = vecy[i];
    outws->dataE(0)[i] = vece[i];
  }

  return outws;
}
Beispiel #10
0
/** Select background automatically
 */
DataObjects::Workspace2D_sptr
ProcessBackground::autoBackgroundSelection(Workspace2D_sptr bkgdWS) {
  // Get background type and create bakground function
  BackgroundFunction_sptr bkgdfunction = createBackgroundFunction(m_bkgdType);

  int bkgdorder = getProperty("BackgroundOrder");
  if (bkgdorder == 0)
    g_log.warning("(Input) background function order is 0.  It might not be "
                  "able to give a good estimation.");

  bkgdfunction->setAttributeValue("n", bkgdorder);
  bkgdfunction->initialize();

  g_log.information() << "Input background points has "
                      << bkgdWS->readX(0).size() << " data points for fit "
                      << bkgdorder << "-th order " << bkgdfunction->name()
                      << " (background) function" << bkgdfunction->asString()
                      << "\n";

  // Fit input (a few) background pionts to get initial guess
  API::IAlgorithm_sptr fit;
  try {
    fit = this->createChildAlgorithm("Fit", 0.0, 0.2, true);
  } catch (Exception::NotFoundError &) {
    g_log.error() << "Requires CurveFitting library." << std::endl;
    throw;
  }

  double startx = m_lowerBound;
  double endx = m_upperBound;
  fit->setProperty("Function",
                   boost::dynamic_pointer_cast<API::IFunction>(bkgdfunction));
  fit->setProperty("InputWorkspace", bkgdWS);
  fit->setProperty("WorkspaceIndex", 0);
  fit->setProperty("MaxIterations", 500);
  fit->setProperty("StartX", startx);
  fit->setProperty("EndX", endx);
  fit->setProperty("Minimizer", "Levenberg-Marquardt");
  fit->setProperty("CostFunction", "Least squares");

  fit->executeAsChildAlg();

  // Get fit result
  // a) Status
  std::string fitStatus = fit->getProperty("OutputStatus");
  bool allowedfailure = (fitStatus.find("cannot") < fitStatus.size()) &&
                        (fitStatus.find("tolerance") < fitStatus.size());
  if (fitStatus.compare("success") != 0 && !allowedfailure) {
    g_log.error() << "ProcessBackground: Fit Status = " << fitStatus
                  << ".  Not to update fit result" << std::endl;
    throw std::runtime_error("Bad Fit");
  }

  // b) check that chi2 got better
  const double chi2 = fit->getProperty("OutputChi2overDoF");
  g_log.information() << "Fit background: Fit Status = " << fitStatus
                      << ", chi2 = " << chi2 << "\n";

  // Filter and construct for the output workspace
  Workspace2D_sptr outws = filterForBackground(bkgdfunction);

  return outws;
} // END OF FUNCTION
Beispiel #11
0
/**
 * Creates and initialises a workspace with instrument definition and fills it
 * with data
 *
 * @param fileInfo information for the current file
 *
 * @param newFileNumber sequence number for the new file when added
 * into ws group
 *
 * @param buffer pre-allocated buffer to contain data values
 * @param imageY Object to set the Y data values in
 * @param imageE Object to set the E data values in
 *
 * @param parent A workspace which can be used to copy initialisation
 * information from (size/instrument def etc)
 *
 * @param loadAsRectImg if true, the new workspace will have one
 * spectrum per row and one bin per column, instead of the (default)
 * as many spectra as pixels.
 *
 * @param binSize size to rebin (1 == no re-bin == default)
 *
 * @param noiseThresh threshold for noise filtering
 *
 * @returns A newly created Workspace2D, as a shared pointer
 */
Workspace2D_sptr
LoadFITS::makeWorkspace(const FITSInfo &fileInfo, size_t &newFileNumber,
                        std::vector<char> &buffer, MantidImage &imageY,
                        MantidImage &imageE, const Workspace2D_sptr parent,
                        bool loadAsRectImg, int binSize, double noiseThresh) {
  // Create workspace (taking into account already here if rebinning is
  // going to happen)
  Workspace2D_sptr ws;
  if (!parent) {
    if (!loadAsRectImg) {
      size_t finalPixelCount = m_pixelCount / binSize * binSize;
      ws = boost::dynamic_pointer_cast<Workspace2D>(
          WorkspaceFactory::Instance().create("Workspace2D", finalPixelCount, 2,
                                              1));
    } else {
      ws = boost::dynamic_pointer_cast<Workspace2D>(
          WorkspaceFactory::Instance().create(
              "Workspace2D",
              fileInfo.axisPixelLengths[1] / binSize, // one bin per column
              fileInfo.axisPixelLengths[0] / binSize +
                  1, // one spectrum per row
              fileInfo.axisPixelLengths[0] / binSize));
    }
  } else {
    ws = boost::dynamic_pointer_cast<Workspace2D>(
        WorkspaceFactory::Instance().create(parent));
  }

  // this pixel scale property is used to set the workspace X values
  double cm_1 = getProperty("Scale");
  // amount of width units (e.g. cm) per pixel
  double cmpp = 1; // cm per pixel == bin width
  if (0.0 != cm_1)
    cmpp /= cm_1;
  cmpp *= static_cast<double>(binSize);

  if (loadAsRectImg && 1 == binSize) {
    // set data directly into workspace
    readDataToWorkspace(fileInfo, cmpp, ws, buffer);
  } else {
    readDataToImgs(fileInfo, imageY, imageE, buffer);
    doFilterNoise(noiseThresh, imageY, imageE);

    // Note this can change the sizes of the images and the number of pixels
    if (1 == binSize) {
      ws->setImageYAndE(imageY, imageE, 0, loadAsRectImg, cmpp,
                        false /* no parallel load */);

    } else {
      MantidImage rebinnedY(imageY.size() / binSize,
                            std::vector<double>(imageY[0].size() / binSize));
      MantidImage rebinnedE(imageE.size() / binSize,
                            std::vector<double>(imageE[0].size() / binSize));

      doRebin(binSize, imageY, imageE, rebinnedY, rebinnedE);
      ws->setImageYAndE(rebinnedY, rebinnedE, 0, loadAsRectImg, cmpp,
                        false /* no parallel load */);
    }
  }

  try {
    ws->setTitle(Poco::Path(fileInfo.filePath).getFileName());
  } catch (std::runtime_error &) {
    ws->setTitle(padZeros(newFileNumber, g_DIGIT_SIZE_APPEND));
  }
  ++newFileNumber;

  addAxesInfoAndLogs(ws, loadAsRectImg, fileInfo, binSize, cmpp);

  return ws;
}
  /** Construct output
   */
  Workspace2D_sptr RefinePowderInstrumentParameters2::genOutputWorkspace(FunctionDomain1DVector domain,
                                                               FunctionValues rawvalues)
  {
    // 1. Create and set up output workspace
    size_t lenx = m_dataWS->readX(m_wsIndex).size();
    size_t leny = m_dataWS->readY(m_wsIndex).size();

    Workspace2D_sptr outws = boost::dynamic_pointer_cast<Workspace2D>
        (WorkspaceFactory::Instance().create("Workspace2D", 6, lenx, leny));

    outws->getAxis(0)->setUnit("dSpacing");

    TextAxis* taxis = new TextAxis(outws->getNumberHistograms());
    taxis->setLabel(0, "Data");
    taxis->setLabel(1, "Model");
    taxis->setLabel(2, "DiffDM");
    taxis->setLabel(3, "Start");
    taxis->setLabel(4, "DiffDS");
    taxis->setLabel(5, "Zdiff");
    outws->replaceAxis(1, taxis);

    // 3. Re-calculate values
    FunctionValues funcvalues(domain);
    m_positionFunc->function(domain, funcvalues);

    // 4. Add values
    // a) X axis
    for (size_t iws = 0; iws < outws->getNumberHistograms(); ++iws)
    {
      MantidVec& vecX = outws->dataX(iws);
      for (size_t n = 0; n < lenx; ++n)
        vecX[n] = domain[n];
    }

    // b) Y axis
    const MantidVec& dataY = m_dataWS->readY(m_wsIndex);

    for (size_t i = 0; i < domain.size(); ++i)
    {
      outws->dataY(0)[i] = dataY[i];
      outws->dataY(1)[i] = funcvalues[i];
      outws->dataY(2)[i] = dataY[i] - funcvalues[i];
      outws->dataY(3)[i] = rawvalues[i];
      outws->dataY(4)[i] = dataY[i] - rawvalues[i];
    }

    // 5. Zscore
    vector<double> zscore = Kernel::getZscore(outws->readY(2));
    for (size_t i = 0; i < domain.size(); ++i)
      outws->dataY(5)[i] = zscore[i];

    return outws;
  }
  /** 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;
  }
Beispiel #14
0
void TOFSANSResolution::exec()
{
  Workspace2D_sptr iqWS = getProperty("InputWorkspace");
  MatrixWorkspace_sptr reducedWS = getProperty("ReducedWorkspace");
  EventWorkspace_sptr reducedEventWS = boost::dynamic_pointer_cast<EventWorkspace>(reducedWS);
  const double min_wl = getProperty("MinWavelength");
  const double max_wl = getProperty("MaxWavelength");
  double pixel_size_x = getProperty("PixelSizeX");
  double pixel_size_y = getProperty("PixelSizeY");
  double R1 = getProperty("SourceApertureRadius");
  double R2 = getProperty("SampleApertureRadius");
  // Convert to meters
  pixel_size_x /= 1000.0;
  pixel_size_y /= 1000.0;
  R1 /= 1000.0;
  R2 /= 1000.0;
  wl_resolution = getProperty("DeltaT");

  // Although we want the 'ReducedWorkspace' to be an event workspace for this algorithm to do
  // anything, we don't want the algorithm to 'fail' if it isn't
  if (!reducedEventWS)
  {
    g_log.warning() << "An Event Workspace is needed to compute dQ. Calculation skipped." << std::endl;
    return;
  }

  // Calculate the output binning
  const std::vector<double> binParams = getProperty("OutputBinning");

  // Count histogram for normalization
  const int xLength = static_cast<int>(iqWS->readX(0).size());
  std::vector<double> XNorm(xLength-1, 0.0);

  // Create workspaces with each component of the resolution for debugging purposes
  MatrixWorkspace_sptr thetaWS = WorkspaceFactory::Instance().create(iqWS);
  declareProperty(new WorkspaceProperty<>("ThetaError","",Direction::Output));
  setPropertyValue("ThetaError","__"+iqWS->getName()+"_theta_error");
  setProperty("ThetaError",thetaWS);
  thetaWS->setX(0,iqWS->readX(0));
  MantidVec& ThetaY = thetaWS->dataY(0);

  MatrixWorkspace_sptr tofWS = WorkspaceFactory::Instance().create(iqWS);
  declareProperty(new WorkspaceProperty<>("TOFError","",Direction::Output));
  setPropertyValue("TOFError","__"+iqWS->getName()+"_tof_error");
  setProperty("TOFError",tofWS);
  tofWS->setX(0,iqWS->readX(0));
  MantidVec& TOFY = tofWS->dataY(0);

  // Initialize Dq
  MantidVec& DxOut = iqWS->dataDx(0);
  for ( int i = 0; i<xLength-1; i++ ) DxOut[i] = 0.0;

  const V3D samplePos = reducedWS->getInstrument()->getSample()->getPos();
  const V3D sourcePos = reducedWS->getInstrument()->getSource()->getPos();
  const V3D SSD = samplePos - sourcePos;
  const double L1 = SSD.norm();

  const int numberOfSpectra = static_cast<int>(reducedWS->getNumberHistograms());
  Progress progress(this,0.0,1.0,numberOfSpectra);

  PARALLEL_FOR2(reducedEventWS, iqWS)
  for (int i = 0; i < numberOfSpectra; i++)
  {
    PARALLEL_START_INTERUPT_REGION
    IDetector_const_sptr det;
    try {
      det = reducedEventWS->getDetector(i);
    } catch (Exception::NotFoundError&) {
      g_log.warning() << "Spectrum index " << i << " has no detector assigned to it - discarding" << std::endl;
      // Catch if no detector. Next line tests whether this happened - test placed
      // outside here because Mac Intel compiler doesn't like 'continue' in a catch
      // in an openmp block.
    }
    // If no detector found or if it's masked or a monitor, skip onto the next spectrum
    if ( !det || det->isMonitor() || det->isMasked() ) continue;

    // Get the flight path from the sample to the detector pixel
    const V3D scattered_flight_path = det->getPos() - samplePos;

    // Multiplicative factor to go from lambda to Q
    // Don't get fooled by the function name...
    const double theta = reducedEventWS->detectorTwoTheta(det);
    const double factor = 4.0 * M_PI * sin( theta/2.0 );

    EventList& el = reducedEventWS->getEventList(i);
    el.switchTo(WEIGHTED);

    std::vector<WeightedEvent>::iterator itev;
    std::vector<WeightedEvent>::iterator itev_end = el.getWeightedEvents().end();

    for (itev = el.getWeightedEvents().begin(); itev != itev_end; ++itev)
    {
      if ( itev->m_weight != itev->m_weight ) continue;
      if (std::abs(itev->m_weight) == std::numeric_limits<double>::infinity()) continue;
      if ( !isEmpty(min_wl) && itev->m_tof < min_wl ) continue;
      if ( !isEmpty(max_wl) && itev->m_tof > max_wl ) continue;

      const double q = factor/itev->m_tof;
      int iq = 0;

      // Bin assignment depends on whether we have log or linear bins
      if(binParams[1]>0.0)
      {
        iq = (int)floor( (q-binParams[0])/ binParams[1] );
      } else {
        iq = (int)floor(log(q/binParams[0])/log(1.0-binParams[1]));
      }

      const double L2 = scattered_flight_path.norm();
      const double src_to_pixel = L1+L2;
      const double dTheta2 = ( 3.0*R1*R1/(L1*L1) + 3.0*R2*R2*src_to_pixel*src_to_pixel/(L1*L1*L2*L2)
            + 2.0*(pixel_size_x*pixel_size_x+pixel_size_y*pixel_size_y)/(L2*L2) )/12.0;

      const double dwl_over_wl = 3.9560*getTOFResolution(itev->m_tof)/(1000.0*(L1+L2)*itev->m_tof);
      const double dq_over_q = std::sqrt(dTheta2/(theta*theta)+dwl_over_wl*dwl_over_wl);

      PARALLEL_CRITICAL(iq)    /* Write to shared memory - must protect */
      if (iq>=0 && iq < xLength-1 && !dq_over_q!=dq_over_q && dq_over_q>0)
      {
        DxOut[iq] += q*dq_over_q*itev->m_weight;
        XNorm[iq] += itev->m_weight;
        TOFY[iq] += q*std::fabs(dwl_over_wl)*itev->m_weight;
        ThetaY[iq] += q*std::sqrt(dTheta2)/theta*itev->m_weight;
      }
    }

    progress.report("Computing Q resolution");
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION
  // Normalize according to the chosen weighting scheme
  for ( int i = 0; i<xLength-1; i++ )
  {
    if (XNorm[i]>0)
    {
      DxOut[i] /= XNorm[i];
      TOFY[i] /= XNorm[i];
      ThetaY[i] /= XNorm[i];
    }
  }
}
Beispiel #15
0
    /**
    * Executes the algorithm.
    * Saves the workspace specified by the user to the VTK XML format
    */
    void SaveVTK::exec()
    {
      std::string filename = getProperty("Filename");
      g_log.debug() << "Parameters: Filename='" << filename << "'" << std::endl;
      //add extension
      filename += ".vtu";

      MatrixWorkspace_sptr inputWorkspace = getProperty("InputWorkspace");
      if( !inputWorkspace )
      {
        g_log.error("Failed to retrieve inputWorkspace.");
        throw Exception::NullPointerException("SaveVTK::exec()", "inputWorkspace");
      }

      checkOptionalProperties();

      //Open file for writing
      std::ofstream outVTP(filename.c_str());
      if( !outVTP )
      {
        g_log.error("Failed to open file: " + filename);
        throw Exception::FileError("Failed to open file ", filename);
      }

      // First write document level XML header
      outVTP << "<?xml version=\"1.0\"?>\n"
        "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n"
        "<UnstructuredGrid>\n";

      const std::string workspaceID = inputWorkspace->id();    
      if( workspaceID.find("Workspace2D") != std::string::npos )
      {
        const Workspace2D_sptr localWorkspace = 
          boost::dynamic_pointer_cast<Workspace2D>(inputWorkspace);
        //      const size_t numberOfHist = localWorkspace->getNumberHistograms();

        //Write out whole range
        bool xMin(m_Xmin > 0.0), xMax(m_Xmax > 0.0);
        Progress prog(this,0.0,1.0,97);
        if( !xMin && !xMax )
        {
          for( int hNum = 2; hNum < 100; ++hNum )
          {
            writeVTKPiece(outVTP, localWorkspace->dataX(hNum), localWorkspace->dataY(hNum), 
              localWorkspace->dataE(hNum), hNum);
            prog.report();
          }
        }
        else
        {
          for( int hNum = 2; hNum < 100; ++hNum )
          {
            std::vector<double> xValue, yValue, errors;
            std::vector<double>::size_type nVals(localWorkspace->dataY(hNum).size());
            for( int i = 0; i < (int)nVals; ++i )
            {
              if( xMin && localWorkspace->dataX(hNum)[i] < m_Xmin ) continue;
              if( xMax && localWorkspace->dataX(hNum)[i+1] > m_Xmax)
              {
                xValue.push_back(localWorkspace->dataX(hNum)[i]);
                break;
              }
              xValue.push_back(localWorkspace->dataX(hNum)[i]);
              if( i == (int)nVals - 1 )
              {
                xValue.push_back(localWorkspace->dataX(hNum)[i+1]);
              } 	    
              yValue.push_back(localWorkspace->dataY(hNum)[i]);
              errors.push_back(localWorkspace->dataE(hNum)[i]);
            }
            //sanity check
            assert( (int)xValue.size() == (int)yValue.size() + 1 );

            writeVTKPiece(outVTP, xValue, yValue, errors, hNum);
            prog.report();
          }
        }
      }
      else
      {
        outVTP.close();
        Poco::File(filename).remove();
        throw Exception::NotImplementedError("SaveVTK only implemented for Workspace2D\n");
      }

      // Final XML end block tags
      outVTP << "</UnstructuredGrid>\n</VTKFile>\n";
      outVTP.close();
    }
Beispiel #16
0
void PoldiPeakSearch::exec() {
  g_log.information() << "PoldiPeakSearch:" << std::endl;

  Workspace2D_sptr correlationWorkspace = getProperty("InputWorkspace");
  MantidVec correlationQValues = correlationWorkspace->readX(0);
  MantidVec correlatedCounts = correlationWorkspace->readY(0);
  g_log.information() << "   Auto-correlation data read." << std::endl;

  Unit_sptr xUnit = correlationWorkspace->getAxis(0)->unit();

  if (xUnit->caption() == "") {
    g_log.information()
        << "   Workspace does not have unit, defaulting to MomentumTransfer."
        << std::endl;

    xUnit = UnitFactory::Instance().create("MomentumTransfer");
  } else {
    g_log.information() << "   Unit of workspace is " << xUnit->caption() << "."
                        << std::endl;
  }

  setMinimumDistance(getProperty("MinimumPeakSeparation"));
  setMinimumPeakHeight(getProperty("MinimumPeakHeight"));
  setMaximumPeakNumber(getProperty("MaximumPeakNumber"));

  if (m_doubleMinimumDistance > static_cast<int>(correlatedCounts.size())) {
    throw(std::runtime_error("MinimumPeakSeparation is smaller than number of "
                             "spectrum points - no peaks possible."));
  }

  g_log.information() << "   Parameters set." << std::endl;

  MantidVec summedNeighborCounts = getNeighborSums(correlatedCounts);
  g_log.information() << "   Neighboring counts summed, contains "
                      << summedNeighborCounts.size() << " data points."
                      << std::endl;

  std::list<MantidVec::const_iterator> peakPositionsSummed =
      findPeaks(summedNeighborCounts.begin(), summedNeighborCounts.end());
  g_log.information() << "   Peaks detected in summed spectrum: "
                      << peakPositionsSummed.size() << std::endl;

  /* This step is required because peaks are actually searched in the
   * "sum-of-neighbors"-spectrum.
   * The mapping removes the offset from the peak position which results from
   * different beginning
   * of this vector compared to the original correlation counts.
   */
  std::list<MantidVec::const_iterator> peakPositionsCorrelation =
      mapPeakPositionsToCorrelationData(peakPositionsSummed,
                                        summedNeighborCounts.begin(),
                                        correlatedCounts.begin());
  g_log.information() << "   Peak positions transformed to original spectrum."
                      << std::endl;

  /* Since intensities are required for filtering, they are extracted from the
   * original count data,
   * along with the Q-values.
   */
  std::vector<PoldiPeak_sptr> peakCoordinates =
      getPeaks(correlatedCounts.begin(), correlatedCounts.end(),
               peakPositionsCorrelation, correlationQValues, xUnit);
  g_log.information()
      << "   Extracted peak positions in Q and intensity guesses." << std::endl;

  UncertainValue backgroundWithSigma =
      getBackgroundWithSigma(peakPositionsCorrelation, correlatedCounts);
  g_log.information() << "   Calculated average background and deviation: "
                      << UncertainValueIO::toString(backgroundWithSigma)
                      << std::endl;

  if ((*getProperty("MinimumPeakHeight")).isDefault()) {
    setMinimumPeakHeight(minimumPeakHeightFromBackground(backgroundWithSigma));
  }

  std::vector<PoldiPeak_sptr> intensityFilteredPeaks(peakCoordinates.size());
  auto newEnd = std::remove_copy_if(
      peakCoordinates.begin(), peakCoordinates.end(),
      intensityFilteredPeaks.begin(),
      boost::bind(&PoldiPeakSearch::isLessThanMinimum, this, _1));
  intensityFilteredPeaks.resize(
      std::distance(intensityFilteredPeaks.begin(), newEnd));

  g_log.information() << "   Peaks above minimum intensity ("
                      << m_minimumPeakHeight
                      << "): " << intensityFilteredPeaks.size() << std::endl;

  std::sort(intensityFilteredPeaks.begin(), intensityFilteredPeaks.end(),
            boost::bind<bool>(&PoldiPeak::greaterThan, _1, _2,
                              &PoldiPeak::intensity));

  for (std::vector<PoldiPeak_sptr>::const_iterator peak =
           intensityFilteredPeaks.begin();
       peak != intensityFilteredPeaks.end(); ++peak) {
    m_peaks->addPeak(*peak);
  }

  /* The derived background error is set as error in the workspace containing
   * correlation data, so it may be used as weights for peak fitting later on.
   */
  setErrorsOnWorkspace(correlationWorkspace, backgroundWithSigma.error());

  setProperty("OutputWorkspace", m_peaks->asTableWorkspace());
}
Beispiel #17
0
  /** Select background automatically
   */
  DataObjects::Workspace2D_sptr ProcessBackground::autoBackgroundSelection(Workspace2D_sptr bkgdWS)
  {
    // Get background type and create bakground function
    BackgroundFunction_sptr bkgdfunction = createBackgroundFunction(m_bkgdType);

    int bkgdorder = getProperty("BackgroundOrder");
    bkgdfunction->setAttributeValue("n", bkgdorder);

    g_log.debug() << "DBx622 Background Workspace has " << bkgdWS->readX(0).size()
                  << " data points." << std::endl;

    // Fit input (a few) background pionts to get initial guess
    API::IAlgorithm_sptr fit;
    try
    {
      fit = this->createChildAlgorithm("Fit", 0.0, 0.2, true);
    }
    catch (Exception::NotFoundError &)
    {
      g_log.error() << "Requires CurveFitting library." << std::endl;
      throw;
    }

    double startx = m_lowerBound;
    double endx = m_upperBound;
    fit->setProperty("Function", boost::dynamic_pointer_cast<API::IFunction>(bkgdfunction));
    fit->setProperty("InputWorkspace", bkgdWS);
    fit->setProperty("WorkspaceIndex", 0);
    fit->setProperty("MaxIterations", 500);
    fit->setProperty("StartX", startx);
    fit->setProperty("EndX", endx);
    fit->setProperty("Minimizer", "Levenberg-Marquardt");
    fit->setProperty("CostFunction", "Least squares");

    fit->executeAsChildAlg();

    // Get fit result
    // a) Status
    std::string fitStatus = fit->getProperty("OutputStatus");
    bool allowedfailure = (fitStatus.find("cannot") < fitStatus.size()) &&
        (fitStatus.find("tolerance") < fitStatus.size());
    if (fitStatus.compare("success") != 0 && !allowedfailure)
    {
      g_log.error() << "ProcessBackground: Fit Status = " << fitStatus
                    << ".  Not to update fit result" << std::endl;
      throw std::runtime_error("Bad Fit");
    }

    // b) check that chi2 got better
    const double chi2 = fit->getProperty("OutputChi2overDoF");
    g_log.information() << "Fit background: Fit Status = " << fitStatus << ", chi2 = "
                        << chi2 << "\n";

    // c) get out the parameter names
    API::IFunction_sptr func = fit->getProperty("Function");
    /* Comment out as not being used
    std::vector<std::string> parnames = func->getParameterNames();
    std::map<std::string, double> parvalues;
    for (size_t iname = 0; iname < parnames.size(); ++iname)
    {
      double value = func->getParameter(parnames[iname]);
      parvalues.insert(std::make_pair(parnames[iname], value));
    }
    DataObject::Workspace2D_const_sptr theorybackground = AnalysisDataService::Instance().retrieve(wsname);
    */

    // Filter and construct for the output workspace
    Workspace2D_sptr outws = filterForBackground(bkgdfunction);

    return outws;
  } // END OF FUNCTION
/** Output distributions in order for a better understanding of the log
  * Result is written to a Workspace2D
  *
  * @param timevec  :: a vector of time stamps
  * @param stepsize :: resolution of the delta time count bin
  */
Workspace2D_sptr GetTimeSeriesLogInformation::calDistributions(
    std::vector<Kernel::DateAndTime> timevec, double stepsize) {
  // 1. Get a vector of delta T (in unit of seconds)
  double dtmin = static_cast<double>(timevec.back().totalNanoseconds() -
                                     timevec[0].totalNanoseconds()) *
                 1.0E-9;
  double dtmax = 0.0;

  vector<double> vecdt(timevec.size() - 1, 0.0);
  for (size_t i = 1; i < timevec.size(); ++i) {
    vecdt[i - 1] = static_cast<double>(timevec[i].totalNanoseconds() -
                                       timevec[i - 1].totalNanoseconds()) *
                   1.0E-9;
    if (vecdt[i - 1] < dtmin)
      dtmin = vecdt[i - 1];
    else if (vecdt[i - 1] > dtmax)
      dtmax = vecdt[i - 1];
  }

  // 2. Create a vector of counts
  size_t numbins;
  if (m_ignoreNegativeTime && dtmin < 0) {
    numbins = static_cast<size_t>(ceil((dtmax) / stepsize)) + 2;
  } else {
    numbins = static_cast<size_t>(ceil((dtmax - dtmin) / stepsize)) + 2;
  }

  g_log.notice() << "Distribution has " << numbins << " bins.  Delta T = ("
                 << dtmin << ", " << dtmax << ")\n";

  Workspace2D_sptr distws = boost::dynamic_pointer_cast<Workspace2D>(
      API::WorkspaceFactory::Instance().create("Workspace2D", 1, numbins,
                                               numbins));
  auto &vecDeltaT = distws->mutableX(0);
  auto &vecCount = distws->mutableY(0);

  double countmin = dtmin;
  if (m_ignoreNegativeTime && dtmin < 0)
    countmin = 0;

  for (size_t i = 0; i < numbins; ++i)
    vecDeltaT[i] = countmin + (static_cast<double>(i) - 1) * stepsize;
  for (size_t i = 0; i < numbins; ++i)
    vecCount[i] = 0;

  // 3. Count
  for (double dt : vecdt) {
    int index;
    if (dt < 0 && m_ignoreNegativeTime) {
      index = 0;
    } else {
      auto viter = lower_bound(vecDeltaT.begin(), vecDeltaT.end(), dt);
      index = static_cast<int>(viter - vecDeltaT.begin());
      if (index >= static_cast<int>(vecDeltaT.size())) {
        // Out of upper boundary
        g_log.error() << "Find index = " << index
                      << " > vecX.size = " << vecDeltaT.size() << ".\n";
      } else if (dt < vecDeltaT[index]) {
        --index;
      }

      if (index < 0)
        throw runtime_error("How can this happen.");
    }
    vecCount[index] += 1;
  }

  return distws;
}
Beispiel #19
0
/**
 * Add information to the workspace being loaded: labels, units, logs related to
 * the image size, etc.
 *
 * @param ws workspace to manipulate
 *
 * @param loadAsRectImg if true, the workspace has one spectrum per
 * row and one bin per column
 *
 * @param fileInfo information for the current file
 *
 * @param binSize size to rebin (1 == no re-bin == default)
 *
 * @param cmpp centimeters per pixel (already taking into account
 * possible rebinning)
 */
void LoadFITS::addAxesInfoAndLogs(Workspace2D_sptr ws, bool loadAsRectImg,
                                  const FITSInfo &fileInfo, int binSize,
                                  double cmpp) {
  // add axes
  size_t width = fileInfo.axisPixelLengths[0] / binSize;
  size_t height = fileInfo.axisPixelLengths[1] / binSize;
  if (loadAsRectImg) {
    // width/X axis
    auto axw = new Mantid::API::NumericAxis(width + 1);
    axw->title() = "width";
    for (size_t i = 0; i < width + 1; i++) {
      axw->setValue(i, static_cast<double>(i) * cmpp);
    }
    ws->replaceAxis(0, axw);
    // "cm" width label unit
    boost::shared_ptr<Kernel::Units::Label> unitLbl =
        boost::dynamic_pointer_cast<Kernel::Units::Label>(
            UnitFactory::Instance().create("Label"));
    unitLbl->setLabel("width", "cm");
    ws->getAxis(0)->unit() = unitLbl;

    // height/Y axis
    auto axh = new Mantid::API::NumericAxis(height);
    axh->title() = "height";
    for (size_t i = 0; i < height; i++) {
      axh->setValue(i, static_cast<double>(i) * cmpp);
    }
    ws->replaceAxis(1, axh);
    // "cm" height label unit
    unitLbl = boost::dynamic_pointer_cast<Kernel::Units::Label>(
        UnitFactory::Instance().create("Label"));
    unitLbl->setLabel("height", "cm");
    ws->getAxis(1)->unit() = unitLbl;

    ws->setDistribution(true);
  } else {
    // TODO: what to do when loading 1pixel - 1 spectrum?
  }
  ws->setYUnitLabel("brightness");

  // Add all header info to log.
  for (const auto &headerKey : fileInfo.headerKeys) {
    ws->mutableRun().removeLogData(headerKey.first, true);
    ws->mutableRun().addLogData(
        new PropertyWithValue<std::string>(headerKey.first, headerKey.second));
  }

  // Add rotational data to log. Clear first from copied WS
  auto it = fileInfo.headerKeys.find(m_sampleRotation);
  ws->mutableRun().removeLogData("Rotation", true);
  if (fileInfo.headerKeys.end() != it) {
    double rot = boost::lexical_cast<double>(it->second);
    if (rot >= 0) {
      ws->mutableRun().addLogData(
          new PropertyWithValue<double>("Rotation", rot));
    }
  }

  // Add axis information to log. Clear first from copied WS
  ws->mutableRun().removeLogData("Axis1", true);
  ws->mutableRun().addLogData(new PropertyWithValue<int>(
      "Axis1", static_cast<int>(fileInfo.axisPixelLengths[0])));
  ws->mutableRun().removeLogData("Axis2", true);
  ws->mutableRun().addLogData(new PropertyWithValue<int>(
      "Axis2", static_cast<int>(fileInfo.axisPixelLengths[1])));

  // Add image key data to log. Clear first from copied WS
  ws->mutableRun().removeLogData("ImageKey", true);
  ws->mutableRun().addLogData(
      new PropertyWithValue<std::string>("ImageKey", fileInfo.imageKey));
}