Skip to content
Snippets Groups Projects
Unverified Commit 55d3a4ea authored by Pete Peterson's avatar Pete Peterson Committed by GitHub
Browse files

Merge pull request #24037 from mantidproject/24032_Refactor_setsampleMaterial

Pull code out of setSampleMaterial
parents 64c445a1 f09922c7
No related branches found
No related tags found
No related merge requests found
......@@ -136,6 +136,7 @@
src/PatchBBY.cpp
src/ProcessBankData.cpp
src/RawFileInfo.cpp
src/ReadMaterial.cpp
src/RemoveLogs.cpp
src/RenameLog.cpp
src/RotateInstrumentComponent.cpp
......@@ -329,6 +330,7 @@ set ( INC_FILES
inc/MantidDataHandling/PatchBBY.h
inc/MantidDataHandling/ProcessBankData.h
inc/MantidDataHandling/RawFileInfo.h
inc/MantidDataHandling/ReadMaterial.h
inc/MantidDataHandling/RemoveLogs.h
inc/MantidDataHandling/RenameLog.h
inc/MantidDataHandling/RotateInstrumentComponent.h
......@@ -511,6 +513,7 @@ set ( TEST_FILES
ORNLDataArchiveTest.h
PDLoadCharacterizationsTest.h
RawFileInfoTest.h
ReadMaterialTest.h
RemoveLogsTest.h
RenameLogTest.h
RotateInstrumentComponentTest.h
......
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2009 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source
// & Institut Laue - Langevin
// SPDX - License - Identifier: GPL - 3.0 +
#ifndef MANTID_DATAHANDLING_ReadMaterial_H_
#define MANTID_DATAHANDLING_ReadMaterial_H_
#include "MantidKernel/EmptyValues.h"
#include "MantidKernel/MaterialBuilder.h"
#include <map>
namespace Mantid {
namespace Kernel {
class Material;
}
namespace DataHandling {
using ValidationErrors = std::map<std::string, std::string>;
/**
This class contains code for interpreting a material input for
SetSampleMaterial, validating the parameters before sending them on to
MaterialBuilder
*/
class DLLExport ReadMaterial {
public:
/**
This struct contains the parameters for constructing a material,
and gives them a default value for ease of testing
*/
struct MaterialParameters {
/// The chemical formula to set, defaults to the empty string
std::string chemicalSymbol = "";
/// The atomic number to set, defaults to 0
int atomicNumber = 0;
/// The mass number to set, defaults to 0
int massNumber = 0;
/// The sample number density to set, defaults to EMPTY_DBL()
double sampleNumberDensity = EMPTY_DBL();
/// The zParameter to set, defaults to EMPTY_DBL()
double zParameter = EMPTY_DBL();
/// The unit cell volume to set, defaults to EMPTY_DBL()
double unitCellVolume = EMPTY_DBL();
/// The sample mass density to set, defaults to EMPTY_DBL()
double sampleMassDensity = EMPTY_DBL();
/// The coherent scattering cross section to set, defaults to EMPTY_DBL()
double coherentXSection = EMPTY_DBL();
/// The incoherent scattering cross section to set, defaults to EMPTY_DBL()
double incoherentXSection = EMPTY_DBL();
/// The absorption cross section to set, defaults to EMPTY_DBL()
double attenuationXSection = EMPTY_DBL();
/// The total scattering cross section to set, defaults to EMPTY_DBL()
double scatteringXSection = EMPTY_DBL();
};
/**
* Validate the parameters to build the material from, this returns
* any errors in the inputs.
*
* @param params A struct containing all the parameters to be set.
* @returns A map containing the relevent failure messages, if any.
*/
static ValidationErrors validateInputs(MaterialParameters params);
/**
* Set the parameters to build the material to the builder,
* taking into account which values were and weren't set.
*
* @param params A struct containing all the parameters to be set.
*/
void setMaterialParameters(MaterialParameters params);
/**
* Construct the material,
*
* @returns A unique pointer to the newly made material
*/
std::unique_ptr<Kernel::Material> buildMaterial();
private:
/**
* @brief The builder used to construct the material
*
*/
Kernel::MaterialBuilder builder;
void setMaterial(const std::string chemicalSymbol, const int atomicNumber,
const int massNumber);
void setNumberDensity(const double rho_m, const double rho,
const double zParameter, const double unitCellVolume);
void setScatteringInfo(double coherentXSection, double incoherentXSection,
double attenuationXSection, double scatteringXSection);
static bool isEmpty(const double toCheck);
};
} // namespace DataHandling
} // namespace Mantid
#endif /* MANTID_DATAHANDLING_ReadMaterial_H_*/
......@@ -8,8 +8,8 @@
#define MANTID_DATAHANDLING_SetSampleMaterial_H_
#include "MantidAPI/DistributedAlgorithm.h"
#include "MantidDataHandling/ReadMaterial.h"
#include "MantidKernel/NeutronAtom.h"
namespace Mantid {
namespace DataHandling {
......@@ -48,6 +48,8 @@ private:
/// Print out the list of information for the material
void fixNeutron(PhysicalConstants::NeutronAtom &neutron, double coh_xs,
double inc_xs, double abs_xs, double tot_xs);
ReadMaterial::MaterialParameters params;
};
} // namespace DataHandling
} // namespace Mantid
......
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright &copy; 2009 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source
// & Institut Laue - Langevin
// SPDX - License - Identifier: GPL - 3.0 +
#include "MantidDataHandling/ReadMaterial.h"
#include "MantidAPI/Algorithm.h"
#include "MantidKernel/Material.h"
#include <iostream>
namespace Mantid {
namespace DataHandling {
/**
* Validate the parameters to build the material from, this returns
* any errors in the inputs.
*
* @param params A struct containing all the parameters to be set.
* @returns A map containing the relevent failure messages, if any.
*/
ValidationErrors ReadMaterial::validateInputs(const MaterialParameters params) {
ValidationErrors result;
if (params.chemicalSymbol.empty()) {
if (params.atomicNumber <= 0) {
result["ChemicalFormula"] = "Need to specify the material";
}
} else {
if (params.atomicNumber > 0)
result["AtomicNumber"] =
"Cannot specify both ChemicalFormula and AtomicNumber";
}
if (params.massNumber > 0 && params.atomicNumber <= 0)
result["AtomicNumber"] = "Specified MassNumber without AtomicNumber";
if (!isEmpty(params.zParameter)) {
if (isEmpty(params.unitCellVolume)) {
result["UnitCellVolume"] =
"UnitCellVolume must be provided with ZParameter";
}
if (!isEmpty(params.sampleNumberDensity)) {
result["ZParameter"] =
"Can not give ZParameter with SampleNumberDensity set";
}
if (!isEmpty(params.sampleMassDensity)) {
result["SampleMassDensity"] =
"Can not give SampleMassDensity with ZParameter set";
}
} else if (!isEmpty(params.sampleNumberDensity)) {
if (!isEmpty(params.sampleMassDensity)) {
result["SampleMassDensity"] =
"Can not give SampleMassDensity with SampleNumberDensity set";
}
}
return result;
}
/**
* Set the parameters to build the material to the builder,
* taking into account which values were and weren't set.
*
* @param params A struct containing all the parameters to be set.
*/
void ReadMaterial::setMaterialParameters(MaterialParameters params) {
setMaterial(params.chemicalSymbol, params.atomicNumber, params.massNumber);
setNumberDensity(params.sampleMassDensity, params.sampleNumberDensity,
params.zParameter, params.unitCellVolume);
setScatteringInfo(params.coherentXSection, params.incoherentXSection,
params.attenuationXSection, params.scatteringXSection);
}
/**
* Construct the material,
*
* @returns A unique pointer to the newly made material
*/
std::unique_ptr<Kernel::Material> ReadMaterial::buildMaterial() {
return std::make_unique<Kernel::Material>(builder.build());
}
void ReadMaterial::setMaterial(const std::string chemicalSymbol,
const int atomicNumber, const int massNumber) {
if (!chemicalSymbol.empty()) {
std::cout << "CHEM: " << chemicalSymbol << std::endl;
builder.setFormula(chemicalSymbol);
} else {
builder.setAtomicNumber(atomicNumber);
builder.setMassNumber(massNumber);
}
}
void ReadMaterial::setNumberDensity(const double rho_m, const double rho,
const double zParameter,
const double unitCellVolume) {
if (!isEmpty(rho_m))
builder.setMassDensity(rho_m);
if (isEmpty(rho)) {
if (!isEmpty(zParameter)) {
builder.setZParameter(zParameter);
builder.setUnitCellVolume(unitCellVolume);
}
} else {
builder.setNumberDensity(rho);
}
}
void ReadMaterial::setScatteringInfo(double coherentXSection,
double incoherentXSection,
double attenuationXSection,
double scatteringXSection) {
builder.setCoherentXSection(coherentXSection); // in barns
builder.setIncoherentXSection(incoherentXSection); // in barns
builder.setAbsorptionXSection(attenuationXSection); // in barns
builder.setTotalScatterXSection(scatteringXSection); // in barns
}
bool ReadMaterial::isEmpty(const double toCheck) {
return std::abs((toCheck - EMPTY_DBL()) / (EMPTY_DBL())) < 1e-8;
}
} // namespace DataHandling
} // namespace Mantid
\ No newline at end of file
......@@ -14,12 +14,8 @@
#include "MantidKernel/EnabledWhenProperty.h"
#include "MantidKernel/MandatoryValidator.h"
#include "MantidKernel/Material.h"
#include "MantidKernel/MaterialBuilder.h"
#include "MantidKernel/PhysicalConstants.h"
#include <boost/scoped_ptr.hpp>
#include <cmath>
#include <iostream>
using namespace Mantid::PhysicalConstants;
......@@ -112,47 +108,14 @@ void SetSampleMaterial::init() {
}
std::map<std::string, std::string> SetSampleMaterial::validateInputs() {
std::map<std::string, std::string> result;
const std::string chemicalSymbol = getProperty("ChemicalFormula");
const int z_number = getProperty("AtomicNumber");
const int a_number = getProperty("MassNumber");
if (chemicalSymbol.empty()) {
if (z_number <= 0) {
result["ChemicalFormula"] = "Need to specify the material";
}
} else {
if (z_number > 0)
result["AtomicNumber"] =
"Cannot specify both ChemicalFormula and AtomicNumber";
}
if (a_number > 0 && z_number <= 0)
result["AtomicNumber"] = "Specified MassNumber without AtomicNumber";
const double sampleNumberDensity = getProperty("SampleNumberDensity");
const double zParameter = getProperty("ZParameter");
const double unitCellVolume = getProperty("UnitCellVolume");
const double sampleMassDensity = getProperty("SampleMassDensity");
if (!isEmpty(zParameter)) {
if (isEmpty(unitCellVolume)) {
result["UnitCellVolume"] =
"UnitCellVolume must be provided with ZParameter";
}
if (!isEmpty(sampleNumberDensity)) {
result["ZParameter"] =
"Can not give ZParameter with SampleNumberDensity set";
}
if (!isEmpty(sampleMassDensity)) {
result["SampleMassDensity"] =
"Can not give SampleMassDensity with ZParameter set";
}
} else if (!isEmpty(sampleNumberDensity)) {
if (!isEmpty(sampleMassDensity)) {
result["SampleMassDensity"] =
"Can not give SampleMassDensity with SampleNumberDensity set";
}
}
params.chemicalSymbol = getPropertyValue("ChemicalFormula");
params.atomicNumber = getProperty("AtomicNumber");
params.massNumber = getProperty("MassNumber");
params.sampleNumberDensity = getProperty("SampleNumberDensity");
params.zParameter = getProperty("ZParameter");
params.unitCellVolume = getProperty("UnitCellVolume");
params.sampleMassDensity = getProperty("SampleMassDensity");
auto result = ReadMaterial::validateInputs(params);
return result;
}
......@@ -193,46 +156,18 @@ void SetSampleMaterial::exec() {
throw std::runtime_error("InputWorkspace does not have a sample object");
}
boost::scoped_ptr<Material> material;
MaterialBuilder builder;
ReadMaterial reader;
params.coherentXSection = getProperty("CoherentXSection");
params.incoherentXSection = getProperty("IncoherentXSection");
params.attenuationXSection = getProperty("AttenuationXSection");
params.scatteringXSection = getProperty("ScatteringXSection");
reader.setMaterialParameters(params);
// determine the material
const std::string chemicalSymbol = getProperty("ChemicalFormula");
const int z_number = getProperty("AtomicNumber");
const int a_number = getProperty("MassNumber");
if (!chemicalSymbol.empty()) {
std::cout << "CHEM: " << chemicalSymbol << std::endl;
builder.setFormula(chemicalSymbol);
} else {
builder.setAtomicNumber(z_number);
builder.setMassNumber(a_number);
}
// determine the sample number density
double rho_m = getProperty("SampleMassDensity"); // in g/cc
if (!isEmpty(rho_m))
builder.setMassDensity(rho_m);
double rho = getProperty("SampleNumberDensity"); // in atoms / Angstroms^3
if (isEmpty(rho)) {
double zParameter = getProperty("ZParameter"); // number of atoms
if (!isEmpty(zParameter)) {
builder.setZParameter(zParameter);
double unitCellVolume = getProperty("UnitCellVolume");
builder.setUnitCellVolume(unitCellVolume);
}
} else {
builder.setNumberDensity(rho);
}
// get the scattering information - this will override table values
builder.setCoherentXSection(getProperty("CoherentXSection")); // in barns
builder.setIncoherentXSection(getProperty("IncoherentXSection")); // in barns
builder.setAbsorptionXSection(getProperty("AttenuationXSection")); // in barns
builder.setTotalScatterXSection(
getProperty("ScatteringXSection")); // in barns
// create the material
material.reset(new Material(builder.build()));
auto material = reader.buildMaterial();
// calculate derived values
const double bcoh_avg_sq = material->cohScatterLengthSqrd(); // <b>
......
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright &copy; 2009 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source
// & Institut Laue - Langevin
// SPDX - License - Identifier: GPL - 3.0 +
#include "MantidDataHandling/ReadMaterial.h"
#include "MantidKernel/Atom.h"
#include "MantidKernel/Material.h"
#include <cxxtest/TestSuite.h>
using namespace Mantid;
using namespace Mantid::Kernel;
using namespace Mantid::DataHandling;
class ReadMaterialTest : public CxxTest::TestSuite {
public:
static ReadMaterialTest *createSuite() { return new ReadMaterialTest(); }
static void destroySuite(ReadMaterialTest *suite) { delete suite; }
void testSuccessfullValidateInputsFormula() {
const ReadMaterial::MaterialParameters params = [this]() -> auto {
ReadMaterial::MaterialParameters setMaterial;
setMaterial.chemicalSymbol = FORMULA;
setMaterial.atomicNumber = 0;
setMaterial.massNumber = 0;
return setMaterial;
}
();
auto result = ReadMaterial::validateInputs(params);
TS_ASSERT(result.empty());
}
void testSuccessfullValidateInputsAtomicNumber() {
const ReadMaterial::MaterialParameters params = [this]() -> auto {
ReadMaterial::MaterialParameters setMaterial;
setMaterial.atomicNumber = 1;
setMaterial.massNumber = 1;
return setMaterial;
}
();
auto result = ReadMaterial::validateInputs(params);
TS_ASSERT(result.empty());
}
void testFailureValidateInputsFormulaPlusAtomicNumber() {
const ReadMaterial::MaterialParameters params = [this]() -> auto {
ReadMaterial::MaterialParameters setMaterial;
setMaterial.chemicalSymbol = FORMULA;
setMaterial.atomicNumber = 1;
setMaterial.massNumber = 1;
return setMaterial;
}
();
auto result = ReadMaterial::validateInputs(params);
TS_ASSERT_EQUALS(result["AtomicNumber"],
"Cannot specify both ChemicalFormula and AtomicNumber")
}
void testFailureValidateInputsNoMaterial() {
const ReadMaterial::MaterialParameters params = [this]() -> auto {
ReadMaterial::MaterialParameters setMaterial;
setMaterial.atomicNumber = 0;
setMaterial.massNumber = 0;
return setMaterial;
}
();
auto result = ReadMaterial::validateInputs(params);
TS_ASSERT_EQUALS(result["ChemicalFormula"], "Need to specify the material")
}
void testSuccessfullValidateInputsSampleNumber() {
const ReadMaterial::MaterialParameters params = [this]() -> auto {
ReadMaterial::MaterialParameters setMaterial;
setMaterial.atomicNumber = 1;
setMaterial.massNumber = 1;
setMaterial.sampleNumberDensity = 1;
return setMaterial;
}
();
auto result = ReadMaterial::validateInputs(params);
TS_ASSERT(result.empty());
}
void testSuccessfullValidateInputsZParam() {
const ReadMaterial::MaterialParameters params = [this]() -> auto {
ReadMaterial::MaterialParameters setMaterial;
setMaterial.atomicNumber = 1;
setMaterial.massNumber = 1;
setMaterial.zParameter = 1;
setMaterial.unitCellVolume = 1;
return setMaterial;
}
();
auto result = ReadMaterial::validateInputs(params);
TS_ASSERT(result.empty());
}
void testSuccessfullValidateInputsSampleMass() {
const ReadMaterial::MaterialParameters params = [this]() -> auto {
ReadMaterial::MaterialParameters setMaterial;
setMaterial.atomicNumber = 1;
setMaterial.massNumber = 1;
setMaterial.sampleMassDensity = 1;
return setMaterial;
}
();
auto result = ReadMaterial::validateInputs(params);
TS_ASSERT(result.empty());
}
void testFailureValidateInputsSampleNumberAndZParam() {
const ReadMaterial::MaterialParameters params = [this]() -> auto {
ReadMaterial::MaterialParameters setMaterial;
setMaterial.atomicNumber = 1;
setMaterial.massNumber = 1;
setMaterial.sampleNumberDensity = 1;
setMaterial.zParameter = 1;
setMaterial.unitCellVolume = 1;
return setMaterial;
}
();
auto result = ReadMaterial::validateInputs(params);
TS_ASSERT_EQUALS(result["ZParameter"],
"Can not give ZParameter with SampleNumberDensity set")
}
void testFailureValidateInputsZParamWithSampleMass() {
const ReadMaterial::MaterialParameters params = [this]() -> auto {
ReadMaterial::MaterialParameters setMaterial;
setMaterial.atomicNumber = 1;
setMaterial.massNumber = 1;
setMaterial.zParameter = 1;
setMaterial.unitCellVolume = 1;
setMaterial.sampleMassDensity = 1;
return setMaterial;
}
();
auto result = ReadMaterial::validateInputs(params);
TS_ASSERT_EQUALS(result["SampleMassDensity"],
"Can not give SampleMassDensity with ZParameter set")
}
void testFailureValidateInputsZParamWithoutUnitCell() {
const ReadMaterial::MaterialParameters params = [this]() -> auto {
ReadMaterial::MaterialParameters setMaterial;
setMaterial.atomicNumber = 1;
setMaterial.massNumber = 1;
setMaterial.zParameter = 1;
return setMaterial;
}
();
auto result = ReadMaterial::validateInputs(params);
TS_ASSERT_EQUALS(result["UnitCellVolume"],
"UnitCellVolume must be provided with ZParameter")
}
void testFailureValidateInputsSampleNumWithSampleMass() {
const ReadMaterial::MaterialParameters params = [this]() -> auto {
ReadMaterial::MaterialParameters setMaterial;
setMaterial.atomicNumber = 1;
setMaterial.massNumber = 1;
setMaterial.sampleNumberDensity = 1;
setMaterial.sampleMassDensity = 1;
return setMaterial;
}
();
auto result = ReadMaterial::validateInputs(params);
TS_ASSERT_EQUALS(
result["SampleMassDensity"],
"Can not give SampleMassDensity with SampleNumberDensity set")
}
void testMaterialIsCorrect() {
const ReadMaterial::MaterialParameters params = [this]() -> auto {
ReadMaterial::MaterialParameters setMaterial;
setMaterial.chemicalSymbol = FORMULA;
setMaterial.sampleNumberDensity = 1;
setMaterial.coherentXSection = 1;
setMaterial.incoherentXSection = 2;
setMaterial.attenuationXSection = 3;
setMaterial.scatteringXSection = 4;
return setMaterial;
}
();
ReadMaterial reader;
reader.setMaterialParameters(params);
auto material = reader.buildMaterial();
Kernel::MaterialBuilder builder;
builder.setFormula(FORMULA);
builder.setNumberDensity(1);
builder.setCoherentXSection(1);
builder.setIncoherentXSection(2);
builder.setAbsorptionXSection(3);
builder.setTotalScatterXSection(4);
auto check = builder.build();
compareMaterial(*material, check);
}
void testGenerateScatteringInfo() {
const ReadMaterial::MaterialParameters params = [this]() -> auto {
ReadMaterial::MaterialParameters setMaterial;
setMaterial.chemicalSymbol = FORMULA;
setMaterial.sampleNumberDensity = 1;
return setMaterial;
}
();
ReadMaterial reader;
reader.setMaterialParameters(params);
auto material = reader.buildMaterial();
Kernel::MaterialBuilder builder;
builder.setFormula(FORMULA);
builder.setNumberDensity(1);
builder.setCoherentXSection(0.0184000000);
builder.setIncoherentXSection(5.0800000022);
builder.setAbsorptionXSection(5.0800000022);
builder.setTotalScatterXSection(5.1000000044);
auto check = builder.build();
compareMaterial(*material, check);
}
void testNoMaterialFailure() {
const ReadMaterial::MaterialParameters params = [this]() -> auto {
ReadMaterial::MaterialParameters setMaterial;
setMaterial.chemicalSymbol = EMPTY;
setMaterial.atomicNumber = 0;
setMaterial.massNumber = 0;
setMaterial.sampleNumberDensity = 1;
setMaterial.zParameter = EMPTY_DOUBLE_VAL;
setMaterial.unitCellVolume = EMPTY_DOUBLE_VAL;
setMaterial.sampleMassDensity = EMPTY_DOUBLE_VAL;
return setMaterial;
}
();
ReadMaterial reader;
reader.setMaterialParameters(params);
TS_ASSERT_THROWS(reader.buildMaterial(), std::runtime_error);
}
private:
const double EMPTY_DOUBLE_VAL = 8.9884656743115785e+307;
const double PRECISION = 1e-8;
const std::string EMPTY = "";
const std::string FORMULA = "V";
void compareMaterial(const Material &material, const Material &check) {
std::vector<Material::FormulaUnit> checkFormula = check.chemicalFormula();
std::vector<Material::FormulaUnit> materialFormula =
material.chemicalFormula();
TS_ASSERT_EQUALS(material.numberDensity(), check.numberDensity());
TS_ASSERT_DELTA(material.cohScatterXSection(), check.cohScatterXSection(),
PRECISION);
TS_ASSERT_DELTA(material.incohScatterXSection(),
check.incohScatterXSection(), PRECISION);
TS_ASSERT_DELTA(material.absorbXSection(), check.absorbXSection(),
PRECISION);
TS_ASSERT_DELTA(material.totalScatterXSection(),
check.totalScatterXSection(), PRECISION);
TS_ASSERT_EQUALS(checkFormula[0].multiplicity,
materialFormula[0].multiplicity);
TS_ASSERT_EQUALS(checkFormula.size(), materialFormula.size())
}
};
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment