Newer
Older
Roman Tolchenov
committed
#include "MantidDataHandling/ManagedRawFileWorkspace2D.h"
#include "MantidKernel/Exception.h"
#include "MantidAPI/RefAxis.h"
#include "MantidAPI/LocatedDataRef.h"
#include "MantidAPI/WorkspaceIterator.h"
#include "MantidAPI/WorkspaceIteratorCode.h"
#include "MantidAPI/WorkspaceProperty.h"
#include "MantidAPI/WorkspaceFactory.h"
Roman Tolchenov
committed
#include "MantidKernel/UnitFactory.h"
Roman Tolchenov
committed
#include "MantidKernel/ConfigService.h"
Gigg, Martyn Anthony
committed
#include "MantidKernel/System.h"
Roman Tolchenov
committed
#include "LoadRaw/isisraw2.h"
Roman Tolchenov
committed
#include <boost/timer.hpp>
Gigg, Martyn Anthony
committed
#include "Poco/File.h"
#include "Poco/Path.h"
#include "Poco/Exception.h"
Roman Tolchenov
committed
//DECLARE_WORKSPACE(ManagedRawFileWorkspace2D)
namespace Mantid
{
namespace DataHandling
{
// Get a reference to the logger
Kernel::Logger& ManagedRawFileWorkspace2D::g_log = Kernel::Logger::get("ManagedRawFileWorkspace2D");
Roman Tolchenov
committed
// Initialise the instance count
int ManagedRawFileWorkspace2D::g_uniqueID = 1;
Roman Tolchenov
committed
/// Constructor
ManagedRawFileWorkspace2D::ManagedRawFileWorkspace2D(const std::string& fileName, int opt) :
ManagedWorkspace2D(),
isisRaw(new ISISRAW2),m_filenameRaw(fileName),m_fileRaw(NULL),m_readIndex(0)
Roman Tolchenov
committed
{
Russell Taylor
committed
this->setRawFile(opt);
Roman Tolchenov
committed
}
///Destructor
ManagedRawFileWorkspace2D::~ManagedRawFileWorkspace2D()
{
if (m_fileRaw) fclose(m_fileRaw);
removeTempFile();
Roman Tolchenov
committed
}
/** Sets the RAW file for this workspace.
\param opt Caching option. 0 - cache on local drive if raw file is very slow to read.
1 - cache anyway, 2 - never cache.
Russell Taylor
committed
void ManagedRawFileWorkspace2D::setRawFile(const int opt)
Roman Tolchenov
committed
{
m_fileRaw = fopen(m_filenameRaw.c_str(),"rb");
if (m_fileRaw == NULL)
{
g_log.error("Unable to open file " + m_filenameRaw);
throw Kernel::Exception::FileError("Unable to open File:" , m_filenameRaw);
}
if ( needCache(opt) )
{
openTempFile();
}
isisRaw->ioRAW(m_fileRaw, true);
m_numberOfBinBoundaries = isisRaw->t_ntc1 + 1;
m_numberOfPeriods = isisRaw->t_nper;
initialize(isisRaw->t_nsp1,m_numberOfBinBoundaries,isisRaw->t_ntc1);
int noOfBlocks = m_noVectors / m_vectorsPerBlock;
if ( noOfBlocks * m_vectorsPerBlock != m_noVectors ) ++noOfBlocks;
m_changedBlock.resize(noOfBlocks,false);
isisRaw->skipData(0);
fgetpos(m_fileRaw, &m_data_pos); //< Save the data start position.
Russell Taylor
committed
getTimeChannels();
getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("TOF");
Roman Tolchenov
committed
}
Russell Taylor
committed
/// Constructs the time channel (X) vector(s)
void ManagedRawFileWorkspace2D::getTimeChannels()
Roman Tolchenov
committed
{
Russell Taylor
committed
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
float* const timeChannels = new float[m_numberOfBinBoundaries];
isisRaw->getTimeChannels(timeChannels, m_numberOfBinBoundaries);
const int regimes = isisRaw->daep.n_tr_shift;
if ( regimes >=2 )
{
g_log.debug() << "Raw file contains " << regimes << " time regimes\n";
// If more than 1 regime, create a timeChannelsVec for each regime
for (int i=0; i < regimes; ++i)
{
// Create a vector with the 'base' time channels
boost::shared_ptr<MantidVec> channelsVec(
new MantidVec(timeChannels,timeChannels + m_numberOfBinBoundaries));
const double shift = isisRaw->daep.tr_shift[i];
g_log.debug() << "Time regime " << i+1 << " shifted by " << shift << " microseconds\n";
// Add on the shift for this vector
std::transform(channelsVec->begin(), channelsVec->end(),
channelsVec->begin(), std::bind2nd(std::plus<double>(),shift));
m_timeChannels.push_back(channelsVec);
}
// In this case, also need to populate the map of spectrum-regime correspondence
const int ndet = isisRaw->i_det;
std::map<int,int>::iterator hint = m_specTimeRegimes.begin();
for (int j=0; j < ndet; ++j)
{
// No checking for consistency here - that all detectors for given spectrum
// are declared to use same time regime. Will just use first encountered
hint = m_specTimeRegimes.insert(hint,std::make_pair(isisRaw->spec[j],isisRaw->timr[j]));
}
}
else // Just need one in this case
{
boost::shared_ptr<MantidVec> channelsVec(
new MantidVec(timeChannels,timeChannels + m_numberOfBinBoundaries));
m_timeChannels.push_back(channelsVec);
}
// Done with the timeChannels C array so clean up
delete[] timeChannels;
Roman Tolchenov
committed
}
Russell Taylor
committed
// Pointer to sqrt function (used in calculating errors below)
typedef double (*uf)(double);
static uf dblSqrt = std::sqrt;
Roman Tolchenov
committed
// readData(int) should be changed to readNextSpectrum() returning the spectrum index
// and skipData to skipNextSpectrum()
Roman Tolchenov
committed
void ManagedRawFileWorkspace2D::readDataBlock(DataObjects::ManagedDataBlock2D *newBlock,int startIndex)const
Roman Tolchenov
committed
{
Poco::ScopedLock<Poco::FastMutex> mutex(m_mutex);
if (!m_fileRaw)
{
g_log.error("Raw file was not open.");
throw std::runtime_error("Raw file was not open.");
}
int blockIndex = startIndex / m_vectorsPerBlock;
// Modified data is stored in ManagedWorkspace2D flat file.
if (m_changedBlock[blockIndex])
{
ManagedWorkspace2D::readDataBlock(newBlock,startIndex);
return;
}
if (startIndex > m_readIndex)
{
while(startIndex > m_readIndex)
Roman Tolchenov
committed
{
isisRaw->skipData(m_readIndex+1);// Adding 1 because we dropped the first spectrum.
++m_readIndex;
Roman Tolchenov
committed
}
}
else
{
int nwords = 0;
while(startIndex < m_readIndex)
Roman Tolchenov
committed
{
--m_readIndex;
nwords += 4*isisRaw->ddes[m_readIndex+1].nwords;
Roman Tolchenov
committed
}
if (fseek(m_fileRaw,-nwords,SEEK_CUR) != 0)
Roman Tolchenov
committed
{
fclose(m_fileRaw);
removeTempFile();
g_log.error("Error reading RAW file.");
throw std::runtime_error("ManagedRawFileWorkspace2D: Error reading RAW file.");
Roman Tolchenov
committed
}
}
int endIndex = startIndex+m_vectorsPerBlock < m_noVectors?startIndex+m_vectorsPerBlock:m_noVectors;
if (endIndex >= m_noVectors) endIndex = m_noVectors;
for(int index = startIndex;index<endIndex;index++,m_readIndex++)
{
isisRaw->readData(m_readIndex+1);
MantidVec& y = newBlock->dataY(index);
y.assign(isisRaw->dat1 + 1, isisRaw->dat1 + m_numberOfBinBoundaries);
MantidVec& e = newBlock->dataE(index);
std::transform(y.begin(), y.end(), e.begin(), dblSqrt);
Russell Taylor
committed
if (m_timeChannels.size() == 1)
newBlock->setX(index,m_timeChannels[0]);
else
{
std::map<int,int>::const_iterator regime = m_specTimeRegimes.find(index+1);
if ( regime == m_specTimeRegimes.end() )
{
g_log.error() << "Spectrum " << index << " not present in spec array:\n";
g_log.error(" Assuming time regime of spectrum 1");
regime = m_specTimeRegimes.begin();
}
newBlock->setX(index,m_timeChannels[(*regime).second-1]);
}
}
newBlock->hasChanges(false);
Roman Tolchenov
committed
}
Roman Tolchenov
committed
void ManagedRawFileWorkspace2D::writeDataBlock(DataObjects::ManagedDataBlock2D *toWrite)
Roman Tolchenov
committed
{
Poco::ScopedLock<Poco::FastMutex> mutex(m_mutex);
ManagedWorkspace2D::writeDataBlock(toWrite);
int blockIndex = toWrite->minIndex() / m_vectorsPerBlock;
m_changedBlock[blockIndex] = toWrite->hasChanges();
Roman Tolchenov
committed
}
/**
Decides if the raw file must be copied to a cache file on the local drive to improve reading time.
Roman Tolchenov
committed
*/
Russell Taylor
committed
bool ManagedRawFileWorkspace2D::needCache(const int opt)
Roman Tolchenov
committed
{
if (opt == 1) return true;
if (opt == 2) return false;
Roman Tolchenov
committed
return Kernel::isNetworkDrive(m_filenameRaw);
Roman Tolchenov
committed
}
Roman Tolchenov
committed
/** Opens a temporary file
Roman Tolchenov
committed
void ManagedRawFileWorkspace2D::openTempFile()
{
// Look for the (optional) path from the configuration file
std::string path = Kernel::ConfigService::Instance().getString("ManagedWorkspace.FilePath");
if( path.empty() || !Poco::File(path).exists() || !Poco::File(path).canWrite() )
{
path = Mantid::Kernel::ConfigService::Instance().getBaseDir();
g_log.debug() << "Temporary file written to " << path << std::endl;
}
if ( ( *(path.rbegin()) != '/' ) && ( *(path.rbegin()) != '\\' ) )
{
path.push_back('/');
}
std::stringstream filename;
filename << "WS2D_" << Poco::Path(m_filenameRaw).getBaseName() <<'_'<< ManagedRawFileWorkspace2D::g_uniqueID <<".raw";
// Increment the instance count
++ManagedRawFileWorkspace2D::g_uniqueID;
m_tempfile = path + filename.str();
Poco::File(m_filenameRaw).copyTo(m_tempfile);
FILE *fileRaw = fopen(m_tempfile.c_str(),"rb");
if (fileRaw)
{
fclose(m_fileRaw);
m_fileRaw = fileRaw;
}
Roman Tolchenov
committed
}
Roman Tolchenov
committed
/** Removes the temporary file
Gigg, Martyn Anthony
committed
void ManagedRawFileWorkspace2D::removeTempFile() const
Roman Tolchenov
committed
{
Gigg, Martyn Anthony
committed
if (!m_tempfile.empty()) Poco::File(m_tempfile).remove();
Roman Tolchenov
committed
}
} // namespace DataHandling
} //NamespaceMantid