Newer
Older
#include "MantidAPI/FileProperty.h"
Federico Montesino Pouzols
committed
#include "MantidAPI/MultipleFileProperty.h"
#include "MantidAPI/NumericAxis.h"
#include "MantidDataHandling/LoadFITS.h"
#include "MantidDataObjects/Workspace2D.h"
Federico Montesino Pouzols
committed
#include "MantidKernel/BoundedValidator.h"
#include <boost/algorithm/string.hpp>
Federico Montesino Pouzols
committed
#include <Poco/BinaryReader.h>
#include <Poco/FileStream.h>
using namespace Mantid::API;
using namespace Mantid::Kernel;
using namespace std;
using namespace boost;
Federico Montesino Pouzols
committed
namespace {}
namespace Mantid {
namespace DataHandling {
// Register the algorithm into the AlgorithmFactory
DECLARE_FILELOADER_ALGORITHM(LoadFITS)
const std::string LoadFITS::g_BIT_DEPTH_NAME = "BitDepthName";
const std::string LoadFITS::g_ROTATION_NAME = "RotationName";
const std::string LoadFITS::g_AXIS_NAMES_NAME = "AxisNames";
const std::string LoadFITS::g_IMAGE_KEY_NAME = "ImageKeyName";
const std::string LoadFITS::g_HEADER_MAP_NAME = "HeaderMapFile";
Federico Montesino Pouzols
committed
const std::string LoadFITS::g_defaultImgType = "SAMPLE";
Federico Montesino Pouzols
committed
/**
* Constructor. Just initialize everything to prevent issues.
*/
Federico Montesino Pouzols
committed
LoadFITS::LoadFITS()
: m_headerScaleKey(), m_headerOffsetKey(), m_headerBitDepthKey(),
m_headerRotationKey(), m_headerImageKeyKey(), m_headerAxisNameKeys(),
Federico Montesino Pouzols
committed
m_mapFile(), m_baseName(), m_pixelCount(0), m_rebin(1),
m_noiseThresh(0.0), m_progress(NULL) {
setupDefaultKeywordNames();
}
/**
* Return the confidence with with this algorithm can load the file
* @param descriptor A descriptor for the file
* @returns An integer specifying the confidence level. 0 indicates it will not
* be used
*/
int LoadFITS::confidence(Kernel::FileDescriptor &descriptor) const {
// Should really improve this to check the file header (of first file at
// least) to make sure it contains the fields wanted
return (descriptor.extension() == ".fits" || descriptor.extension() == ".fit")
? 80
: 0;
}
/**
* Sets several keyword names with default (and standard) values. You
* don't want to change these unless you want to break compatibility
* with the FITS standard.
*/
void LoadFITS::setupDefaultKeywordNames() {
// Inits all the absolutely necessary keywords
// standard headers (If SIMPLE=T)
m_headerScaleKey = "BSCALE";
m_headerOffsetKey = "BZERO";
m_headerBitDepthKey = "BITPIX";
m_headerImageKeyKey = "IMAGE_TYPE"; // This is a "HIERARCH Image/Type= "
m_headerRotationKey = "ROTATION";
m_headerNAxisNameKey = "NAXIS";
m_headerAxisNameKeys.push_back("NAXIS1");
m_headerAxisNameKeys.push_back("NAXIS2");
m_mapFile = "";
// extensions
m_sampleRotation = "HIERARCH Sample/Tomo_Angle";
m_imageType = "HIERARCH Image/Type";
}
/**
* Initialise the algorithm. Declare properties which can be set before execution
* (input) or
* read from after the execution (output).
*/
void LoadFITS::init() {
// Specify file extensions which can be associated with a FITS file.
std::vector<std::string> exts, exts2;
// Declare the Filename algorithm property. Mandatory. Sets the path to the
// file to load.
exts.clear();
exts.push_back(".fits");
exts.push_back(".fit");
exts2.push_back(".*");
declareProperty(new MultipleFileProperty("Filename", exts),
Federico Montesino Pouzols
committed
"The name of the input file (note that you can give "
"multiple file names separated by commas).");
declareProperty(new API::WorkspaceProperty<API::Workspace>(
"OutputWorkspace", "", Kernel::Direction::Output));
Federico Montesino Pouzols
committed
declareProperty(
new Kernel::PropertyWithValue<bool>("LoadAsRectImg", false,
Kernel::Direction::Input),
"If enabled (not by default), the output Workspace2D will have "
"one histogram per row and one bin per pixel, such that a 2D "
"color plot (color fill plot) will display an image.");
Federico Montesino Pouzols
committed
auto zeroOrPosDbl = boost::make_shared<BoundedValidator<double>>();
zeroOrPosDbl->setLower(0.0);
declareProperty("FilterNoiseLevel", 0.0, zeroOrPosDbl,
"Threshold to remove noisy pixels. Try 50 for example.");
Federico Montesino Pouzols
committed
auto posInt = boost::make_shared<BoundedValidator<int>>();
posInt->setLower(1);
declareProperty("BinSize", 1, posInt,
"Rebunch n*n on both axes, generating pixels with sums of "
Federico Montesino Pouzols
committed
"blocks of n by n original pixels.");
Federico Montesino Pouzols
committed
auto posDbl = boost::make_shared<BoundedValidator<double>>();
posDbl->setLower(std::numeric_limits<double>::epsilon());
declareProperty("Scale", 80.0, posDbl, "Pixels per cm.",
Kernel::Direction::Input);
new FileProperty(g_HEADER_MAP_NAME, "", FileProperty::OptionalDirectory,
Federico Montesino Pouzols
committed
"", Kernel::Direction::Input),
"A file mapping header key names to non-standard names [line separated "
"values in the format KEY=VALUE, e.g. BitDepthName=BITPIX] - do not use "
"this if you want to keep compatibility with standard FITS files.");
* Execute the algorithm.
*/
// for non-standard headers, by default won't do anything
Federico Montesino Pouzols
committed
std::string fName = getPropertyValue("Filename");
std::vector<std::string> paths;
boost::split(paths, fName, boost::is_any_of(","));
Federico Montesino Pouzols
committed
Federico Montesino Pouzols
committed
m_rebin = getProperty("BinSize");
m_noiseThresh = getProperty("FilterNoiseLevel");
Federico Montesino Pouzols
committed
bool loadAsRectImg = getProperty("LoadAsRectImg");
Federico Montesino Pouzols
committed
const std::string outWSName = getPropertyValue("OutputWorkspace");
doLoadFiles(paths, outWSName, loadAsRectImg);
}
/**
* Create FITS file information for each file selected. Loads headers
Federico Montesino Pouzols
committed
* and data from the files and creates and fills the output
* workspace(s).
*
* @param paths File names as given in the algorithm input property
Federico Montesino Pouzols
committed
*
Federico Montesino Pouzols
committed
* @param outWSName name of the output (group) workspace to create
*
Federico Montesino Pouzols
committed
* @param loadAsRectImg Load files with 1 spectrum per row and 1 bin
* per column, so a color fill plot displays the image
Federico Montesino Pouzols
committed
*
* @throw std::runtime_error when load fails (for example a memory
* allocation issue, wrong rebin requested, etc.)
*/
Federico Montesino Pouzols
committed
void LoadFITS::doLoadFiles(const std::vector<std::string> &paths,
Federico Montesino Pouzols
committed
const std::string &outWSName, bool loadAsRectImg) {
std::vector<FITSInfo> headers;
doLoadHeaders(paths, headers);
// No extension is set -> it's the standard format which we can parse.
if (headers[0].numberOfAxis > 0)
Federico Montesino Pouzols
committed
m_pixelCount += headers[0].axisPixelLengths[0];
// Presumably 2 axis, but futureproofing.
for (int i = 1; i < headers[0].numberOfAxis; ++i) {
Federico Montesino Pouzols
committed
m_pixelCount *= headers[0].axisPixelLengths[i];
}
Federico Montesino Pouzols
committed
// Check consistency of m_rebin asap
for (int i = 0; i < headers[0].numberOfAxis; ++i) {
if (0 != (headers[0].axisPixelLengths[i] % m_rebin)) {
throw std::runtime_error(
"Cannot rebin this image in blocks of " +
boost::lexical_cast<std::string>(m_rebin) + " x " +
boost::lexical_cast<std::string>(m_rebin) +
" pixels as requested because the size of dimension " +
boost::lexical_cast<std::string>(i + 1) + " (" +
boost::lexical_cast<std::string>(headers[0].axisPixelLengths[i]) +
Loading
Loading full blame...