/**
 * Removes error columns from the table if all errors are zero,
 * as these columns correspond to fixed parameters.
 * @param table :: [input, output] Pointer to TableWorkspace to edit
 */
void MuonAnalysisResultTableCreator::removeFixedParameterErrors(
    const ITableWorkspace_sptr table) const {
  assert(table);
  const size_t nRows = table->rowCount();
  const auto colNames = table->getColumnNames();
  std::vector<std::string> zeroErrorColumns;

  for (const auto &name : colNames) {
    // if name does not end with "Error", continue
    const size_t nameLength = name.length();
    if (nameLength < ERROR_LENGTH ||
        name.compare(nameLength - ERROR_LENGTH, ERROR_LENGTH, ERROR_STRING)) {
      continue;
    }

    auto col = table->getColumn(name);
    bool allZeros = true;
    // Check if all values in the column are zero
    for (size_t iRow = 0; iRow < nRows; ++iRow) {
      const double val = col->toDouble(iRow);
      if (std::abs(val) > std::numeric_limits<double>::epsilon()) {
        allZeros = false;
        break;
      }
    }
    if (allZeros) {
      zeroErrorColumns.push_back(name);
    }
  }

  for (const auto &name : zeroErrorColumns) {
    table->removeColumn(name);
  }
}
ITableWorkspace_sptr ReflCatalogSearcher::search(const std::string &text) {
  auto sessions = CatalogManager::Instance().getActiveSessions();
  if (sessions.empty())
    throw std::runtime_error("You are not logged into any catalogs.");

  const std::string sessionId = sessions.front()->getSessionId();

  auto algSearch = AlgorithmManager::Instance().create("CatalogGetDataFiles");
  algSearch->initialize();
  algSearch->setChild(true);
  algSearch->setLogging(false);
  algSearch->setProperty("Session", sessionId);
  algSearch->setProperty("InvestigationId", text);
  algSearch->setProperty("OutputWorkspace", "_ReflSearchResults");
  algSearch->execute();
  ITableWorkspace_sptr results = algSearch->getProperty("OutputWorkspace");

  // Now, tidy up the data
  std::set<size_t> toRemove;
  for (size_t i = 0; i < results->rowCount(); ++i) {
    std::string &run = results->String(i, 0);

    // Too short to be more than ".raw or .nxs"
    if (run.size() < 5) {
      toRemove.insert(i);
    }
  }

  // Sets are sorted so if we go from back to front we won't trip over ourselves
  for (auto row = toRemove.rbegin(); row != toRemove.rend(); ++row)
    results->removeRow(*row);

  return results;
}
Exemple #3
0
/**
 * Convert a grouping table to a grouping struct.
 * @param table :: A table to convert
 * @return Grouping info
 */
boost::shared_ptr<Grouping> tableToGrouping(ITableWorkspace_sptr table)
{
  auto grouping = boost::make_shared<Grouping>();

  for ( size_t row = 0; row < table->rowCount(); ++row )
  {
    std::vector<int> detectors = table->cell< std::vector<int> >(row,0);

    // toString() expects the sequence to be sorted
    std::sort( detectors.begin(), detectors.end() );

    // Convert to a range string, i.e. 1-5,6-8,9
    std::string detectorRange = Strings::toString(detectors);

    grouping->groupNames.push_back(boost::lexical_cast<std::string>(row + 1));
    grouping->groups.push_back(detectorRange);
  }

  // If we have 2 groups only - create a longitudinal pair
  if ( grouping->groups.size() == 2 )
  {
    grouping->pairNames.push_back("long");
    grouping->pairAlphas.push_back(1.0);
    grouping->pairs.push_back(std::make_pair(0,1));
  }

  return grouping;
}
/** Parse profile table workspace to a map (the new ...
  */
void SaveGSASInstrumentFile::parseProfileTableWorkspace(
    ITableWorkspace_sptr ws,
    map<unsigned int, map<string, double>> &profilemap) {
  size_t numbanks = ws->columnCount() - 1;
  size_t numparams = ws->rowCount();
  vector<map<string, double>> vec_maptemp(numbanks);
  vector<unsigned int> vecbankindex(numbanks);

  // Check
  vector<string> colnames = ws->getColumnNames();
  if (colnames[0].compare("Name"))
    throw runtime_error("The first column must be Name");

  // Parse
  for (size_t irow = 0; irow < numparams; ++irow) {
    TableRow tmprow = ws->getRow(irow);
    string parname;
    tmprow >> parname;
    if (parname.compare("BANK")) {
      for (size_t icol = 0; icol < numbanks; ++icol) {
        double tmpdbl;
        tmprow >> tmpdbl;
        vec_maptemp[icol].insert(make_pair(parname, tmpdbl));
      }
    } else {
      for (size_t icol = 0; icol < numbanks; ++icol) {
        double tmpint;
        tmprow >> tmpint;
        vecbankindex[icol] = static_cast<unsigned int>(tmpint);
      }
    }
  }
    ITableWorkspace_sptr ReflCatalogSearcher::search(const std::string& text, const std::string& instrument)
    {
      auto sessions = CatalogManager::Instance().getActiveSessions();
      if(sessions.empty())
        throw std::runtime_error("You are not logged into any catalogs.");

      const std::string sessionId = sessions.front()->getSessionId();

      auto algSearch = AlgorithmManager::Instance().create("CatalogGetDataFiles");
      algSearch->initialize();
      algSearch->setChild(true);
      algSearch->setLogging(false);
      algSearch->setProperty("Session", sessionId);
      algSearch->setProperty("InvestigationId", text);
      algSearch->setProperty("OutputWorkspace", "_ReflSearchResults");
      algSearch->execute();
      ITableWorkspace_sptr results = algSearch->getProperty("OutputWorkspace");

      //Now, tidy up the data
      std::set<size_t> toRemove;
      for(size_t i = 0; i < results->rowCount(); ++i)
      {
        std::string& run = results->String(i,0);

        //Too short to be more than ".raw"
        if(run.size() < 5)
        {
          toRemove.insert(i);
        }
        //If this isn't the right instrument, remove it
        else if(run.substr(0, instrument.size()) != instrument)
        {
          toRemove.insert(i);
        }
        //If it's not a raw file, remove it
        else if(run.substr(run.size() - 4, 4) != ".raw")
        {
          toRemove.insert(i);
        }

        //It's a valid run, so let's trim the instrument prefix and ".raw" suffix
        run = run.substr(instrument.size(), run.size() - (instrument.size() + 4));

        //Let's also get rid of any leading zeros
        size_t numZeros = 0;
        while(run[numZeros] == '0')
          numZeros++;
        run = run.substr(numZeros, run.size() - numZeros);
      }

      //Sets are sorted so if we go from back to front we won't trip over ourselves
      for(auto row = toRemove.rbegin(); row != toRemove.rend(); ++row)
        results->removeRow(*row);

      return results;
    }
/**
 * Run new CompareWorkspaces algorithm as a child algorithm.
 *
 * Result string formatted the same way as before; "Success!" when workspaces
 * match or a newline separated list of mismatch messages.
 *
 * @param group_compare Should output be formatted like group comparison?
 * @return A string containing either successString() or mismatch messages
 */
std::string CheckWorkspacesMatch::runCompareWorkspaces(bool group_compare) {
  // This algorithm produces a single result string
  std::string result;

  // Use new CompareWorkspaces algorithm to perform comparison
  Algorithm_sptr compare = this->createChildAlgorithm("CompareWorkspaces");
  compare->setRethrows(true);
  compare->setLogging(false);

  // Forward workspace properties
  Workspace_sptr ws1 = getProperty("Workspace1");
  Workspace_sptr ws2 = getProperty("Workspace2");
  compare->setProperty("Workspace1", ws1);
  compare->setProperty("Workspace2", ws2);

  // Copy any other non-default properties
  const std::vector<Property *> &allProps = this->getProperties();
  auto propCount = allProps.size();
  for (size_t i = 0; i < propCount; ++i) {
    Property *prop = allProps[i];
    const std::string &pname = prop->name();

    if (!prop->isDefault() && pname != "Workspace1" && pname != "Workspace2" &&
        pname != "Result")
      compare->setPropertyValue(pname, prop->value());
  }

  // Execute comparison
  compare->execute();

  // Generate result string
  if (!compare->getProperty("Result")) {
    ITableWorkspace_sptr table = compare->getProperty("Messages");
    auto rowcount = table->rowCount();
    for (size_t i = 0; i < rowcount; ++i) {
      result += table->cell<std::string>(i, 0);

      // Emulate special case output format when comparing groups
      if (group_compare &&
          table->cell<std::string>(i, 0) !=
              "Type mismatch. One workspace is a group, the other is not." &&
          table->cell<std::string>(i, 0) != "GroupWorkspaces size mismatch.") {

        result += ". Inputs=[" + table->cell<std::string>(i, 1) + "," +
                  table->cell<std::string>(i, 2) + "]";
      }

      if (i < (rowcount - 1))
        result += "\n";
    }
  } else {
    result = successString();
  }

  return result;
}
/**
 * Creates a domain from an ITableWorkspace
 *
 * This method creates a LatticeDomain from a table workspace that contains two
 * columns, HKL and d. HKL can either be a V3D-column or a string column,
 * containing three integers separated by space, comma, semi-colon and
 * optionally surrounded by []. The d-column can be double or a string that can
 * be parsed as a double number.
 *
 * @param workspace :: ITableWorkspace with format specified above.
 * @param domain :: Pointer to outgoing FunctionDomain instance.
 * @param values :: Pointer to outgoing FunctionValues object.
 * @param i0 :: Size offset for values object if it already contains data.
 */
void LatticeDomainCreator::createDomainFromPeakTable(
    const ITableWorkspace_sptr &workspace,
    boost::shared_ptr<FunctionDomain> &domain,
    boost::shared_ptr<FunctionValues> &values, size_t i0) {

  size_t peakCount = workspace->rowCount();

  if (peakCount < 1) {
    throw std::range_error("Cannot create a domain for 0 peaks.");
  }

  try {
    Column_const_sptr hklColumn = workspace->getColumn("HKL");
    Column_const_sptr dColumn = workspace->getColumn("d");

    std::vector<V3D> hkls;
    hkls.reserve(peakCount);

    std::vector<double> dSpacings;
    dSpacings.reserve(peakCount);

    V3DFromHKLColumnExtractor extractor;

    for (size_t i = 0; i < peakCount; ++i) {
      try {
        V3D hkl = extractor(hklColumn, i);

        if (hkl != V3D(0, 0, 0)) {
          hkls.push_back(hkl);

          double d = (*dColumn)[i];
          dSpacings.push_back(d);
        }
      } catch (const std::bad_alloc &) {
        // do nothing.
      }
    }

    domain = boost::make_shared<LatticeDomain>(hkls);
    if (!values) {
      values = boost::make_shared<FunctionValues>(*domain);
    } else {
      values->expand(i0 + domain->size());
    }

    values->setFitData(dSpacings);

    values->setFitWeights(1.0);
  } catch (const std::runtime_error &) {
    // Column does not exist
    throw std::runtime_error("Can not process table, the following columns are "
                             "required: HKL, d.");
  }
}
int PoldiFitPeaks1D2::getBestChebyshevPolynomialDegree(
    const Workspace2D_sptr &dataWorkspace, const RefinedRange_sptr &range) {
  double chiSquareMin = 1e10;
  int nMin = -1;

  try {
    int n = 0;

    while ((n < 3)) {
      IAlgorithm_sptr fit = getFitAlgorithm(dataWorkspace, range, n);
      bool fitSuccess = fit->execute();

      if (fitSuccess) {
        ITableWorkspace_sptr fitCharacteristics =
            fit->getProperty("OutputParameters");
        TableRow row =
            fitCharacteristics->getRow(fitCharacteristics->rowCount() - 1);

        double chiSquare = row.Double(1);

        if (fabs(chiSquare - 1) < fabs(chiSquareMin - 1)) {
          chiSquareMin = chiSquare;
          nMin = n;
        }
      }

      ++n;
    }
  } catch (std::runtime_error) {
    nMin = -1;
  }

  if (nMin == -1) {
    g_log.information() << "Range [" << range->getXStart() << " - "
                        << range->getXEnd() << "] is excluded.";
  } else {
    g_log.information() << "Chi^2 for range [" << range->getXStart() << " - "
                        << range->getXEnd() << "] is minimal at n = " << nMin
                        << " with Chi^2 = " << chiSquareMin << std::endl;
  }

  return nMin;
}
std::vector<size_t>
ConcretePeaksPresenter::findVisiblePeakIndexes(const PeakBoundingBox &box) {
  std::vector<size_t> indexes;
  // Don't bother to find peaks in the region if there are no peaks to find.
  if (this->m_peaksWS->getNumberPeaks() >= 1) {

    double radius =
        m_viewPeaks
            ->getRadius(); // Effective radius of each peak representation.

    Mantid::API::IPeaksWorkspace_sptr peaksWS =
        boost::const_pointer_cast<Mantid::API::IPeaksWorkspace>(
            this->m_peaksWS);

    PeakBoundingBox transformedViewableRegion = box.makeSliceBox(radius);

    transformedViewableRegion.transformBox(m_transform);

    Mantid::API::IAlgorithm_sptr alg =
        AlgorithmManager::Instance().create("PeaksInRegion");
    alg->setChild(true);
    alg->setRethrows(true);
    alg->initialize();
    alg->setProperty("InputWorkspace", peaksWS);
    alg->setProperty("OutputWorkspace", peaksWS->name() + "_peaks_in_region");
    alg->setProperty("Extents", transformedViewableRegion.toExtents());
    alg->setProperty("CheckPeakExtents", false); // consider all peaks as points
    alg->setProperty("PeakRadius", radius);
    alg->setPropertyValue("CoordinateFrame", m_transform->getFriendlyName());
    alg->execute();
    ITableWorkspace_sptr outTable = alg->getProperty("OutputWorkspace");

    for (size_t i = 0; i < outTable->rowCount(); ++i) {
      const bool insideRegion = outTable->cell<Boolean>(i, 1);
      if (insideRegion) {
        indexes.push_back(i);
      }
    }
  }
  return indexes;
}
void ConvertTableToMatrixWorkspace::exec()
{
  ITableWorkspace_sptr inputWorkspace = getProperty("InputWorkspace");
  std::string columnX = getProperty("ColumnX");
  std::string columnY = getProperty("ColumnY");
  std::string columnE = getProperty("ColumnE");

  size_t nrows = inputWorkspace->rowCount();
  std::vector<double> X(nrows);
  std::vector<double> Y(nrows);
  std::vector<double> E(nrows);

  inputWorkspace->getColumn(columnX)->numeric_fill(X);
  inputWorkspace->getColumn(columnY)->numeric_fill(Y);

  if (!columnE.empty())
  {
    inputWorkspace->getColumn(columnE)->numeric_fill(E);
  }
  else
  {
    E.assign(X.size(),1.0);
  }

  MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create("Workspace2D",1,X.size(),X.size());
  outputWorkspace->dataX(0).assign(X.begin(),X.end());
  outputWorkspace->dataY(0).assign(Y.begin(),Y.end());
  outputWorkspace->dataE(0).assign(E.begin(),E.end());

  outputWorkspace->generateSpectraMap();
  boost::shared_ptr<Kernel::Units::Label> labelX = boost::dynamic_pointer_cast<Kernel::Units::Label>(
    Kernel::UnitFactory::Instance().create("Label")
    );
  labelX->setLabel(columnX);
  outputWorkspace->getAxis(0)->unit() = labelX;

  outputWorkspace->setYUnitLabel(columnY);

  setProperty("OutputWorkspace", outputWorkspace);

}
/** Setup the data, initialize member variables using a table workspace and
* whitelist
* @param table : A table workspace containing the data
*/
void QDataProcessorTreeModel::setupModelData(ITableWorkspace_sptr table) {

  int nrows = static_cast<int>(table->rowCount());

  int lastIndex = 0;
  std::map<std::string, int> groupIndex;

  for (int r = 0; r < nrows; r++) {

    const std::string &groupName = m_tWS->String(r, 0);

    if (groupIndex.count(groupName) == 0) {
      groupIndex[groupName] = lastIndex++;

      m_groupName.push_back(groupName);
      m_rowsOfGroup.push_back(std::vector<int>());
    }

    m_rowsOfGroup[groupIndex[groupName]].push_back(r);
  }
}
Exemple #12
0
/**
 * Construct a Grouping from a table
 * @param table :: [input] Table to construct from
 */
Grouping::Grouping(ITableWorkspace_sptr table) {
  for (size_t row = 0; row < table->rowCount(); ++row) {
    std::vector<int> detectors = table->cell<std::vector<int>>(row, 0);

    // toString() expects the sequence to be sorted
    std::sort(detectors.begin(), detectors.end());

    // Convert to a range string, i.e. 1-5,6-8,9
    std::string detectorRange = Kernel::Strings::toString(detectors);

    this->groupNames.push_back(std::to_string(row + 1));
    this->groups.push_back(detectorRange);
  }

  // If we have 2 groups only - create a longitudinal pair
  if (this->groups.size() == 2) {
    this->pairNames.emplace_back("long");
    this->pairAlphas.push_back(1.0);
    this->pairs.emplace_back(0, 1);
  }
}
Workspace_sptr GeneralDomainCreator::createOutputWorkspace(
    const std::string &baseName, IFunction_sptr function,
    boost::shared_ptr<FunctionDomain> domain,
    boost::shared_ptr<FunctionValues> values,
    const std::string &outputWorkspacePropertyName) {
  if (function->getValuesSize(*domain) != values->size()) {
    throw std::runtime_error("Failed to create output workspace: domain and "
                             "values object don't match.");
  }
  size_t rowCount = domain->size();
  if (rowCount == 0) {
    auto &generalFunction = dynamic_cast<IFunctionGeneral &>(*function);
    rowCount = generalFunction.getDefaultDomainSize();
  }

  ITableWorkspace_sptr outputWorkspace;

  auto inputWorkspace = getInputWorkspace();
  // Clone the data and domain columns from inputWorkspace to outputWorkspace.
  if (inputWorkspace) {
    // Collect the names of columns to clone
    std::vector<std::string> columnsToClone;
    for (auto &propName : m_domainColumnNames) {
      auto columnName = m_manager->getPropertyValue(propName);
      columnsToClone.push_back(columnName);
    }
    for (auto &propName : m_dataColumnNames) {
      auto columnName = m_manager->getPropertyValue(propName);
      columnsToClone.push_back(columnName);
    }
    outputWorkspace = inputWorkspace->cloneColumns(columnsToClone);
    if (rowCount != outputWorkspace->rowCount()) {
      throw std::runtime_error("Cloned workspace has wrong number of rows.");
    }

    // Add columns with the calculated data
    size_t i0 = 0;
    for (auto &propName : m_dataColumnNames) {
      auto dataColumnName = m_manager->getPropertyValue(propName);
      auto calcColumnName = dataColumnName + "_calc";
      auto column = outputWorkspace->addColumn("double", calcColumnName);
      for (size_t row = 0; row < rowCount; ++row) {
        auto value = values->getCalculated(i0 + row);
        column->fromDouble(row, value);
      }
      i0 += rowCount;
    }
  } else {
    outputWorkspace = API::WorkspaceFactory::Instance().createTable();
    outputWorkspace->setRowCount(rowCount);
    size_t i0 = 0;
    for (auto &propName : m_dataColumnNames) {
      auto calcColumnName = m_manager->getPropertyValue(propName);
      if (calcColumnName.empty()) {
        calcColumnName = propName;
      }
      auto column = outputWorkspace->addColumn("double", calcColumnName);
      for (size_t row = 0; row < rowCount; ++row) {
        auto value = values->getCalculated(i0 + row);
        column->fromDouble(row, value);
      }
      i0 += rowCount;
    }
  }

  if (!outputWorkspacePropertyName.empty()) {
    declareProperty(
        new API::WorkspaceProperty<API::ITableWorkspace>(
            outputWorkspacePropertyName, "", Kernel::Direction::Output),
        "Name of the output Workspace holding resulting simulated values");
    m_manager->setPropertyValue(outputWorkspacePropertyName,
                                baseName + "Workspace");
    m_manager->setProperty(outputWorkspacePropertyName, outputWorkspace);
  }

  return outputWorkspace;
}
    void GetDetOffsetsMultiPeaks::fitSpectra(const int64_t s, MatrixWorkspace_sptr inputW, const std::vector<double> &peakPositions,
                                             const std::vector<double> &fitWindows, size_t &nparams, double &minD, double &maxD,
                                             std::vector<double>&peakPosToFit, std::vector<double>&peakPosFitted,
                                             std::vector<double> &chisq)
    {
      const MantidVec & X = inputW->readX(s);
      minD = X.front();
      maxD = X.back();
      bool useFitWindows = (!fitWindows.empty());
      std::vector<double> fitWindowsToUse;
      for (int i = 0; i < static_cast<int>(peakPositions.size()); ++i)
      {
        if((peakPositions[i] > minD) && (peakPositions[i] < maxD))
        {
          peakPosToFit.push_back(peakPositions[i]);
          if (useFitWindows)
          {
            fitWindowsToUse.push_back(std::max(fitWindows[2*i], minD));
            fitWindowsToUse.push_back(std::min(fitWindows[2*i+1], maxD));
          }
        }
      }

      API::IAlgorithm_sptr findpeaks = createChildAlgorithm("FindPeaks", -1, -1, false);
      findpeaks->setProperty("InputWorkspace", inputW);
      findpeaks->setProperty<int>("FWHM",7);
      findpeaks->setProperty<int>("Tolerance",4);
      // FindPeaks will do the checking on the validity of WorkspaceIndex
      findpeaks->setProperty("WorkspaceIndex",static_cast<int>(s));
  
      //Get the specified peak positions, which is optional
      findpeaks->setProperty("PeakPositions", peakPosToFit);
      if (useFitWindows)
        findpeaks->setProperty("FitWindows", fitWindowsToUse);
      findpeaks->setProperty<std::string>("PeakFunction", m_peakType);
      findpeaks->setProperty<std::string>("BackgroundType", m_backType);
      findpeaks->setProperty<bool>("HighBackground", this->getProperty("HighBackground"));
      findpeaks->setProperty<int>("MinGuessedPeakWidth",4);
      findpeaks->setProperty<int>("MaxGuessedPeakWidth",4);
      findpeaks->executeAsChildAlg();
      ITableWorkspace_sptr peakslist = findpeaks->getProperty("PeaksList");
      std::vector<size_t> banned;
      std::vector<double> peakWidFitted;
      std::vector<double> peakHighFitted;
      std::vector<double> peakBackground;
      for (size_t i = 0; i < peakslist->rowCount(); ++i)
      {
        // peak value
        double centre = peakslist->getRef<double>("centre",i);
        double width = peakslist->getRef<double>("width",i);
        double height = peakslist->getRef<double>("height", i);

        // 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;

        // goodness of fit
        double chi2 = peakslist->getRef<double>("chi2",i);

        // Get references to the data
        peakPosFitted.push_back(centre);
        peakWidFitted.push_back(width);
        peakHighFitted.push_back(height);
        peakBackground.push_back(background);
        chisq.push_back(chi2);
      }

      // first remove things that just didn't fit (center outside of window, bad chisq, ...)
      for (size_t i = 0; i < peakslist->rowCount(); ++i)
      {
        if (peakPosFitted[i] <= minD || peakPosFitted[i] >= maxD)
        {
            banned.push_back(i);
            continue;
        }
        else if (useFitWindows) // be more restrictive if fit windows were specified
        {
          if (peakPosFitted[i] <= fitWindowsToUse[2*i]
              || peakPosFitted[i] >= fitWindowsToUse[2*i+1])
          {
            banned.push_back(i);
            continue;
          }
        }
        if (chisq[i] > m_maxChiSq)
        {
          banned.push_back(i);
          continue;
        }
      }
      // delete banned peaks
      g_log.debug() << "Deleting " << banned.size() << " of " << peakPosFitted.size()
                    << " peaks in wkspindex = " << s << "\n";
      deletePeaks(banned, peakPosToFit, peakPosFitted,
                  peakWidFitted, peakHighFitted, peakBackground,
                  chisq);

      // ban peaks that are low intensity compared to their widths
      for (size_t i = 0; i < peakWidFitted.size(); ++i)
      {
        if (peakHighFitted[i]  * FWHM_TO_SIGMA / peakWidFitted[i] < 5.)
        {
          g_log.debug() << "Banning peak at " << peakPosFitted[i] << " in wkspindex = " << s
                         << " I/sigma = " << (peakHighFitted[i] * FWHM_TO_SIGMA / peakWidFitted[i]) << "\n";
          banned.push_back(i);
          continue;
        }
      }
      // delete banned peaks
      g_log.debug() << "Deleting " << banned.size() << " of " << peakPosFitted.size()
                    << " peaks in wkspindex = " << s << "\n";
      deletePeaks(banned, peakPosToFit, peakPosFitted,
                  peakWidFitted, peakHighFitted, peakBackground,
                  chisq);

      // determine the (z-value) for constant "width" - (delta d)/d
      std::vector<double> widthDivPos(peakWidFitted.size(), 0.); // DELETEME
      for (size_t i = 0; i < peakWidFitted.size(); ++i)
      {
        widthDivPos[i] = peakWidFitted[i] / peakPosFitted[i]; // DELETEME
      }
      std::vector<double> Zscore = getZscore(widthDivPos);
      for (size_t i = 0; i < peakWidFitted.size(); ++i)
      {
        if (Zscore[i] > 2.0)
        {
          g_log.debug() << "Banning peak at " << peakPosFitted[i] << " in wkspindex = " << s
                         << " sigma/d = " << widthDivPos[i] << "\n";
          banned.push_back(i);
          continue;
        }
      }
      // delete banned peaks
      g_log.debug() << "Deleting " << banned.size() << " of " << peakPosFitted.size()
                    << " peaks in wkspindex = " << s << "\n";
      deletePeaks(banned, peakPosToFit, peakPosFitted,
                  peakWidFitted, peakHighFitted, peakBackground,
                  chisq);

      // ban peaks that are not outside of error bars for the background
      for (size_t i = 0; i < peakWidFitted.size(); ++i)
      {
        if (peakHighFitted[i] < 0.5 * std::sqrt(peakHighFitted[i] + peakBackground[i]))
        {
          g_log.debug() << "Banning peak at " << peakPosFitted[i] << " in wkspindex = " << s
                         << " " << peakHighFitted[i] << " < "
                         << 0.5 * std::sqrt(peakHighFitted[i] + peakBackground[i]) << "\n";
          banned.push_back(i);
          continue;
        }
      }
      // delete banned peaks
      g_log.debug() << "Deleting " << banned.size() << " of " << peakPosFitted.size()
                    << " peaks in wkspindex = " << s << "\n";
      deletePeaks(banned, peakPosToFit, peakPosFitted,
                  peakWidFitted, peakHighFitted, peakBackground,
                  chisq);

      nparams = peakPosFitted.size();
      return;
    }