15#include "MantidHistogramData/Histogram.h"
45 return "Inelastic\\Utility;Diagnostics;Events\\EventFiltering";
50 return "Calculates instrument count rate as the function of the "
51 "experiment time and adds CountRate log to the source workspace.";
61 "Name of the event workspace to calculate counting rate for.");
63 "Minimal value of X-range for the rate calculations. If left "
64 "to default, Workspace X-axis minimal value is used.");
66 "Maximal value of X-range for the rate calculations. If left "
67 "to default, Workspace X-axis maximal value is used.");
69 "RangeUnits",
"Energy",
70 std::make_shared<Kernel::StringListValidator>(Kernel::UnitFactory::Instance().getKeys()),
72 "The units from Mantid Unit factory for calculating the "
73 "counting rate and XMin-XMax ranges are in. If the "
74 "X-axis of the input workspace is not expressed"
75 "in these units, unit conversion will be performed, so the "
76 "workspace should contain all necessary information for this "
77 "conversion. E.g. if *RangeUnits* is *EnergyTransfer*, Ei "
78 "log containing incident energy value should be attached to the "
79 "input workspace. See ConvertUnits algorithm for the details.");
80 std::vector<std::string> propOptions{
"Elastic",
"Direct",
"Indirect"};
81 declareProperty(
"EMode",
"Elastic", std::make_shared<Kernel::StringListValidator>(propOptions),
82 "The energy mode for 'RangeUnits' conversion mode (default: elastic)");
85 std::string used_logs_mode(
"Used normalization logs");
87 "Usually you want to normalize counting rate to some "
88 "rate related to the source beam intensity. Change this to "
89 "'false' if appropriate time series log is broken || not attached to "
90 "the input workspace.");
92 "If the normalization log contains "
93 "cumulative counting, derivative "
94 "of this log is necessary to get "
95 "correct normalization values.");
97 "The name of the log, used in the counting rate normalization. ");
104 "The name of the processed time series log with instrument "
105 "count rate to be added"
106 " to the source workspace");
108 "If true, the count rate log will have the normalization log "
109 "accuracy; If false, the 'NumTimeSteps' in the visualization "
110 "workspace below will be used for the target log granularity too.");
113 std::string spur_vis_mode(
"Spurion visualization");
116 "Optional name to build 2D matrix workspace for spurion visualization. "
117 "If name is provided, a 2D workspace with this name will be created "
118 "containing data to visualize counting rate as function of time in the "
121 auto mustBeReasonable = std::make_shared<Kernel::BoundedValidator<int>>();
122 mustBeReasonable->setLower(3);
125 "Number of time steps (time accuracy) the visualization workspace has. "
126 "Also number of steps in 'CountRateLogName' log if "
127 "'UseNormLogGranularity' is set to false. Should be bigger than 3");
130 "Number of steps (accuracy) of the visualization workspace has along "
145 throw std::runtime_error(
"Event workspace " + sourceWS->getName() +
146 " contains events without necessary frame "
147 "information. Can not process counting rate");
163 const std::string logname =
getProperty(
"CountRateLogName");
164 auto newlog = std::make_unique<Kernel::TimeSeriesProperty<double>>(logname);
167 sourceWS->mutableRun().addProperty(std::move(newlog),
true);
189 std::vector<double> countNormalization;
193 std::unique_ptr<std::mutex[]> pVisWS_locks;
195 pVisWS_locks.reset(
new std::mutex[
m_visWs->getNumberHistograms()]);
198 auto nHist =
static_cast<int64_t
>(InputWorkspace->getNumberHistograms());
202 auto dTRangeMin =
static_cast<double>(
m_TRangeMin.totalNanoseconds());
203 auto dTRangeMax =
static_cast<double>(
m_TRangeMax.totalNanoseconds());
206 std::vector<MantidVec> Buff;
214 Buff.resize(nThreads);
219 for (int64_t i = 0; i < nHist; ++i) {
239 for (
int i = 0; i < nThreads; i++) {
240 countRate[j] += Buff[i][j];
243 if (!countNormalization.empty()) {
244 countRate[j] /= countNormalization[j];
247 if (!countNormalization.empty() && this->buildVisWS()) {
249 for (int64_t j = 0; j < int64_t(
m_visNorm.size()); j++) {
257 double dt = (dTRangeMax - dTRangeMin) /
static_cast<double>(
m_numLogSteps);
260 times[i] = Types::Core::DateAndTime(t0 +
static_cast<int64_t
>((0.5 +
double(i)) * dt));
276 for (
const Types::Event::TofEvent &ev : events) {
277 double pulsetime =
static_cast<double>(ev.pulseTime().totalNanoseconds());
278 double tof = ev.tof();
279 if (pulsetime < m_visT0 || pulsetime >=
m_visTmax)
284 auto n_spec =
static_cast<size_t>((pulsetime -
m_visT0) /
m_visDT);
286 (spectraLocks + n_spec)->lock();
287 auto &
Y =
m_visWs->mutableY(n_spec);
289 (spectraLocks + n_spec)->unlock();
308 std::string NormLogName =
getProperty(
"NormalizationLogName");
309 std::string TargetLog =
getProperty(
"CountRateLogName");
310 if (NormLogName == TargetLog) {
311 throw std::invalid_argument(
"Target log name: " + TargetLog +
" and normalization log name: " + NormLogName +
312 " can not be the same");
316 bool useLogDeriv =
getProperty(
"UseLogDerivative");
317 bool useLogAccuracy =
getProperty(
"UseNormLogGranularity");
319 bool logPresent = InputWorkspace->run().hasProperty(NormLogName);
323 "' values requested but the log is not attached to the "
324 "workspace. Normalization disabled");
327 g_log.
warning() <<
"Normalization by log: '" << NormLogName
328 <<
"' -- log derivative requested but the source log is "
330 "the workspace. Log derivative will not be used.\n";
333 if (useLogAccuracy) {
334 g_log.
warning() <<
"Using accuracy of the log: '" << NormLogName
335 <<
"' is requested but the log is not attached to the "
336 "workspace. Will use accuracy defined by "
337 "'NumTimeSteps' property value.\n";
338 useLogAccuracy =
false;
355 if (!useLogAccuracy) {
356 g_log.
warning() <<
"Change of the counting log accuracy while "
357 "normalizing by log values is not implemented. Will "
358 "use log accuracy.\n";
359 useLogAccuracy =
true;
364 Types::Core::DateAndTime runTMin, runTMax;
365 InputWorkspace->getPulseTimeMinMax(runTMin, runTMax);
367 if (useLogAccuracy) {
368 Types::Core::DateAndTime tLogMin, tLogMax;
371 auto pSource = InputWorkspace->run().getTimeSeriesProperty<
double>(NormLogName);
372 tLogMin = pSource->firstTime();
373 tLogMax = pSource->lastTime();
379 if (tLogMin < runTMin || tLogMax > runTMax) {
380 if (tLogMin > runTMax || tLogMax < runTMin) {
383 " time lies outside of the whole experiment time. "
384 "Log normalization impossible.");
385 useLogAccuracy =
false;
393 filteredLog->filterWith(roi);
397 filteredLog->filterWith(roi);
404 if (tLogMin > runTMin || tLogMax < runTMax) {
406 " time does not cover the whole experiment time. "
407 "Log normalization impossible.");
408 useLogAccuracy =
false;
413 if (useLogAccuracy) {
418 " smaller then 2. Can not normalize using this log.");
420 useLogAccuracy =
false;
426 double t_epsilon = double(runTMax.totalNanoseconds()) * (1 + std::numeric_limits<double>::epsilon());
427 auto eps_increment =
static_cast<int64_t
>(t_epsilon - double(runTMax.totalNanoseconds()));
430 if (useLogAccuracy) {
435 auto iTMax = runTMax.totalNanoseconds();
442 " is not consistent with number of log steps. "
443 "Can not use this log normalization");
444 useLogAccuracy =
false;
447 if (iTMax1 <= iTMax) {
455 if (!useLogAccuracy) {
475 std::string RangeUnits =
getProperty(
"RangeUnits");
476 auto axis = InputWorkspace->getAxis(0);
477 const auto unit = axis->unit();
480 if (unit->unitID() != RangeUnits) {
482 std::string wsName = InputWorkspace->getName();
483 if (wsName.empty()) {
484 wsName =
"_CountRate_UnitsConverted";
486 wsName =
"_" + wsName +
"_converted";
489 conv->setProperty(
"InputWorkspace", InputWorkspace);
490 conv->setPropertyValue(
"OutputWorkspace", wsName);
492 conv->setProperty(
"Emode", Emode);
493 conv->setProperty(
"Target", RangeUnits);
495 conv->setRethrows(
true);
497 wst = conv->getProperty(
"OutputWorkspace");
500 wst = InputWorkspace;
502 m_workingWS = std::dynamic_pointer_cast<DataObjects::EventWorkspace>(wst);
504 throw std::runtime_error(
"SetWSDataRanges:Can not retrieve EventWorkspace "
505 "after converting units");
517 double realMin, realMax;
522 m_XRangeMax = realMax * (1. + std::numeric_limits<double>::epsilon());
531 m_XRangeMax = realMax * (1. + std::numeric_limits<double>::epsilon());
534 g_log.
debug() <<
"Workspace constrain min range changed from: " <<
m_XRangeMin <<
" To: " << realMin << std::endl;
538 g_log.
debug() <<
"Workspace constrain max range changed from: " <<
m_XRangeMax <<
" To: " << realMax << std::endl;
539 m_XRangeMax = realMax * (1. + std::numeric_limits<double>::epsilon());
542 if (m_XRangeMax < realMin || m_XRangeMin > realMax) {
549 throw std::invalid_argument(
" Minimal spurion search data limit is bigger "
550 "than the maximal limit. ( Min: " +
560 std::string visWSName =
getProperty(
"VisualizationWs");
561 if (visWSName.empty()) {
572 "workspace exceeds the number of points in the "
573 "normalization log. This mode is not supported so "
574 "number of time steps decreased to be equal to "
575 "the number of normalization log points\n";
580 std::string RangeUnits =
getProperty(
"RangeUnits");
582 m_visWs = create<Workspace2D>(numTBins, BinEdges(numXBins + 1));
587 if (std::isinf(Xmax)) {
589 for (int64_t i = Xbin.size() - 1; i >= 0; --i) {
590 if (!std::isinf(Xbin[i])) {
595 if (std::isinf(Xmax)) {
596 g_log.
warning() <<
"All X-range for visualization workspace is infinity. "
597 "Can not build visualization workspace in the units "
607 std::vector<double> xx(numXBins);
608 for (
int i = 0; i < numXBins; ++i) {
609 xx[i] =
m_XRangeMin + (0.5 +
static_cast<double>(i)) * dX;
611 auto ax0 = std::make_unique<API::NumericAxis>(xx);
612 ax0->setUnit(RangeUnits);
613 m_visWs->replaceAxis(0, std::move(ax0));
617 static_cast<double>(numTBins)) *
620 for (
int i = 0; i < numTBins; i++) {
621 xx[i] = (0.5 +
static_cast<double>(i)) * dt;
623 auto ax1 = std::make_unique<API::NumericAxis>(xx);
624 auto labelY = std::dynamic_pointer_cast<Kernel::Units::Label>(Kernel::UnitFactory::Instance().
create(
"Label"));
625 labelY->setLabel(
"sec");
626 ax1->unit() = labelY;
627 m_visWs->replaceAxis(1, std::move(ax1));
665 g_log.
warning() <<
"CalculateCountRate::buildVisWSNormalization: No source "
666 "normalization log is found. Will not normalize "
667 "visualization workspace\n";
673 throw std::runtime_error(
"Can not retrieve Y-axis from visualization workspace");
675 normalization.assign(ax->length(), 0.);
#define DECLARE_ALGORITHM(classname)
#define PARALLEL_THREAD_NUMBER
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_NUMBER_OF_THREADS
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
Class to represent a numeric axis of a workspace.
Helper class for reporting progress from algorithms.
A property class for workspaces.
In normal circumstances an instrument in event mode counts neutrons with constant steady rate which d...
void setSourceWSandXRanges(DataObjects::EventWorkspace_sptr &InputWorkspace)
void calcRateLog(DataObjects::EventWorkspace_sptr &InputWorkspace, Kernel::TimeSeriesProperty< double > *const targLog)
Process input workspace to calculate instrument counting rate as function of experiment time.
bool m_doVis
should algo generate visualization VS
void setOutLogParameters(const DataObjects::EventWorkspace_sptr &InputWorkspace)
void checkAndInitVisWorkspace()
Check if visualization workspace is necessary and initiate it if requested.
bool m_normalizeResult
pointer to the log used to normalize results or NULL if no such log present on input workspace.
bool buildVisWS() const
helper function to test if visualization workspace is requested
DataObjects::EventWorkspace_sptr m_workingWS
temporary workspace used to keep intermediate results
double m_XRangeMin
spurion search ranges (TOF or other units requested)
bool normalizeCountRate() const
Helper function: true if count rate should be normalized and false otherwise.
std::vector< double > m_visNorm
void disableNormalization(const std::string &NormLogError)
Disable normalization using normalization log.
Types::Core::DateAndTime m_TRangeMin
experiment time ranges:
DataObjects::Workspace2D_sptr m_visWs
shared pointer to the optional visualization workspace
Types::Core::DateAndTime m_TRangeMax
Kernel::TimeSeriesProperty< double > const * m_pNormalizationLog
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
const std::string category() const override
Algorithm's category for identification.
bool m_rangeExplicit
specify if rate is calculated in selected frame interval (range defined) or all frame should be used
const std::string name() const override
Algorithms name for identification.
void init() override
Declare the algorithm's properties.
void histogramEvents(const DataObjects::EventList &el, std::mutex *spectraLocks)
histogram event list into visualization workspace
std::unique_ptr< Kernel::TimeSeriesProperty< double > > m_tmpLogHolder
void buildVisWSNormalization(std::vector< double > &normalization)
method to prepare normalization vector for the visualisation workspace using data from normalization ...
int m_numLogSteps
default number of points in the target log
int version() const override
Algorithm's version for identification.
bool useLogDerivative() const
Helper function to test if log derivative is used.
void exec() override
Execute the algorithm.
std::vector< Types::Event::TofEvent > & getEvents()
Return the list of TofEvents contained.
void generateCountsHistogramPulseTime(const double &xMin, const double &xMax, MantidVec &Y, const double TofMin=std::numeric_limits< double >::lowest(), const double TofMax=std::numeric_limits< double >::max()) const
With respect to PulseTime fill a histogram given equal histogram bins.
bool empty() const
Much like stl containers, returns true if there is nothing in the event list.
Templated class that defines a filtered time series but still gives access to the original data.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertyGroup(const std::string &name, const std::string &group)
Set the group for a given property.
void debug(const std::string &msg)
Logs at debug level.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
Validator to check that a property is not left empty.
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
The concrete, templated class for properties.
const std::string & name() const
Get the property's name.
TimeROI : Object that holds information about when the time measurement was active.
A specialised Property class for holding a series of time-value pairs.
void replaceValues(const std::vector< Types::Core::DateAndTime > ×, const std::vector< TYPE > &values)
Replaces the time series with new values time series values.
TimeSeriesProperty< TYPE > * clone() const override
"Virtual" copy constructor
int size() const override
Returns the number of values at UNIQUE time intervals in the time series.
std::vector< TYPE > valuesAsVector() const
Return the time series's values (unfiltered) as a vector<TYPE>
Types::Core::DateAndTime firstTime() const
Returns the first time regardless of filter.
void histogramData(const Types::Core::DateAndTime &tMin, const Types::Core::DateAndTime &tMax, std::vector< double > &counts) const
generate constant time-step histogram from the property values
Types::Core::DateAndTime lastTime() const
Returns the last time.
std::unique_ptr< TimeSeriesProperty< double > > getDerivative() const
Return time series property, containing time derivative of current property.
EventType
What kind of event list is being stored.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
std::unique_ptr< T > create(const P &parent, const IndexArg &indexArg, const HistArg &histArg)
This is the create() method that all the other create() methods call.
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ InOut
Both an input & output workspace.
@ Input
An input workspace.
@ Output
An output workspace.