Example #1
0
/** Initialise a workspace from its parent
 * This sets values such as title, instrument, units, sample, spectramap.
 * This does NOT copy any data.
 *
 * @param parent :: the parent workspace
 * @param child :: the child workspace
 * @param differentSize :: A flag to indicate if the two workspace will be different sizes
 */
void WorkspaceFactoryImpl::initializeFromParent(const MatrixWorkspace_const_sptr parent,
  const MatrixWorkspace_sptr child, const bool differentSize) const
{
  child->setTitle(parent->getTitle());
  child->setComment(parent->getComment());
  child->setInstrument(parent->getInstrument());  // This call also copies the SHARED POINTER to the parameter map
  // This call will (should) perform a COPY of the parameter map.
  child->instrumentParameters();
  child->m_sample = parent->m_sample;
  child->m_run = parent->m_run;
  child->setYUnit(parent->m_YUnit);
  child->setYUnitLabel(parent->m_YUnitLabel);
  child->isDistribution(parent->isDistribution());

  // Only copy the axes over if new sizes are not given
  if ( !differentSize )
  {
    // Only copy mask map if same size for now. Later will need to check continued validity.
    child->m_masks = parent->m_masks;
  }

  // Same number of histograms = copy over the spectra data
  if (parent->getNumberHistograms() == child->getNumberHistograms())
  {
    for (size_t wi=0; wi<parent->getNumberHistograms(); wi++)
    {
      ISpectrum * childSpec = child->getSpectrum(wi);
      const ISpectrum * parentSpec = parent->getSpectrum(wi);
      // Copy spectrum number and detector IDs
      childSpec->copyInfoFrom(*parentSpec);
    }
  }

  // deal with axis
  for (size_t i = 0; i < parent->m_axes.size(); ++i)
  {
    const size_t newAxisLength = child->getAxis(i)->length();
    const size_t oldAxisLength = parent->getAxis(i)->length();

    if ( !differentSize || newAxisLength == oldAxisLength )
    {
      // Need to delete the existing axis created in init above
      delete child->m_axes[i];
      // Now set to a copy of the parent workspace's axis
      child->m_axes[i] = parent->m_axes[i]->clone(child.get());
    }
    else
    {
      if (! parent->getAxis(i)->isSpectra()) // WHY???
      {
        delete child->m_axes[i];
        // Call the 'different length' clone variant
        child->m_axes[i] = parent->m_axes[i]->clone(newAxisLength,child.get());
      }
    }
  }

  return;
}
  /**
   * Start fitting process.
   */
  void MuonSequentialFitDialog::startFit()
  {
    if ( m_state != Stopped )
      throw std::runtime_error("Couln't start: already running");

    setState(Preparing);

    // Explicitly run the file search. This might be needed when Start is clicked straigh after 
    // editing the run box. In that case, lost focus event might not be processed yet and search
    // might not have been started yet. Otherwise, search is not done as the widget sees that it
    // has not been changed. Taken from LoadDialog.cpp:124.
    m_ui.runs->findFiles();

    // Wait for file search to finish.
    while ( m_ui.runs->isSearching() )
    {
      QApplication::processEvents();
    }

    // To process events from the finished thread
    QApplication::processEvents();

    // Validate input fields
    if ( ! isInputValid() )
    {
      QMessageBox::critical(this, "Input is not valid", 
        "One or more input fields are invalid.\n\nInvalid fields are marked with a '*'.");
      setState(Stopped);
      return;
    }

    QStringList runFilenames = m_ui.runs->getFilenames();

    const std::string label = m_ui.labelInput->text().toStdString();
    const std::string labelGroupName = SEQUENTIAL_PREFIX + label;

    AnalysisDataServiceImpl& ads = AnalysisDataService::Instance();

    if ( ads.doesExist(labelGroupName) )
    {
      QMessageBox::StandardButton answer = QMessageBox::question(this, "Label already exists", 
          "Label you specified was used for one of the previous fits. Do you want to overwrite it?", 
          QMessageBox::Yes | QMessageBox::Cancel);

      if ( answer != QMessageBox::Yes )
      {
        setState(Stopped);
        return;
      }

      ads.deepRemoveGroup(labelGroupName);
    }
   
    // Create a group for label
    ads.add(labelGroupName, boost::make_shared<WorkspaceGroup>());

    // Tell progress bar how many iterations we will need to make and reset it
    m_ui.progress->setRange( 0, runFilenames.size() );
    m_ui.progress->setFormat("%p%");
    m_ui.progress->setValue(0);

    // Clear diagnosis table for new fit
    m_ui.diagnosisTable->setRowCount(0);

    // Get fit function as specified by user in the fit browser
    IFunction_sptr fitFunction = FunctionFactory::Instance().createInitialized(
        m_fitPropBrowser->getFittingFunction()->asString() );

    // Whether we should use initial function for every fit
    bool useInitFitFunction = (m_ui.paramTypeGroup->checkedButton() == m_ui.paramTypeInitial);

    setState(Running);
    m_stopRequested = false;

    for ( auto fileIt = runFilenames.constBegin(); fileIt != runFilenames.constEnd(); ++fileIt )
    {
      // Process events (so that Stop button press is processed)
      QApplication::processEvents();

      // Stop if requested by user
      if ( m_stopRequested )
        break;

      MatrixWorkspace_sptr ws;

      try {
        auto load = AlgorithmManager::Instance().create("MuonLoad");
        load->initialize();
        load->setChild(true);
        load->setRethrows(true);
        load->updatePropertyValues(*m_loadAlg);
        load->setPropertyValue("Filename", fileIt->toStdString());
        load->setPropertyValue("OutputWorkspace", "__YouDontSeeMeIAmNinja");
        if (m_fitPropBrowser->rawData()) // TODO: or vice verca?
          load->setPropertyValue("RebinParams", "");

        load->execute();

        ws = load->getProperty("OutputWorkspace");
      } catch (...) {
        QMessageBox::critical(
            this, "Loading failed",
            "Unable to load one of the files.\n\nCheck log for details");
        break;
      }

      const std::string runTitle = getRunTitle(ws);
      const std::string wsBaseName = labelGroupName + "_" + runTitle; 

      IFunction_sptr functionToFit;

      if ( useInitFitFunction )
        // Create a copy so that the original function is not changed
        functionToFit = FunctionFactory::Instance().createInitialized( fitFunction->asString() );
      else
        // Use the same function over and over, so that previous fitted params are used for the next fit
        functionToFit = fitFunction;

      IAlgorithm_sptr fit = AlgorithmManager::Instance().create("Fit");
      fit->setRethrows(true);

      try 
      {

        // Set function. Gets updated when fit is done. 
        fit->setProperty("Function", functionToFit);

        fit->setProperty("InputWorkspace", ws);
        fit->setProperty("Output", wsBaseName);

        // We should have one spectra only in the workspace, so use the first one.
        fit->setProperty("WorkspaceIndex", 0);

        // Various properties from the fit prop. browser
        fit->setProperty("StartX", m_fitPropBrowser->startX());
        fit->setProperty("EndX", m_fitPropBrowser->endX());
        fit->setProperty("Minimizer", m_fitPropBrowser->minimizer());
        fit->setProperty("CostFunction", m_fitPropBrowser->costFunction());

        fit->execute();
      }
      catch(...)
      {
        QMessageBox::critical(this, "Fitting failed", 
            "Unable to fit one of the files.\n\nCheck log for details");
        break;
      }

      // Make sure created fit workspaces end-up in the group
      // TODO: this really should use loop
      ads.addToGroup(labelGroupName, wsBaseName + "_NormalisedCovarianceMatrix");
      ads.addToGroup(labelGroupName, wsBaseName + "_Parameters");
      ads.addToGroup(labelGroupName, wsBaseName + "_Workspace");

      // Copy log values
      auto fitWs = ads.retrieveWS<MatrixWorkspace>(wsBaseName + "_Workspace");
      fitWs->copyExperimentInfoFrom(ws.get());

      // Add information about the fit to the diagnosis table
      addDiagnosisEntry(runTitle, fit->getProperty("OutputChi2OverDof"), functionToFit); 

      // Update progress
      m_ui.progress->setFormat("%p% - " + QString::fromStdString(runTitle) );
      m_ui.progress->setValue( m_ui.progress->value() + 1 );
    }

    setState(Stopped);
  }
Example #3
0
/** Executes the rebin algorithm
*
*  @throw runtime_error Thrown if the bin range does not intersect the range of
*the input workspace
*/
void Rebin::exec() {
  // Get the input workspace
  MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
  MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");

  // Are we preserving event workspace-iness?
  bool PreserveEvents = getProperty("PreserveEvents");

  // Rebinning in-place
  bool inPlace = (inputWS == outputWS);

  std::vector<double> rbParams =
      rebinParamsFromInput(getProperty("Params"), *inputWS, g_log);

  const bool dist = inputWS->isDistribution();
  const bool isHist = inputWS->isHistogramData();

  // workspace independent determination of length
  const int histnumber = static_cast<int>(inputWS->getNumberHistograms());

  //-------------------------------------------------------

  bool fullBinsOnly = getProperty("FullBinsOnly");

  MantidVecPtr XValues_new;
  // create new output X axis
  const int ntcnew = VectorHelper::createAxisFromRebinParams(
      rbParams, XValues_new.access(), true, fullBinsOnly);

  //---------------------------------------------------------------------------------
  // Now, determine if the input workspace is actually an EventWorkspace
  EventWorkspace_const_sptr eventInputWS =
      boost::dynamic_pointer_cast<const EventWorkspace>(inputWS);

  if (eventInputWS != NULL) {
    //------- EventWorkspace as input -------------------------------------
    EventWorkspace_sptr eventOutputWS =
        boost::dynamic_pointer_cast<EventWorkspace>(outputWS);

    if (inPlace && PreserveEvents) {
      // -------------Rebin in-place, preserving events
      // ----------------------------------------------
      // This only sets the X axis. Actual rebinning will be done upon data
      // access.
      eventOutputWS->setAllX(XValues_new);
      this->setProperty(
          "OutputWorkspace",
          boost::dynamic_pointer_cast<MatrixWorkspace>(eventOutputWS));
    } else if (!inPlace && PreserveEvents) {
      // -------- NOT in-place, but you want to keep events for some reason.
      // ----------------------
      // Must copy the event workspace to a new EventWorkspace (and bin that).

      // Make a brand new EventWorkspace
      eventOutputWS = boost::dynamic_pointer_cast<EventWorkspace>(
          API::WorkspaceFactory::Instance().create(
              "EventWorkspace", inputWS->getNumberHistograms(), 2, 1));
      // Copy geometry over.
      API::WorkspaceFactory::Instance().initializeFromParent(
          inputWS, eventOutputWS, false);
      // You need to copy over the data as well.
      eventOutputWS->copyDataFrom((*eventInputWS));

      // This only sets the X axis. Actual rebinning will be done upon data
      // access.
      eventOutputWS->setAllX(XValues_new);

      // Cast to the matrixOutputWS and save it
      this->setProperty(
          "OutputWorkspace",
          boost::dynamic_pointer_cast<MatrixWorkspace>(eventOutputWS));
    } else {
      //--------- Different output, OR you're inplace but not preserving Events
      //--- create a Workspace2D -------
      g_log.information() << "Creating a Workspace2D from the EventWorkspace "
                          << eventInputWS->getName() << ".\n";

      // Create a Workspace2D
      // This creates a new Workspace2D through a torturous route using the
      // WorkspaceFactory.
      // The Workspace2D is created with an EMPTY CONSTRUCTOR
      outputWS = WorkspaceFactory::Instance().create("Workspace2D", histnumber,
                                                     ntcnew, ntcnew - 1);
      WorkspaceFactory::Instance().initializeFromParent(inputWS, outputWS,
                                                        true);

      // Initialize progress reporting.
      Progress prog(this, 0.0, 1.0, histnumber);

      // Go through all the histograms and set the data
      PARALLEL_FOR3(inputWS, eventInputWS, outputWS)
      for (int i = 0; i < histnumber; ++i) {
        PARALLEL_START_INTERUPT_REGION

        // Set the X axis for each output histogram
        outputWS->setX(i, XValues_new);

        // Get a const event list reference. eventInputWS->dataY() doesn't work.
        const EventList &el = eventInputWS->getEventList(i);
        MantidVec y_data, e_data;
        // The EventList takes care of histogramming.
        el.generateHistogram(*XValues_new, y_data, e_data);

        // Copy the data over.
        outputWS->dataY(i).assign(y_data.begin(), y_data.end());
        outputWS->dataE(i).assign(e_data.begin(), e_data.end());

        // Report progress
        prog.report(name());
        PARALLEL_END_INTERUPT_REGION
      }
      PARALLEL_CHECK_INTERUPT_REGION

      // Copy all the axes
      for (int i = 1; i < inputWS->axes(); i++) {
        outputWS->replaceAxis(i, inputWS->getAxis(i)->clone(outputWS.get()));
        outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
      }

      // Copy the units over too.
      for (int i = 0; i < outputWS->axes(); ++i)
        outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
      outputWS->setYUnit(eventInputWS->YUnit());
      outputWS->setYUnitLabel(eventInputWS->YUnitLabel());

      // Assign it to the output workspace property
      setProperty("OutputWorkspace", outputWS);
    }

  } // END ---- EventWorkspace
Example #4
0
/** Execute the algorithm.
 */
void ResampleX::exec() {
  // generically having access to the input workspace is a good idea
  MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
  MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
  bool inPlace = (inputWS == outputWS); // Rebinning in-place
  m_isDistribution = inputWS->isDistribution();
  m_isHistogram = inputWS->isHistogramData();
  int numSpectra = static_cast<int>(inputWS->getNumberHistograms());

  // the easy parameters
  m_useLogBinning = getProperty("LogBinning");
  m_numBins = getProperty("NumberBins");
  m_preserveEvents = getProperty("PreserveEvents");

  // determine the xmin/xmax for the workspace
  vector<double> xmins = getProperty("XMin");
  vector<double> xmaxs = getProperty("XMax");
  string error = determineXMinMax(inputWS, xmins, xmaxs);
  if (!error.empty())
    throw std::runtime_error(error);

  bool common_limits = true;
  {
    double xmin_common = xmins[0];
    double xmax_common = xmaxs[0];
    for (size_t i = 1; i < xmins.size(); ++i) {
      if (xmins[i] != xmin_common) {
        common_limits = false;
        break;
      }
      if (xmaxs[i] != xmax_common) {
        common_limits = false;
        break;
      }
    }
  }
  if (common_limits) {
    g_log.debug() << "Common limits between all spectra\n";
  } else {
    g_log.debug() << "Does not have common limits between all spectra\n";
  }

  // start doing actual work
  EventWorkspace_const_sptr inputEventWS =
      boost::dynamic_pointer_cast<const EventWorkspace>(inputWS);
  if (inputEventWS != NULL) {
    if (m_preserveEvents) {
      EventWorkspace_sptr outputEventWS =
          boost::dynamic_pointer_cast<EventWorkspace>(outputWS);
      if (inPlace) {
        g_log.debug() << "Rebinning event workspace in place\n";
      } else {
        g_log.debug() << "Rebinning event workspace out of place\n";

        // copy the event workspace to a new EventWorkspace
        outputEventWS = boost::dynamic_pointer_cast<EventWorkspace>(
            API::WorkspaceFactory::Instance().create(
                "EventWorkspace", inputWS->getNumberHistograms(), 2, 1));
        // copy geometry over.
        API::WorkspaceFactory::Instance().initializeFromParent(
            inputEventWS, outputEventWS, false);
        // copy over the data as well.
        outputEventWS->copyDataFrom((*inputEventWS));
      }

      if (common_limits) {
        // get the delta from the first since they are all the same
        MantidVecPtr xValues;
        double delta =
            this->determineBinning(xValues.access(), xmins[0], xmaxs[0]);
        g_log.debug() << "delta = " << delta << "\n";
        outputEventWS->setAllX(xValues);
      } else {
        // initialize progress reporting.
        Progress prog(this, 0.0, 1.0, numSpectra);

        // do the rebinning
        PARALLEL_FOR2(inputEventWS, outputWS)
        for (int wkspIndex = 0; wkspIndex < numSpectra; ++wkspIndex) {
          PARALLEL_START_INTERUPT_REGION
          MantidVec xValues;
          double delta = this->determineBinning(xValues, xmins[wkspIndex],
                                                xmaxs[wkspIndex]);
          g_log.debug() << "delta[wkspindex=" << wkspIndex << "] = " << delta
                        << " xmin=" << xmins[wkspIndex]
                        << " xmax=" << xmaxs[wkspIndex] << "\n";
          outputEventWS->getSpectrum(wkspIndex)->setX(xValues);
          prog.report(name()); // Report progress
          PARALLEL_END_INTERUPT_REGION
        }
        PARALLEL_CHECK_INTERUPT_REGION
      }

      this->setProperty(
          "OutputWorkspace",
          boost::dynamic_pointer_cast<MatrixWorkspace>(outputEventWS));
    }    // end if (m_preserveEvents)
    else // event workspace -> matrix workspace
    {
      //--------- Different output, OR you're inplace but not preserving Events
      //--- create a Workspace2D -------
      g_log.information() << "Creating a Workspace2D from the EventWorkspace "
                          << inputEventWS->getName() << ".\n";

      // Create a Workspace2D
      // This creates a new Workspace2D through a torturous route using the
      // WorkspaceFactory.
      // The Workspace2D is created with an EMPTY CONSTRUCTOR
      outputWS = WorkspaceFactory::Instance().create("Workspace2D", numSpectra,
                                                     m_numBins, m_numBins - 1);
      WorkspaceFactory::Instance().initializeFromParent(inputWS, outputWS,
                                                        true);
      // Initialize progress reporting.
      Progress prog(this, 0.0, 1.0, numSpectra);

      // Go through all the histograms and set the data
      PARALLEL_FOR2(inputEventWS, outputWS)
      for (int wkspIndex = 0; wkspIndex < numSpectra; ++wkspIndex) {
        PARALLEL_START_INTERUPT_REGION

        // Set the X axis for each output histogram
        MantidVec xValues;
        double delta =
            this->determineBinning(xValues, xmins[wkspIndex], xmaxs[wkspIndex]);
        g_log.debug() << "delta[wkspindex=" << wkspIndex << "] = " << delta
                      << "\n";
        outputWS->setX(wkspIndex, xValues);

        // Get a const event list reference. inputEventWS->dataY() doesn't work.
        const EventList &el = inputEventWS->getEventList(wkspIndex);
        MantidVec y_data, e_data;
        // The EventList takes care of histogramming.
        el.generateHistogram(xValues, y_data, e_data);

        // Copy the data over.
        outputWS->dataY(wkspIndex).assign(y_data.begin(), y_data.end());
        outputWS->dataE(wkspIndex).assign(e_data.begin(), e_data.end());

        // Report progress
        prog.report(name());
        PARALLEL_END_INTERUPT_REGION
      }
      PARALLEL_CHECK_INTERUPT_REGION

      // Copy all the axes
      for (int i = 1; i < inputWS->axes(); i++) {
        outputWS->replaceAxis(i, inputWS->getAxis(i)->clone(outputWS.get()));
        outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
      }

      // Copy the units over too.
      for (int i = 0; i < outputWS->axes(); ++i)
        outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
      outputWS->setYUnit(inputEventWS->YUnit());
      outputWS->setYUnitLabel(inputEventWS->YUnitLabel());

      // Assign it to the output workspace property
      setProperty("OutputWorkspace", outputWS);
    }
    return;
  } else // (inputeventWS != NULL)
Example #5
0
/**
 * Execute the algorithm.
 */
void RebinByTimeBase::exec() {
  using Mantid::DataObjects::EventWorkspace;
  IEventWorkspace_sptr inWS = getProperty("InputWorkspace");

  if (!boost::dynamic_pointer_cast<EventWorkspace>(inWS)) {
    const std::string algName = this->name();
    throw std::invalid_argument(
        algName + " Algorithm requires an EventWorkspace as an input.");
  }

  MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");

  // retrieve the properties
  const std::vector<double> inParams = getProperty("Params");
  std::vector<double> rebinningParams;

  // workspace independent determination of length
  const int histnumber = static_cast<int>(inWS->getNumberHistograms());

  const uint64_t nanoSecondsInASecond = static_cast<uint64_t>(1e9);
  const DateAndTime runStartTime = inWS->run().startTime();
  // The validator only passes parameters with size 1, or 3xn.

  double tStep = 0;
  if (inParams.size() >= 3) {
    // Use the start of the run to offset the times provided by the user. pulse
    // time of the events are absolute.
    const DateAndTime startTime = runStartTime + inParams[0];
    const DateAndTime endTime = runStartTime + inParams[2];
    // Rebinning params in nanoseconds.
    rebinningParams.push_back(
        static_cast<double>(startTime.totalNanoseconds()));
    tStep = inParams[1] * nanoSecondsInASecond;
    rebinningParams.push_back(tStep);
    rebinningParams.push_back(static_cast<double>(endTime.totalNanoseconds()));
  } else if (inParams.size() == 1) {
    const uint64_t xmin = getMinX(inWS);
    const uint64_t xmax = getMaxX(inWS);

    rebinningParams.push_back(static_cast<double>(xmin));
    tStep = inParams[0] * nanoSecondsInASecond;
    rebinningParams.push_back(tStep);
    rebinningParams.push_back(static_cast<double>(xmax));
  }

  // Validate the timestep.
  if (tStep <= 0) {
    throw std::invalid_argument(
        "Cannot have a timestep less than or equal to zero.");
  }

  // Initialize progress reporting.
  Progress prog(this, 0.0, 1.0, histnumber);

  MantidVecPtr XValues_new;
  // create new X axis, with absolute times in seconds.
  const int ntcnew = VectorHelper::createAxisFromRebinParams(
      rebinningParams, XValues_new.access());

  ConvertToRelativeTime transformToRelativeT(runStartTime);

  // Transform the output into relative times in seconds.
  MantidVec OutXValues_scaled(XValues_new->size());
  std::transform(XValues_new->begin(), XValues_new->end(),
                 OutXValues_scaled.begin(), transformToRelativeT);

  outputWS = WorkspaceFactory::Instance().create("Workspace2D", histnumber,
                                                 ntcnew, ntcnew - 1);
  WorkspaceFactory::Instance().initializeFromParent(inWS, outputWS, true);

  // Copy all the axes
  for (int i = 1; i < inWS->axes(); i++) {
    outputWS->replaceAxis(i, inWS->getAxis(i)->clone(outputWS.get()));
    outputWS->getAxis(i)->unit() = inWS->getAxis(i)->unit();
  }

  // X-unit is relative time since the start of the run.
  outputWS->getAxis(0)->unit() = boost::make_shared<Units::Time>();

  // Copy the units over too.
  for (int i = 1; i < outputWS->axes(); ++i) {
    outputWS->getAxis(i)->unit() = inWS->getAxis(i)->unit();
  }
  outputWS->setYUnit(inWS->YUnit());
  outputWS->setYUnitLabel(inWS->YUnitLabel());

  // Assign it to the output workspace property
  setProperty("OutputWorkspace", outputWS);

  // Go through all the histograms and set the data
  doHistogramming(inWS, outputWS, XValues_new, OutXValues_scaled, prog);
}
Example #6
0
/** Execute the algorithm.
 */
void ResampleX::exec() {
  // generically having access to the input workspace is a good idea
  MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
  MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
  bool inPlace = (inputWS == outputWS); // Rebinning in-place
  m_isDistribution = inputWS->isDistribution();
  m_isHistogram = inputWS->isHistogramData();
  const int numSpectra = static_cast<int>(inputWS->getNumberHistograms());

  // the easy parameters
  m_useLogBinning = getProperty("LogBinning");
  m_numBins = getProperty("NumberBins");
  m_preserveEvents = getProperty("PreserveEvents");

  // determine the xmin/xmax for the workspace
  vector<double> xmins = getProperty("XMin");
  vector<double> xmaxs = getProperty("XMax");
  string error = determineXMinMax(inputWS, xmins, xmaxs);
  if (!error.empty())
    throw std::runtime_error(error);

  bool common_limits = true;
  {
    double xmin_common = xmins[0];
    double xmax_common = xmaxs[0];
    for (size_t i = 1; i < xmins.size(); ++i) {
      if (xmins[i] != xmin_common) {
        common_limits = false;
        break;
      }
      if (xmaxs[i] != xmax_common) {
        common_limits = false;
        break;
      }
    }
  }
  if (common_limits) {
    g_log.debug() << "Common limits between all spectra\n";
  } else {
    g_log.debug() << "Does not have common limits between all spectra\n";
  }

  // start doing actual work
  EventWorkspace_const_sptr inputEventWS =
      boost::dynamic_pointer_cast<const EventWorkspace>(inputWS);
  if (inputEventWS != nullptr) {
    if (m_preserveEvents) {
      if (inPlace) {
        g_log.debug() << "Rebinning event workspace in place\n";
      } else {
        g_log.debug() << "Rebinning event workspace out of place\n";
        outputWS = inputWS->clone();
      }
      auto outputEventWS =
          boost::dynamic_pointer_cast<EventWorkspace>(outputWS);

      if (common_limits) {
        // get the delta from the first since they are all the same
        BinEdges xValues(0);
        const double delta = this->determineBinning(xValues.mutableRawData(),
                                                    xmins[0], xmaxs[0]);
        g_log.debug() << "delta = " << delta << "\n";
        outputEventWS->setAllX(xValues);
      } else {
        // initialize progress reporting.
        Progress prog(this, 0.0, 1.0, numSpectra);

        // do the rebinning
        PARALLEL_FOR_IF(Kernel::threadSafe(*inputEventWS, *outputWS))
        for (int wkspIndex = 0; wkspIndex < numSpectra; ++wkspIndex) {
          PARALLEL_START_INTERUPT_REGION
          BinEdges xValues(0);
          const double delta = this->determineBinning(
              xValues.mutableRawData(), xmins[wkspIndex], xmaxs[wkspIndex]);
          g_log.debug() << "delta[wkspindex=" << wkspIndex << "] = " << delta
                        << " xmin=" << xmins[wkspIndex]
                        << " xmax=" << xmaxs[wkspIndex] << "\n";
          outputEventWS->setHistogram(wkspIndex, xValues);
          prog.report(name()); // Report progress
          PARALLEL_END_INTERUPT_REGION
        }
        PARALLEL_CHECK_INTERUPT_REGION
      }
    }    // end if (m_preserveEvents)
    else // event workspace -> matrix workspace
    {
      //--------- Different output, OR you're inplace but not preserving Events
      g_log.information() << "Creating a Workspace2D from the EventWorkspace "
                          << inputEventWS->getName() << ".\n";
      outputWS = create<DataObjects::Workspace2D>(
          *inputWS, numSpectra, HistogramData::BinEdges(m_numBins + 1));

      // Initialize progress reporting.
      Progress prog(this, 0.0, 1.0, numSpectra);

      // Go through all the histograms and set the data
      PARALLEL_FOR_IF(Kernel::threadSafe(*inputEventWS, *outputWS))
      for (int wkspIndex = 0; wkspIndex < numSpectra; ++wkspIndex) {
        PARALLEL_START_INTERUPT_REGION

        // Set the X axis for each output histogram
        MantidVec xValues;
        const double delta =
            this->determineBinning(xValues, xmins[wkspIndex], xmaxs[wkspIndex]);
        g_log.debug() << "delta[wkspindex=" << wkspIndex << "] = " << delta
                      << "\n";
        outputWS->setBinEdges(wkspIndex, xValues);

        // Get a const event list reference. inputEventWS->dataY() doesn't work.
        const EventList &el = inputEventWS->getSpectrum(wkspIndex);
        MantidVec y_data, e_data;
        // The EventList takes care of histogramming.
        el.generateHistogram(xValues, y_data, e_data);

        // Copy the data over.
        outputWS->mutableY(wkspIndex) = std::move(y_data);
        outputWS->mutableE(wkspIndex) = std::move(e_data);

        // Report progress
        prog.report(name());
        PARALLEL_END_INTERUPT_REGION
      }
      PARALLEL_CHECK_INTERUPT_REGION

      // Copy all the axes
      for (int i = 1; i < inputWS->axes(); i++) {
        outputWS->replaceAxis(i, inputWS->getAxis(i)->clone(outputWS.get()));
        outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
      }

      // Copy the units over too.
      for (int i = 0; i < outputWS->axes(); ++i) {
        outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
      }
      outputWS->setYUnit(inputEventWS->YUnit());
      outputWS->setYUnitLabel(inputEventWS->YUnitLabel());
    }
    // Assign it to the output workspace property
    setProperty("OutputWorkspace", outputWS);
    return;
  } else // (inputeventWS != NULL)