/** 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; }
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; }
/** * 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 }
/** 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)