Unverified Commit dccf0867 authored by DannyHindson's avatar DannyHindson Committed by GitHub
Browse files

Enhance conversions between dSpacing and TOF in ConvertUnits (#30163)

* Changes to dSpacing to TOF in ConvertUnits

Changes to the Unit class and ConvertUnits algorithm to allow
diffractometer constants (DIFA, DIFC, TZERO) stored in the instrument map
to be used in conversions between d spacing and TOF and v.v.

Rather than add 3 more parameters to lots of methods provided by the Unit
class I have changed some of the methods to take a std:map containing the
optional parameters relevant to only some units. I have included efixed
and delta in this new map

New diffractometerConstants method added to SpectrumInfo and DetectorInfo
to allow retrieval for a particular spectrum including averaging across
detectors. Also manages situations where some of the three constants are
missing.

New algorithm created called ApplyDiffCal to read the diffractometer
constants from a diffraction calibration table workspace and write them
into the instrument parameter map

Add diffractometer constants to the Show Detectors screen for elastic
workspaces

Remove the Diffraction.cpp unit and replace with calls to dSpacing unit class

Add ability to write difa, difc, tzero into a reduced instrument
geometry as part of EditInstrumentGeometry

* Fix unit tests using old unit conversion logic

* Add overload to spectrumInfo::diffractometerConstants

Add overload that doesn't require the 2nd warning dets parameter

* Remove unused variable declarations

* Replace costly call to spectrumInfo() with spectrumInfo object

* Correct incorrect capitalisation in unit name

* Fix bug in CreateDetectorTable

The exception handler in populateTable assumed the column counter
was always at 1. Reset the column counter to 0 by calling colValues.row
and then fill in default values.
Also add if statement to manage diff constants for monitors which
was the specific exception that caused me to find problem with general
exception handler

* Update HRPD system test ref files to accommodate new unit conversion

Update HRPD system test reference files to accommodate changes to the
unit conversions between TOF and dSpacing. As part of this I have updated
the reference file HRPD66031_splined. This is used as an input to the two
system tests that run a focus and it should match the output of the create
vanadium tests but it had got out of sync over the last couple of years
eg changes to Bragg peak stripping didn't result in an update to
HRPD66031_splined. So some changes in HRPD66031_splined that aren't purely
from the unit conversion logic change

* Make EnggFitPeaks use ConvertUnits for focussed ws

* Update engineering diffraction system test ref files

* Update calls to convertSingleFromTOF in spectrum viewer code

* Remove unused variable in spectrum viewer code

* Backout change to Qt4 unit because it causes cppcheck problem

* Various changes

The ParameterMap::diff method has been updated to take an extra
parameter representing a tolerance to be used when comparing double
values between two parameter maps
The overloaded == operator has been modified to call diff with a
zero tolerance to avoid duplicating code
CompareWorkspaces also updated to pass the value of CheckAllData
into diff so diff can stop after first change rather than going
through the whole map
The diff logic has also been speeded up to cope with larger parameter
maps now that diff constants stored (esp for GEM)
Various updates to doc test and system test files
Shorten UnitConversionParameters enum class name
Remove use of EMPTY_DBL() from ConvertUnits::getDetectorValues in
preparation for moving into ExperimentInfo class and also fix
RemoveSpectraTest unit test that relied on this

* Refactor code to retrieve unit related quantities from workspace

* Improve performance of getDetectorValues

* Delete Kernel Diffraction code files

* Delete Kernel Diffraction code files

* Performance improvements to diff constant lookup

* Delete Kernel Diffraction code files

* Performance improvements to diff constant lookup

Restrict diff constant lookup to elastic conversions to or
from d spacing
Just look up diff constants on the specified detector rather
than recursive look through all parents (slow if workspace
doesn't have any diff constants in the pmap at all)
Make the main loop in ConvertUnits parallel (as was the case
in AlignDetectors)

* Replace std::map with std::unordered_map for better performance

* Remove some duplicated code to fetch detector values

* Readd blank line to avoid showing up in diff

* Readd blank line to avoid showing up in diff

* Fix clang format

* Reinstate Efixed from property logic

* Fix failing unit tests

Also defer more decisions on whether missing detector values are
a problem to the code inside the Unit class rather than
experimentInfo::getDetectorValues

* Remove default (empty) value for extra params argument

This will force users to supply the diff constants for dSpacing
conversions rather than assuming supplying L2 and twoTheta is sufficient

* Move all detectors parameters into the map

* Fix Doxygen warnings

* Fix compilation error and expose new unit conv signature to python

* Various changes

Update new case using Unit::Initialize from merge
Reinstate dropped getEFixedForIndirect method
Remove one of the duplicates for the WISH Powder system tests
Also replace duplicate code to retrieve detector info with a call to
getDetectorValues instead
Move getDetectorValues into API::SpectrumInfo

* Fix compilation error in common widgets

* Fix bug in SaveGDA relating to d to TOF spacing conversion

difa and difc were back to front. Rather than swap here I've
changed the code to call the official unit conversion logic
in the dSpacing unit class

* Make momentum transfer (q) unit conversion use diff constants

Had to make minor adjustment to dSpacing::singleFromTOF to avoid
rounding problem on conversion max\min
Also changed qsquared over since this also used v similar formula
Removed epsilon from the check ranges call in unit tests for qsquared
because doesn't seem to be needed any more

* Couples of changes

Modify method of calculating average difc for a spectrum if there's no
calibration present (to avoid changing behaviour for most instruments)
Remove changes to EditInstrumentGeometry to attach diff constants
because can do this using ApplyDiffCal after EditInstrumentGeometry has
been run

* Fix clang format issue

* Fix compilation error on Windows

* Fix failing tests and compilation error

* Fix compilation error from missing include

* Extra way of initialising dSpacing and MomentumTransfer

Enable initialising dSpacing and MomentumTransfer using L2 and two theta
as an alternative to supplying the diff constants. This might be more
user friendly and it also moves the difc formula into the Unit class

Add utility functions to manage extra params map

* Add feature to ApplyDiffCal to clear calibration

* Various changes

Update some more unit tests to cope with changes MomentumTransfer unit
to make it use the diff constants
Improve validation on the L2\ttheta params in dSpacing unit
Allow negative DIFCs in conversions to TOF -
do this by setting up validation on to FromTOF direction only
Revert some files now that I'm doing more "input" averaging in DIFC
calculation on spectra with more than one detector

* Fix failing docs tests

* Rework MomentumTransfer to depend on difc only

* Fix linux compilation error

* Reinstate validation on MomentumTransfer unit class

* Revert some more tests files now that average difc calc reverted

* Revert change to remove local difc calculation so can do in separate PR

* Revert some more enginx system test files

* Revert some WISH system test files

* Revert SNS Powder Reduction ref file

* Revert another SNS ref file

* Update reference file

The changes are due to the StripVanadiumPeaks step in the SNSPowderReduction
algorithm. This algorithm seems v sensitive to even tiny changes in the input
workspace. The input workspace has some v small changes in at the ~15 decimal
place level as a result of this PR which updates the TOF\dSpacing unit conversion.
This causes the fits on some of the V peaks to behave differently and result
in the output having some much bigger differences on a 5-10% level
There is a composite function fit used in StripVanadiumPeaks (in FitPeak to be
precise) that seems a bit unstable and v sensitive to the input data

* Revert conversion from dSpacing to TOF to happen without calibration for ISIS Powder

* Update reference file

The changes are due to the StripVanadiumPeaks step. This algorithm seems very
sensitive to even tiny changes in the input workspace. The workspace that is
input to this step has some v small changes in at the ~15 decimal place level
as a result of this PR which updates the TOF\dSpacing unit conversion. This
causes the fits on some of the V peaks to behave differently and result in the
output having some much bigger differences on a 5-10% level. There is a
composite function fit used in StripVanadiumPeaks (in FitPeak to be precise)
that seems a bit unstable and v sensitive to the input data

* Temporary fix to get Polaris FocusTest to pass

The Polaris FocusTest currently has a couple of problems:
1) the sample empty run it uses looks wrong. 98532 is a V sample run
2) the POLARIS00098532_splined workspace seems to have been generatedthe
using some wrong\old crop ranges. This results in the normalization process
dividing by zero which generates infinities in the output of the test. There
are also some v large values (not quite double max) that get output which makes
setting an absolute tolerance difficult

* Update various ISIS Powder system test files to include masked spectra

* Two changes

Turn off caching in the SNSPowderRedux.PG3Analysis system test so the result of
the system test doesn't depend on the previous job that ran on Jenkins
Load the calibration in from a GSAS file in addition to the other instrument
geometry information so any subsequent unit conversions in Mantid work properly

* Widen tolerance so that Polaris focus system test passes

* Turn off caching in SNSPowderRedux system test

* Make it possible to override calibration to use on focused datasets
parent 65e6c99e
......@@ -12,6 +12,7 @@
#include "MantidGeometry/Instrument_fwd.h"
#include "MantidKernel/DeltaEMode.h"
#include "MantidKernel/Unit.h"
#include "MantidKernel/V3D.h"
#include "MantidKernel/cow_ptr.h"
......@@ -110,6 +111,12 @@ public:
double getEFixed(const std::shared_ptr<const Geometry::IDetector> &detector =
std::shared_ptr<const Geometry::IDetector>{
nullptr}) const;
double getEFixedGivenEMode(
const std::shared_ptr<const Geometry::IDetector> &detector,
const Kernel::DeltaEMode::Type emode) const;
double getEFixedForIndirect(
const std::shared_ptr<const Geometry::IDetector> &detector,
const std::vector<std::string> &parameterNames) const;
/// Set the efixed value for a given detector ID
void setEFixed(const detid_t detID, const double value);
......
......@@ -8,6 +8,8 @@
#include "MantidAPI/DllConfig.h"
#include "MantidAPI/SpectrumInfoIterator.h"
#include "MantidKernel/DeltaEMode.h"
#include "MantidKernel/Unit.h"
#include "MantidKernel/V3D.h"
#include "MantidKernel/cow_ptr.h"
......@@ -70,6 +72,11 @@ public:
double azimuthal(const size_t index) const;
std::pair<double, double> geographicalAngles(const size_t index) const;
Kernel::V3D position(const size_t index) const;
Kernel::UnitParametersMap
diffractometerConstants(const size_t index,
std::vector<detid_t> &uncalibratedDets) const;
Kernel::UnitParametersMap diffractometerConstants(const size_t index) const;
double difcUncalibrated(const size_t index) const;
bool hasDetectors(const size_t index) const;
bool hasUniqueDetector(const size_t index) const;
......@@ -86,6 +93,14 @@ public:
Kernel::V3D samplePosition() const;
double l1() const;
void getDetectorValues(const Kernel::Unit &inputUnit,
const Kernel::Unit &outputUnit,
const Kernel::DeltaEMode::Type emode,
const bool signedTheta, int64_t wsIndex,
Kernel::UnitParametersMap &pmap) const;
void createDetectorIdLogMessages(const std::vector<detid_t> &detids,
int64_t wsIndex) const;
SpectrumInfoIterator<SpectrumInfo> begin();
SpectrumInfoIterator<SpectrumInfo> end();
const SpectrumInfoIterator<const SpectrumInfo> cbegin() const;
......
......@@ -676,39 +676,70 @@ double ExperimentInfo::getEFixed(
const std::shared_ptr<const Geometry::IDetector> &detector) const {
populateIfNotLoaded();
Kernel::DeltaEMode::Type emode = getEMode();
if (emode == Kernel::DeltaEMode::Direct) {
try {
return this->run().getPropertyValueAsType<double>("Ei");
} catch (Kernel::Exception::NotFoundError &) {
throw std::runtime_error(
"Experiment logs do not contain an Ei value. Have you run GetEi?");
}
} else if (emode == Kernel::DeltaEMode::Indirect) {
if (!detector)
throw std::runtime_error("ExperimentInfo::getEFixed - Indirect mode "
"efixed requested without a valid detector.");
return getEFixedGivenEMode(detector, emode);
}
double ExperimentInfo::getEFixedForIndirect(
const std::shared_ptr<const Geometry::IDetector> &detector,
const std::vector<std::string> &parameterNames) const {
double efixed = 0.;
for (auto &parameterName : parameterNames) {
Parameter_sptr par =
constInstrumentParameters().getRecursive(detector.get(), "Efixed");
constInstrumentParameters().getRecursive(detector.get(), parameterName);
if (par) {
return par->value<double>();
efixed = par->value<double>();
} else {
std::vector<double> efixedVec = detector->getNumberParameter("Efixed");
std::vector<double> efixedVec =
detector->getNumberParameter(parameterName);
if (efixedVec.empty()) {
int detid = detector->getID();
IDetector_const_sptr detectorSingle =
getInstrument()->getDetector(detid);
efixedVec = detectorSingle->getNumberParameter("Efixed");
efixedVec = detectorSingle->getNumberParameter(parameterName);
}
if (!efixedVec.empty()) {
return efixedVec.at(0);
} else {
std::ostringstream os;
os << "ExperimentInfo::getEFixed - Indirect mode efixed requested but "
"detector has no Efixed parameter attached. ID="
<< detector->getID();
throw std::runtime_error(os.str());
efixed = efixedVec.at(0);
}
}
}
if (efixed == 0.) {
std::ostringstream os;
os << "ExperimentInfo::getEFixed - Indirect mode efixed requested but "
"detector has no Efixed parameter attached. ID="
<< detector->getID();
throw std::runtime_error(os.str());
}
return efixed;
}
/**
* Easy access to the efixed value for this run & detector
* @param detector :: The detector object to ask for the efixed mode. Only
* required for Indirect mode
* @param emode :: enum value indicating whether elastic, direct or indirect
* @return The current efixed value
*/
double ExperimentInfo::getEFixedGivenEMode(
const std::shared_ptr<const Geometry::IDetector> &detector,
const Kernel::DeltaEMode::Type emode) const {
if (emode == Kernel::DeltaEMode::Direct) {
double efixed = 0.;
for (auto &parameterName : {"Ei", "EnergyRequested", "EnergyEstimate"}) {
if (run().hasProperty(parameterName)) {
efixed = run().getPropertyValueAsType<double>(parameterName);
break;
}
}
if (efixed == 0.) {
throw std::runtime_error("Experiment logs do not contain an Ei "
"value. Have you run GetEi?");
}
return efixed;
} else if (emode == Kernel::DeltaEMode::Indirect) {
if (!detector)
throw std::runtime_error("ExperimentInfo::getEFixed - Indirect mode "
"efixed requested without a valid detector.");
return getEFixedForIndirect(detector, {"Efixed", "EFixed-val"});
} else {
throw std::runtime_error("ExperimentInfo::getEFixed - EFixed requested for "
"elastic mode, don't know what to do!");
......
......@@ -1143,12 +1143,12 @@ void IFunction::setMatrixWorkspace(
if (centreUnit) {
g_log.debug()
<< "For FitParameter " << parameterName(i)
<< " centre of peak before any unit convertion is "
<< " centre of peak before any unit conversion is "
<< centreValue << '\n';
centreValue =
convertValue(centreValue, centreUnit, workspace, wi);
g_log.debug() << "For FitParameter " << parameterName(i)
<< " centre of peak after any unit convertion is "
<< " centre of peak after any unit conversion is "
<< centreValue << '\n';
}
......@@ -1165,11 +1165,11 @@ void IFunction::setMatrixWorkspace(
fitParam.getLookUpTable().getYUnit(); // from table
g_log.debug()
<< "The FitParameter " << parameterName(i) << " = "
<< paramValue << " before y-unit convertion\n";
<< paramValue << " before y-unit conversion\n";
paramValue /= convertValue(1.0, resultUnit, workspace, wi);
g_log.debug()
<< "The FitParameter " << parameterName(i) << " = "
<< paramValue << " after y-unit convertion\n";
<< paramValue << " after y-unit conversion\n";
} else {
// so from formula
......@@ -1195,12 +1195,12 @@ void IFunction::setMatrixWorkspace(
p.SetExpr(resultUnitStr);
g_log.debug() << "The FitParameter " << parameterName(i)
<< " = " << paramValue
<< " before result-unit convertion (using "
<< " before result-unit conversion (using "
<< resultUnitStr << ")\n";
paramValue *= p.Eval();
g_log.debug()
<< "The FitParameter " << parameterName(i) << " = "
<< paramValue << " after result-unit convertion\n";
<< paramValue << " after result-unit conversion\n";
} catch (mu::Parser::exception_type &e) {
g_log.error()
<< "Cannot convert formula unit to workspace unit"
......@@ -1308,31 +1308,25 @@ void IFunction::convertValue(std::vector<double> &values,
if (sample == nullptr) {
g_log.error()
<< "No sample defined instrument. Cannot convert units for function\n"
<< "Ignore convertion.";
<< "Ignore conversion.";
return;
}
const auto &spectrumInfo = ws->spectrumInfo();
double l1 = spectrumInfo.l1();
// If this is a monitor then l1+l2 = source-detector distance and twoTheta=0
double l2 = spectrumInfo.l2(wsIndex);
double twoTheta(0.0);
if (!spectrumInfo.isMonitor(wsIndex))
twoTheta = spectrumInfo.twoTheta(wsIndex);
auto emode = static_cast<int>(ws->getEMode());
double efixed(0.0);
auto emode = ws->getEMode();
Kernel::UnitParametersMap pmap{};
spectrumInfo.getDetectorValues(*wsUnit, *outUnit, emode, false, wsIndex,
pmap);
std::vector<double> emptyVec;
try {
std::shared_ptr<const Geometry::IDetector> det(
&spectrumInfo.detector(wsIndex), NoDeleting());
efixed = ws->getEFixed(det);
wsUnit->toTOF(values, emptyVec, l1, emode, pmap);
outUnit->fromTOF(values, emptyVec, l1, emode, pmap);
} catch (std::exception &) {
// assume elastic
efixed = 0.0;
emode = 0;
throw std::runtime_error("Unable to perform unit conversion to " +
outUnit->unitID());
}
std::vector<double> emptyVec;
wsUnit->toTOF(values, emptyVec, l1, l2, twoTheta, emode, efixed, 0.0);
outUnit->fromTOF(values, emptyVec, l1, l2, twoTheta, emode, efixed, 0.0);
}
}
......
......@@ -8,17 +8,23 @@
#include "MantidAPI/ExperimentInfo.h"
#include "MantidAPI/SpectrumInfoIterator.h"
#include "MantidBeamline/SpectrumInfo.h"
#include "MantidGeometry/Instrument.h"
#include "MantidGeometry/Instrument/DetectorGroup.h"
#include "MantidGeometry/Instrument/DetectorInfo.h"
#include "MantidKernel/Exception.h"
#include "MantidKernel/Logger.h"
#include "MantidKernel/MultiThreaded.h"
#include "MantidTypes/SpectrumDefinition.h"
#include <algorithm>
#include <memory>
using namespace Mantid::Kernel;
namespace Mantid {
namespace API {
/// static logger object
Kernel::Logger g_log("ExperimentInfo");
SpectrumInfo::SpectrumInfo(const Beamline::SpectrumInfo &spectrumInfo,
const ExperimentInfo &experimentInfo,
......@@ -140,7 +146,175 @@ Kernel::V3D SpectrumInfo::position(const size_t index) const {
return newPos / static_cast<double>(spectrumDefinition(index).size());
}
/// Returns true if the spectrum is associated with detectors in the instrument.
/** Calculate average diffractometer constants (DIFA, DIFC, TZERO) of detectors
* associated with this spectrum. Use calibrated values where possible, filling
* in with uncalibrated values where they're missing
* @param index Index of the spectrum that constants are required for
* @param warningDets A vector containing the det ids where an uncalibrated
* value was used in the situation where some dets have calibrated values and
* some don't
* @return map containing the average constants
*/
UnitParametersMap
SpectrumInfo::diffractometerConstants(const size_t index,
std::vector<detid_t> &warningDets) const {
if (m_detectorInfo.isScanning()) {
throw std::runtime_error("Retrieval of diffractometer constants not "
"implemented for scanning instrument");
}
auto spectrumDef = checkAndGetSpectrumDefinition(index);
std::vector<size_t> detectorIndicesOnly;
std::vector<detid_t> calibratedDets;
std::vector<detid_t> uncalibratedDets;
std::transform(spectrumDef.begin(), spectrumDef.end(),
std::back_inserter(detectorIndicesOnly),
[](auto const &pair) { return pair.first; });
double difa{0.}, difc{0.}, tzero{0.};
for (const auto &detIndex : detectorIndicesOnly) {
auto newDiffConstants = m_detectorInfo.diffractometerConstants(
detIndex, calibratedDets, uncalibratedDets);
difa += std::get<0>(newDiffConstants);
difc += std::get<1>(newDiffConstants);
tzero += std::get<2>(newDiffConstants);
}
if (calibratedDets.size() > 0 && uncalibratedDets.size() > 0) {
warningDets.insert(warningDets.end(), uncalibratedDets.begin(),
uncalibratedDets.end());
};
// if no calibration is found then return difc only based on the average
// of the detector L2 and twoThetas.
if (calibratedDets.size() == 0) {
return {{UnitParams::difc, difcUncalibrated(index)}};
}
return {{UnitParams::difa,
difa / static_cast<double>(spectrumDefinition(index).size())},
{UnitParams::difc,
difc / static_cast<double>(spectrumDefinition(index).size())},
{UnitParams::tzero,
tzero / static_cast<double>(spectrumDefinition(index).size())}};
}
/** Calculate average diffractometer constants (DIFA, DIFC, TZERO) of
* detectors associated with this spectrum. Use calibrated values where
* possible, filling in with uncalibrated values where they're missing
* @param index Index of the spectrum that constants are required for
* @return map containing the average constants
*/
UnitParametersMap
SpectrumInfo::diffractometerConstants(const size_t index) const {
std::vector<int> warningDets;
return diffractometerConstants(index, warningDets);
}
/** Calculate average uncalibrated DIFC value of detectors associated with
* this spectrum
* @param index Index of the spectrum that DIFC is required for
* @return The average DIFC
*/
double SpectrumInfo::difcUncalibrated(const size_t index) const {
// calculate difc based on the average of the detector L2 and twoThetas.
// This will be different to the average of the per detector difcs. This is
// for backwards compatibility because Mantid always used to calculate
// spectrum level difc's this way
return 1. / Kernel::Units::tofToDSpacingFactor(l1(), l2(index),
twoTheta(index), 0.);
}
/** Get the detector values relevant to unit conversion for a workspace index
* @param inputUnit :: The input unit (Empty implies "all")
* @param outputUnit :: The output unit (Empty implies "all")
* @param emode :: The energy mode
* @param signedTheta :: Return twotheta with sign or without
* @param wsIndex :: The workspace index
* @param pmap :: a map containing values for conversion parameters that are
required by unit classes to perform their conversions eg efixed. It can
contain values on the way in if a look up isn't desired here eg if value
supplied in parameters to the calling algorithm
*/
void SpectrumInfo::getDetectorValues(const Kernel::Unit &inputUnit,
const Kernel::Unit &outputUnit,
const Kernel::DeltaEMode::Type emode,
const bool signedTheta, int64_t wsIndex,
UnitParametersMap &pmap) const {
if (!hasDetectors(wsIndex))
return;
pmap[UnitParams::l2] = l2(wsIndex);
if (!isMonitor(wsIndex)) {
// The scattering angle for this detector (in radians).
try {
if (signedTheta)
pmap[UnitParams::twoTheta] = signedTwoTheta(wsIndex);
else
pmap[UnitParams::twoTheta] = twoTheta(wsIndex);
} catch (const std::runtime_error &e) {
g_log.warning(e.what());
}
if (emode != Kernel::DeltaEMode::Elastic &&
pmap.find(UnitParams::efixed) == pmap.end()) {
std::shared_ptr<const Geometry::IDetector> det(&detector(wsIndex),
Mantid::NoDeleting());
try {
pmap[UnitParams::efixed] =
m_experimentInfo.getEFixedGivenEMode(det, emode);
g_log.debug() << "Detector: " << det->getID()
<< " EFixed: " << pmap[UnitParams::efixed] << "\n";
} catch (std::runtime_error) {
// let the unit classes work out if this is a problem
}
}
std::vector<detid_t> warnDetIds;
try {
std::set<std::string> diffConstUnits = {"dSpacing", "MomentumTransfer",
"Empty"};
if ((emode == Kernel::DeltaEMode::Elastic) &&
(diffConstUnits.count(inputUnit.unitID()) ||
diffConstUnits.count(outputUnit.unitID()))) {
auto diffConstsMap = diffractometerConstants(wsIndex, warnDetIds);
pmap.insert(diffConstsMap.begin(), diffConstsMap.end());
if (warnDetIds.size() > 0) {
createDetectorIdLogMessages(warnDetIds, wsIndex);
}
} else {
pmap[UnitParams::difc] = difcUncalibrated(wsIndex);
}
} catch (const std::runtime_error &e) {
g_log.warning(e.what());
}
} else {
pmap[UnitParams::twoTheta] = 0.0;
pmap[UnitParams::efixed] = DBL_MIN;
// Energy transfer is meaningless for a monitor, so set l2 to 0.
if (outputUnit.unitID().find("DeltaE") != std::string::npos) {
pmap[UnitParams::l2] = 0.0;
}
pmap[UnitParams::difc] = 0;
}
}
void SpectrumInfo::createDetectorIdLogMessages(
const std::vector<detid_t> &detids, int64_t wsIndex) const {
std::string detIDstring;
auto iter = detids.begin();
auto itEnd = detids.end();
for (; iter != itEnd; ++iter) {
detIDstring += std::to_string(*iter) + ",";
}
if (!detIDstring.empty()) {
detIDstring.pop_back(); // Drop last comma
}
g_log.warning(
"Incomplete set of calibrated diffractometer constants found for "
"workspace index" +
std::to_string(wsIndex) + ". Using uncalibrated values for detectors " +
detIDstring);
}
/// Returns true if the spectrum is associated with detectors in the
/// instrument.
bool SpectrumInfo::hasDetectors(const size_t index) const {
// Workspaces can contain invalid detector IDs. Those IDs will be silently
// ignored here until this is fixed.
......
......@@ -7,6 +7,7 @@
#pragma once
#include "MantidAPI/Algorithm.h"
#include "MantidAPI/DeprecatedAlgorithm.h"
#include "MantidAPI/ITableWorkspace_fwd.h"
#include "MantidAlgorithms/DllConfig.h"
#include "MantidDataObjects/OffsetsWorkspace.h"
......@@ -39,7 +40,8 @@ class ConversionFactors;
@author Russell Taylor, Tessella Support Services plc
@date 18/08/2008
*/
class MANTID_ALGORITHMS_DLL AlignDetectors : public API::Algorithm {
class MANTID_ALGORITHMS_DLL AlignDetectors : public API::Algorithm,
public API::DeprecatedAlgorithm {
public:
AlignDetectors();
......@@ -69,9 +71,7 @@ private:
void exec() override;
void align(const ConversionFactors &converter, API::Progress &progress,
API::MatrixWorkspace &outputWS);
void align(const ConversionFactors &converter, API::Progress &progress,
DataObjects::EventWorkspace &outputWS);
API::MatrixWorkspace_sptr &outputWS);
void loadCalFile(const API::MatrixWorkspace_sptr &inputWS,
const std::string &filename);
......
......@@ -103,13 +103,6 @@ protected:
convertQuickly(const API::MatrixWorkspace_const_sptr &inputWS,
const double &factor, const double &power);
/// Internal function to gather detector specific L2, theta and efixed values
bool getDetectorValues(const API::SpectrumInfo &spectrumInfo,
const Kernel::Unit &outputUnit, int emode,
const API::MatrixWorkspace &ws, const bool signedTheta,
int64_t wsIndex, double &efixed, double &l2,
double &twoTheta);
/// Convert the workspace units using TOF as an intermediate step in the
/// conversion
virtual API::MatrixWorkspace_sptr
......
......@@ -68,9 +68,10 @@ void populateTable(Mantid::API::ITableWorkspace_sptr &t,
const Mantid::Geometry::PointingAlong &beamAxisIndex,
const double sampleDist, const bool isScanning,
const bool include_data, const bool calcQ,
Kernel::Logger &logger);
const bool includeDiffConstants, Kernel::Logger &logger);
std::vector<std::pair<std::string, std::string>>
createColumns(const bool isScanning, const bool includeData, const bool calcQ);
createColumns(const bool isScanning, const bool includeData, const bool calcQ,
const bool hasDiffConstants);
} // namespace Algorithms
} // namespace Mantid
......@@ -44,7 +44,7 @@ private:
void createCalTableFromExisting();
void createCalTableNew();
void createInformationWorkspaces();
std::function<double(double)>
std::tuple<double, double, double>
getDSpacingToTof(const std::set<detid_t> &detIds);
std::vector<double> dSpacingWindows(const std::vector<double> &centres,
const double widthMax);
......
......@@ -9,6 +9,7 @@
#include "MantidAPI/Algorithm.h"
#include "MantidAlgorithms/DllConfig.h"
#include "MantidGeometry/IComponent.h"
#include "MantidKernel/DeltaEMode.h"
#include "MantidKernel/cow_ptr.h"
namespace Mantid {
......@@ -46,7 +47,8 @@ public:
BackgroundHelper(const BackgroundHelper &) = delete;
void initialize(const API::MatrixWorkspace_const_sptr &bkgWS,
const API::MatrixWorkspace_sptr &sourceWS, int emode,
const API::MatrixWorkspace_sptr &sourceWS,
Kernel::DeltaEMode::Type emode,
Kernel::Logger *pLog = nullptr, int nThreads = 1,
bool inPlace = true, bool nullifyNegative = false);
void removeBackground(int nHist, HistogramData::HistogramX &x_data,
......@@ -81,16 +83,11 @@ private:
// workspace
double m_ErrSq;
// energy conversion mode
int m_Emode;
// incident for direct or analysis for indirect energy for units conversion
double m_Efix;
Kernel::DeltaEMode::Type m_Emode;
// if true, negative signals are nullified
bool m_nullifyNegative;
// removing negative values from ws with background removed previously.
bool m_previouslyRemovedBkgMode;
// get Ei attached to direct or indirect instrument workspace
double getEi(const API::MatrixWorkspace_const_sptr &inputWS) const;
};
class MANTID_ALGORITHMS_DLL RemoveBackground : public API::Algorithm {
......
......@@ -72,8 +72,6 @@ private:
void crop(const double &start, const double &end);
void transformRangeUnit(const int index, double &startX, double &endX);
void calculateDetectorPosition(const int index, double &l1, double &l2,
double &twoTheta);
int findIndex(const double &value, const HistogramData::HistogramX &vec);
void RemoveFromEnds(int start, int end, HistogramData::HistogramY &Y,
HistogramData::HistogramE &E);
......
......@@ -83,6 +83,9 @@ void AddPeak::exec() {
double Qz = 1.0 - cos(theta2);
double l1 = detectorInfo.l1();
double l2 = detectorInfo.l2(detectorIndex);
std::vector<int> emptyWarningVec;
auto [difa, difc, tzero] = detectorInfo.diffractometerConstants(
detectorIndex, emptyWarningVec, emptyWarningVec);
Mantid::Kernel::Unit_sptr unit = runWS->getAxis(0)->unit();
if (unit->unitID() != "TOF") {
......@@ -112,7 +115,13 @@ void AddPeak::exec() {
}
std::vector<double> xdata(1, tof);
std::vector<double> ydata;
unit->toTOF(xdata, ydata, l1, l2, theta2, emode, efixed, 0.0);
unit->toTOF(xdata, ydata, l1, emode,
{{Kernel::UnitParams::l2, l2},
{Kernel::UnitParams::twoTheta, theta2},
{Kernel::UnitParams::efixed, efixed},
{Kernel::UnitParams::difa, difa},
{Kernel::UnitParams::difc, difc},
{Kernel::UnitParams::tzero, tzero}});
tof = xdata[0];
}
......
......@@ -17,7 +17,6 @@
#include "MantidDataObjects/EventWorkspace.h"
#includ