Mantid
Loading...
Searching...
No Matches
Unit.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7//----------------------------------------------------------------------
8// Includes
9//----------------------------------------------------------------------
10#include "MantidKernel/Unit.h"
11#include "MantidKernel/Logger.h"
15#include <cfloat>
16#include <limits>
17#include <math.h>
18#include <sstream>
19
20namespace Mantid::Kernel {
21
22namespace {
23// static logger object
24Logger g_log("Unit");
25
26bool ParamPresent(const UnitParametersMap &params, UnitParams param) { return params.find(param) != params.end(); }
27
28bool ParamPresentAndSet(const UnitParametersMap *params, UnitParams param, double &var) {
29 auto it = params->find(param);
30 if (it != params->end()) {
31 var = it->second;
32 return true;
33 } else {
34 return false;
35 }
36}
37} // namespace
38
43Unit::Unit() : initialized(false), l1(0), emode(0) {}
44
45bool Unit::operator==(const Unit &u) const { return unitID() == u.unitID(); }
46
47bool Unit::operator!=(const Unit &u) const { return !(*this == u); }
48
63bool Unit::quickConversion(const Unit &destination, double &factor, double &power) const {
64 // Just extract the unit's name and forward to other quickConversion method
65 return quickConversion(destination.unitID(), factor, power);
66}
67
83bool Unit::quickConversion(std::string destUnitName, double &factor, double &power) const {
84 // From the global map, try to get the map holding the conversions for this
85 // unit
86 ConversionsMap::const_iterator it = s_conversionFactors.find(unitID());
87 // Return false if there are no conversions entered for this unit
88 if (it == s_conversionFactors.end())
89 return false;
90
91 // See if there's a conversion listed for the requested destination unit
92 std::transform(destUnitName.begin(), destUnitName.end(), destUnitName.begin(), toupper);
93 auto iter = it->second.find(destUnitName);
94 // If not, return false
95 if (iter == it->second.end())
96 return false;
97
98 // Conversion found - set the conversion factors
99 factor = iter->second.first;
100 power = iter->second.second;
101 return true;
102}
103
104// Initialise the static map holding the 'quick conversions'
106
107//---------------------------------------------------------------------------------------
114void Unit::addConversion(std::string to, const double &factor, const double &power) const {
115 std::transform(to.begin(), to.end(), to.begin(), toupper);
116 // Add the conversion to the map (does nothing if it's already there)
117 s_conversionFactors[unitID()][to] = std::make_pair(factor, power);
118}
119
120//---------------------------------------------------------------------------------------
133void Unit::initialize(const double &_l1, const int &_emode, const UnitParametersMap &params) {
134 l1 = _l1;
135 validateUnitParams(_emode, params);
136 emode = _emode;
137 m_params = &params;
138 initialized = true;
139 this->init();
140}
141
143
144//---------------------------------------------------------------------------------------
148void Unit::toTOF(std::vector<double> &xdata, std::vector<double> const &ydata, const double &_l1, const int &_emode,
149 std::initializer_list<std::pair<const UnitParams, double>> params) {
150 UnitParametersMap paramsMap(params);
151 toTOF(xdata, ydata, _l1, _emode, paramsMap);
152}
153
154void Unit::toTOF(std::vector<double> &xdata, std::vector<double> const &ydata, const double &_l1, const int &_emode,
155 const UnitParametersMap &params) {
156 UNUSED_ARG(ydata);
157 this->initialize(_l1, _emode, params);
158 size_t numX = xdata.size();
159 for (size_t i = 0; i < numX; i++)
160 xdata[i] = this->singleToTOF(xdata[i]);
161}
162
169double Unit::convertSingleToTOF(const double xvalue, const double &l1, const int &emode,
170 const UnitParametersMap &params) {
171 this->initialize(l1, emode, params);
172 return this->singleToTOF(xvalue);
173}
174
175//---------------------------------------------------------------------------------------
178void Unit::fromTOF(std::vector<double> &xdata, std::vector<double> const &ydata, const double &_l1, const int &_emode,
179 std::initializer_list<std::pair<const UnitParams, double>> params) {
180 UnitParametersMap paramsMap(params);
181 fromTOF(xdata, ydata, _l1, _emode, paramsMap);
182}
183
184void Unit::fromTOF(std::vector<double> &xdata, std::vector<double> const &ydata, const double &_l1, const int &_emode,
185 const UnitParametersMap &params) {
186 UNUSED_ARG(ydata);
187 this->initialize(_l1, _emode, params);
188 size_t numX = xdata.size();
189 for (size_t i = 0; i < numX; i++)
190 xdata[i] = this->singleFromTOF(xdata[i]);
191}
192
199double Unit::convertSingleFromTOF(const double xvalue, const double &l1, const int &emode,
200 const UnitParametersMap &params) {
201 this->initialize(l1, emode, params);
202 return this->singleFromTOF(xvalue);
203}
204
205std::pair<double, double> Unit::conversionRange() const {
206 double u1 = this->singleFromTOF(this->conversionTOFMin());
207 double u2 = this->singleFromTOF(this->conversionTOFMax());
208 //
209 return std::pair<double, double>(std::min(u1, u2), std::max(u1, u2));
210}
211
212namespace Units {
213
214/* =============================================================================
215 * EMPTY
216 * =============================================================================
217 */
218DECLARE_UNIT(Empty)
219
220const UnitLabel Empty::label() const { return Symbol::EmptyLabel; }
221
222void Empty::init() {}
223
224double Empty::singleToTOF(const double x) const {
225 UNUSED_ARG(x);
226 throw Kernel::Exception::NotImplementedError("Cannot convert unit " + this->unitID() + " to time of flight");
227}
228
229double Empty::singleFromTOF(const double tof) const {
230 UNUSED_ARG(tof);
231 throw Kernel::Exception::NotImplementedError("Cannot convert to unit " + this->unitID() + " from time of flight");
232}
233
234Unit *Empty::clone() const { return new Empty(*this); }
235
239double Empty::conversionTOFMin() const { return std::numeric_limits<double>::quiet_NaN(); }
240
244double Empty::conversionTOFMax() const { return std::numeric_limits<double>::quiet_NaN(); }
245
246/* =============================================================================
247 * LABEL
248 * =============================================================================
249 */
250
252
253const UnitLabel Label::label() const { return m_label; }
254
256Label::Label() : Empty(), m_caption("Quantity"), m_label(Symbol::EmptyLabel) {}
257
258Label::Label(const std::string &caption, const std::string &label) : Empty(), m_caption(), m_label(Symbol::EmptyLabel) {
260}
261
265void Label::setLabel(const std::string &cpt, const UnitLabel &lbl) {
266 m_caption = cpt;
267 m_label = lbl;
268}
269
270Unit *Label::clone() const { return new Label(*this); }
271
272/* =============================================================================
273 * TIME OF FLIGHT
274 * =============================================================================
275 */
277
278const UnitLabel TOF::label() const { return Symbol::Microsecond; }
279
281
282void TOF::init() {}
283
284double TOF::singleToTOF(const double x) const {
285 // Nothing to do
286 return x;
287}
288
289double TOF::singleFromTOF(const double tof) const {
290 // Nothing to do
291 return tof;
292}
293
294Unit *TOF::clone() const { return new TOF(*this); }
295double TOF::conversionTOFMin() const { return -DBL_MAX; }
297double TOF::conversionTOFMax() const { return DBL_MAX; }
298
299// ============================================================================================
300/* WAVELENGTH
301 * ===================================================================================================
302 *
303 * This class makes use of the de Broglie relationship: lambda = h/p = h/mv,
304 *where v is (l1+l2)/tof.
305 */
307
309 : Unit(), efixed(0.), sfpTo(DBL_MIN), factorTo(DBL_MIN), sfpFrom(DBL_MIN), factorFrom(DBL_MIN), do_sfpFrom(false) {
310 const double AngstromsSquared = 1e20;
311 const double factor = (AngstromsSquared * PhysicalConstants::h * PhysicalConstants::h) /
313 addConversion("Energy", factor, -2.0);
314 addConversion("Energy_inWavenumber", factor * PhysicalConstants::meVtoWavenumber, -2.0);
315 addConversion("Momentum", 2 * M_PI, -1.0);
316}
317
319
320void Wavelength::validateUnitParams(const int emode, const UnitParametersMap &params) {
321 if (!ParamPresent(params, UnitParams::l2)) {
322 throw std::runtime_error("An l2 value must be supplied in the extra "
323 "parameters when initialising " +
324 this->unitID() + " for conversion via TOF");
325 }
326 if ((emode != 0) && (!ParamPresent(params, UnitParams::efixed))) {
327 throw std::runtime_error("An efixed value must be supplied in the extra "
328 "parameters when initialising " +
329 this->unitID() + " for conversion via TOF");
330 }
331}
332
334 // ------------ Factors to convert TO TOF ---------------------
335 double l2 = 0.0;
336 double ltot = 0.0;
337 double TOFisinMicroseconds = 1e6;
338 double toAngstroms = 1e10;
339 sfpTo = 0.0;
340
341 ParamPresentAndSet(m_params, UnitParams::efixed, efixed);
342 ParamPresentAndSet(m_params, UnitParams::l2, l2);
343
344 if (emode == 1) {
345 ltot = l2;
346 sfpTo = (sqrt(PhysicalConstants::NeutronMass / (2.0 * PhysicalConstants::meV)) * TOFisinMicroseconds * l1) /
347 sqrt(efixed);
348 } else if (emode == 2) {
349 ltot = l1;
350 sfpTo = (sqrt(PhysicalConstants::NeutronMass / (2.0 * PhysicalConstants::meV)) * TOFisinMicroseconds * l2) /
351 sqrt(efixed);
352 } else {
353 ltot = l1 + l2;
354 }
356 // Now adjustments for the scale of units used
357 factorTo *= TOFisinMicroseconds / toAngstroms;
358
359 // ------------ Factors to convert FROM TOF ---------------------
360 // Now apply the factor to the input data vector
361 do_sfpFrom = false;
362 if (efixed != DBL_MIN) {
363 if (emode == 1) // Direct
364 {
365 sfpFrom = (sqrt(PhysicalConstants::NeutronMass / (2.0 * PhysicalConstants::meV)) * TOFisinMicroseconds * l1) /
366 sqrt(efixed);
367 do_sfpFrom = true;
368 } else if (emode == 2) // Indirect
369 {
370 sfpFrom = (sqrt(PhysicalConstants::NeutronMass / (2.0 * PhysicalConstants::meV)) * TOFisinMicroseconds * l2) /
371 sqrt(efixed);
372 do_sfpFrom = true;
373 }
374 }
375
376 // Protect against divide by zero
377 if (ltot == 0.0)
378 ltot = DBL_MIN;
379
380 // First the crux of the conversion
382
383 // Now adjustments for the scale of units used
384 factorFrom *= toAngstroms / TOFisinMicroseconds;
385}
386
387double Wavelength::singleToTOF(const double x) const {
388 double tof = x * factorTo;
389 // If Direct or Indirect we want to correct TOF values..
390 if (emode == 1 || emode == 2)
391 tof += sfpTo;
392 return tof;
393}
394double Wavelength::singleFromTOF(const double tof) const {
395 double x = tof;
396 if (do_sfpFrom)
397 x -= sfpFrom;
398 x *= factorFrom;
399 return x;
400}
404 double min_tof(0);
405 if (emode == 1 || emode == 2)
406 min_tof = sfpTo;
407 return min_tof;
408}
412 double max_tof;
413 if (factorTo > 1) {
414 max_tof = (DBL_MAX - sfpTo) / factorTo;
415 } else {
416 max_tof = DBL_MAX - sfpTo / factorTo;
417 }
418 return max_tof;
419}
420
421Unit *Wavelength::clone() const { return new Wavelength(*this); }
422
423// ============================================================================================
424/* ENERGY
425 * ===============================================================================================
426 *
427 * Conversion uses E = 1/2 mv^2, where v is (l1+l2)/tof.
428 */
430
431const UnitLabel Energy::label() const { return Symbol::MilliElectronVolts; }
432
434Energy::Energy() : Unit(), factorTo(DBL_MIN), factorFrom(DBL_MIN) {
436 const double toAngstroms = 1e10;
437 const double factor =
439 addConversion("Wavelength", factor, -0.5);
440 addConversion("Momentum", 2 * M_PI / factor, 0.5);
441}
442
443void Energy::validateUnitParams(const int, const UnitParametersMap &params) {
444 if (!ParamPresent(params, UnitParams::l2)) {
445 throw std::runtime_error("An l2 value must be supplied in the extra "
446 "parameters when initialising " +
447 this->unitID() + " for conversion via TOF");
448 }
449}
450
452 double l2 = 0.0;
453 ParamPresentAndSet(m_params, UnitParams::l2, l2);
454 {
455 const double TOFinMicroseconds = 1e6;
456 factorTo = sqrt(PhysicalConstants::NeutronMass / (2.0 * PhysicalConstants::meV)) * (l1 + l2) * TOFinMicroseconds;
457 }
458 {
459 const double TOFisinMicroseconds = 1e-12; // The input tof number gets squared so this is (10E-6)^2
460 const double ltot = l1 + l2;
461 factorFrom =
462 ((PhysicalConstants::NeutronMass / 2.0) * (ltot * ltot)) / (PhysicalConstants::meV * TOFisinMicroseconds);
463 }
464}
465
466double Energy::singleToTOF(const double x) const {
467 double temp = x;
468 if (temp == 0.0)
469 temp = DBL_MIN; // Protect against divide by zero
470 return factorTo / sqrt(temp);
471}
473double Energy::conversionTOFMin() const { return factorTo / sqrt(DBL_MAX); }
474double Energy::conversionTOFMax() const { return sqrt(DBL_MAX); }
475
476double Energy::singleFromTOF(const double tof) const {
477 double temp = tof;
478 if (temp == 0.0)
479 temp = DBL_MIN; // Protect against divide by zero
480 return factorFrom / (temp * temp);
481}
482
483Unit *Energy::clone() const { return new Energy(*this); }
484
485// ============================================================================================
486/* ENERGY IN UNITS OF WAVENUMBER
487 * ============================================================================================
488 *
489 * Conversion uses E = 1/2 mv^2, where v is (l1+l2)/tof.
490 */
492
493const UnitLabel Energy_inWavenumber::label() const { return Symbol::InverseCM; }
494
496Energy_inWavenumber::Energy_inWavenumber() : Unit(), factorTo(DBL_MIN), factorFrom(DBL_MIN) {
498 const double toAngstroms = 1e10;
499 const double factor =
500 toAngstroms * PhysicalConstants::h /
502 addConversion("Wavelength", factor, -0.5);
503
504 addConversion("Momentum", 2 * M_PI / factor, 0.5);
505}
506
508 if (!ParamPresent(params, UnitParams::l2)) {
509 throw std::runtime_error("An l2 value must be supplied in the extra "
510 "parameters when initialising " +
511 this->unitID() + " for conversion via TOF");
512 }
513}
514
516 double l2 = 0.0;
517 ParamPresentAndSet(m_params, UnitParams::l2, l2);
518 {
519 const double TOFinMicroseconds = 1e6;
520 factorTo =
522 (l1 + l2) * TOFinMicroseconds;
523 }
524 {
525 const double TOFisinMicroseconds = 1e-12; // The input tof number gets squared so this is (10E-6)^2
526 const double ltot = l1 + l2;
528 (PhysicalConstants::meV * TOFisinMicroseconds);
529 }
530}
531
532double Energy_inWavenumber::singleToTOF(const double x) const {
533 double temp = x;
534 if (temp <= DBL_MIN)
535 temp = DBL_MIN; // Protect against divide by zero and define conversion range
536 return factorTo / sqrt(temp);
537}
540double Energy_inWavenumber::conversionTOFMin() const { return factorTo / sqrt(std::numeric_limits<double>::max()); }
541double Energy_inWavenumber::conversionTOFMax() const { return factorTo / sqrt(std::numeric_limits<double>::max()); }
542
543double Energy_inWavenumber::singleFromTOF(const double tof) const {
544 double temp = tof;
545 if (temp == 0.0)
546 temp = DBL_MIN; // Protect against divide by zero
547 return factorFrom / (temp * temp);
548}
549
551
552// used in calculate of DIFC
554
565double calculateDIFCCorrection(const double l1, const double l2, const double twotheta, const double offset,
566 const double binWidth) {
567 const double sinTheta = std::sin(twotheta / 2.0);
568 const double newDIFC = NEUTRON_MASS_OVER_H * (l1 + l2) * 2.0 * sinTheta * pow((1.0 + fabs(binWidth)), -1.0 * offset);
569 return newDIFC;
570}
571
572// ==================================================================================================
573/* D-SPACING
574 * ==================================================================================================
575 *
576 * Conversion uses Bragg's Law: 2d sin(theta) = n * lambda
577 */
578
580
589double tofToDSpacingFactor(const double l1, const double l2, const double twoTheta, const double offset) {
590 if (offset <= -1.) // not physically possible, means result is negative d-spacing
591 {
592 std::stringstream msg;
593 msg << "Encountered offset of " << offset << " which converts data to negative d-spacing\n";
594 throw std::logic_error(msg.str());
595 }
596
597 auto sinTheta = std::sin(twoTheta / 2);
598
599 const double numerator = (1.0 + offset);
600 sinTheta *= (l1 + l2);
601
602 return (numerator * H_OVER_NEUTRON_MASS) / sinTheta;
603}
604
605DECLARE_UNIT(dSpacing)
606
607dSpacing::dSpacing() : Unit(), toDSpacingError(""), difa(0), difc(DBL_MIN), tzero(0) {
608 const double factor = 2.0 * M_PI;
609 addConversion("MomentumTransfer", factor, -1.0);
610 addConversion("QSquared", (factor * factor), -2.0);
611}
612
614
615Unit *dSpacing::clone() const { return new dSpacing(*this); }
616
617void dSpacing::validateUnitParams(const int, const UnitParametersMap &params) {
618 double difc_set = 0.;
619 if (ParamPresentAndSet(&params, UnitParams::difc, difc_set)) {
620 // check validations only applicable to fromTOF
621 toDSpacingError = "";
622 double difa_set = 0.;
623 ParamPresentAndSet(&params, UnitParams::difa, difa_set);
624 if ((difa_set == 0) && (difc_set == 0)) {
625 toDSpacingError = "Cannot convert to d spacing with DIFA=0 and DIFC=0";
626 };
627 // singleFromTOF currently assuming difc not negative
628 if (difc_set < 0.) {
629 toDSpacingError = "A positive difc value must be supplied in the extra parameters when "
630 "initialising " +
631 this->unitID() + " for conversion via TOF";
632 }
633 } else {
634 if (!ParamPresent(params, UnitParams::twoTheta) || (!ParamPresent(params, UnitParams::l2))) {
635 throw std::runtime_error("A difc value or L2/two theta must be supplied "
636 "in the extra parameters when initialising " +
637 this->unitID() + " for conversion via TOF");
638 }
639 }
640}
641
643 // First the crux of the conversion
644 difa = 0.;
645 difc = 0.;
646 tzero = 0.;
647 ParamPresentAndSet(m_params, UnitParams::difa, difa);
648 ParamPresentAndSet(m_params, UnitParams::tzero, tzero);
649
650 if (!ParamPresentAndSet(m_params, UnitParams::difc, difc)) {
651 // also support inputs as L2, two theta
652 double l2;
653 if (ParamPresentAndSet(m_params, UnitParams::l2, l2)) {
654 double twoTheta;
655 if (ParamPresentAndSet(m_params, UnitParams::twoTheta, twoTheta)) {
656 if (difa != 0.) {
657 g_log.warning("Supplied difa ignored");
658 difa = 0.;
659 }
660 difc = 1. / tofToDSpacingFactor(l1, l2, twoTheta, 0.);
661 if (tzero != 0.) {
662 g_log.warning("Supplied tzero ignored");
663 tzero = 0.;
664 }
665 }
666 }
667 }
668}
669
670double dSpacing::singleToTOF(const double x) const {
671 if (!isInitialized())
672 throw std::runtime_error("dSpacingBase::singleToTOF called before object "
673 "has been initialized.");
674 if (difa == 0.)
675 return difc * x + tzero;
676 else
677 return difa * x * x + difc * x + tzero;
678}
679
696double dSpacing::singleFromTOF(const double tof) const {
697 // dealing with various edge cases
698 if (!isInitialized())
699 throw std::runtime_error("dSpacingBase::singleFromTOF called before object "
700 "has been initialized.");
701 if (!toDSpacingError.empty())
702 throw std::runtime_error(toDSpacingError);
703
704 // this is with the opposite sign from the equation above
705 // as it reduces number of individual flops
706 const double negativeConstantTerm = tof - tzero;
707
708 // don't need to solve a quadratic when difa==0
709 // this allows negative d-spacing to be returned
710 // which was the behavior before v6.2 was released
711 if (difa == 0.)
712 return negativeConstantTerm / difc;
713
714 // non-physical result
715 if (tzero > tof) {
716 if (difa > 0.) {
717 throw std::runtime_error("Cannot convert to d spacing because tzero > time-of-flight and difa is positive. "
718 "Quadratic doesn't have a positive root");
719 }
720 }
721
722 // citardauq formula hides non-zero root if tof==tzero
723 // wich means that the constantTerm == 0
724 if (tof == tzero) {
725 if (difa < 0.)
726 return -difc / difa;
727 else
728 return 0.;
729 }
730
731 // general citarqauq equation
732 const double sqrtTerm = 1 + 4 * difa * negativeConstantTerm / (difc * difc);
733 if (sqrtTerm < 0.) {
734 throw std::runtime_error("Cannot convert to d spacing. Quadratic doesn't have real roots");
735 }
736 // pick smallest positive root. Since difc is positive it just depends on sign of constantTerm
737 // Note - constantTerm is generally negative
738 if (negativeConstantTerm < 0)
739 // single positive root
740 return negativeConstantTerm / (0.5 * difc * (1 - sqrt(sqrtTerm)));
741 else
742 // two positive roots. pick most negative denominator to get smallest root
743 return negativeConstantTerm / (0.5 * difc * (1 + sqrt(sqrtTerm)));
744}
745
747 // quadratic only has a min if difa is positive
748 if (difa > 0) {
749 // min of the quadratic is at d=-difc/(2*difa)
750 return std::max(0., tzero - difc * difc / (4 * difa));
751 } else {
752 // no min so just pick value closest to zero that works
753 double TOFmin = singleToTOF(0.);
754 if (TOFmin < std::numeric_limits<double>::min()) {
755 TOFmin = 0.;
756 }
757 return TOFmin;
758 }
759}
760
762 // quadratic only has a max if difa is negative
763 if (difa < 0) {
764 return std::min(DBL_MAX, tzero - difc * difc / (4 * difa));
765 } else {
766 // no max so just pick value closest to DBL_MAX that works
767 double TOFmax = singleToTOF(DBL_MAX);
768 if (std::isinf(TOFmax)) {
769 TOFmax = DBL_MAX;
770 }
771 return TOFmax;
772 }
773}
774
775double dSpacing::calcTofMin(const double difc, const double difa, const double tzero, const double tofmin) {
778 initialize(-1., 0, params);
779 return std::max(conversionTOFMin(), tofmin);
780}
781
782double dSpacing::calcTofMax(const double difc, const double difa, const double tzero, const double tofmax) {
785 initialize(-1, 0, params);
786 return std::min(conversionTOFMax(), tofmax);
787}
788
789// ==================================================================================================
790/* D-SPACING Perpendicular
791 * ==================================================================================================
792 *
793 * Conversion uses equation: dp^2 = lambda^2 - 2[Angstrom^2]*ln(cos(theta))
794 */
796
797const UnitLabel dSpacingPerpendicular::label() const { return Symbol::Angstrom; }
798
799dSpacingPerpendicular::dSpacingPerpendicular() : Unit(), factorTo(DBL_MIN), factorFrom(DBL_MIN) {}
800
802 if (!ParamPresent(params, UnitParams::l2)) {
803 throw std::runtime_error("A l2 value must be supplied in the extra parameters when "
804 "initialising " +
805 this->unitID() + " for conversion via TOF");
806 }
807 if (!ParamPresent(params, UnitParams::twoTheta)) {
808 throw std::runtime_error("A two theta value must be supplied in the extra parameters when "
809 "initialising " +
810 this->unitID() + " for conversion via TOF");
811 }
812}
813
815 double l2 = 0.0;
816 ParamPresentAndSet(m_params, UnitParams::l2, l2);
817 ParamPresentAndSet(m_params, UnitParams::twoTheta, twoTheta);
819
820 // Now adjustments for the scale of units used
821 const double TOFisinMicroseconds = 1e6;
822 const double toAngstroms = 1e10;
823 factorTo *= TOFisinMicroseconds / toAngstroms;
825 if (factorFrom == 0.0)
826 factorFrom = DBL_MIN; // Protect against divide by zero
827 double cos_theta = cos(twoTheta / 2.0);
828 sfpTo = 0.0;
829 if (cos_theta > 0)
830 sfpTo = 2.0 * log(cos_theta);
831 sfpFrom = sfpTo;
832}
833
834double dSpacingPerpendicular::singleToTOF(const double x) const {
835 double sqrtarg = x * x + sfpTo;
836 // consider very small values to be a rounding error
837 if (sqrtarg < 1.0e-17)
838 return 0.0;
839 return sqrt(sqrtarg) * factorTo;
840}
841double dSpacingPerpendicular::singleFromTOF(const double tof) const {
842 double temp = tof / factorFrom;
843 return sqrt(temp * temp - sfpFrom);
844}
845double dSpacingPerpendicular::conversionTOFMin() const { return sqrt(-1.0 * sfpFrom); }
846double dSpacingPerpendicular::conversionTOFMax() const { return sqrt(std::numeric_limits<double>::max()) / factorFrom; }
847
849
850// ================================================================================
851/* MOMENTUM TRANSFER
852 * ================================================================================
853 *
854 * The relationship is Q = 2k sin (theta). where k is 2*pi/wavelength
855 */
857
858const UnitLabel MomentumTransfer::label() const { return Symbol::InverseAngstrom; }
859
861 addConversion("QSquared", 1.0, 2.0);
862 const double factor = 2.0 * M_PI;
863 addConversion("dSpacing", factor, -1.0);
864}
865
867 double difc_set = 0.;
868 if (!ParamPresentAndSet(&params, UnitParams::difc, difc_set)) {
869 if (!ParamPresent(params, UnitParams::twoTheta) || (!ParamPresent(params, UnitParams::l2)))
870 throw std::runtime_error("A difc value or L2/two theta must be supplied "
871 "in the extra parameters when initialising " +
872 this->unitID() + " for conversion via TOF");
873 };
874}
875
877 // First the crux of the conversion
878 difc = 0.;
879
880 if (!ParamPresentAndSet(m_params, UnitParams::difc, difc)) {
881 // also support inputs as L2, two theta
882 double l2;
883 if (ParamPresentAndSet(m_params, UnitParams::l2, l2)) {
884 double twoTheta;
885 if (ParamPresentAndSet(m_params, UnitParams::twoTheta, twoTheta)) {
886 difc = 1. / tofToDSpacingFactor(l1, l2, twoTheta, 0.);
887 }
888 }
889 }
890}
891
892double MomentumTransfer::singleToTOF(const double x) const { return 2. * M_PI * difc / x; }
893//
894double MomentumTransfer::singleFromTOF(const double tof) const { return 2. * M_PI * difc / tof; }
895
896double MomentumTransfer::conversionTOFMin() const { return 2. * M_PI * difc / DBL_MAX; }
897double MomentumTransfer::conversionTOFMax() const { return DBL_MAX; }
898
899Unit *MomentumTransfer::clone() const { return new MomentumTransfer(*this); }
900
901/* ===================================================================================================
902 * Q-SQUARED
903 * ===================================================================================================
904 */
906
907const UnitLabel QSquared::label() const { return Symbol::InverseAngstromSq; }
908
910 addConversion("MomentumTransfer", 1.0, 0.5);
911 const double factor = 2.0 * M_PI;
912 addConversion("dSpacing", factor, -0.5);
913}
914
915double QSquared::singleToTOF(const double x) const { return MomentumTransfer::singleToTOF(sqrt(x)); }
916double QSquared::singleFromTOF(const double tof) const { return pow(MomentumTransfer::singleFromTOF(tof), 2); }
917
918double QSquared::conversionTOFMin() const { return 2 * M_PI * difc / sqrt(DBL_MAX); }
920 double tofmax = 2 * M_PI * difc / sqrt(DBL_MIN);
921 if (std::isinf(tofmax))
922 tofmax = DBL_MAX;
923 return tofmax;
924}
925
926Unit *QSquared::clone() const { return new QSquared(*this); }
927
928/* ==============================================================================
929 * Energy Transfer
930 * ==============================================================================
931 */
933
934const UnitLabel DeltaE::label() const { return Symbol::MilliElectronVolts; }
935
937 : Unit(), factorTo(DBL_MIN), factorFrom(DBL_MIN), t_other(DBL_MIN), t_otherFrom(DBL_MIN), unitScaling(DBL_MIN) {
938 addConversion("DeltaE_inWavenumber", PhysicalConstants::meVtoWavenumber, 1.);
939 addConversion("DeltaE_inFrequency", PhysicalConstants::meVtoFrequency, 1.);
940}
941
942void DeltaE::validateUnitParams(const int emode, const UnitParametersMap &params) {
943 if (emode != 1 && emode != 2) {
944 throw std::invalid_argument("emode must be equal to 1 or 2 for energy transfer calculation");
945 }
946 // Efixed must be set to something
947 double efixed_set;
948 if (!ParamPresentAndSet(&params, UnitParams::efixed, efixed_set)) {
949 if (emode == 1) { // direct, efixed=ei
950 throw std::invalid_argument("efixed must be set for energy transfer calculation");
951 } else {
952 throw std::runtime_error("efixed must be set for energy transfer calculation");
953 }
954 }
955 if (efixed_set <= 0) {
956 throw std::runtime_error("efixed must be greater than zero");
957 }
958 if (!ParamPresent(params, UnitParams::l2)) {
959 throw std::runtime_error("A l2 value must be supplied in the extra parameters when "
960 "initialising " +
961 this->unitID() + " for conversion via TOF");
962 }
963}
964
966 double l2 = 0.0;
967 ParamPresentAndSet(m_params, UnitParams::l2, l2);
968 ParamPresentAndSet(m_params, UnitParams::efixed, efixed);
969 const double TOFinMicroseconds = 1e6;
970 factorTo = sqrt(PhysicalConstants::NeutronMass / (2.0 * PhysicalConstants::meV)) * TOFinMicroseconds;
971 if (emode == 1) {
972 // t_other is t1
973 t_other = (factorTo * l1) / sqrt(efixed);
974 factorTo *= l2;
975 } else if (emode == 2) {
976 // t_other is t2
977 t_other = (factorTo * l2) / sqrt(efixed);
978 factorTo *= l1;
979 }
980
981 //------------ from conversion ------------------
982 factorFrom = sqrt(PhysicalConstants::NeutronMass / (2.0 * PhysicalConstants::meV)) * TOFinMicroseconds;
983
984 if (emode == 1) {
985 // t_otherFrom = t1
986 t_otherFrom = (factorFrom * l1) / sqrt(efixed);
988 } else if (emode == 2) {
989 // t_otherFrom = t2
990 t_otherFrom = (factorFrom * l2) / sqrt(efixed);
992 }
993
994 // This will be changed for the wavenumber one
995 unitScaling = 1;
996}
997
998double DeltaE::singleToTOF(const double x) const {
999 if (emode == 1) {
1000 const double e2 = efixed - x / unitScaling;
1001 if (e2 <= 0.0) // This shouldn't ever happen (unless the efixed value is wrong)
1002 return DeltaE::conversionTOFMax();
1003 else {
1004 // this_t = t2;
1005 const double this_t = factorTo / sqrt(e2);
1006 return this_t + t_other; // (t1+t2);
1007 }
1008 } else if (emode == 2) {
1009 const double e1 = efixed + x / unitScaling;
1010 if (e1 <= 0.0) // This shouldn't ever happen (unless the efixed value is wrong)
1011 return DeltaE::conversionTOFMax();
1012 else {
1013 // this_t = t1;
1014 const double this_t = factorTo / sqrt(e1);
1015 return this_t + t_other; // (t1+t2);
1016 }
1017 } else {
1018 return DeltaE::conversionTOFMax();
1019 }
1020}
1021
1022double DeltaE::singleFromTOF(const double tof) const {
1023 if (emode == 1) {
1024 // This is t2
1025 const double this_t = tof - t_otherFrom;
1026 if (this_t <= 0.0)
1027 return -DBL_MAX;
1028 else {
1029 const double e2 = factorFrom / (this_t * this_t);
1030 return (efixed - e2) * unitScaling;
1031 }
1032 } else if (emode == 2) {
1033 // This is t1
1034 const double this_t = tof - t_otherFrom;
1035 if (this_t <= 0.0)
1036 return DBL_MAX;
1037 else {
1038 const double e1 = factorFrom / (this_t * this_t);
1039 return (e1 - efixed) * unitScaling;
1040 }
1041 } else
1042 return DBL_MAX;
1043}
1044
1046 double time(DBL_MAX); // impossible for elastic, this units do not work for elastic
1047 if (emode == 1 || emode == 2)
1048 time = t_otherFrom * (1 + DBL_EPSILON);
1049 return time;
1050}
1052 // 0.1 here to provide at least two significant units to conversion range as
1053 // this conversion range comes from 1-epsilon
1054 if (efixed > 1)
1055 return t_otherFrom + sqrt(factorFrom / efixed) / sqrt(DBL_MIN);
1056 else
1057 return t_otherFrom + sqrt(factorFrom) / sqrt(DBL_MIN);
1058}
1059
1060Unit *DeltaE::clone() const { return new DeltaE(*this); }
1061
1062// =====================================================================================================
1063/* Energy Transfer in units of wavenumber
1064 * =====================================================================================================
1065 *
1066 * This is identical to the above (Energy Transfer in meV) with one division
1067 *by meVtoWavenumber.
1068 */
1070
1071const UnitLabel DeltaE_inWavenumber::label() const { return Symbol::InverseCM; }
1072
1074 DeltaE::init();
1075 // Change the unit scaling factor
1077}
1078
1080
1084
1085// =====================================================================================================
1086/* Energy Transfer in units of frequency
1087 * =====================================================================================================
1088 *
1089 * This is identical to Energy Transfer in meV, with one division by Plank's
1090 *constant, or multiplication
1091 * by factor PhysicalConstants::meVtoFrequency
1092 */
1094
1095const UnitLabel DeltaE_inFrequency::label() const { return Symbol::GHz; }
1096
1098 DeltaE::init();
1099 // Change the unit scaling factor
1101}
1102
1104
1108
1109// =====================================================================================================
1110/* Momentum in Angstrom^-1. It is 2*Pi/wavelength
1111 * =====================================================================================================
1112 */
1114
1115const UnitLabel Momentum::label() const { return Symbol::InverseAngstrom; }
1116
1118 : Unit(), efixed(0.), sfpTo(DBL_MIN), factorTo(DBL_MIN), sfpFrom(DBL_MIN), factorFrom(DBL_MIN), do_sfpFrom(false) {
1119
1120 const double AngstromsSquared = 1e20;
1121 const double factor = (AngstromsSquared * PhysicalConstants::h * PhysicalConstants::h) /
1122 (2.0 * PhysicalConstants::NeutronMass * PhysicalConstants::meV) / (4 * M_PI * M_PI);
1123
1124 addConversion("Energy", factor, 2.0);
1125 addConversion("Energy_inWavenumber", factor * PhysicalConstants::meVtoWavenumber, 2.0);
1126 addConversion("Wavelength", 2 * M_PI, -1.0);
1127 //
1128}
1129
1130void Momentum::validateUnitParams(const int emode, const UnitParametersMap &params) {
1131 if (!ParamPresent(params, UnitParams::l2)) {
1132 throw std::runtime_error("An l2 value must be supplied in the extra parameters when "
1133 "initialising momentum for conversion via TOF");
1134 }
1135 if ((emode != 0) && (!ParamPresent(params, UnitParams::efixed))) {
1136 throw std::runtime_error("An efixed value must be supplied in the extra parameters when "
1137 "initialising momentum for conversion via TOF");
1138 }
1139}
1140
1142 // ------------ Factors to convert TO TOF ---------------------
1143 double l2 = 0.0;
1144 double ltot = 0.0;
1145 double TOFisinMicroseconds = 1e6;
1146 double toAngstroms = 1e10;
1147 sfpTo = 0.0;
1148
1149 ParamPresentAndSet(m_params, UnitParams::l2, l2);
1150 ParamPresentAndSet(m_params, UnitParams::efixed, efixed);
1151
1152 if (emode == 1) {
1153 ltot = l2;
1154 sfpTo = (sqrt(PhysicalConstants::NeutronMass / (2.0 * PhysicalConstants::meV)) * TOFisinMicroseconds * l1) /
1155 sqrt(efixed);
1156 } else if (emode == 2) {
1157 ltot = l1;
1158 sfpTo = (sqrt(PhysicalConstants::NeutronMass / (2.0 * PhysicalConstants::meV)) * TOFisinMicroseconds * l2) /
1159 sqrt(efixed);
1160 } else {
1161 ltot = l1 + l2;
1162 }
1164 // Now adjustments for the scale of units used
1165 factorTo *= TOFisinMicroseconds / toAngstroms;
1166
1167 // ------------ Factors to convert FROM TOF ---------------------
1168
1169 // Now apply the factor to the input data vector
1170 do_sfpFrom = false;
1171 if (efixed != DBL_MIN) {
1172 if (emode == 1) // Direct
1173 {
1174 sfpFrom = sfpTo;
1175 do_sfpFrom = true;
1176 } else if (emode == 2) // Indirect
1177 {
1178 sfpFrom = sfpTo;
1179 do_sfpFrom = true;
1180 }
1181 }
1182
1183 // Protect against divide by zero
1184 if (ltot == 0.0)
1185 ltot = DBL_MIN;
1186
1187 // First the crux of the conversion
1189
1190 // Now adjustments for the scale of units used
1191 factorFrom *= toAngstroms / TOFisinMicroseconds;
1192 factorFrom = 2 * M_PI / factorFrom;
1193}
1194
1195double Momentum::singleToTOF(const double ki) const {
1196 double tof = factorTo / ki;
1197 // If Direct or Indirect we want to correct TOF values..
1198 if (emode == 1 || emode == 2)
1199 tof += sfpTo;
1200 return tof;
1201}
1203 double range = DBL_MIN * factorFrom;
1204 if (emode == 1 || emode == 2)
1205 range = sfpFrom * (1 + DBL_EPSILON * factorFrom);
1206 return range;
1207}
1209 double range = DBL_MAX / factorTo;
1210 if (emode == 1 || emode == 2) {
1211 range = 1 + DBL_MAX / factorTo + sfpFrom;
1212 }
1213 return range;
1214}
1215
1216double Momentum::singleFromTOF(const double tof) const {
1217 double x = tof;
1218 if (do_sfpFrom)
1219 x -= sfpFrom;
1220 if (x == 0)
1221 x = DBL_MIN;
1222
1223 return factorFrom / x;
1224}
1225
1226Unit *Momentum::clone() const { return new Momentum(*this); }
1227
1228// ============================================================================================
1229/* SpinEchoLength
1230 * ===================================================================================================
1231 *
1232 * Delta = (constant)*(wavelength)^2
1233 */
1235
1236const UnitLabel SpinEchoLength::label() const { return Symbol::Nanometre; }
1237
1239
1241 ParamPresentAndSet(m_params, UnitParams::efixed, efixed);
1242 // Efixed must be set to something
1243 if (efixed == 0.0)
1244 throw std::invalid_argument("efixed must be set for spin echo length calculation");
1245 if (emode > 0) {
1246 throw std::invalid_argument("emode must be equal to 0 for spin echo length calculation");
1247 }
1249}
1250
1251double SpinEchoLength::singleToTOF(const double x) const {
1252 double wavelength = sqrt(x / efixed);
1253 double tof = Wavelength::singleToTOF(wavelength);
1254 return tof;
1255}
1256
1258 double wl = Wavelength::conversionTOFMin();
1259 return efixed * wl * wl;
1260}
1262 double sel = sqrt(DBL_MAX);
1263 if (efixed > 1) {
1264 sel /= efixed;
1265 }
1266
1267 return sel;
1268}
1269
1270double SpinEchoLength::singleFromTOF(const double tof) const {
1271 double wavelength = Wavelength::singleFromTOF(tof);
1272 double x = efixed * wavelength * wavelength;
1273 return x;
1274}
1275
1276Unit *SpinEchoLength::clone() const { return new SpinEchoLength(*this); }
1277
1278// ============================================================================================
1279/* SpinEchoTime
1280 * ===================================================================================================
1281 *
1282 * Tau = (constant)*(wavelength)^3
1283 */
1285
1286const UnitLabel SpinEchoTime::label() const { return Symbol::Nanosecond; }
1287
1289
1291 ParamPresentAndSet(m_params, UnitParams::efixed, efixed);
1292 // Efixed must be set to something
1293 if (efixed == 0.0)
1294 throw std::invalid_argument("efixed must be set for spin echo time calculation");
1295 if (emode > 0) {
1296 throw std::invalid_argument("emode must be equal to 0 for spin echo time calculation");
1297 }
1299}
1300
1301double SpinEchoTime::singleToTOF(const double x) const {
1302 double wavelength = pow(x / efixed, 1.0 / 3.0);
1303 double tof = Wavelength::singleToTOF(wavelength);
1304 return tof;
1305}
1306double SpinEchoTime::conversionTOFMin() const { return 0; }
1308 double tm = std::pow(DBL_MAX, 1. / 3.);
1309 if (efixed > 1)
1310 tm /= efixed;
1311 return tm;
1312}
1313
1314double SpinEchoTime::singleFromTOF(const double tof) const {
1315 double wavelength = Wavelength::singleFromTOF(tof);
1316 double x = efixed * wavelength * wavelength * wavelength;
1317 return x;
1318}
1319
1320Unit *SpinEchoTime::clone() const { return new SpinEchoTime(*this); }
1321
1322// ================================================================================
1323/* Time
1324 * ================================================================================
1325 *
1326 * Time is an independant unit to others related to energy and neutron
1327 */
1329
1330const UnitLabel Time::label() const { return Symbol::Second; }
1331
1332Time::Time() : Unit(), factorTo(DBL_MIN), factorFrom(DBL_MIN) {}
1333
1334void Time::init() {}
1335
1336double Time::singleToTOF(const double x) const {
1337 UNUSED_ARG(x);
1338 throw std::runtime_error("Time is not allowed to be convert to TOF. ");
1339}
1340
1341double Time::singleFromTOF(const double tof) const {
1342 UNUSED_ARG(tof);
1343 throw std::runtime_error("Time is not allowed to be converted from TOF. ");
1344}
1345
1346double Time::conversionTOFMax() const { return std::numeric_limits<double>::quiet_NaN(); }
1347double Time::conversionTOFMin() const { return std::numeric_limits<double>::quiet_NaN(); }
1348
1349Unit *Time::clone() const { return new Time(*this); }
1350
1351// ================================================================================
1352/* Degrees
1353 * ================================================================================
1354 *
1355 * Degrees prints degrees as a label
1356 */
1357
1359
1360Degrees::Degrees() : Empty(), m_label("degrees") {}
1361
1362const UnitLabel Degrees::label() const { return m_label; }
1363
1364double Degrees::singleToTOF(const double x) const {
1365 UNUSED_ARG(x);
1366 throw std::runtime_error("Degrees is not allowed to be converted to TOF. ");
1367}
1368
1369double Degrees::singleFromTOF(const double tof) const {
1370 UNUSED_ARG(tof);
1371 throw std::runtime_error("Degrees is not allowed to be converted from TOF. ");
1372}
1373
1374Unit *Degrees::clone() const { return new Degrees(*this); }
1375
1376// Phi
1378
1379// ================================================================================
1380/* Temperature in kelvin
1381 * ================================================================================
1382 *
1383 * TemperatureKelvin prints Temperature in units of Kelvin as a label
1384 */
1385
1387
1388Temperature::Temperature() : Empty(), m_label("K") {}
1389
1390const UnitLabel Temperature::label() const { return m_label; }
1391
1392double Temperature::singleToTOF(const double x) const {
1393 UNUSED_ARG(x);
1394 throw std::runtime_error("Temperature is not allowed to be converted to TOF. ");
1395}
1396
1397double Temperature::singleFromTOF(const double tof) const {
1398 UNUSED_ARG(tof);
1399 throw std::runtime_error("Temperature is not allowed to be converted from TOF. ");
1400}
1401
1402Unit *Temperature::clone() const { return new Temperature(*this); }
1403
1404// =====================================================================================================
1405/* Atomic Distance in units of Angstroms
1406 * =====================================================================================================
1407 *
1408 * The distance from the center of an atom in Angstroms
1409 */
1411
1412AtomicDistance::AtomicDistance() : Empty(), m_label("Atomic Distance") {}
1413
1415
1416Unit *AtomicDistance::clone() const { return new AtomicDistance(*this); }
1417
1418double AtomicDistance::singleToTOF(const double x) const {
1419 UNUSED_ARG(x);
1420 throw std::runtime_error("Atomic Distance is not allowed to be converted to TOF. ");
1421}
1422
1423double AtomicDistance::singleFromTOF(const double tof) const {
1424 UNUSED_ARG(tof);
1425 throw std::runtime_error("Atomic Distance is not allowed to be converted from TOF. ");
1426}
1427
1428// ================================================================================
1429
1430double timeConversionValue(const std::string &input_unit, const std::string &output_unit) {
1431 std::map<std::string, double> timesList;
1432 double seconds = 1.0e9;
1433 double milliseconds = 1.0e-3 * seconds;
1434 double microseconds = 1.0e-3 * milliseconds;
1435 double nanoseconds = 1.0e-3 * microseconds;
1436
1437 timesList["seconds"] = seconds;
1438 timesList["second"] = seconds;
1439 timesList["s"] = seconds;
1440 timesList["milliseconds"] = milliseconds;
1441 timesList["millisecond"] = milliseconds;
1442 timesList["ms"] = milliseconds;
1443 timesList["microseconds"] = microseconds;
1444 timesList["microsecond"] = microseconds;
1445 timesList["us"] = microseconds;
1446 timesList["nanoseconds"] = nanoseconds;
1447 timesList["nanosecond"] = nanoseconds;
1448 timesList["ns"] = nanoseconds;
1449
1450 double input_float = timesList[input_unit];
1451 double output_float = timesList[output_unit];
1452 if (input_float == 0)
1453 throw std::runtime_error("timeConversionValue: input unit " + input_unit + " not known.");
1454 if (output_float == 0)
1455 throw std::runtime_error("timeConversionValue: output unit " + input_unit + " not known.");
1456 return input_float / output_float;
1457}
1458
1459} // namespace Units
1460
1461} // namespace Mantid::Kernel
#define fabs(x)
Definition Matrix.cpp:22
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:48
#define DECLARE_UNIT(classname)
Definition UnitFactory.h:17
Marks code as not implemented yet.
Definition Exception.h:138
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
A base-class for the a class that is able to return unit labels in different representations.
Definition UnitLabel.h:20
The base units (abstract) class.
Definition Unit.h:41
const UnitParametersMap * m_params
additional parameters l2 :: distance from sample to detector (in metres) twoTheta :: scattering angle...
Definition Unit.h:177
bool operator!=(const Unit &u) const
Definition Unit.cpp:47
virtual void init()=0
Finalize the initialization.
virtual std::pair< double, double > conversionRange() const
The range where conversion to TOF from given units is monotonic and reversible.
Definition Unit.cpp:205
virtual double conversionTOFMin() const =0
some units can be converted from TOF only in the range of TOF ; This function returns minimal TOF val...
virtual double conversionTOFMax() const =0
This function returns maximal TOF value still reversibly convertible into the unit.
virtual double singleToTOF(const double x) const =0
Convert a single X value to TOF.
void fromTOF(std::vector< double > &xdata, std::vector< double > const &ydata, const double &_l1, const int &_emode, std::initializer_list< std::pair< const UnitParams, double > > params)
Convert from time-of-flight to the concrete unit.
Definition Unit.cpp:178
bool initialized
The unit values have been initialized.
Definition Unit.h:166
void initialize(const double &_l1, const int &_emode, const UnitParametersMap &params)
Initialize the unit to perform conversion using singleToTof() and singleFromTof()
Definition Unit.cpp:133
void toTOF(std::vector< double > &xdata, std::vector< double > const &ydata, const double &_l1, const int &_emode, std::initializer_list< std::pair< const UnitParams, double > > params)
Convert from the concrete unit to time-of-flight.
Definition Unit.cpp:148
Unit()
(Empty) Constructor
Definition Unit.cpp:43
tbb::concurrent_unordered_map< std::string, UnitConversions > ConversionsMap
The possible 'quick conversions' are held in a map with the starting unit as the key.
Definition Unit.h:188
double convertSingleToTOF(const double xvalue, const double &l1, const int &emode, const UnitParametersMap &params)
Convert from the concrete unit to time-of-flight. TOF is in microseconds.
Definition Unit.cpp:169
virtual const std::string unitID() const =0
The name of the unit.
double convertSingleFromTOF(const double xvalue, const double &l1, const int &emode, const UnitParametersMap &params)
Convert from the time-of-flight to the concrete unit. TOF is in microseconds.
Definition Unit.cpp:199
virtual double singleFromTOF(const double tof) const =0
Convert a single tof value to this unit.
bool quickConversion(const Unit &destination, double &factor, double &power) const
Is conversion by constant multiplication possible?
Definition Unit.cpp:63
double l1
l1 :: The source-sample distance (in metres)
Definition Unit.h:168
bool operator==(const Unit &u) const
Definition Unit.cpp:45
static ConversionsMap s_conversionFactors
The table of possible 'quick conversions'.
Definition Unit.h:190
int emode
emode :: The energy mode (0=elastic, 1=direct geometry, 2=indirect geometry)
Definition Unit.h:171
bool isInitialized() const
Definition Unit.h:141
void addConversion(std::string to, const double &factor, const double &power=1.0) const
Add a 'quick conversion' from the unit class on which this method is called.
Definition Unit.cpp:114
virtual void validateUnitParams(const int emode, const UnitParametersMap &params)
Definition Unit.cpp:142
Atomic Distance in Angstroms.
Definition Unit.h:640
double singleFromTOF(const double tof) const override
Convert a single tof value to this unit.
Definition Unit.cpp:1423
double singleToTOF(const double x) const override
Convert a single X value to TOF.
Definition Unit.cpp:1418
const UnitLabel label() const override
A label for the unit to be printed on axes,.
Definition Unit.cpp:1414
Unit * clone() const override
Definition Unit.cpp:1416
Degrees that has degrees as unit and "Scattering angle" as title.
Definition Unit.h:596
Unit * clone() const override
Definition Unit.cpp:1374
const UnitLabel label() const override
A label for the unit to be printed on axes,.
Definition Unit.cpp:1362
double singleToTOF(const double x) const override
Convert a single X value to TOF.
Definition Unit.cpp:1364
double singleFromTOF(const double tof) const override
Convert a single tof value to this unit.
Definition Unit.cpp:1369
Energy transfer in units of frequency (MHz)
Definition Unit.h:487
void init() override
Finalize the initialization.
Definition Unit.cpp:1097
Energy transfer in units of wavenumber (cm^-1)
Definition Unit.h:474
void init() override
Finalize the initialization.
Definition Unit.cpp:1073
Energy transfer in milli-electronvolts.
Definition Unit.h:445
double singleToTOF(const double x) const override
Convert a single X value to TOF.
Definition Unit.cpp:998
const std::string unitID() const override
"DeltaE"
Unit * clone() const override
Definition Unit.cpp:1060
double singleFromTOF(const double tof) const override
Convert a single tof value to this unit.
Definition Unit.cpp:1022
void validateUnitParams(const int emode, const UnitParametersMap &params) override
Definition Unit.cpp:942
void init() override
Finalize the initialization.
Definition Unit.cpp:965
double conversionTOFMin() const override
some units can be converted from TOF only in the range of TOF ; This function returns minimal TOF val...
Definition Unit.cpp:1045
double factorFrom
Constant factor for from conversion.
Definition Unit.h:466
double factorTo
Constant factor for to conversion.
Definition Unit.h:465
double conversionTOFMax() const override
This function returns maximal TOF value still reversibly convertible into the unit.
Definition Unit.cpp:1051
double t_otherFrom
Energy mode dependent factor in from conversion.
Definition Unit.h:468
double unitScaling
Apply unit scaling to energy value.
Definition Unit.h:469
double t_other
Energy mode dependent factor in to conversion.
Definition Unit.h:467
double conversionTOFMin() const override
Definition Unit.cpp:239
Empty()
Constructor.
Definition Unit.h:223
double singleFromTOF(const double tof) const override
Convert a single tof value to this unit.
Definition Unit.cpp:229
double singleToTOF(const double x) const override
Convert a single X value to TOF.
Definition Unit.cpp:224
void init() override
Finalize the initialization.
Definition Unit.cpp:222
Unit * clone() const override
Definition Unit.cpp:234
double conversionTOFMax() const override
Definition Unit.cpp:244
const std::string unitID() const override
"Empty"
Absolute energy in units of wavenumber (cm^-1)
Definition Unit.h:321
const std::string unitID() const override
"Energy_inWavenumber"
double factorFrom
Constant factor for from conversion.
Definition Unit.h:340
void validateUnitParams(const int emode, const UnitParametersMap &params) override
Definition Unit.cpp:507
double factorTo
Constant factor for to conversion.
Definition Unit.h:339
double singleToTOF(const double x) const override
Convert a single X value to TOF.
Definition Unit.cpp:532
void init() override
Finalize the initialization.
Definition Unit.cpp:515
double conversionTOFMin() const override
Definition Unit.cpp:540
double conversionTOFMax() const override
This function returns maximal TOF value still reversibly convertible into the unit.
Definition Unit.cpp:541
double singleFromTOF(const double tof) const override
Convert a single tof value to this unit.
Definition Unit.cpp:543
Energy in milli-electronvolts.
Definition Unit.h:296
double singleFromTOF(const double tof) const override
Convert a single tof value to this unit.
Definition Unit.cpp:476
void validateUnitParams(const int emode, const UnitParametersMap &params) override
Definition Unit.cpp:443
double conversionTOFMax() const override
This function returns maximal TOF value still reversibly convertible into the unit.
Definition Unit.cpp:474
double singleToTOF(const double x) const override
Convert a single X value to TOF.
Definition Unit.cpp:466
const std::string unitID() const override
"Energy"
void init() override
Finalize the initialization.
Definition Unit.cpp:451
double conversionTOFMin() const override
Definition Unit.cpp:473
Unit * clone() const override
Definition Unit.cpp:483
double factorTo
Constant factor for to conversion.
Definition Unit.h:315
double factorFrom
Constant factor for from conversion.
Definition Unit.h:316
const std::string caption() const override
The full name of the unit.
Definition Unit.h:231
UnitLabel m_label
Label.
Definition Unit.h:243
std::string m_caption
Caption.
Definition Unit.h:241
const UnitLabel label() const override
A label for the unit to be printed on axes,.
Definition Unit.cpp:253
Unit * clone() const override
Definition Unit.cpp:270
void setLabel(const std::string &cpt, const UnitLabel &lbl=UnitLabel(""))
Set a caption and a label.
Definition Unit.cpp:265
Momentum Transfer in Angstrom^-1.
Definition Unit.h:405
double singleToTOF(const double x) const override
Convert a single X value to TOF.
Definition Unit.cpp:892
Unit * clone() const override
Definition Unit.cpp:899
double conversionTOFMax() const override
This function returns maximal TOF value still reversibly convertible into the unit.
Definition Unit.cpp:897
const std::string unitID() const override
"MomentumTransfer"
void validateUnitParams(const int emode, const UnitParametersMap &params) override
Definition Unit.cpp:866
void init() override
Finalize the initialization.
Definition Unit.cpp:876
double conversionTOFMin() const override
some units can be converted from TOF only in the range of TOF ; This function returns minimal TOF val...
Definition Unit.cpp:896
double singleFromTOF(const double tof) const override
Convert a single tof value to this unit.
Definition Unit.cpp:894
Momentum in Angstrom^-1.
Definition Unit.h:500
double sfpTo
Extra correction factor in to conversion.
Definition Unit.h:519
void validateUnitParams(const int emode, const UnitParametersMap &params) override
Definition Unit.cpp:1130
double sfpFrom
Extra correction factor in from conversion.
Definition Unit.h:521
double conversionTOFMax() const override
This function returns maximal TOF value still reversibly convertible into the unit.
Definition Unit.cpp:1208
void init() override
Finalize the initialization.
Definition Unit.cpp:1141
double conversionTOFMin() const override
some units can be converted from TOF only in the range of TOF ; This function returns minimal TOF val...
Definition Unit.cpp:1202
bool do_sfpFrom
Apply the sfpFrom value.
Definition Unit.h:523
double singleToTOF(const double ki) const override
Convert a single X value to TOF.
Definition Unit.cpp:1195
Unit * clone() const override
Definition Unit.cpp:1226
double singleFromTOF(const double tof) const override
Convert a single tof value to this unit.
Definition Unit.cpp:1216
double factorTo
Constant factor for to conversion.
Definition Unit.h:520
double factorFrom
Constant factor for from conversion.
Definition Unit.h:522
Phi that has degrees as unit and "Phi" as title.
Definition Unit.h:614
Momentum transfer squared in Angstrom^-2.
Definition Unit.h:427
double singleToTOF(const double x) const override
Convert a single X value to TOF.
Definition Unit.cpp:915
double conversionTOFMax() const override
This function returns maximal TOF value still reversibly convertible into the unit.
Definition Unit.cpp:919
Unit * clone() const override
Definition Unit.cpp:926
double conversionTOFMin() const override
some units can be converted from TOF only in the range of TOF ; This function returns minimal TOF val...
Definition Unit.cpp:918
double singleFromTOF(const double tof) const override
Convert a single tof value to this unit.
Definition Unit.cpp:916
SpinEchoLength in nm.
Definition Unit.h:528
double singleToTOF(const double x) const override
Convert a single X value to TOF.
Definition Unit.cpp:1251
double conversionTOFMax() const override
This function returns maximal TOF value still reversibly convertible into the unit.
Definition Unit.cpp:1261
double conversionTOFMin() const override
some units can be converted from TOF only in the range of TOF ; This function returns minimal TOF val...
Definition Unit.cpp:1257
double singleFromTOF(const double tof) const override
Convert a single tof value to this unit.
Definition Unit.cpp:1270
Unit * clone() const override
Definition Unit.cpp:1276
void init() override
Finalize the initialization.
Definition Unit.cpp:1240
SpinEchoTime in ns.
Definition Unit.h:550
double singleFromTOF(const double tof) const override
Convert a single tof value to this unit.
Definition Unit.cpp:1314
double singleToTOF(const double x) const override
Convert a single X value to TOF.
Definition Unit.cpp:1301
double conversionTOFMax() const override
This function returns maximal TOF value still reversibly convertible into the unit.
Definition Unit.cpp:1307
double conversionTOFMin() const override
some units can be converted from TOF only in the range of TOF ; This function returns minimal TOF val...
Definition Unit.cpp:1306
void init() override
Finalize the initialization.
Definition Unit.cpp:1290
Unit * clone() const override
Definition Unit.cpp:1320
A simple class containing common symbol types.
static const UnitLabel InverseAngstrom
InverseAngstrom.
static const UnitLabel InverseAngstromSq
InverseAngstromSq.
static const UnitLabel Microsecond
Microsecond.
static const UnitLabel Angstrom
Angstrom.
static const UnitLabel Second
Second.
static const UnitLabel Nanometre
Nanometre.
static const UnitLabel MilliElectronVolts
MilliElectronVolts.
static const UnitLabel Nanosecond
Nanosecond.
static const UnitLabel GHz
GHz.
static const UnitLabel InverseCM
Inverse centimeters.
static const UnitLabel EmptyLabel
Empty label.
Time of flight in microseconds.
Definition Unit.h:248
void init() override
Finalize the initialization.
Definition Unit.cpp:282
double singleFromTOF(const double tof) const override
Convert a single tof value to this unit.
Definition Unit.cpp:289
Unit * clone() const override
Definition Unit.cpp:294
double conversionTOFMax() const override
Definition Unit.cpp:297
double singleToTOF(const double x) const override
Convert a single X value to TOF.
Definition Unit.cpp:284
double conversionTOFMin() const override
Definition Unit.cpp:295
Temperature in kelvin.
Definition Unit.h:622
const UnitLabel label() const override
A label for the unit to be printed on axes,.
Definition Unit.cpp:1390
double singleFromTOF(const double tof) const override
Convert a single tof value to this unit.
Definition Unit.cpp:1397
double singleToTOF(const double x) const override
Convert a single X value to TOF.
Definition Unit.cpp:1392
Unit * clone() const override
Definition Unit.cpp:1402
Time In Second.
Definition Unit.h:572
double singleToTOF(const double x) const override
Convert a single X value to TOF.
Definition Unit.cpp:1336
double singleFromTOF(const double tof) const override
Convert a single tof value to this unit.
Definition Unit.cpp:1341
void init() override
Finalize the initialization.
Definition Unit.cpp:1334
double conversionTOFMax() const override
This function returns maximal TOF value still reversibly convertible into the unit.
Definition Unit.cpp:1346
Unit * clone() const override
Definition Unit.cpp:1349
double conversionTOFMin() const override
some units can be converted from TOF only in the range of TOF ; This function returns minimal TOF val...
Definition Unit.cpp:1347
Wavelength in Angstrom.
Definition Unit.h:267
const UnitLabel label() const override
A label for the unit to be printed on axes,.
Definition Unit.cpp:318
const std::string unitID() const override
"Wavelength"
bool do_sfpFrom
Apply the sfpFrom value.
Definition Unit.h:291
double sfpFrom
Extra correction factor in from conversion.
Definition Unit.h:289
void init() override
Finalize the initialization.
Definition Unit.cpp:333
double singleToTOF(const double x) const override
Convert a single X value to TOF.
Definition Unit.cpp:387
double singleFromTOF(const double tof) const override
Convert a single tof value to this unit.
Definition Unit.cpp:394
double factorTo
Constant factor for to conversion.
Definition Unit.h:288
double sfpTo
Extra correction factor in to conversion.
Definition Unit.h:287
double conversionTOFMin() const override
Definition Unit.cpp:403
void validateUnitParams(const int emode, const UnitParametersMap &params) override
Definition Unit.cpp:320
double conversionTOFMax() const override
Definition Unit.cpp:411
double factorFrom
Constant factor for from conversion.
Definition Unit.h:290
Unit * clone() const override
Definition Unit.cpp:421
d-SpacingPerpendicular in Angstrom
Definition Unit.h:378
double sfpFrom
Extra correction factor in to conversion.
Definition Unit.h:400
double factorFrom
Constant factor for from conversion.
Definition Unit.h:399
void validateUnitParams(const int emode, const UnitParametersMap &params) override
Definition Unit.cpp:801
double factorTo
Constant factor for to conversion.
Definition Unit.h:397
double conversionTOFMin() const override
some units can be converted from TOF only in the range of TOF ; This function returns minimal TOF val...
Definition Unit.cpp:845
double singleFromTOF(const double tof) const override
Convert a single tof value to this unit.
Definition Unit.cpp:841
const std::string unitID() const override
"dSpacingPerpendicular"
void init() override
Finalize the initialization.
Definition Unit.cpp:814
double sfpTo
Extra correction factor in to conversion.
Definition Unit.h:398
double conversionTOFMax() const override
This function returns maximal TOF value still reversibly convertible into the unit.
Definition Unit.cpp:846
double singleToTOF(const double x) const override
Convert a single X value to TOF.
Definition Unit.cpp:834
d-Spacing in Angstrom
Definition Unit.h:351
double conversionTOFMax() const override
This function returns maximal TOF value still reversibly convertible into the unit.
Definition Unit.cpp:761
const UnitLabel label() const override
A label for the unit to be printed on axes,.
Definition Unit.cpp:613
const std::string unitID() const override
"dSpacing"
void validateUnitParams(const int emode, const UnitParametersMap &params) override
Definition Unit.cpp:617
double conversionTOFMin() const override
some units can be converted from TOF only in the range of TOF ; This function returns minimal TOF val...
Definition Unit.cpp:746
Unit * clone() const override
Definition Unit.cpp:615
double calcTofMax(const double difc, const double difa, const double tzero, const double tofmax=0.)
Definition Unit.cpp:782
void init() override
Finalize the initialization.
Definition Unit.cpp:642
double calcTofMin(const double difc, const double difa, const double tzero, const double tofmin=0.)
Definition Unit.cpp:775
double singleFromTOF(const double tof) const override
DIFA * d^2 + DIFC * d + T0 - TOF = 0.
Definition Unit.cpp:696
double singleToTOF(const double x) const override
Convert a single X value to TOF.
Definition Unit.cpp:670
MANTID_KERNEL_DLL double calculateDIFCCorrection(const double l1, const double l2, const double twotheta, const double offset, const double binWidth)
Calculate DIFC in case of logarithmic binning, used in CalculateDIFC with Signed mode.
Definition Unit.cpp:565
MANTID_KERNEL_DLL double tofToDSpacingFactor(const double l1, const double l2, const double twoTheta, const double offset)
Calculate and return conversion factor from tof to d-spacing.
Definition Unit.cpp:589
const double H_OVER_NEUTRON_MASS
Definition Unit.cpp:579
MANTID_KERNEL_DLL double timeConversionValue(const std::string &input_unit, const std::string &output_unit)
Definition Unit.cpp:1430
const double NEUTRON_MASS_OVER_H
Definition Unit.cpp:553
std::unordered_map< UnitParams, double > UnitParametersMap
Definition Unit.h:30
static constexpr double meVtoFrequency
1 meV in frequency (GHz).
static constexpr double NeutronMass
Mass of the neutron in kg.
static constexpr double h
Planck constant in J*s.
static constexpr double meVtoWavenumber
1 meV in wavenumber (cm-1).
static constexpr double meV
1 meV in Joules.