Example #1
0
void StepScan::fillPlotVarCombobox( const MatrixWorkspace_const_sptr & ws )
{
  // Hold the name of the scan index log in a common place
  const std::string scan_index("scan_index");
  // Clear the combobox and immediately re-insert 'scan_index' (so it's the first entry)
  m_uiForm.plotVariable->clear();
  m_uiForm.plotVariable->addItem( QString::fromStdString(scan_index) );

  // First check that the provided workspace has the scan_index - complain if it doesn't
  try {
    auto scan_index_prop = ws->run().getTimeSeriesProperty<int>(scan_index);
    if ( scan_index_prop->realSize() < 2 )
    {
      // TODO: This might be mistakenly triggered for live datasets.
      QMessageBox::warning(this,"scan_index log empty","This data does not appear to be an alignment scan");
      return;
    }
  } catch ( std::exception& ) {
  // Old way: ws->run().hasProperty(scan_index)
    QMessageBox::warning(this,"scan_index log not found","Is this an ADARA-style dataset?");
    return;
  }

  // This is unfortunately more or less a copy of SumEventsByLogValue::getNumberSeriesLogs
  // but I want to populate the box before running the algorithm
  const auto & logs = ws->run().getLogData();
  for ( auto log = logs.begin(); log != logs.end(); ++log )
  {
    const std::string logName = (*log)->name();
    // Don't add scan_index - that's already there
    if ( logName == scan_index ) continue;
    // Try to cast to an ITimeSeriesProperty
    auto tsp = dynamic_cast<const ITimeSeriesProperty*>(*log);
    // Move on to the next one if this is not a TSP
    if ( tsp == NULL ) continue;
    // Don't keep ones with only one entry
    if ( tsp->realSize() < 2 ) continue;
    // Now make sure it's either an int or double tsp, and if so add log to the list
    if ( dynamic_cast<TimeSeriesProperty<double>* >(*log) || dynamic_cast<TimeSeriesProperty<int>* >(*log))
    {
      m_uiForm.plotVariable->addItem( QString::fromStdString( logName ) );
    }
  }

  // Now that this has been populated, allow the user to select from it
  m_uiForm.plotVariable->setEnabled(true);
  // Now's the time to enable the start button as well
  m_uiForm.startButton->setEnabled(true);
}
Example #2
0
double
ConvertSpectrumAxis::getEfixed(const Mantid::Geometry::IDetector &detector,
                               MatrixWorkspace_const_sptr inputWS,
                               int emode) const {
  double efixed(0);
  double efixedProp = getProperty("Efixed");
  if (efixedProp != EMPTY_DBL()) {
    efixed = efixedProp;
    g_log.debug() << "Detector: " << detector.getID() << " Efixed: " << efixed
                  << "\n";
  } else {
    if (emode == 1) {
      if (inputWS->run().hasProperty("Ei")) {
        Kernel::Property *p = inputWS->run().getProperty("Ei");
        Kernel::PropertyWithValue<double> *doublep =
            dynamic_cast<Kernel::PropertyWithValue<double> *>(p);
        if (doublep) {
          efixed = (*doublep)();
        } else {
          efixed = 0.0;
          g_log.warning() << "Efixed could not be found for detector "
                          << detector.getID() << ", set to 0.0\n";
        }
      } else {
        efixed = 0.0;
        g_log.warning() << "Efixed could not be found for detector "
                        << detector.getID() << ", set to 0.0\n";
      }
    } else if (emode == 2) {
      std::vector<double> efixedVec = detector.getNumberParameter("Efixed");
      if (efixedVec.empty()) {
        int detid = detector.getID();
        IDetector_const_sptr detectorSingle =
            inputWS->getInstrument()->getDetector(detid);
        efixedVec = detectorSingle->getNumberParameter("Efixed");
      }
      if (!efixedVec.empty()) {
        efixed = efixedVec.at(0);
        g_log.debug() << "Detector: " << detector.getID()
                      << " EFixed: " << efixed << "\n";
      } else {
        efixed = 0.0;
        g_log.warning() << "Efixed could not be found for detector "
                        << detector.getID() << ", set to 0.0\n";
      }
    }
  }
  return efixed;
}
Example #3
0
void ALCDataLoadingPresenter::updateAvailableLogs()
{
    Workspace_sptr loadedWs;

    try //... to load the first run
    {
        IAlgorithm_sptr load = AlgorithmManager::Instance().create("LoadMuonNexus");
        load->setChild(true); // Don't want workspaces in the ADS
        load->setProperty("Filename", m_view->firstRun());
        // Don't load any data - we need logs only
        load->setPropertyValue("SpectrumMin","0");
        load->setPropertyValue("SpectrumMax","0");
        load->setPropertyValue("OutputWorkspace", "__NotUsed");
        load->execute();

        loadedWs = load->getProperty("OutputWorkspace");
    }
    catch(...)
    {
        m_view->setAvailableLogs(std::vector<std::string>()); // Empty logs list
        return;
    }

    MatrixWorkspace_const_sptr ws = MuonAnalysisHelper::firstPeriod(loadedWs);
    std::vector<std::string> logs;

    const auto& properties = ws->run().getProperties();
    for(auto it = properties.begin(); it != properties.end(); ++it)
    {
        logs.push_back((*it)->name());
    }

    m_view->setAvailableLogs(logs);
}
void ALCDataLoadingPresenter::updateAvailableInfo() {
  Workspace_sptr loadedWs;
  double firstGoodData = 0, timeZero = 0;

  try //... to load the first run
  {
    IAlgorithm_sptr load = AlgorithmManager::Instance().create("LoadMuonNexus");
    load->setChild(true); // Don't want workspaces in the ADS
    load->setProperty("Filename", m_view->firstRun());
    // We need logs only but we have to use LoadMuonNexus
    // (can't use LoadMuonLogs as not all the logs would be
    // loaded), so we load the minimum amount of data, i.e., one spectrum
    load->setPropertyValue("SpectrumMin", "1");
    load->setPropertyValue("SpectrumMax", "1");
    load->setPropertyValue("OutputWorkspace", "__NotUsed");
    load->execute();

    loadedWs = load->getProperty("OutputWorkspace");
    firstGoodData = load->getProperty("FirstGoodData");
    timeZero = load->getProperty("TimeZero");
  } catch (...) {
    m_view->setAvailableLogs(std::vector<std::string>()); // Empty logs list
    m_view->setAvailablePeriods(
        std::vector<std::string>()); // Empty period list
    m_view->setTimeLimits(0, 0);     // "Empty" time limits
    return;
  }

  // Set logs
  MatrixWorkspace_const_sptr ws = MuonAnalysisHelper::firstPeriod(loadedWs);
  std::vector<std::string> logs;

  const auto &properties = ws->run().getProperties();
  for (auto it = properties.begin(); it != properties.end(); ++it) {
    logs.push_back((*it)->name());
  }
  m_view->setAvailableLogs(logs);

  // Set periods
  size_t numPeriods = MuonAnalysisHelper::numPeriods(loadedWs);
  std::vector<std::string> periods;
  for (size_t i = 0; i < numPeriods; i++) {
    std::stringstream buffer;
    buffer << i + 1;
    periods.push_back(buffer.str());
  }
  m_view->setAvailablePeriods(periods);

  // Set time limits if this is the first data loaded (will both be zero)
  if (auto timeLimits = m_view->timeRange()) {
    if (std::abs(timeLimits->first) < 0.0001 &&
        std::abs(timeLimits->second) < 0.0001) {
      m_view->setTimeLimits(firstGoodData - timeZero, ws->readX(0).back());
    }
  }

  // Update number of detectors for this new first run
  m_numDetectors = ws->getInstrument()->getNumberDetectors();
}
Example #5
0
double ConvertSpectrumAxis2::getEfixed(IDetector_const_sptr detector,
                                       MatrixWorkspace_const_sptr inputWS,
                                       int emode) const {
  double efixed(0);
  double efixedProp = getProperty("Efixed");
  if (efixedProp != EMPTY_DBL()) {
    efixed = efixedProp;
    g_log.debug() << "Detector: " << detector->getID() << " Efixed: " << efixed
                  << "\n";
  } else {
    if (emode == 1) {
      if (inputWS->run().hasProperty("Ei")) {
        efixed = inputWS->run().getLogAsSingleValue("Ei");
      } else {
        throw std::invalid_argument("Could not retrieve Efixed from the "
                                    "workspace. Please provide a value.");
      }
    } else if (emode == 2) {
      std::vector<double> efixedVec = detector->getNumberParameter("Efixed");
      if (efixedVec.empty()) {
        int detid = detector->getID();
        IDetector_const_sptr detectorSingle =
            inputWS->getInstrument()->getDetector(detid);
        efixedVec = detectorSingle->getNumberParameter("Efixed");
      }
      if (!efixedVec.empty()) {
        efixed = efixedVec.at(0);
        g_log.debug() << "Detector: " << detector->getID()
                      << " EFixed: " << efixed << "\n";
      } else {
        g_log.warning() << "Efixed could not be found for detector "
                        << detector->getID() << ", please provide a value\n";
        throw std::invalid_argument("Could not retrieve Efixed from the "
                                    "detector. Please provide a value.");
      }
    }
  }
  return efixed;
}
/**
 * Validate the multiperiods workspace groups. Gives the opportunity to exit
 * processing if things don't look right.
 * @param vecMultiPeriodGroups : vector of multiperiod groups.
 */
void MultiPeriodGroupWorker::validateMultiPeriodGroupInputs(
    const VecWSGroupType &vecMultiPeriodGroups) const {
  const size_t multiPeriodGroupsSize = vecMultiPeriodGroups.size();

  if (multiPeriodGroupsSize > 0) {
    const size_t benchMarkGroupSize = vecMultiPeriodGroups[0]->size();
    for (size_t i = 0; i < multiPeriodGroupsSize; ++i) {
      WorkspaceGroup_sptr currentGroup = vecMultiPeriodGroups[i];
      if (currentGroup->size() != benchMarkGroupSize) {
        throw std::runtime_error("Not all the input Multi-period-group input "
                                 "workspaces are the same size.");
      }
      for (size_t j = 0; j < currentGroup->size(); ++j) {
        MatrixWorkspace_const_sptr currentNestedWS =
            boost::dynamic_pointer_cast<const MatrixWorkspace>(
                currentGroup->getItem(j));
        Property *nPeriodsProperty =
            currentNestedWS->run().getLogData("nperiods");
        size_t nPeriods = std::stoul(nPeriodsProperty->value());
        if (nPeriods != benchMarkGroupSize) {
          throw std::runtime_error("Missmatch between nperiods log and the "
                                   "number of workspaces in the input group: " +
                                   vecMultiPeriodGroups[i]->getName());
        }
        Property *currentPeriodProperty =
            currentNestedWS->run().getLogData("current_period");
        size_t currentPeriod = std::stoul(currentPeriodProperty->value());
        if (currentPeriod != (j + 1)) {
          throw std::runtime_error("Multiperiod group workspaces must be "
                                   "ordered by current_period. Correct: " +
                                   currentNestedWS->getName());
        }
      }
    }
  }
}
Example #7
0
/**
Reduce the peak list by removing duplicates
then convert SXPeaks objects to PeakObjects and add them to the output workspace
@param pcv : current peak list containing potential duplicates
@param progress: a progress object
*/
void FindSXPeaks::reducePeakList(const peakvector &pcv, Progress &progress) {
  MatrixWorkspace_const_sptr localworkspace = getProperty("InputWorkspace");
  auto &goniometerMatrix = localworkspace->run().getGoniometer().getR();
  auto compareStrategy = getCompareStrategy();
  auto reductionStrategy = getReducePeakListStrategy(compareStrategy.get());
  auto finalv = reductionStrategy->reduce(pcv, progress);

  for (auto &finalPeak : finalv) {
    finalPeak.reduce();
    try {
      Geometry::IPeak *peak = m_peaks->createPeak(finalPeak.getQ());
      if (peak) {
        peak->setIntensity(finalPeak.getIntensity());
        peak->setDetectorID(finalPeak.getDetectorId());
        peak->setGoniometerMatrix(goniometerMatrix);
        m_peaks->addPeak(*peak);
        delete peak;
      }
    } catch (std::exception &e) {
      g_log.error() << e.what() << '\n';
    }
  }
}
Example #8
0
double EQSANSMonitorTOF::getTofOffset(MatrixWorkspace_const_sptr inputWS,
                                      bool frame_skipping,
                                      double source_to_monitor) {
    //# Storage for chopper information read from the logs
    double chopper_set_phase[4] = {0, 0, 0, 0};
    double chopper_speed[4] = {0, 0, 0, 0};
    double chopper_actual_phase[4] = {0, 0, 0, 0};
    double chopper_wl_1[4] = {0, 0, 0, 0};
    double chopper_wl_2[4] = {0, 0, 0, 0};
    double frame_wl_1 = 0;
    double frame_srcpulse_wl_1 = 0;
    double frame_wl_2 = 0;
    double chopper_srcpulse_wl_1[4] = {0, 0, 0, 0};
    double chopper_frameskip_wl_1[4] = {0, 0, 0, 0};
    double chopper_frameskip_wl_2[4] = {0, 0, 0, 0};
    double chopper_frameskip_srcpulse_wl_1[4] = {0, 0, 0, 0};

    // Calculate the frame width
    auto log = inputWS->run().getTimeSeriesProperty<double>("frequency");
    double frequency = log->getStatistics().mean;
    double tof_frame_width = 1.0e6 / frequency;

    double tmp_frame_width = tof_frame_width;
    if (frame_skipping)
        tmp_frame_width *= 2.0;

    // Choice of parameter set
    int m_set = 0;
    if (frame_skipping)
        m_set = 1;

    bool first = true;
    bool first_skip = true;
    double frameskip_wl_1 = 0;
    double frameskip_srcpulse_wl_1 = 0;
    double frameskip_wl_2 = 0;

    for (int i = 0; i < 4; i++) {
        // Read chopper information
        std::ostringstream phase_str;
        phase_str << "Phase" << i + 1;
        log = inputWS->run().getTimeSeriesProperty<double>(phase_str.str());
        chopper_set_phase[i] = log->getStatistics().mean;
        std::ostringstream speed_str;
        speed_str << "Speed" << i + 1;
        log = inputWS->run().getTimeSeriesProperty<double>(speed_str.str());
        chopper_speed[i] = log->getStatistics().mean;

        // Only process choppers with non-zero speed
        if (chopper_speed[i] <= 0)
            continue;

        chopper_actual_phase[i] =
            chopper_set_phase[i] - CHOPPER_PHASE_OFFSET[m_set][i];

        while (chopper_actual_phase[i] < 0)
            chopper_actual_phase[i] += tmp_frame_width;

        double x1 =
            (chopper_actual_phase[i] -
             (tmp_frame_width * 0.5 * CHOPPER_ANGLE[i] / 360.)); // opening edge
        double x2 =
            (chopper_actual_phase[i] +
             (tmp_frame_width * 0.5 * CHOPPER_ANGLE[i] / 360.)); // closing edge
        if (!frame_skipping)                                     // not skipping
        {
            while (x1 < 0) {
                x1 += tmp_frame_width;
                x2 += tmp_frame_width;
            }
        }

        if (x1 > 0) {
            chopper_wl_1[i] = 3.9560346 * x1 / CHOPPER_LOCATION[i];
            chopper_srcpulse_wl_1[i] =
                3.9560346 * (x1 - chopper_wl_1[i] * PULSEWIDTH) / CHOPPER_LOCATION[i];
        } else
            chopper_wl_1[i] = chopper_srcpulse_wl_1[i] = 0.;

        if (x2 > 0)
            chopper_wl_2[i] = 3.9560346 * x2 / CHOPPER_LOCATION[i];
        else
            chopper_wl_2[i] = 0.;

        if (first) {
            frame_wl_1 = chopper_wl_1[i];
            frame_srcpulse_wl_1 = chopper_srcpulse_wl_1[i];
            frame_wl_2 = chopper_wl_2[i];
            first = false;
        } else {
            if (frame_skipping &&
                    i == 2) // ignore chopper 1 and 2 forthe shortest wl.
            {
                frame_wl_1 = chopper_wl_1[i];
                frame_srcpulse_wl_1 = chopper_srcpulse_wl_1[i];
            }
            if (frame_wl_1 < chopper_wl_1[i])
                frame_wl_1 = chopper_wl_1[i];
            if (frame_wl_2 > chopper_wl_2[i])
                frame_wl_2 = chopper_wl_2[i];
            if (frame_srcpulse_wl_1 < chopper_srcpulse_wl_1[i])
                frame_srcpulse_wl_1 = chopper_srcpulse_wl_1[i];
        }

        if (frame_skipping) {
            if (x1 > 0) {
                x1 += tof_frame_width; // skipped pulse
                chopper_frameskip_wl_1[i] = 3.9560346 * x1 / CHOPPER_LOCATION[i];
                chopper_frameskip_srcpulse_wl_1[i] =
                    3.9560346 * (x1 - chopper_wl_1[i] * PULSEWIDTH) /
                    CHOPPER_LOCATION[i];
            } else
                chopper_wl_1[i] = chopper_srcpulse_wl_1[i] = 0.;

            if (x2 > 0) {
                x2 += tof_frame_width;
                chopper_frameskip_wl_2[i] = 3.9560346 * x2 / CHOPPER_LOCATION[i];
            } else
                chopper_wl_2[i] = 0.;

            if (i < 2 && chopper_frameskip_wl_1[i] > chopper_frameskip_wl_2[i])
                continue;

            if (first_skip) {
                frameskip_wl_1 = chopper_frameskip_wl_1[i];
                frameskip_srcpulse_wl_1 = chopper_frameskip_srcpulse_wl_1[i];
                frameskip_wl_2 = chopper_frameskip_wl_2[i];
                first_skip = false;
            } else {
                if (i == 2) // ignore chopper 1 and 2 forthe longest wl.
                    frameskip_wl_2 = chopper_frameskip_wl_2[i];

                if (chopper_frameskip_wl_1[i] < chopper_frameskip_wl_2[i] &&
                        frameskip_wl_1 < chopper_frameskip_wl_1[i])
                    frameskip_wl_1 = chopper_frameskip_wl_1[i];

                if (chopper_frameskip_wl_1[i] < chopper_frameskip_wl_2[i] &&
                        frameskip_srcpulse_wl_1 < chopper_frameskip_srcpulse_wl_1[i])
                    frameskip_srcpulse_wl_1 = chopper_frameskip_srcpulse_wl_1[i];

                if (frameskip_wl_2 > chopper_frameskip_wl_2[i])
                    frameskip_wl_2 = chopper_frameskip_wl_2[i];
            }
        }
    }

    if (frame_wl_1 >= frame_wl_2) // too many frames later. So figure it out
    {
        double n_frame[4] = {0, 0, 0, 0};
        double c_wl_1[4] = {0, 0, 0, 0};
        double c_wl_2[4] = {0, 0, 0, 0};
        bool passed = false;

        do {
            frame_wl_1 = c_wl_1[0] =
                             chopper_wl_1[0] +
                             3.9560346 * n_frame[0] * tof_frame_width / CHOPPER_LOCATION[0];
            frame_wl_2 = c_wl_2[0] =
                             chopper_wl_2[0] +
                             3.9560346 * n_frame[0] * tof_frame_width / CHOPPER_LOCATION[0];

            for (int i = 1; i < 4; i++) {
                n_frame[i] = n_frame[i - 1] - 1;
                passed = false;

                do {
                    n_frame[i] += 1;
                    c_wl_1[i] =
                        chopper_wl_1[i] +
                        3.9560346 * n_frame[i] * tof_frame_width / CHOPPER_LOCATION[i];
                    c_wl_2[i] =
                        chopper_wl_2[i] +
                        3.9560346 * n_frame[i] * tof_frame_width / CHOPPER_LOCATION[i];

                    if (frame_wl_1 < c_wl_2[i] && frame_wl_2 > c_wl_1[i]) {
                        passed = true;
                        break;
                    }
                    if (frame_wl_2 < c_wl_1[i])
                        break; // over shot
                } while (n_frame[i] - n_frame[i - 1] < 10);

                if (!passed) {
                    n_frame[0] += 1;
                    break;
                } else {
                    if (frame_wl_1 < c_wl_1[i])
                        frame_wl_1 = c_wl_1[i];
                    if (frame_wl_2 > c_wl_2[i])
                        frame_wl_2 = c_wl_2[i];
                }
            }
        } while (!passed && n_frame[0] < 99);

        if (frame_wl_2 > frame_wl_1) {
            int n = 3;
            if (c_wl_1[2] > c_wl_1[3])
                n = 2;

            frame_srcpulse_wl_1 =
                c_wl_1[n] - 3.9560346 * c_wl_1[n] * PULSEWIDTH / CHOPPER_LOCATION[n];

            for (int i = 0; i < 4; i++) {
                chopper_wl_1[i] = c_wl_1[i];
                chopper_wl_2[i] = c_wl_2[i];
                if (frame_skipping) {
                    chopper_frameskip_wl_1[i] =
                        c_wl_1[i] +
                        3.9560346 * 2. * tof_frame_width / CHOPPER_LOCATION[i];
                    chopper_frameskip_wl_2[i] =
                        c_wl_2[i] +
                        3.9560346 * 2. * tof_frame_width / CHOPPER_LOCATION[i];
                    if (i == 0) {
                        frameskip_wl_1 = chopper_frameskip_wl_1[i];
                        frameskip_wl_2 = chopper_frameskip_wl_2[i];
                    } else {
                        if (frameskip_wl_1 < chopper_frameskip_wl_1[i])
                            frameskip_wl_1 = chopper_frameskip_wl_1[i];
                        if (frameskip_wl_2 > chopper_frameskip_wl_2[i])
                            frameskip_wl_2 = chopper_frameskip_wl_2[i];
                    }
                }
            }
        } else
            frame_srcpulse_wl_1 = 0.0;
    }

    double frame_tof0 = frame_srcpulse_wl_1 / 3.9560346 * source_to_monitor;

    g_log.information() << "Frame width " << tmp_frame_width << std::endl;
    g_log.information() << "TOF offset = " << frame_tof0 << " microseconds"
                        << std::endl;
    g_log.information() << "Band defined by T1-T4 " << frame_wl_1 << " "
                        << frame_wl_2;
    if (frame_skipping)
        g_log.information() << " + " << frameskip_wl_1 << " " << frameskip_wl_2
                            << std::endl;
    else
        g_log.information() << std::endl;
    g_log.information() << "Chopper    Actual Phase    Lambda1    Lambda2"
                        << std::endl;
    for (int i = 0; i < 4; i++)
        g_log.information() << i << "    " << chopper_actual_phase[i] << "  "
                            << chopper_wl_1[i] << "  " << chopper_wl_2[i]
                            << std::endl;

    setProperty("FrameSkipping", frame_skipping);

    return frame_tof0;
}
Example #9
0
/** Constructor with workspace argument
  *
  * This constructor directly takes a matrix workspace and extracts instrument
  *and run information.
  *
  * @param matrixWorkspace :: Workspace with a valid POLDI instrument and run
  *information
  */
PoldiInstrumentAdapter::PoldiInstrumentAdapter(
    const MatrixWorkspace_const_sptr &matrixWorkspace) {
  initializeFromInstrumentAndRun(matrixWorkspace->getInstrument(),
                                 matrixWorkspace->run());
}
Example #10
0
void EQSANSMonitorTOF::exec()
{
  MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");

  // Now create the output workspace
  MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
  if ( outputWS != inputWS )
  {
    outputWS = WorkspaceFactory::Instance().create(inputWS);
    setProperty("OutputWorkspace",outputWS);
  }

  // Get the nominal sample-to-detector distance (in mm)
  // const double MD = MONITORPOS/1000.0;

  // Get the monitor
  const std::vector<detid_t> monitor_list = inputWS->getInstrument()->getMonitors();
  if (monitor_list.size() != 1) {
    g_log.error() << "EQSANS workspace does not have exactly ones monitor! This should not happen" << std::endl;
  }
  IDetector_const_sptr mon;
  try {
    mon = inputWS->getInstrument()->getDetector(monitor_list[0]);
  } catch (Exception::NotFoundError&) {
    g_log.error() << "Spectrum index " << monitor_list[0] << " has no detector assigned to it - discarding" << std::endl;
    return;
  }

  // Get the source to monitor distance in mm
  double source_z = inputWS->getInstrument()->getSource()->getPos().Z();
  double monitor_z = mon->getPos().Z();
  double source_to_monitor = (monitor_z - source_z)*1000.0;

  // Calculate the frame width
  double frequency = dynamic_cast<TimeSeriesProperty<double>*>(inputWS->run().getLogData("frequency"))->getStatistics().mean;
  double tof_frame_width = 1.0e6/frequency;

  // Determine whether we need frame skipping or not by checking the chopper speed
  bool frame_skipping = false;
  const double chopper_speed = dynamic_cast<TimeSeriesProperty<double>*>(inputWS->run().getLogData("Speed1"))->getStatistics().mean;
  if (std::fabs(chopper_speed-frequency/2.0)<1.0) frame_skipping = true;

  // Get TOF offset
  // this is the call to the chopper code to say where
  // the start of the data frame is relative to the native facility frame
  double frame_tof0 = getTofOffset(inputWS, frame_skipping, source_to_monitor);

  // Calculate the frame width
  // none of this changes in response to just looking at the monitor
  double tmp_frame_width = frame_skipping ? tof_frame_width * 2.0 : tof_frame_width;
  double frame_offset=0.0;
  if (frame_tof0 >= tmp_frame_width) frame_offset = tmp_frame_width * ( (int)( frame_tof0/tmp_frame_width ) );

  // Find the new binning first
  const MantidVec XIn = inputWS->readX(0); // Copy here to avoid holding on to reference for too long (problem with managed workspaces)

  // Since we are swapping the low-TOF and high-TOF regions around the cutoff value,
  // there is the potential for having an overlap between the two regions. We exclude
  // the region beyond a single frame by considering only the first 1/60 sec of the
  // TOF histogram. (Bins 1 to 1666, as opposed to 1 to 2000)
  const int nTOF = static_cast<int>(XIn.size());

  // Loop through each bin to find the cutoff where the TOF distribution wraps around
  int cutoff = 0;
  double threshold = frame_tof0-frame_offset;
  int tof_bin_range = 0;
  double frame = 1000000.0/frequency;
  for (int i=0; i<nTOF; i++)
  {
      if (XIn[i] < threshold) cutoff = i;
      if (XIn[i] < frame) tof_bin_range = i;
  }
  g_log.information() << "Cutoff=" << cutoff << "; Threshold=" << threshold << std::endl;
  g_log.information() << "Low TOFs: old = [" << (cutoff+1) << ", " << (tof_bin_range-2) << "]  ->  new = [0, " << (tof_bin_range-3-cutoff) << "]" << std::endl;
  g_log.information() << "High bin boundary of the Low TOFs: old = " << tof_bin_range-1 << "; new = " << (tof_bin_range-2-cutoff) << std::endl;
  g_log.information() << "High TOFs: old = [0, " << (cutoff-1) << "]  ->  new = [" << (tof_bin_range-1-cutoff) << ", " << (tof_bin_range-2) << "]" << std::endl;
  g_log.information() << "Overlap: new = [" << (tof_bin_range-1) << ", " << (nTOF-2) << "]" << std::endl;

  // Keep a copy of the input data since we may end up overwriting it
  // if the input workspace is equal to the output workspace.
  // This is necessary since we are shuffling around the TOF bins.
  MantidVec YCopy = MantidVec(inputWS->readY(0));
  MantidVec& YIn = YCopy;
  MantidVec ECopy = MantidVec(inputWS->readE(0));
  MantidVec& EIn = ECopy;

  MantidVec& XOut = outputWS->dataX(0);
  MantidVec& YOut = outputWS->dataY(0);
  MantidVec& EOut = outputWS->dataE(0);

  // Here we modify the TOF according to the offset we calculated.
  // Since this correction will change the order of the TOF bins,
  // we do it in sequence so that we obtain a valid distribution
  // as our result (with increasing TOF values).

  // Move up the low TOFs
  for (int i=0; i<cutoff; i++)
  {
    XOut[i+tof_bin_range-1-cutoff] = XIn[i] + frame_offset + tmp_frame_width;
    YOut[i+tof_bin_range-1-cutoff] = YIn[i];
    EOut[i+tof_bin_range-1-cutoff] = EIn[i];
  }

  // Get rid of extra bins
  for (int i=tof_bin_range-1; i<nTOF-1; i++)
  {
    XOut[i] = XOut[i-1]+10.0;
    YOut[i] = 0.0;
    EOut[i] = 0.0;
  }
  XOut[nTOF-1] = XOut[nTOF-2]+10.0;

  // Move down the high TOFs
  for (int i=cutoff+1; i<tof_bin_range-1; i++)
  {
    XOut[i-cutoff-1] = XIn[i] + frame_offset;
    YOut[i-cutoff-1] = YIn[i];
    EOut[i-cutoff-1] = EIn[i];
  }
  // Don't forget the low boundary
  XOut[tof_bin_range-2-cutoff] = XIn[tof_bin_range] + frame_offset;

  // Zero out the cutoff bin, which no longer makes sense because
  // len(x) = len(y)+1
  YOut[tof_bin_range-2-cutoff] = 0.0;
  EOut[tof_bin_range-2-cutoff] = 0.0;

  setProperty("OutputWorkspace",outputWS);
}