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