/** Create histogram workspace
 */
MatrixWorkspace_sptr CreateSampleWorkspace::createHistogramWorkspace(
    int numPixels, int numBins, double x0, double binDelta,
    int start_at_pixelID, Geometry::Instrument_sptr inst,
    const std::string &functionString, bool isRandom) {
  MantidVecPtr x, y, e;
  x.access().resize(numBins + 1);
  e.access().resize(numBins);
  for (int i = 0; i < numBins + 1; ++i) {
    x.access()[i] = x0 + i * binDelta;
  }

  std::vector<double> xValues(x.access().begin(), x.access().end() - 1);
  y.access() = evalFunction(functionString, xValues, isRandom ? 1 : 0);
  e.access().resize(numBins);

  // calculate e as sqrt(y)
  typedef double (*uf)(double);
  uf dblSqrt = std::sqrt;
  std::transform(y.access().begin(), y.access().end(), e.access().begin(),
                 dblSqrt);

  MatrixWorkspace_sptr retVal(new DataObjects::Workspace2D);
  retVal->initialize(numPixels, numBins + 1, numBins);
  retVal->setInstrument(inst);

  for (size_t wi = 0; wi < static_cast<size_t>(numPixels); wi++) {
    retVal->setX(wi, x);
    retVal->setData(wi, y, e);
    retVal->getSpectrum(wi)->setDetectorID(detid_t(start_at_pixelID + wi));
    retVal->getSpectrum(wi)->setSpectrumNo(specid_t(wi + 1));
  }

  return retVal;
}
Exemple #2
0
void QniteXYArtist::processData() {
  if (qMin(xValues().size(), yValues().size()) < 1) {
    return;
  }

  // get bounds
  qreal xLower = axes()->axisX()->lowerBound();
  qreal xUpper = axes()->axisX()->upperBound();
  qreal yLower = axes()->axisY()->lowerBound();
  qreal yUpper = axes()->axisY()->upperBound();

  // TODO: this should be improved. clipping should be done only when bounds
  // changes and tranforsm should always be performed
  QMap<int, qreal> xClipped;
  QMap<int, qreal> yClipped;
  // clip non visible data
  if (clipper() != nullptr) {
    clipper()->clip(m_xValues, m_yValues, xLower, xUpper, yLower, yUpper,
                    xClipped, yClipped);
  } else {
    xClipped = m_xValues;
    yClipped = m_yValues;
  }

  // map to display
  m_xMapped = xMapper()->mapTo(xLower, xUpper, 0, width(), xClipped);
  m_yMapped = yMapper()->mapTo(yLower, yUpper, 0, height(), yClipped, true);

  // TODO: this is ugly and inefficient. move into a pipelino or something
  // similar move to the output area
  m_xProcessed = m_xMapped.values();
  m_yProcessed = m_yMapped.values();
}
void QmitkHistogramWidget::SetHistogram(HistogramType::ConstPointer itkHistogram)
{
  HistogramType::SizeType size = itkHistogram->GetSize();
  HistogramType::IndexType index;
  HistogramType::MeasurementVectorType currentMeasurementVector;

  QwtArray<QwtDoubleInterval> xValues(size[0]);
  QwtArray<double> yValues(size[0]);

  for (unsigned int i = 0; i < size[0]; ++i)
  {
    index[0] = static_cast<HistogramType::IndexValueType> (i);
    currentMeasurementVector = itkHistogram->GetMeasurementVector(index);
    if (currentMeasurementVector[0] != 0.0)
    {
      xValues[i] = QwtDoubleInterval(Round(currentMeasurementVector[0]-1), Round(currentMeasurementVector[0]));
      yValues[i] = static_cast<double> (itkHistogram->GetFrequency(index));
    }
  }

  // rebuild the plot
  m_Plot->clear();

  m_Histogram = new QmitkHistogram();
  m_Histogram->setColor(Qt::darkCyan);
  m_Histogram->setData(QwtIntervalData(xValues, yValues));
  m_Histogram->attach(m_Plot);

  this->InitializeMarker();
  this->InitializeZoomer();

  m_Plot->replot();
}
/** Create event workspace
 */
EventWorkspace_sptr CreateSampleWorkspace::createEventWorkspace(
    int numPixels, int numBins, int numEvents, double x0, double binDelta,
    int start_at_pixelID, Geometry::Instrument_sptr inst,
    const std::string &functionString, bool isRandom) {
  DateAndTime run_start("2010-01-01T00:00:00");

  // add one to the number of bins as this is histogram
  int numXBins = numBins + 1;

  EventWorkspace_sptr retVal(new EventWorkspace);
  retVal->initialize(numPixels, 1, 1);

  retVal->setInstrument(inst);

  // Create the x-axis for histogramming.
  MantidVecPtr x1;
  MantidVec &xRef = x1.access();
  xRef.resize(numXBins);
  for (int i = 0; i < numXBins; ++i) {
    xRef[i] = x0 + i * binDelta;
  }

  // Set all the histograms at once.
  retVal->setAllX(x1);

  std::vector<double> xValues(xRef.begin(), xRef.end() - 1);
  std::vector<double> yValues =
      evalFunction(functionString, xValues, isRandom ? 1 : 0);

  // we need to normalise the results and then multiply by the number of events
  // to find the events per bin
  double sum_of_elems = std::accumulate(yValues.begin(), yValues.end(), 0.0);
  double event_distrib_factor = numEvents / sum_of_elems;
  std::transform(yValues.begin(), yValues.end(), yValues.begin(),
                 std::bind1st(std::multiplies<double>(), event_distrib_factor));
  // the array should now contain the number of events required per bin

  // Make fake events
  size_t workspaceIndex = 0;

  const double hourInSeconds = 60 * 60;
  for (int wi = 0; wi < numPixels; wi++) {
    EventList &el = retVal->getEventList(workspaceIndex);
    el.setSpectrumNo(wi + 1);
    el.setDetectorID(wi + start_at_pixelID);

    // for each bin

    for (int i = 0; i < numBins; ++i) {
      // create randomised events within the bin to match the number required -
      // calculated in yValues earlier
      int eventsInBin = static_cast<int>(yValues[i]);
      for (int q = 0; q < eventsInBin; q++) {
        DateAndTime pulseTime =
            run_start + (m_randGen->nextValue() * hourInSeconds);
        el += TofEvent((i + m_randGen->nextValue()) * binDelta, pulseTime);
      }
    }
    workspaceIndex++;
  }

  return retVal;
}
Exemple #5
0
/**
 * Computed the normalization for the input workspace. Results are stored in
 * m_normWS
 * @param otherValues
 * @param affineTrans
 */
void MDNormSCD::calculateNormalization(
    const std::vector<coord_t> &otherValues,
    const Kernel::Matrix<coord_t> &affineTrans) {
  API::MatrixWorkspace_const_sptr integrFlux = getProperty("FluxWorkspace");
  integrFlux->getXMinMax(m_kiMin, m_kiMax);
  API::MatrixWorkspace_const_sptr solidAngleWS =
      getProperty("SolidAngleWorkspace");

  const auto &exptInfoZero = *(m_inputWS->getExperimentInfo(0));
  typedef Kernel::PropertyWithValue<std::vector<double>> VectorDoubleProperty;
  auto *rubwLog =
      dynamic_cast<VectorDoubleProperty *>(exptInfoZero.getLog("RUBW_MATRIX"));
  if (!rubwLog) {
    throw std::runtime_error(
        "Wokspace does not contain a log entry for the RUBW matrix."
        "Cannot continue.");
  } else {
    Kernel::DblMatrix rubwValue(
        (*rubwLog)()); // includes the 2*pi factor but not goniometer for now :)
    m_rubw = exptInfoZero.run().getGoniometerMatrix() * rubwValue;
    m_rubw.Invert();
  }
  const double protonCharge = exptInfoZero.run().getProtonCharge();

  auto instrument = exptInfoZero.getInstrument();
  std::vector<detid_t> detIDs = instrument->getDetectorIDs(true);
  // Prune out those that are part of a group and simply leave the head of the
  // group
  detIDs = removeGroupedIDs(exptInfoZero, detIDs);

  // Mappings
  const int64_t ndets = static_cast<int64_t>(detIDs.size());
  const detid2index_map fluxDetToIdx =
      integrFlux->getDetectorIDToWorkspaceIndexMap();
  const detid2index_map solidAngDetToIdx =
      solidAngleWS->getDetectorIDToWorkspaceIndexMap();

  auto prog = make_unique<API::Progress>(this, 0.3, 1.0, ndets);
  PARALLEL_FOR1(integrFlux)
  for (int64_t i = 0; i < ndets; i++) {
    PARALLEL_START_INTERUPT_REGION

    const auto detID = detIDs[i];
    double theta(0.0), phi(0.0);
    bool skip(false);
    try {
      auto spectrum = getThetaPhi(detID, exptInfoZero, theta, phi);
      if (spectrum->isMonitor() || spectrum->isMasked())
        continue;
    } catch (
        std::exception &) // detector might not exist or has no been included
                          // in grouping
    {
      skip = true; // Intel compiler has a problem with continue inside a catch
                   // inside openmp...
    }
    if (skip)
      continue;

    // Intersections
    auto intersections = calculateIntersections(theta, phi);
    if (intersections.empty())
      continue;

    // get the flux spetrum number
    size_t wsIdx = fluxDetToIdx.find(detID)->second;
    // Get solid angle for this contribution
    double solid =
        solidAngleWS->readY(solidAngDetToIdx.find(detID)->second)[0] *
        protonCharge;

    // -- calculate integrals for the intersection --
    // momentum values at intersections
    auto intersectionsBegin = intersections.begin();
    std::vector<double> xValues(intersections.size()),
        yValues(intersections.size());
    {
      // copy momenta to xValues
      auto x = xValues.begin();
      for (auto it = intersectionsBegin; it != intersections.end(); ++it, ++x) {
        *x = (*it)[3];
      }
    }
    // calculate integrals at momenta from xValues by interpolating between
    // points in spectrum sp
    // of workspace integrFlux. The result is stored in yValues
    calcIntegralsForIntersections(xValues, *integrFlux, wsIdx, yValues);

    // Compute final position in HKL
    const size_t vmdDims = intersections.front().size();
    // pre-allocate for efficiency and copy non-hkl dim values into place
    std::vector<coord_t> pos(vmdDims + otherValues.size());
    std::copy(otherValues.begin(), otherValues.end(),
              pos.begin() + vmdDims - 1);
    pos.push_back(1.);

    for (auto it = intersectionsBegin + 1; it != intersections.end(); ++it) {
      const auto &curIntSec = *it;
      const auto &prevIntSec = *(it - 1);
      // the full vector isn't used so compute only what is necessary
      double delta = curIntSec[3] - prevIntSec[3];
      if (delta < 1e-07)
        continue; // Assume zero contribution if difference is small

      // Average between two intersections for final position
      std::transform(curIntSec.getBareArray(),
                     curIntSec.getBareArray() + vmdDims - 1,
                     prevIntSec.getBareArray(), pos.begin(),
                     VectorHelper::SimpleAverage<coord_t>());
      std::vector<coord_t> posNew = affineTrans * pos;
      size_t linIndex = m_normWS->getLinearIndexAtCoord(posNew.data());
      if (linIndex == size_t(-1))
        continue;

      // index of the current intersection
      size_t k = static_cast<size_t>(std::distance(intersectionsBegin, it));
      // signal = integral between two consecutive intersections
      double signal = (yValues[k] - yValues[k - 1]) * solid;

      PARALLEL_CRITICAL(updateMD) {
        signal += m_normWS->getSignalAt(linIndex);
        m_normWS->setSignalAt(linIndex, signal);
      }
    }
    prog->report();

    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION
}
Exemple #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)