Skip to content

Commit

Permalink
Refs #11282. Fixed some issues related to reduce HFIR data.
Browse files Browse the repository at this point in the history
1. LoadSpiceAscii has date time format with default to SPICE's current
standard
2. ConvertCWPDMDToSpectra is explained in the sumary;
3. Binning parameters can accept bin size only in
ConvertCWPDMDToSpectra.  Xmin and Xmax will be searched automatically.

	- modified:   ../Mantid/Framework/DataHandling/src/LoadSpiceAscii.cpp
	- modified:   ../Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertCWPDMDToSpectra.h
	- modified:   ../Mantid/Framework/MDAlgorithms/src/ConvertCWPDMDToSpectra.cpp
	- modified:   ../Mantid/Framework/MDAlgorithms/test/ConvertCWPDMDToSpectraTest.h
  • Loading branch information
wdzhou committed Mar 9, 2015
1 parent 58e003d commit 6dab661
Show file tree
Hide file tree
Showing 4 changed files with 224 additions and 16 deletions.
18 changes: 14 additions & 4 deletions Code/Mantid/Framework/DataHandling/src/LoadSpiceAscii.cpp
Expand Up @@ -129,8 +129,16 @@ void LoadSpiceAscii::init() {
"Otherwise, any log name is not listed will be treated as "
"string property.");

declareProperty(new ArrayProperty<std::string>("DateAndTimeLog"),
"Name and format for date and time");
// date: MM/DD/YYYY,time: HH:MM:SS AM is the standard SPICE date time log name
// and format
std::vector<std::string> defaultlogformat(4);
defaultlogformat[0] = "date";
defaultlogformat[1] = "MM/DD/YYYY";
defaultlogformat[2] = "time";
defaultlogformat[3] = "HH:MM:SS AM";
declareProperty(
new ArrayProperty<std::string>("DateAndTimeLog", defaultlogformat),
"Name and format for date and time");

// Output
declareProperty(new WorkspaceProperty<ITableWorkspace>("OutputWorkspace", "",
Expand Down Expand Up @@ -461,8 +469,10 @@ void LoadSpiceAscii::setupRunStartTime(
runinfows->run().hasProperty(timelogname))) {
std::stringstream errss;
errss << "Unable to locate user specified date and time sample logs "
<< datelogname << " and " << timelogname << ".";
throw std::runtime_error(errss.str());
<< datelogname << " and " << timelogname << "."
<< "run_start will not be set up.";
g_log.error(errss.str());
return;
}

const std::string &rawdatestring =
Expand Down
Expand Up @@ -108,8 +108,12 @@ class DLLExport ConvertCWPDMDToSpectra : public API::Algorithm {

/// Summary of algorithms purpose
virtual const std::string summary() const {
return "Binning the constant wavelength powder diffracton data stored in "
"MDWorkspaces to single spectrum.";
return "Convert constant wavelength (CW) powder diffraction (PD) data in "
"MDEventWorksapces "
" to a single-spectrum MatrixWorkspace, i.e., binning the "
"diffraction data "
" to single spectrum according to neutron's scattering angle, "
"d-spacing or Q. ";
}

/// Algorithm's version
Expand All @@ -134,6 +138,12 @@ class DLLExport ConvertCWPDMDToSpectra : public API::Algorithm {
const std::map<int, double> &map_runwavelength, const double xmin,
const double xmax, const double binsize, bool dolinearinterpolation);

/// Find the binning boundary according to detectors' positions
void findXBoundary(API::IMDEventWorkspace_const_sptr dataws,
const std::string &targetunit,
const std::map<int, double> &map_runwavelength,
double &xmin, double &xmax);

/// Bin signals to its 2theta position
void binMD(API::IMDEventWorkspace_const_sptr mdws, const char &unitbit,
const std::map<int, double> &map_runlambda,
Expand Down
159 changes: 151 additions & 8 deletions Code/Mantid/Framework/MDAlgorithms/src/ConvertCWPDMDToSpectra.cpp
Expand Up @@ -15,6 +15,8 @@ using namespace Mantid::MDAlgorithms;

DECLARE_ALGORITHM(ConvertCWPDMDToSpectra)

const double BIGNUMBER = 1.0E100;

//----------------------------------------------------------------------------------------------
/** Constructor
*/
Expand Down Expand Up @@ -140,16 +142,33 @@ void ConvertCWPDMDToSpectra::exec() {
}

// bin parameters
if (binParams.size() != 3)
throw std::runtime_error("Binning parameters must have 3 items.");
if (binParams[0] >= binParams[2])
double xmin, xmax, binsize;
xmin = xmax = binsize = -1;
if (binParams.size() == 1) {
binsize = binParams[0];
g_log.warning()
<< "Only bin size " << binParams[0]
<< " is specified. Xmin and Xmax "
" will be calcualted from motor positions and wavelength. "
"More CPU time will be used."
<< "\n";
} else if (binParams.size() == 3) {
xmin = binParams[0];
binsize = binParams[1];
xmax = binParams[2];
if (xmin >= xmax)
throw std::runtime_error(
"Min value of the bin must be smaller than maximum value.");
} else {
// Either 1 or 3 parameters. Throw exception
throw std::runtime_error(
"Min value of the bin must be smaller than maximum value.");
"Binning parameters must have either 1 or 3 items.");
}

// Rebin
API::MatrixWorkspace_sptr outws = reducePowderData(
inputDataWS, inputMonitorWS, outputunit, map_runWavelength, binParams[0],
binParams[2], binParams[1], doLinearInterpolation);
inputDataWS, inputMonitorWS, outputunit, map_runWavelength, xmin, xmax,
binsize, doLinearInterpolation);

// Scale
scaleMatrixWorkspace(outws, scaleFactor, m_infitesimal);
Expand Down Expand Up @@ -188,9 +207,24 @@ API::MatrixWorkspace_sptr ConvertCWPDMDToSpectra::reducePowderData(
// Get some information
int64_t numevents = dataws->getNEvents();

// check xmin and xmax
double lowerboundary, upperboundary;
if (xmin < 0 || xmax < 0) {
// xmin or xmax cannot be negative (2theta, dspace and q are always
// positive)
findXBoundary(dataws, targetunit, map_runwavelength, lowerboundary,
upperboundary);
} else {
lowerboundary = xmin;
upperboundary = xmax;
}

g_log.notice() << "[DB] Binning from " << lowerboundary << " to "
<< upperboundary << "\n";

// Create bins in 2theta (degree)
size_t sizex, sizey;
sizex = static_cast<size_t>((xmax - xmin) / binsize + 0.5);
sizex = static_cast<size_t>((upperboundary - lowerboundary) / binsize + 0.5);
sizey = sizex - 1;
g_log.debug() << "Number of events = " << numevents
<< "bin size = " << binsize << ", SizeX = " << sizex << ", "
Expand All @@ -199,7 +233,7 @@ API::MatrixWorkspace_sptr ConvertCWPDMDToSpectra::reducePowderData(
vece(sizex - 1, 0);

for (size_t i = 0; i < sizex; ++i) {
vecx[i] = xmin + static_cast<double>(i) * binsize;
vecx[i] = lowerboundary + static_cast<double>(i) * binsize;
}

// Convert unit to unit char bit
Expand Down Expand Up @@ -270,6 +304,115 @@ API::MatrixWorkspace_sptr ConvertCWPDMDToSpectra::reducePowderData(
return pdws;
}

//----------------------------------------------------------------------------------------------
/** Find the binning boundaries for 2theta (det position), d-spacing or Q.
* @brief ConvertCWPDMDToSpectra::findXBoundary
* @param dataws
* @param targetunit
* @param wavelength
* @param xmin :: (output) lower binning boundary
* @param xmax :: (output) upper binning boundary
*/
void ConvertCWPDMDToSpectra::findXBoundary(
API::IMDEventWorkspace_const_sptr dataws, const std::string &targetunit,
const std::map<int, double> &map_runwavelength, double &xmin,
double &xmax) {
// Go through all instruments
uint16_t numruns = dataws->getNumExperimentInfo();
g_log.notice() << "[DB] Tota number of ExperimentInfo = " << numruns << "\n";

xmin = BIGNUMBER;
xmax = -1;

for (uint16_t irun = 0; irun < numruns; ++irun) {
// Skip the Experiment Information does not have run
if (!dataws->getExperimentInfo(irun)->getInstrument()) {
g_log.warning() << "iRun = " << irun << " of total " << numruns
<< " does not have instrument associated"
<< "\n";
continue;
}

// Get run number
int runnumber = dataws->getExperimentInfo(irun)->getRunNumber();
g_log.notice() << "Run " << runnumber << ": ";
std::map<int, double>::const_iterator miter =
map_runwavelength.find(runnumber);
double wavelength = -1;
if (miter != map_runwavelength.end()) {
wavelength = miter->second;
g_log.notice() << " wavelength = " << wavelength << "\n";
} else {
g_log.notice() << " no matched wavelength."
<< "\n";
}

// Get source and sample position
std::vector<detid_t> vec_detid =
dataws->getExperimentInfo(irun)->getInstrument()->getDetectorIDs(true);
if (vec_detid.size() == 0) {
g_log.notice() << "[DB] Run " << runnumber << " has no detectors."
<< "\n";
continue;
}
const V3D samplepos =
dataws->getExperimentInfo(irun)->getInstrument()->getSample()->getPos();
const V3D sourcepos =
dataws->getExperimentInfo(irun)->getInstrument()->getSource()->getPos();

// Get all detectors
// std::vector<detid_t> vec_detid =
// dataws->getExperimentInfo(irun)->getInstrument()->getDetectorIDs(true);
std::vector<Geometry::IDetector_const_sptr> vec_det =
dataws->getExperimentInfo(irun)->getInstrument()->getDetectors(
vec_detid);
size_t numdets = vec_det.size();
g_log.notice() << "[DB] Run = " << runnumber
<< ": Number of detectors = " << numdets << "\n";

// Scan all the detectors to get Xmin and Xmax
for (size_t idet = 0; idet < numdets; ++idet) {
Geometry::IDetector_const_sptr tmpdet = vec_det[idet];
const V3D detpos = tmpdet->getPos();

double R, theta, phi;
detpos.getSpherical(R, theta, phi);
if (R < 0.0001)
g_log.error("Invalid detector position");

Kernel::V3D v_det_sample = detpos - samplepos;
Kernel::V3D v_sample_src = samplepos - sourcepos;
double twotheta =
calculate2Theta(v_det_sample, v_sample_src) / M_PI * 180.;

// convert unit optionally
double outx = -1;
if (targetunit.compare("2tehta") == 0)
outx = twotheta;
else {
if (wavelength <= 0)
throw std::runtime_error("Wavelength is not defined!");

if (targetunit.compare("dSpacing") == 0)
outx = calculateDspaceFrom2Theta(twotheta, wavelength);
else if (targetunit.compare("Q") == 0)
outx = calculateQFrom2Theta(twotheta, wavelength);
else
throw std::runtime_error("Unrecognized unit.");
}

// Compare with xmin and xmax
if (outx < xmin)
xmin = outx;
else if (outx > xmax)
xmax = outx;
}
}

g_log.notice() << "[DB] Auto boundary: [" << xmin << ", " << xmax << "]"
<< "\n";
}

//----------------------------------------------------------------------------------------------
/** Bin MD Workspace for detector's position at 2theta
* @brief ConvertCWPDMDToSpectra::binMD
Expand Down
Expand Up @@ -38,7 +38,7 @@ class ConvertCWPDMDToSpectraTest : public CxxTest::TestSuite {
/** Unit test to reduce/bin the HB2A data
* @brief test_ReduceHB2AData
*/
void test_ReduceHB2AData() {
void Ptest_ReduceHB2AData() {
// Init
ConvertCWPDMDToSpectra alg;
alg.initialize();
Expand Down Expand Up @@ -100,7 +100,7 @@ class ConvertCWPDMDToSpectraTest : public CxxTest::TestSuite {
/** Unit test to reduce/bin the HB2A data with more options
* @brief test_ReduceHB2AData
*/
void test_ReduceHB2ADataMoreOptions() {
void Ptest_ReduceHB2ADataMoreOptions() {
// Init
ConvertCWPDMDToSpectra alg;
alg.initialize();
Expand Down Expand Up @@ -139,6 +139,51 @@ class ConvertCWPDMDToSpectraTest : public CxxTest::TestSuite {

// Check statistics

// Clean
AnalysisDataService::Instance().remove("ReducedData");
}

//----------------------------------------------------------------------------------------------
/** Unit test to reduce/bin the HB2A data with more options
* @brief test_ReduceHB2AData
*/
void test_ReduceHB2ADataAutoBinBoundary() {
// Init
ConvertCWPDMDToSpectra alg;
alg.initialize();

// Set properties
TS_ASSERT_THROWS_NOTHING(
alg.setPropertyValue("InputWorkspace", m_dataMD->name()));
TS_ASSERT_THROWS_NOTHING(
alg.setPropertyValue("InputMonitorWorkspace", m_monitorMD->name()));
TS_ASSERT_THROWS_NOTHING(alg.setProperty("UnitOutput", "dSpacing"));
TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("BinningParams", "0.01"));
TS_ASSERT_THROWS_NOTHING(
alg.setProperty("LinearInterpolateZeroCounts", true));
TS_ASSERT_THROWS_NOTHING(alg.setProperty("ScaleFactor", 10.0));
TS_ASSERT_THROWS_NOTHING(alg.setProperty("NeutronWaveLength", 2.41));
TS_ASSERT_THROWS_NOTHING(alg.setProperty("OutputWorkspace", "ReducedData"));

// Execute
TS_ASSERT_THROWS_NOTHING(alg.execute());
TS_ASSERT(alg.isExecuted());

// Get ouput
MatrixWorkspace_sptr outws = boost::dynamic_pointer_cast<MatrixWorkspace>(
AnalysisDataService::Instance().retrieve("ReducedData"));
TS_ASSERT(outws);

// Check unit and range of X
std::string unit = outws->getAxis(0)->unit()->unitID();
TS_ASSERT_EQUALS(unit, "dSpacing");

const Mantid::MantidVec &vecX = outws->readX(0);
TS_ASSERT_DELTA(vecX.front(), 0.5, 0.0001);
TS_ASSERT_DELTA(vecX.back(), 4.99, 0.0001);

// Check statistics

// Clean
AnalysisDataService::Instance().remove("ReducedData");

Expand Down

0 comments on commit 6dab661

Please sign in to comment.