void EnggDiffFittingModel::mergeTables(
    const API::ITableWorkspace_sptr tableToCopy,
    API::ITableWorkspace_sptr targetTable) const {
  for (size_t i = 0; i < tableToCopy->rowCount(); ++i) {
    API::TableRow rowToCopy = tableToCopy->getRow(i);
    API::TableRow newRow = targetTable->appendRow();

    for (size_t j = 0; j < tableToCopy->columnCount(); ++j) {
      double valueToCopy;
      rowToCopy >> valueToCopy;
      newRow << valueToCopy;
    }
  }
}
size_t LatticeDomainCreator::getDomainSize() const {
  API::IPeaksWorkspace_sptr peaksWorkspace =
      boost::dynamic_pointer_cast<IPeaksWorkspace>(m_workspace);
  if (peaksWorkspace) {
    return peaksWorkspace->getNumberPeaks();
  }

  API::ITableWorkspace_sptr tableWorkspace =
      boost::dynamic_pointer_cast<ITableWorkspace>(m_workspace);
  if (tableWorkspace) {
    return tableWorkspace->rowCount();
  }

  return 0;
}
/* This function fills in a list of the row numbers starting 0 of the parameters
   in the table workspace, so one can find the position in a column of
   the value of the given parameter.
*/
void LoadFullprofResolution::getTableRowNumbers(
    const API::ITableWorkspace_sptr &tablews,
    std::map<std::string, size_t> &parammap) {
  parammap.clear();

  size_t numrows = tablews->rowCount();
  for (size_t i = 0; i < numrows; ++i) {
    TableRow row = tablews->getRow(i);
    std::string name;
    row >> name;
    parammap.emplace(name, i);
  }

  return;
}
Exemple #4
0
/** This method saves investigations  to a table workspace
 *  @param investigations :: a vector containing investigation data
 *  @param outputws :: shared pointer to output workspace
 */
void CICatHelper::saveInvestigations(
    const std::vector<ns1__investigation *> &investigations,
    API::ITableWorkspace_sptr &outputws) {
  try {
    std::vector<ns1__investigation *>::const_iterator citr;
    for (citr = investigations.begin(); citr != investigations.end(); ++citr) {
      API::TableRow t = outputws->appendRow();

      std::string id = std::to_string(*(*citr)->id);

      savetoTableWorkspace(&id, t);
      savetoTableWorkspace((*citr)->facility, t);
      savetoTableWorkspace((*citr)->title, t);
      savetoTableWorkspace((*citr)->instrument, t);
      savetoTableWorkspace((*citr)->invParamValue, t);

      std::string startDate = std::to_string(*(*citr)->invStartDate);
      savetoTableWorkspace(&startDate, t);

      std::string endDate = std::to_string(*(*citr)->invEndDate);
      savetoTableWorkspace(&endDate, t);

      std::string sessionID = m_session->getSessionId();
      savetoTableWorkspace(&sessionID, t);
    }
  } catch (std::runtime_error &) {
    throw std::runtime_error(
        "Error when saving  the ICat Search Results data to Workspace");
  }
}
/** Fits each spectrum in the workspace to f(x) = A * sin( w * x + p)
* @param ws :: [input] The workspace to fit
* @param freq :: [input] Hint for the frequency (w)
* @param groupName :: [input] The name of the output workspace group
* @param resTab :: [output] Table workspace storing the asymmetries and phases
* @param resGroup :: [output] Workspace group storing the fitting results
*/
void CalMuonDetectorPhases::fitWorkspace(const API::MatrixWorkspace_sptr &ws,
                                         double freq, std::string groupName,
                                         API::ITableWorkspace_sptr &resTab,
                                         API::WorkspaceGroup_sptr &resGroup) {

  int nhist = static_cast<int>(ws->getNumberHistograms());

  // Create the fitting function f(x) = A * sin ( w * x + p )
  // The same function and initial parameters are used for each fit
  std::string funcStr = createFittingFunction(freq, true);

  // Set up results table
  resTab->addColumn("int", "Spectrum number");
  resTab->addColumn("double", "Asymmetry");
  resTab->addColumn("double", "Phase");

  // Loop through fitting all spectra individually
  const static std::string success = "success";
  for (int wsIndex = 0; wsIndex < nhist; wsIndex++) {
    reportProgress(wsIndex, nhist);
    auto fit = createChildAlgorithm("Fit");
    fit->initialize();
    fit->setPropertyValue("Function", funcStr);
    fit->setProperty("InputWorkspace", ws);
    fit->setProperty("WorkspaceIndex", wsIndex);
    fit->setProperty("CreateOutput", true);
    fit->setPropertyValue("Output", groupName);
    fit->execute();

    std::string status = fit->getProperty("OutputStatus");
    if (!fit->isExecuted() || status != success) {
      std::ostringstream error;
      error << "Fit failed for spectrum at workspace index " << wsIndex;
      error << ": " << status;
      throw std::runtime_error(error.str());
    }

    API::MatrixWorkspace_sptr fitOut = fit->getProperty("OutputWorkspace");
    resGroup->addWorkspace(fitOut);
    API::ITableWorkspace_sptr tab = fit->getProperty("OutputParameters");
    // Now we have our fitting results stored in tab
    // but we need to extract the relevant information, i.e.
    // the detector phases (parameter 'p') and asymmetries ('A')
    const auto &spectrum = ws->getSpectrum(static_cast<size_t>(wsIndex));
    extractDetectorInfo(tab, resTab, spectrum.getSpectrumNo());
  }
}
Exemple #6
0
/**
   Read from the instrument file the dead wires and store the information in a TableWorkspace.
   If asked, the dead wires are removed from the data set.

   @param localWorkspace :: input raw data workspace, containing the information about the instrument
   @param outputws :: input dead wire liste workspace
  */
void PoldiRemoveDeadWires::runExcludWires3
(
    DataObjects::Workspace2D_sptr &localWorkspace,
    API::ITableWorkspace_sptr &outputws
)
{
    outputws->addColumn("int","DeadWires");

    boost::shared_ptr<const Mantid::Geometry::IComponent> comp = localWorkspace->getInstrument()->getComponentByName("holder");
    boost::shared_ptr<const Mantid::Geometry::ICompAssembly> bank = boost::dynamic_pointer_cast<const Mantid::Geometry::ICompAssembly>(comp);
    if (bank)
    {
        // Get a vector of children (recursively)
        std::vector<boost::shared_ptr<const Mantid::Geometry::IComponent> > children;
        bank->getChildren(children, true);

        std::vector<double> defaultDeadWires;
        int ewLine = 0;

        for (unsigned int it = 0; it < children.size(); ++it)
        {
            string wireName = children.at(it)->getName();
            std::vector<boost::shared_ptr<const Mantid::Geometry::IComponent> > tyty =
                localWorkspace.get()->getInstrument().get()->getAllComponentsWithName(wireName);

            std::vector<double> tempWire = tyty[0]->getNumberParameter("excluded");
            if(tempWire.size()>0) {
                int val = (int)tempWire[0];
                g_log.debug() << "_poldi : dead wires :" << val <<  std::endl;
                defaultDeadWires.push_back(val);
                for(unsigned int j=0; j<m_channelsPerSpectrum; j++) {
                    localWorkspace->maskBin(val-1,j,1);
                }
                ewLine++;


                TableRow t = outputws->appendRow();
                t << val ;

            }
        }
        g_log.information() << "_poldi : dead wires set to 0 (nb:" << ewLine << ")" <<  std::endl;
        setProperty("nbExcludedWires",ewLine);
    } else {
        g_log.information() << "_poldi : no dead wire removed" <<  std::endl;
    }
}
Exemple #7
0
/** This method saves the search response( investigations )data to a table
 * workspace
 *  @param response :: const reference to response object
 *  @param outputws :: shared pointer to output workspace
 */
void CICatHelper::saveSearchRessults(
    const ns1__searchByAdvancedPaginationResponse &response,
    API::ITableWorkspace_sptr &outputws) {
  if (outputws->getColumnNames().empty()) {
    outputws->addColumn("str", "Investigation id");
    outputws->addColumn("str", "Facility");
    outputws->addColumn("str", "Title");
    outputws->addColumn("str", "Instrument");
    outputws->addColumn("str", "Run range");
    outputws->addColumn("str", "Start date");
    outputws->addColumn("str", "End date");
    outputws->addColumn("str", "SessionID");
  }
  saveInvestigations(response.return_, outputws);
}
void SaveDiffFittingAscii::writeData(const API::ITableWorkspace_sptr workspace,
                                     std::ofstream &file,
                                     const size_t columnSize) {

  for (size_t rowIndex = 0; rowIndex < workspace->rowCount(); ++rowIndex) {
    TableRow row = workspace->getRow(rowIndex);
    for (size_t columnIndex = 0; columnIndex < columnSize; columnIndex++) {

      const auto row_str =
          boost::lexical_cast<std::string>(row.Double(columnIndex));
      g_log.debug() << row_str << std::endl;

      if (columnIndex == columnSize - 1)
        writeVal(row_str, file, true);
      else
        writeVal(row_str, file, false);
    }
  }
}
/**
 * Fit the asymmetry and return the frequency found.
 * Starting value for the frequency is taken from the hint.
 * If the fit fails, return the initial hint.
 * @param wsAsym :: [input] Workspace with asymmetry to fit
 * @return :: Frequency found from fit
 */
double CalMuonDetectorPhases::fitFrequencyFromAsymmetry(
    const API::MatrixWorkspace_sptr &wsAsym) {
  // Starting value for frequency is hint
  double hint = getFrequencyHint();
  std::string funcStr = createFittingFunction(hint, false);
  double frequency = hint;

  std::string fitStatus = "success";
  try {
    auto func = API::FunctionFactory::Instance().createInitialized(funcStr);
    auto fit = createChildAlgorithm("Fit");
    fit->setProperty("Function", func);
    fit->setProperty("InputWorkspace", wsAsym);
    fit->setProperty("WorkspaceIndex", 0);
    fit->setProperty("CreateOutput", true);
    fit->setProperty("OutputParametersOnly", true);
    fit->setProperty("Output", "__Invisible");
    fit->executeAsChildAlg();
    fitStatus = fit->getPropertyValue("OutputStatus");
    if (fitStatus == "success") {
      API::ITableWorkspace_sptr params = fit->getProperty("OutputParameters");
      const size_t rows = params->rowCount();
      static size_t colName(0), colValue(1);
      for (size_t iRow = 0; iRow < rows; iRow++) {
        if (params->cell<std::string>(iRow, colName) == "w") {
          frequency = params->cell<double>(iRow, colValue);
          break;
        }
      }
    }
  } catch (const std::exception &e) {
    // Report fit failure to user
    fitStatus = e.what();
  }
  if (fitStatus != "success") { // Either failed, or threw an exception
    std::ostringstream message;
    message << "Fit failed (" << fitStatus << "), using omega hint = " << hint;
    g_log.error(message.str());
  }
  return frequency;
}
/** Extracts detector asymmetries and phases from fitting results
* and adds a new row to the results table with them
* @param paramTab :: [input] Output parameter table resulting from the fit
* @param resultsTab :: [input] Results table to update with a new row
* @param spectrumNumber :: [input] Spectrum number
*/
void CalMuonDetectorPhases::extractDetectorInfo(
    const API::ITableWorkspace_sptr &paramTab,
    const API::ITableWorkspace_sptr &resultsTab,
    const specnum_t spectrumNumber) {

  double asym = paramTab->Double(0, 1);
  double phase = paramTab->Double(2, 1);
  // If asym<0, take the absolute value and add \pi to phase
  // f(x) = A * sin( w * x + p) = -A * sin( w * x + p + PI)
  if (asym < 0) {
    asym = -asym;
    phase = phase + M_PI;
  }
  // Now convert phases to interval [0, 2PI)
  int factor = static_cast<int>(floor(phase / 2 / M_PI));
  if (factor) {
    phase = phase - factor * 2 * M_PI;
  }
  // Copy parameters to new row in results table
  API::TableRow row = resultsTab->appendRow();
  row << static_cast<int>(spectrumNumber) << asym << phase;
}
Exemple #11
0
/** Execute the algorithm.
 */
void CreateEPP::exec() {
  API::MatrixWorkspace_sptr inputWS =
      getProperty(PropertyNames::INPUT_WORKSPACE);
  const auto &spectrumInfo = inputWS->spectrumInfo();
  API::ITableWorkspace_sptr outputWS =
      API::WorkspaceFactory::Instance().createTable("TableWorkspace");
  addEPPColumns(outputWS);
  const double sigma = getProperty(PropertyNames::SIGMA);
  const size_t spectraCount = spectrumInfo.size();
  outputWS->setRowCount(spectraCount);
  const auto l1 = spectrumInfo.l1();
  const double EFixed = inputWS->run().getPropertyAsSingleValue("Ei");
  for (size_t i = 0; i < spectraCount; ++i) {
    const auto l2 = spectrumInfo.l2(i);
    const auto elasticTOF = Kernel::UnitConversion::run(
        "Energy", "TOF", EFixed, l1, l2, 0, Kernel::DeltaEMode::Direct, EFixed);
    outputWS->getRef<int>(ColumnNames::WS_INDEX, i) = static_cast<int>(i);
    outputWS->getRef<double>(ColumnNames::PEAK_CENTRE, i) = elasticTOF;
    outputWS->getRef<double>(ColumnNames::PEAK_CENTRE_ERR, i) = 0;
    outputWS->getRef<double>(ColumnNames::SIGMA, i) = sigma;
    outputWS->getRef<double>(ColumnNames::SIGMA_ERR, i) = 0;
    double height = 0;
    try {
      const auto elasticIndex = inputWS->binIndexOf(elasticTOF, i);
      height = inputWS->y(i)[elasticIndex];
    } catch (std::out_of_range &) {
      std::ostringstream sout;
      sout << "EPP out of TOF range for workspace index " << i
           << ". Peak height set to zero.";
      g_log.warning() << sout.str();
    }
    outputWS->getRef<double>(ColumnNames::HEIGHT, i) = height;
    outputWS->getRef<double>(ColumnNames::CHI_SQUARED, i) = 1;
    outputWS->getRef<std::string>(ColumnNames::STATUS, i) = "success";
  }
  setProperty(PropertyNames::OUTPUT_WORKSPACE, outputWS);
}
Exemple #12
0
/**
 * Saves result from "getDataFiles" to workspace.
 * @param response :: result response from the catalog.
 * @param outputws :: shared pointer to datasets
 */
void ICat4Catalog::saveDataFiles(std::vector<xsd__anyType *> response,
                                 API::ITableWorkspace_sptr &outputws) {
  if (outputws->getColumnNames().empty()) {
    // Add rows headers to the output workspace.
    outputws->addColumn("str", "Name");
    outputws->addColumn("str", "Location");
    outputws->addColumn("str", "Create Time");
    outputws->addColumn("long64", "Id");
    outputws->addColumn("long64", "File size(bytes)");
    outputws->addColumn("str", "File size");
    outputws->addColumn("str", "Description");
  }

  std::vector<xsd__anyType *>::const_iterator iter;
  for (iter = response.begin(); iter != response.end(); ++iter) {
    ns1__datafile *datafile = dynamic_cast<ns1__datafile *>(*iter);
    if (datafile) {
      API::TableRow table = outputws->appendRow();
      // Now add the relevant investigation data to the table.
      savetoTableWorkspace(datafile->name, table);
      savetoTableWorkspace(datafile->location, table);

      std::string createDate =
          formatDateTime(*datafile->createTime, "%Y-%m-%d %H:%M:%S");
      savetoTableWorkspace(&createDate, table);

      savetoTableWorkspace(datafile->id, table);
      savetoTableWorkspace(datafile->fileSize, table);

      std::string fileSize = bytesToString(*datafile->fileSize);
      savetoTableWorkspace(&fileSize, table);

      if (datafile->description)
        savetoTableWorkspace(datafile->description, table);
    } else {
      throw std::runtime_error("ICat4Catalog::saveDataFiles expected a "
                               "datafile. Please contact the Mantid "
                               "development team.");
    }
  }
}
Exemple #13
0
    /** Executes the algorithm. Moving detectors of input workspace to positions indicated in table workspace
    *
    *  @throw FileError Thrown if unable to get instrument from workspace, 
    *                   table workspace is incompatible with instrument
    */
    void ApplyCalibration::exec()
    {
      // Get pointers to the workspace, parameter map and table
      API::MatrixWorkspace_sptr inputWS = getProperty("Workspace");
      m_pmap = &(inputWS->instrumentParameters()); // Avoids a copy if you get the reference before the instrument

      API::ITableWorkspace_sptr PosTable = getProperty("PositionTable");
      Geometry::Instrument_const_sptr instrument = inputWS->getInstrument();
      if(!instrument)
      {
        throw std::runtime_error("Workspace to apply calibration to has no defined instrument");
      }

      size_t numDetector = PosTable->rowCount();
      ColumnVector<int> detID = PosTable->getVector("Detector ID");
      ColumnVector<V3D> detPos = PosTable->getVector("Detector Position");
      // numDetector needs to be got as the number of rows in the table and the detID got from the (i)th row of table.
      for (size_t i = 0; i < numDetector; ++i)
      {
        setDetectorPosition(instrument, detID[i], detPos[i], false );
      }
      // Ensure pointer is only valid for execution
      m_pmap = NULL;
    }
Exemple #14
0
/**
 * Loops through the response vector and saves the datasets details to a table
 * workspace.
 * @param response :: A vector containing the results of the search query.
 * @param outputws :: Shared pointer to output workspace.
 */
void ICat4Catalog::saveDataSets(std::vector<xsd__anyType *> response,
                                API::ITableWorkspace_sptr &outputws) {
  if (outputws->getColumnNames().empty()) {
    // Add rows headers to the output workspace.
    outputws->addColumn("long64", "ID");
    outputws->addColumn("str", "Name");
    outputws->addColumn("str", "Description");
    outputws->addColumn("str", "Type");
    outputws->addColumn("str", "Related investigation ID");
    outputws->addColumn("size_t", "Number of datafiles");
  }

  std::string emptyCell;
  for (auto &iter : response) {
    ns1__dataset *dataset = dynamic_cast<ns1__dataset *>(iter);
    if (dataset) {
      API::TableRow table = outputws->appendRow();

      savetoTableWorkspace(dataset->id, table);
      savetoTableWorkspace(dataset->name, table);

      if (dataset->description)
        savetoTableWorkspace(dataset->description, table);
      else
        savetoTableWorkspace(&emptyCell, table);

      if (dataset->type)
        savetoTableWorkspace(dataset->type->name, table);
      else
        savetoTableWorkspace(&emptyCell, table);

      if (dataset->investigation)
        savetoTableWorkspace(dataset->investigation->name, table);
      else
        savetoTableWorkspace(&emptyCell, table);

      size_t datafileCount = dataset->datafiles.size();
      savetoTableWorkspace(&datafileCount, table);
    } else {
      throw std::runtime_error("ICat4Catalog::saveDataSets expected a dataset. "
                               "Please contact the Mantid development team.");
    }
  }
}
Exemple #15
0
    /** This method loops through the response return_vector and saves the datasets details to a table workspace
     * @param response :: const reference to response object
     * @param outputws ::  shred pointer to workspace
     * @returns shared pointer to table workspace which stores the data
     */
    void  CICatHelper::saveDataSets(const ns1__getInvestigationIncludesResponse& response,API::ITableWorkspace_sptr& outputws)
    {
      //create table workspace
      if (outputws->getColumnNames().empty())
      {
        outputws->addColumn("str","Name");//File name
        outputws->addColumn("str","Status");
        outputws->addColumn("str","Type");
        outputws->addColumn("str","Description");
        outputws->addColumn("long64","Sample Id");
      }
      try
      {

        std::vector<ns1__dataset*> datasetVec;
        datasetVec.assign((response.return_)->datasetCollection.begin(),(response.return_)->datasetCollection.end());

        std::vector<ns1__dataset*>::const_iterator dataset_citr;
        for(dataset_citr=datasetVec.begin();dataset_citr!=datasetVec.end();++dataset_citr)
        {
          API::TableRow t = outputws->appendRow();

          // DataSet Name
          savetoTableWorkspace((*dataset_citr)->name,t);
          // DataSet Status
          savetoTableWorkspace((*dataset_citr)->datasetStatus,t);
          //DataSet Type
          savetoTableWorkspace((*dataset_citr)->datasetType,t);
          //DataSet Type
          savetoTableWorkspace((*dataset_citr)->description,t);
          //DataSet Type
          savetoTableWorkspace((*dataset_citr)->sampleId,t);
        }
      }

      catch(std::runtime_error& )
      {
        throw;
      }

      //return outputws;
    }
/**
 * Parse the (optional) exp.ini file found on NOMAD
 * @param filename full path to a exp.ini file
 * @param wksp The table workspace to modify.
 */
void PDLoadCharacterizations::readExpIni(const std::string &filename,
                                         API::ITableWorkspace_sptr &wksp) {
  if (wksp->rowCount() == 0)
    throw std::runtime_error("Characterizations file does not have any "
                             "characterizations information");

  std::ifstream file(filename.c_str());
  if (!file) {
    throw Exception::FileError("Unable to open file", filename);
  }

  // parse the file
  for (std::string line = Strings::getLine(file); !file.eof();
       line = Strings::getLine(file)) {
    line = Strings::strip(line);
    // skip empty lines and "comments"
    if (line.empty())
      continue;
    if (line.substr(0, 1) == "#")
      continue;

    // split the line and see if it has something meaningful
    std::vector<std::string> splitted;
    boost::split(splitted, line, boost::is_any_of("\t "),
                 boost::token_compress_on);
    if (splitted.size() < 2)
      continue;

    // update the various charaterization runs
    if (splitted[0] == EXP_INI_VAN_KEY) {
      wksp->getRef<std::string>("vanadium", 0) = splitted[1];
    } else if (splitted[0] == EXP_INI_EMPTY_KEY) {
      wksp->getRef<std::string>("container", 0) = splitted[1];
    } else if (splitted[0] == EXP_INI_CAN_KEY) {
      wksp->getRef<std::string>("empty", 0) = splitted[1];
    }
  }
}
/** Load PhaseTable file to a vector of HistData.
* @param phaseTable :: [input] phase table containing detector info
* @param deadTimeTable :: [output] phase table containing dead times
*/
void PhaseQuadMuon::loadPhaseTable(API::ITableWorkspace_sptr phaseTable, API::ITableWorkspace_sptr deadTimeTable)
{
  if ( phaseTable->rowCount() )
  {
    if ( phaseTable->columnCount()<4 )
    {
      throw std::invalid_argument("PhaseQuad: PhaseTable must contain at least four columns");
    }

    // Check number of histograms in inputWs match number of detectors in phase table
    if (m_nHist != static_cast<int>(phaseTable->rowCount()))
    {
      throw std::runtime_error("PhaseQuad: Number of histograms in phase table does not match number of spectra in workspace");
    }

    for (size_t i=0; i<phaseTable->rowCount(); ++i)
    {
      API::TableRow phaseRow = phaseTable->getRow(i);

      // The first three columns go to m_histData
      HistData tempHist;
      tempHist.detOK = phaseRow.Bool(0);
      tempHist.alpha = phaseRow.Double(1);
      tempHist.phi   = phaseRow.Double(2);
      m_histData.push_back(tempHist);

      // The last column goes to deadTimeTable
      API::TableRow deadRow = deadTimeTable->appendRow();
      deadRow << static_cast<int>(i)+1 << phaseRow.Double(3);
    }

  }
  else
  {
    throw std::invalid_argument("PhaseQuad: PhaseTable is empty");
  }

}
Exemple #18
0
/**
 * Load a table
 */
API::Workspace_sptr LoadNexusProcessed::loadTableEntry(NXEntry & entry)
{
  API::ITableWorkspace_sptr workspace;
  workspace = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace");

  NXData nx_tw = entry.openNXData("table_workspace");

  std::vector<double> values;

  bool hasNumberOfRowBeenSet = false;
  //int numberOfRows = 0;

  int columnNumber = 1;
  do
  {
    std::string str = "column_" + boost::lexical_cast<std::string>(columnNumber);

    NXInfo info = nx_tw.getDataSetInfo(str.c_str());
    if (info.stat == NX_ERROR)
    {
      break;
    }

    if ( info.type == NX_FLOAT64 )
    {
      NXDouble nxDouble = nx_tw.openNXDouble(str.c_str());
      std::string columnTitle = nxDouble.attributes("name");
      if (!columnTitle.empty())
      {
        workspace->addColumn("double", columnTitle);
        nxDouble.load();
        int length = nxDouble.dim0();
        if ( !hasNumberOfRowBeenSet )
        { 
          workspace->setRowCount(length);
          hasNumberOfRowBeenSet = true;
        }
        for (int i = 0; i < length; i++)
          workspace->cell<double>(i,columnNumber-1) = *(nxDouble() + i);
      }
    }
    else if ( info.type == NX_CHAR )
    {
      NXChar data = nx_tw.openNXChar(str.c_str());
      std::string columnTitle = data.attributes("name");
      if (!columnTitle.empty())
      {
        workspace->addColumn("str", columnTitle);
        int nRows = info.dims[0];
        if ( !hasNumberOfRowBeenSet )
        {
          workspace->setRowCount(nRows);
          hasNumberOfRowBeenSet = true;
        }
        int maxStr = info.dims[1];

        std::string fromCrap(maxStr,' ');

        data.load();
        for (int iR = 0; iR < nRows; iR++)
        {
          for (int i = 0; i < maxStr; i++)
            fromCrap[i] = *(data()+i+maxStr*iR);
          workspace->cell<std::string>(iR,columnNumber-1) = fromCrap;
        }
      }
    } 

    columnNumber++;
  
  } while ( 1 );

  return boost::static_pointer_cast<API::Workspace>(workspace);
}
Exemple #19
0
/**
   Auto detecte the dead wires and store the information in the TableWorkspace.
   If asked, the dead wires are removed from the data set.

   @param localWorkspace :: input raw data workspace, containing the information about the instrument
   @param outputws :: input dead wire liste workspace
  */
void PoldiRemoveDeadWires::autoRemoveDeadWires
(
    DataObjects::Workspace2D_sptr &localWorkspace,
    API::ITableWorkspace_sptr &outputws
)
{


    double autoDeadWiresThreshold = 0;
    autoDeadWiresThreshold = getProperty("BadWiresThreshold");
    if(!autoDeadWiresThreshold) autoDeadWiresThreshold = m_defautDWThreshold;
    autoDeadWiresThreshold = 1.-autoDeadWiresThreshold;
//	double autoDeadWiresThreshold = 1-0.4;
    g_log.information() << "_poldi : auto removed wires : BadWiresThreshold:" << autoDeadWiresThreshold  <<  std::endl;
    int count = 0;

    double minValue=INFINITY;
    unsigned int minPos = 0;

    bool checkContinue = true;

    std::vector<double> average(this->m_numberOfSpectra);
    double globalAverage = 0;

    //compute the average intensity per spectrum
    for(unsigned int i=0; i<this->m_numberOfSpectra; i++) {
        if(!localWorkspace.get()->hasMaskedBins(i)) {
            average.at(i) = 0;
            MantidVec& tempY = localWorkspace.get()->dataY(i);
            for(unsigned int j=0; j<this->m_channelsPerSpectrum; j++) {
                average.at(i) += tempY[j];
            }
            average.at(i) /= static_cast<double>(this->m_channelsPerSpectrum);
            if(average[i]<minValue) {
                minValue = average[i];
                minPos   = i;
            }
        }
    }

    g_log.debug() << "_poldi : auto removed wires : average done"  <<  std::endl;

    while(checkContinue) {
        checkContinue = false;
        minValue=INFINITY;
        minPos = 0;
        int n = 0;
        // find the minimum average position, the most probably wrong spectra
        for(unsigned int i=0; i<this->m_numberOfSpectra; i++) {
            if(!localWorkspace.get()->hasMaskedBins(i)) {
                globalAverage += average[i];
                n++;
                if(average[i]<minValue) {
                    minValue = average[i];
                    minPos   = i;
                }
            }
        }
        globalAverage /=n;


        //applied the threshold to determine if a wires should be excluded
        //check if the wire is not already excluded
        if(!localWorkspace.get()->hasMaskedBins(minPos)) {

            if(average[minPos]<globalAverage*autoDeadWiresThreshold) {
                //mask the wires
                for(unsigned int j=0; j<this->m_channelsPerSpectrum; j++) {
                    localWorkspace->maskBin(minPos,j,1);
                }
                count++;
                checkContinue = true;
                TableRow t = outputws->appendRow();
                t << int(minPos) ;
            }
        }



        //applied the threshold to determine if a wires should be excluded
        //check if the wire is not already excluded
        if(!localWorkspace.get()->hasMaskedBins(minPos)) {
            //check the threshold on the left
            unsigned int left = minPos-1;
            //find the first used wires on the left
            while(localWorkspace.get()->hasMaskedBins(left) && left>0) {
                left--;
            }
            if(left>0 && average[minPos]<average[left]*autoDeadWiresThreshold) {
                //mask the wires
                for(unsigned int j=0; j<this->m_channelsPerSpectrum; j++) {
                    localWorkspace->maskBin(minPos,j,1);
                }
                count++;
                checkContinue = true;
                TableRow t = outputws->appendRow();
                t << int(minPos) ;
            }
        }

        if(!localWorkspace.get()->hasMaskedBins(minPos)) {
            //check the threshold on the right
            unsigned int right = minPos+1;
            //find the first used wires on the left
            while(localWorkspace.get()->hasMaskedBins(right) && right<this->m_numberOfSpectra) {
                right++;
            }
            if(right<m_numberOfSpectra-1 && average[minPos]<average[right]*autoDeadWiresThreshold) {
                //mask the wires
                for(unsigned int j=0; j<this->m_channelsPerSpectrum; j++) {
                    localWorkspace->maskBin(minPos,j,1);
                }
                count++;
                checkContinue = true;
                TableRow t = outputws->appendRow();
                t << int(minPos) ;
            }
        }

    }


    g_log.information() << "_poldi : auto removed wires (nb:" << count << ")" <<  std::endl;
    setProperty("nbAuteDeadWires",count);

}
Exemple #20
0
/**
 * Saves investigations to a table workspace.
 * @param response :: A vector containing the results of the search query.
 * @param outputws :: Shared pointer to output workspace.
 */
void ICat4Catalog::saveInvestigations(std::vector<xsd__anyType *> response,
                                      API::ITableWorkspace_sptr &outputws) {
  if (outputws->getColumnNames().empty()) {
    // Add rows headers to the output workspace.
    outputws->addColumn("long64", "DatabaseID");
    outputws->addColumn("str", "InvestigationID");
    outputws->addColumn("str", "Facility");
    outputws->addColumn("str", "Title");
    outputws->addColumn("str", "Instrument");
    outputws->addColumn("str", "Run range");
    outputws->addColumn("str", "Start date");
    outputws->addColumn("str", "End date");
    outputws->addColumn("str", "SessionID");
  }

  // Add data to each row in the output workspace.
  std::vector<xsd__anyType *>::const_iterator iter;
  for (iter = response.begin(); iter != response.end(); ++iter) {
    // Cast from xsd__anyType to subclass (xsd__string).
    ns1__investigation *investigation =
        dynamic_cast<ns1__investigation *>(*iter);
    if (investigation) {
      API::TableRow table = outputws->appendRow();
      // Used to insert an empty string into the cell if value does not exist.
      std::string emptyCell;

      // Now add the relevant investigation data to the table (They always
      // exist).
      savetoTableWorkspace(investigation->id, table);
      savetoTableWorkspace(investigation->name, table);
      savetoTableWorkspace(investigation->facility->name, table);
      savetoTableWorkspace(investigation->title, table);
      savetoTableWorkspace(
          investigation->investigationInstruments.at(0)->instrument->name,
          table);

      // Verify that the run parameters vector exist prior to doing anything.
      // Since some investigations may not have run parameters.
      if (!investigation->parameters.empty()) {
        savetoTableWorkspace(investigation->parameters[0]->stringValue, table);
      } else {
        savetoTableWorkspace(&emptyCell, table);
      }

      // Again, we need to check first if start and end date exist prior to
      // insertion.
      if (investigation->startDate) {
        std::string startDate =
            formatDateTime(*investigation->startDate, "%Y-%m-%d");
        savetoTableWorkspace(&startDate, table);
      } else {
        savetoTableWorkspace(&emptyCell, table);
      }

      if (investigation->endDate) {
        std::string endDate =
            formatDateTime(*investigation->endDate, "%Y-%m-%d");
        savetoTableWorkspace(&endDate, table);
      } else {
        savetoTableWorkspace(&emptyCell, table);
      }
      std::string sessionID = m_session->getSessionId();
      savetoTableWorkspace(&sessionID, table);
    } else {
      throw std::runtime_error("ICat4Catalog::saveInvestigations expected an "
                               "investigation. Please contact the Mantid "
                               "development team.");
    }
  }
}
/** Generate a list of peaks that meets= all the requirements for fitting offset
  * @param peakslist :: table workspace as the output of FindPeaks
  * @param wi :: workspace index of the spectrum
  * @param peakPositionRef :: reference peaks positions
  * @param peakPosToFit :: output of reference centres of the peaks used to fit
 * offset
  * @param peakPosFitted :: output of fitted centres of the peaks used to fit
 * offset
  * @param peakHeightFitted :: heights of the peaks used to fit offset
  * @param chisq :: chi squares of the peaks used to fit offset
  * @param useFitWindows :: boolean whether FitWindows is used
  * @param fitWindowsToUse :: fit windows
  * @param minD :: minimum d-spacing of the spectrum
  * @param maxD :: minimum d-spacing of the spectrum
  * @param deltaDovD :: delta(d)/d of the peak for fitting
  * @param dev_deltaDovD :: standard deviation of delta(d)/d of all the peaks in
 * the spectrum
  */
void GetDetOffsetsMultiPeaks::generatePeaksList(
    const API::ITableWorkspace_sptr &peakslist, int wi,
    const std::vector<double> &peakPositionRef,
    std::vector<double> &peakPosToFit, std::vector<double> &peakPosFitted,
    std::vector<double> &peakHeightFitted, std::vector<double> &chisq,
    bool useFitWindows, const std::vector<double> &fitWindowsToUse,
    const double minD, const double maxD, double &deltaDovD,
    double &dev_deltaDovD) {
  // FIXME - Need to make sure that the peakPositionRef and peakslist have the
  // same order of peaks

  // Check
  size_t numrows = peakslist->rowCount();
  if (numrows != peakPositionRef.size()) {
    std::stringstream msg;
    msg << "Number of peaks in PeaksList (from FindPeaks=" << numrows
        << ") is not same as number of "
        << "referenced peaks' positions (" << peakPositionRef.size() << ")";
    throw std::runtime_error(msg.str());
  }

  std::vector<double> vec_widthDivPos;
  std::vector<double> vec_offsets;

  for (size_t i = 0; i < peakslist->rowCount(); ++i) {
    // Get peak value
    double centre = peakslist->getRef<double>("centre", i);
    double width = peakslist->getRef<double>("width", i);
    double height = peakslist->getRef<double>("height", i);
    double chi2 = peakslist->getRef<double>("chi2", i);

    // Identify whether this peak would be accepted to optimize offset
    // - peak position within D-range
    if (centre <= minD || centre >= maxD) {
      std::stringstream dbss;
      dbss << " wi = " << wi << " c = " << centre << " out of D-range ";
      g_log.debug(dbss.str());
      continue;
    }

    // - rule out of peak with wrong position
    if (useFitWindows) {
      // outside peak fit window o
      if (centre <= fitWindowsToUse[2 * i] ||
          centre >= fitWindowsToUse[2 * i + 1]) {
        std::stringstream dbss;
        dbss << " wi = " << wi << " c = " << centre << " out of fit window ";
        g_log.debug(dbss.str());
        continue;
      }
    }

    // - check chi-square
    if (chi2 > m_maxChiSq || chi2 < 0) {
      std::stringstream dbss;
      dbss << " wi = " << wi << " c = " << centre << " chi2 = " << chi2
           << ": Too large";
      g_log.debug(dbss.str());
      continue;
    }

    // - check peak height
    if (height < m_minPeakHeight) {
      g_log.debug() << " wi = " << wi << " c = " << centre << " h = " << height
                    << ": Too low "
                    << "\n";
      continue;
    }

    // - check peak's resolution
    double widthdevpos = width / centre;
    if (m_hasInputResolution) {
      double recres = m_inputResolutionWS->readY(wi)[0];
      double resmax = recres * m_maxResFactor;
      double resmin = recres * m_minResFactor;
      if (widthdevpos < resmin || widthdevpos > resmax) {
        std::stringstream dbss;
        dbss << " wi = " << wi << " c = " << centre
             << " Delta(d)/d = " << widthdevpos
             << " too far away from suggested value " << recres;
        g_log.debug(dbss.str());
        continue;
      }
    }

    // background value
    double back_intercept = peakslist->getRef<double>("backgroundintercept", i);
    double back_slope = peakslist->getRef<double>("backgroundslope", i);
    double back_quad = peakslist->getRef<double>("A2", i);
    double background =
        back_intercept + back_slope * centre + back_quad * centre * centre;

    // Continue to identify whether this peak will be accepted
    // (e) peak signal/noise ratio
    if (height * FWHM_TO_SIGMA / width < 5.)
      continue;

    // (f) ban peaks that are not outside of error bars for the background
    if (height < 0.5 * std::sqrt(height + background))
      continue;

    // - calcualte offsets as to determine the (z-value)
    double offset = fabs(peakPositionRef[i] / centre - 1);
    if (offset > m_maxOffset) {
      std::stringstream dbss;
      dbss << " wi = " << wi << " c = " << centre
           << " exceeds maximum offset. ";
      g_log.debug(dbss.str());
      continue;
    } else
      vec_offsets.push_back(offset);

    // (g) calculate width/pos as to determine the (z-value) for constant
    // "width" - (delta d)/d
    // double widthdevpos = width/centre;
    vec_widthDivPos.push_back(widthdevpos);

    // g_log.debug() << " h:" << height << " c:" << centre << " w:" <<
    // (width/(2.*std::sqrt(2.*std::log(2.))))
    //               << " b:" << background << " chisq:" << chi2 << "\n";

    // Add peak to vectors
    double refcentre = peakPositionRef[i];
    peakPosFitted.push_back(centre);
    peakPosToFit.push_back(refcentre);
    peakHeightFitted.push_back(height);
    chisq.push_back(chi2);
  }

  // Remove by Z-score on delta d/d
  std::vector<size_t> banned;
  std::vector<double> Zscore = getZscore(vec_widthDivPos);
  std::vector<double> Z_offset = getZscore(vec_offsets);
  for (size_t i = 0; i < peakPosFitted.size(); ++i) {
    if (Zscore[i] > 2.0 || Z_offset[i] > 2.0) {
      g_log.debug() << "Banning peak at " << peakPosFitted[i]
                    << " in wkspindex = (no show)" // << wi
                    << " sigma/d = " << vec_widthDivPos[i] << "\n";
      banned.push_back(i);
      continue;
    }
  }

  // Delete banned peaks
  if (!banned.empty()) {
    g_log.debug() << "Deleting " << banned.size() << " of "
                  << peakPosFitted.size() << " peaks in wkspindex = ??? "
                  << "\n"; // << wi << "\n";

    deletePeaks(banned, peakPosToFit, peakPosFitted, peakHeightFitted, chisq,
                vec_widthDivPos);
  }

  Statistics widthDivPos = getStatistics(vec_widthDivPos);
  deltaDovD = widthDivPos.mean;
  dev_deltaDovD = widthDivPos.standard_deviation;

  return;
}
Exemple #22
0
/**
 * This method loops through the response return_vector and saves the datafile
 * details to a table workspace
 * @param response :: const reference to response object
 * @param outputws :: shared pointer to table workspace which stores the data
 */
void CICatHelper::saveInvestigationIncludesResponse(
    const ns1__getInvestigationIncludesResponse &response,
    API::ITableWorkspace_sptr &outputws) {
  if (outputws->getColumnNames().empty()) {
    outputws->addColumn("str", "Name");
    outputws->addColumn("str", "Location");
    outputws->addColumn("str", "Create Time");
    outputws->addColumn("long64", "Id");
    outputws->addColumn("long64", "File size(bytes)");
    outputws->addColumn("str", "File size");
    outputws->addColumn("str", "Description");
  }

  try {
    std::vector<ns1__dataset *> datasetVec;
    datasetVec.assign((response.return_)->datasetCollection.begin(),
                      (response.return_)->datasetCollection.end());
    if (datasetVec.empty()) {
      throw std::runtime_error("No data files exists in the ICAT database for "
                               "the selected investigation");
    }
    std::vector<ns1__dataset *>::const_iterator dataset_citr;
    for (dataset_citr = datasetVec.begin(); dataset_citr != datasetVec.end();
         ++dataset_citr) {
      std::vector<ns1__datafile *> datafileVec;
      datafileVec.assign((*dataset_citr)->datafileCollection.begin(),
                         (*dataset_citr)->datafileCollection.end());
      if (datafileVec.empty()) {
        throw std::runtime_error("No data files exists in the ICAT database "
                                 "for the selected  investigation ");
      }

      std::vector<ns1__datafile *>::const_iterator datafile_citr;
      for (datafile_citr = datafileVec.begin();
           datafile_citr != datafileVec.end(); ++datafile_citr) {

        API::TableRow t = outputws->appendRow();

        // File Name
        savetoTableWorkspace((*datafile_citr)->name, t);
        savetoTableWorkspace((*datafile_citr)->location, t);

        // File creation Time.
        std::string *creationtime = nullptr;
        if ((*datafile_citr)->datafileCreateTime != nullptr) {
          time_t crtime = *(*datafile_citr)->datafileCreateTime;
          char temp[25];
          strftime(temp, 25, "%Y-%b-%d %H:%M:%S", localtime(&crtime));
          std::string ftime(temp);
          creationtime = new std::string;
          creationtime->assign(ftime);
        }
        savetoTableWorkspace(creationtime, t);
        if (creationtime)
          delete creationtime;

        //
        savetoTableWorkspace((*datafile_citr)->id, t);

        LONG64 fileSize =
            boost::lexical_cast<LONG64>(*(*datafile_citr)->fileSize);
        savetoTableWorkspace(&fileSize, t);

        savetoTableWorkspace((*datafile_citr)->description, t);
      }
    }

  } catch (std::runtime_error &) {
    throw;
  }
}
/** Load PhaseList file to a vector of HistData and a deadTimeTable.
* @param filename :: [input] phase list .inf filename
* @param deadTimeTable :: [output] table containing dead times
*/
void PhaseQuadMuon::loadPhaseList(const std::string& filename, API::ITableWorkspace_sptr deadTimeTable )
{

  std::ifstream input(filename.c_str(), std::ios_base::in);

  if (input.is_open())
  {

    if ( input.eof() )
    {
      throw Exception::FileError("PhaseQuad: File is empty.", filename);
    }
    else
    {
      std::string line;

      // Header of .INF file is as follows:
      //
      // Comment on the output file
      // Top row of numbers are:
      // #histos, typ. first good bin#, typ. bin# when pulse over, mean lag.
      // Tabulated numbers are, per histogram:
      // det ok, asymmetry, phase, lag, deadtime_c, deadtime_m.
      //
      std::getline( input, line ); // Skip first line in header
      std::getline( input, line ); // Skip second line
      std::getline( input, line ); // ...
      std::getline( input, line );
      std::getline( input, line );

      // Read first useful line
      int nHist;
      input >> nHist >> m_tValid >> m_tPulseOver >> m_meanLag;
      if (m_nHist!=nHist)
      {
        throw std::runtime_error("PhaseQuad: Number of histograms in phase list does not match number of spectra in workspace");
      }

      // Read histogram data
      int cont=0;
      HistData tempData;
      double lag, dead, deadm;
      while( input >> tempData.detOK >> tempData.alpha >> tempData.phi >> lag >> dead >> deadm )
      {
        m_histData.push_back (tempData);
        cont++;

        // Add dead time to deadTimeTable
        API::TableRow row = deadTimeTable->appendRow();
        row << cont << dead;

      }

      if ( cont != m_nHist )
      {
        if ( cont < m_nHist )
        {
          throw Exception::FileError("PhaseQuad: Lines missing in phase list", filename);
        }
        else
        {
          throw Exception::FileError("PhaseQuad: Extra lines in phase list", filename);
        }
      }

    }
  }
  else
  {
    // Throw exception if file cannot be opened
    throw std::runtime_error("PhaseQuad: Unable to open PhaseList");
/** Forms the quadrature phase signal (squashogram)
* @param ws :: [input] workspace containing the measured spectra
* @param phase :: [input] table workspace containing the detector phases
* @param n0 :: [input] vector containing the normalization constants
* @return :: workspace containing the quadrature phase signal
*/
API::MatrixWorkspace_sptr
PhaseQuadMuon::squash(const API::MatrixWorkspace_sptr &ws,
                      const API::ITableWorkspace_sptr &phase,
                      const std::vector<double> &n0) {

  // Poisson limit: below this number we consider we don't have enough
  // statistics
  // to apply sqrt(N). This is an arbitrary number used in the original code
  // provided by scientists
  double poissonLimit = 30.;

  size_t nspec = ws->getNumberHistograms();
  size_t npoints = ws->blocksize();

  // Muon life time in microseconds
  double muLife = PhysicalConstants::MuonLifetime * 1e6;

  if (n0.size() != nspec) {
    throw std::invalid_argument("Invalid normalization constants");
  }

  // Get the maximum asymmetry
  double maxAsym = 0.;
  for (size_t h = 0; h < nspec; h++) {
    if (phase->Double(h, 1) > maxAsym) {
      maxAsym = phase->Double(h, 1);
    }
  }
  if (maxAsym == 0.0) {
    throw std::invalid_argument("Invalid detector asymmetries");
  }

  std::vector<double> aj, bj;
  {
    // Calculate coefficients aj, bj

    double sxx = 0;
    double syy = 0;
    double sxy = 0;

    for (size_t h = 0; h < nspec; h++) {
      double asym = phase->Double(h, 1) / maxAsym;
      double phi = phase->Double(h, 2);
      double X = n0[h] * asym * cos(phi);
      double Y = n0[h] * asym * sin(phi);
      sxx += X * X;
      syy += Y * Y;
      sxy += X * Y;
    }

    double lam1 = 2 * syy / (sxx * syy - sxy * sxy);
    double mu1 = 2 * sxy / (sxy * sxy - sxx * syy);
    double lam2 = 2 * sxy / (sxy * sxy - sxx * syy);
    double mu2 = 2 * sxx / (sxx * syy - sxy * sxy);
    for (size_t h = 0; h < nspec; h++) {
      double asym = phase->Double(h, 1) / maxAsym;
      double phi = phase->Double(h, 2);
      double X = n0[h] * asym * cos(phi);
      double Y = n0[h] * asym * sin(phi);
      aj.push_back((lam1 * X + mu1 * Y) * 0.5);
      bj.push_back((lam2 * X + mu2 * Y) * 0.5);
    }
  }

  // First X value
  double X0 = ws->x(0).front();

  // Create and populate output workspace
  API::MatrixWorkspace_sptr ows = API::WorkspaceFactory::Instance().create(
      "Workspace2D", 2, npoints + 1, npoints);

  // X
  ows->setSharedX(0, ws->sharedX(0));
  ows->setSharedX(1, ws->sharedX(0));

  // Phase quadrature
  auto &realY = ows->mutableY(0);
  auto &imagY = ows->mutableY(1);
  auto &realE = ows->mutableE(0);
  auto &imagE = ows->mutableE(1);

  for (size_t i = 0; i < npoints; i++) {
    for (size_t h = 0; h < nspec; h++) {

      // (X,Y,E) with exponential decay removed
      const double X = ws->x(h)[i];
      const double Y = ws->y(h)[i] - n0[h] * exp(-(X - X0) / muLife);
      const double E = (ws->y(h)[i] > poissonLimit)
                           ? ws->e(h)[i]
                           : sqrt(n0[h] * exp(-(X - X0) / muLife));

      realY[i] += aj[h] * Y;
      imagY[i] += bj[h] * Y;
      realE[i] += aj[h] * aj[h] * E * E;
      imagE[i] += bj[h] * bj[h] * E * E;
    }
    realE[i] = sqrt(realE[i]);
    imagE[i] = sqrt(imagE[i]);

    // Regain exponential decay
    const double X = ws->getSpectrum(0).x()[i];
    const double e = exp(-(X - X0) / muLife);
    realY[i] /= e;
    imagY[i] /= e;
    realE[i] /= e;
    imagE[i] /= e;
  }

  return ows;
}
/** Forms the quadrature phase signal (squashogram)
 * @param ws :: [input] workspace containing the measured spectra
 * @param phase :: [input] table workspace containing the detector phases
 * @param n0 :: [input] vector containing the normalization constants
 * @return :: workspace containing the quadrature phase signal
 */
API::MatrixWorkspace_sptr
PhaseQuadMuon::squash(const API::MatrixWorkspace_sptr &ws,
                      const API::ITableWorkspace_sptr &phase,
                      const std::vector<double> &n0) {

  // Poisson limit: below this number we consider we don't have enough
  // statistics
  // to apply sqrt(N). This is an arbitrary number used in the original code
  // provided by scientists
  const double poissonLimit = 30.;

  // Muon life time in microseconds
  const double muLife = PhysicalConstants::MuonLifetime * 1e6;

  const size_t nspec = ws->getNumberHistograms();

  if (n0.size() != nspec) {
    throw std::invalid_argument("Invalid normalization constants");
  }

  auto names = phase->getColumnNames();
  for (auto &name : names) {
    std::transform(name.begin(), name.end(), name.begin(), ::tolower);
  }
  auto phaseIndex = findName(phaseNames, names);
  auto asymmetryIndex = findName(asymmNames, names);

  // Get the maximum asymmetry
  double maxAsym = 0.;
  for (size_t h = 0; h < nspec; h++) {
    if (phase->Double(h, asymmetryIndex) > maxAsym &&
        phase->Double(h, asymmetryIndex) != ASYMM_ERROR) {
      maxAsym = phase->Double(h, asymmetryIndex);
    }
  }

  if (maxAsym == 0.0) {
    throw std::invalid_argument("Invalid detector asymmetries");
  }
  std::vector<bool> emptySpectrum;
  emptySpectrum.reserve(nspec);
  std::vector<double> aj, bj;
  {
    // Calculate coefficients aj, bj

    double sxx = 0.;
    double syy = 0.;
    double sxy = 0.;
    for (size_t h = 0; h < nspec; h++) {
      emptySpectrum.push_back(
          std::all_of(ws->y(h).begin(), ws->y(h).end(),
                      [](double value) { return value == 0.; }));
      if (!emptySpectrum[h]) {
        const double asym = phase->Double(h, asymmetryIndex) / maxAsym;
        const double phi = phase->Double(h, phaseIndex);
        const double X = n0[h] * asym * cos(phi);
        const double Y = n0[h] * asym * sin(phi);
        sxx += X * X;
        syy += Y * Y;
        sxy += X * Y;
      }
    }

    const double lam1 = 2 * syy / (sxx * syy - sxy * sxy);
    const double mu1 = 2 * sxy / (sxy * sxy - sxx * syy);
    const double lam2 = 2 * sxy / (sxy * sxy - sxx * syy);
    const double mu2 = 2 * sxx / (sxx * syy - sxy * sxy);
    for (size_t h = 0; h < nspec; h++) {
      if (emptySpectrum[h]) {
        aj.push_back(0.0);
        bj.push_back(0.0);
      } else {
        const double asym = phase->Double(h, asymmetryIndex) / maxAsym;
        const double phi = phase->Double(h, phaseIndex);
        const double X = n0[h] * asym * cos(phi);
        const double Y = n0[h] * asym * sin(phi);
        aj.push_back((lam1 * X + mu1 * Y) * 0.5);
        bj.push_back((lam2 * X + mu2 * Y) * 0.5);
      }
    }
  }

  const size_t npoints = ws->blocksize();
  // Create and populate output workspace
  API::MatrixWorkspace_sptr ows =
      API::WorkspaceFactory::Instance().create(ws, 2, npoints + 1, npoints);

  // X
  ows->setSharedX(0, ws->sharedX(0));
  ows->setSharedX(1, ws->sharedX(0));

  // Phase quadrature
  auto &realY = ows->mutableY(0);
  auto &imagY = ows->mutableY(1);
  auto &realE = ows->mutableE(0);
  auto &imagE = ows->mutableE(1);

  const auto xPointData = ws->histogram(0).points();
  // First X value
  const double X0 = xPointData.front();

  // calculate exponential decay outside of the loop
  std::vector<double> expDecay = xPointData.rawData();
  std::transform(expDecay.begin(), expDecay.end(), expDecay.begin(),
                 [X0, muLife](double x) { return exp(-(x - X0) / muLife); });

  for (size_t i = 0; i < npoints; i++) {
    for (size_t h = 0; h < nspec; h++) {
      if (!emptySpectrum[h]) {
        // (X,Y,E) with exponential decay removed
        const double X = ws->x(h)[i];
        const double exponential = n0[h] * exp(-(X - X0) / muLife);
        const double Y = ws->y(h)[i] - exponential;
        const double E =
            (ws->y(h)[i] > poissonLimit) ? ws->e(h)[i] : sqrt(exponential);

        realY[i] += aj[h] * Y;
        imagY[i] += bj[h] * Y;
        realE[i] += aj[h] * aj[h] * E * E;
        imagE[i] += bj[h] * bj[h] * E * E;
      }
    }
    realE[i] = sqrt(realE[i]);
    imagE[i] = sqrt(imagE[i]);

    // Regain exponential decay
    realY[i] /= expDecay[i];
    imagY[i] /= expDecay[i];
    realE[i] /= expDecay[i];
    imagE[i] /= expDecay[i];
  }

  // New Y axis label
  ows->setYUnit("Asymmetry");

  return ows;
}
/**
 * Calculates the EISF if the fit includes a Delta function
 * @param tableWs - The TableWorkspace to append the EISF calculation to
 */
void ConvolutionFitSequential::calculateEISF(
    API::ITableWorkspace_sptr &tableWs) {
  // Get height data from parameter table
  const auto columns = tableWs->getColumnNames();
  const auto height = searchForFitParams("Height", columns).at(0);
  const auto heightErr = searchForFitParams("Height_Err", columns).at(0);
  auto heightY = tableWs->getColumn(height)->numeric_fill<>();
  auto heightE = tableWs->getColumn(heightErr)->numeric_fill<>();

  // Get amplitude column names
  const auto ampNames = searchForFitParams("Amplitude", columns);
  const auto ampErrorNames = searchForFitParams("Amplitude_Err", columns);

  // For each lorentzian, calculate EISF
  size_t maxSize = ampNames.size();
  if (ampErrorNames.size() > maxSize) {
    maxSize = ampErrorNames.size();
  }
  for (size_t i = 0; i < maxSize; i++) {
    // Get amplitude from column in table workspace
    const auto ampName = ampNames.at(i);
    auto ampY = tableWs->getColumn(ampName)->numeric_fill<>();
    const auto ampErrorName = ampErrorNames.at(i);
    auto ampErr = tableWs->getColumn(ampErrorName)->numeric_fill<>();

    // Calculate EISF and EISF error
    // total = heightY + ampY
    auto total = cloneVector(heightY);
    std::transform(total.begin(), total.end(), ampY.begin(), total.begin(),
                   std::plus<double>());
    // eisfY = heightY / total
    auto eisfY = cloneVector(heightY);
    std::transform(eisfY.begin(), eisfY.end(), total.begin(), eisfY.begin(),
                   std::divides<double>());
    // heightE squared
    auto heightESq = cloneVector(heightE);
    heightESq = squareVector(heightESq);
    // ampErr squared
    auto ampErrSq = cloneVector(ampErr);
    ampErrSq = squareVector(ampErrSq);
    // totalErr = heightE squared + ampErr squared
    auto totalErr = cloneVector(heightESq);
    std::transform(totalErr.begin(), totalErr.end(), ampErrSq.begin(),
                   totalErr.begin(), std::plus<double>());
    // heightY squared
    auto heightYSq = cloneVector(heightY);
    heightYSq = squareVector(heightYSq);
    // total Squared
    auto totalSq = cloneVector(total);
    totalSq = squareVector(totalSq);
    // errOverTotalSq = totalErr / total squared
    auto errOverTotalSq = cloneVector(totalErr);
    std::transform(errOverTotalSq.begin(), errOverTotalSq.end(),
                   totalSq.begin(), errOverTotalSq.begin(),
                   std::divides<double>());
    // heightESqOverYSq = heightESq / heightYSq
    auto heightESqOverYSq = cloneVector(heightESq);
    std::transform(heightESqOverYSq.begin(), heightESqOverYSq.end(),
                   heightYSq.begin(), heightESqOverYSq.begin(),
                   std::divides<double>());
    // sqrtESqOverYSq = squareRoot( heightESqOverYSq )
    auto sqrtESqOverYSq = cloneVector(heightESqOverYSq);
    std::transform(sqrtESqOverYSq.begin(), sqrtESqOverYSq.end(),
                   sqrtESqOverYSq.begin(),
                   static_cast<double (*)(double)>(sqrt));
    // eisfYSumRoot = eisfY * sqrtESqOverYSq
    auto eisfYSumRoot = cloneVector(eisfY);
    std::transform(eisfYSumRoot.begin(), eisfYSumRoot.end(),
                   sqrtESqOverYSq.begin(), eisfYSumRoot.begin(),
                   std::multiplies<double>());
    // eisfErr = eisfYSumRoot + errOverTotalSq
    auto eisfErr = cloneVector(eisfYSumRoot);
    std::transform(eisfErr.begin(), eisfErr.end(), errOverTotalSq.begin(),
                   eisfErr.begin(), std::plus<double>());

    // Append the calculated values to the table workspace
    auto columnName =
        ampName.substr(0, (ampName.size() - std::string("Amplitude").size()));
    columnName += "EISF";
    auto errorColumnName = ampErrorName.substr(
        0, (ampErrorName.size() - std::string("Amplitude_Err").size()));
    errorColumnName += "EISF_Err";

    tableWs->addColumn("double", columnName);
    tableWs->addColumn("double", errorColumnName);
    size_t maxEisf = eisfY.size();
    if (eisfErr.size() > maxEisf) {
      maxEisf = eisfErr.size();
    }

    Column_sptr col = tableWs->getColumn(columnName);
    Column_sptr errCol = tableWs->getColumn(errorColumnName);
    for (size_t j = 0; j < maxEisf; j++) {
      col->cell<double>(j) = eisfY.at(j);
      errCol->cell<double>(j) = eisfErr.at(j);
    }
  }
}
/** Fits each spectrum in the workspace to f(x) = A * sin( w * x + p)
 * @param ws :: [input] The workspace to fit
 * @param freq :: [input] Hint for the frequency (w)
 * @param groupName :: [input] The name of the output workspace group
 * @param resTab :: [output] Table workspace storing the asymmetries and phases
 * @param resGroup :: [output] Workspace group storing the fitting results
 */
void CalMuonDetectorPhases::fitWorkspace(const API::MatrixWorkspace_sptr &ws,
                                         double freq, std::string groupName,
                                         API::ITableWorkspace_sptr resTab,
                                         API::WorkspaceGroup_sptr &resGroup) {

  int nhist = static_cast<int>(ws->getNumberHistograms());

  // Create the fitting function f(x) = A * sin ( w * x + p )
  // The same function and initial parameters are used for each fit
  std::string funcStr = createFittingFunction(freq, true);

  // Set up results table
  resTab->addColumn("int", "Spectrum number");
  resTab->addColumn("double", "Asymmetry");
  resTab->addColumn("double", "Phase");

  const auto &indexInfo = ws->indexInfo();

  // Loop through fitting all spectra individually
  const static std::string success = "success";
  for (int wsIndex = 0; wsIndex < nhist; wsIndex++) {
    reportProgress(wsIndex, nhist);
    const auto &yValues = ws->y(wsIndex);
    auto emptySpectrum = std::all_of(yValues.begin(), yValues.end(),
                                     [](double value) { return value == 0.; });
    if (emptySpectrum) {
      g_log.warning("Spectrum " + std::to_string(wsIndex) + " is empty");
      TableWorkspace_sptr tab = boost::make_shared<TableWorkspace>();
      tab->addColumn("str", "Name");
      tab->addColumn("double", "Value");
      tab->addColumn("double", "Error");
      for (int j = 0; j < 4; j++) {
        API::TableRow row = tab->appendRow();
        if (j == PHASE_ROW) {
          row << "dummy" << 0.0 << 0.0;
        } else {
          row << "dummy" << ASYMM_ERROR << 0.0;
        }
      }

      extractDetectorInfo(*tab, *resTab, indexInfo.spectrumNumber(wsIndex));

    } else {
      auto fit = createChildAlgorithm("Fit");
      fit->initialize();
      fit->setPropertyValue("Function", funcStr);
      fit->setProperty("InputWorkspace", ws);
      fit->setProperty("WorkspaceIndex", wsIndex);
      fit->setProperty("CreateOutput", true);
      fit->setPropertyValue("Output", groupName);
      fit->execute();

      std::string status = fit->getProperty("OutputStatus");
      if (!fit->isExecuted()) {
        std::ostringstream error;
        error << "Fit failed for spectrum at workspace index " << wsIndex;
        error << ": " << status;
        throw std::runtime_error(error.str());
      } else if (status != success) {
        g_log.warning("Fit failed for spectrum at workspace index " +
                      std::to_string(wsIndex) + ": " + status);
      }

      API::MatrixWorkspace_sptr fitOut = fit->getProperty("OutputWorkspace");
      resGroup->addWorkspace(fitOut);
      API::ITableWorkspace_sptr tab = fit->getProperty("OutputParameters");
      // Now we have our fitting results stored in tab
      // but we need to extract the relevant information, i.e.
      // the detector phases (parameter 'p') and asymmetries ('A')
      extractDetectorInfo(*tab, *resTab, indexInfo.spectrumNumber(wsIndex));
    }
  }
}