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"
#include <cstdio>
Roman Tolchenov
committed
#include <boost/timer.hpp>
#include <Poco/File.h>
#include <Poco/Path.h>
#include <Poco/Exception.h>
#include "MantidDataObjects/ManagedHistogram1D.h"
using Mantid::DataObjects::ManagedHistogram1D;
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
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),m_nmonitorSkipCounter(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.
Janik Zikovsky
committed
@param opt :: Caching option. 0 - cache on local drive if raw file is very slow to read.
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);
if ( noOfBlocks * m_vectorsPerBlock != m_noVectors ) ++noOfBlocks;
m_changedBlock.resize(noOfBlocks,false);
fgetpos(m_fileRaw, &m_data_pos); //< Save the data start position.
Russell Taylor
committed
getTimeChannels();
getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("TOF");
Russell Taylor
committed
setYUnit("Counts");
setTitle(std::string(isisRaw->r_title, 80));
Roman Tolchenov
committed
}
Russell Taylor
committed
/// Constructs the time channel (X) vector(s)
void ManagedRawFileWorkspace2D::getTimeChannels()
Roman Tolchenov
committed
{
Russell Taylor
committed
float* const timeChannels = new float[m_numberOfBinBoundaries];
isisRaw->getTimeChannels(timeChannels, static_cast<int>(m_numberOfBinBoundaries));
Russell Taylor
committed
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(),
Gigg, Martyn Anthony
committed
channelsVec->begin(), std::bind2nd(std::plus<double>(),shift));
Russell Taylor
committed
m_timeChannels.push_back(channelsVec);
}
// In this case, also need to populate the map of spectrum-regime correspondence
const int64_t ndet = static_cast<int64_t>(isisRaw->i_det);
std::map<int64_t,int64_t>::iterator hint = m_specTimeRegimes.begin();
for (int64_t j=0; j < ndet; ++j)
Russell Taylor
committed
{
// 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
}
// 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()
void ManagedRawFileWorkspace2D::readDataBlock(DataObjects::ManagedDataBlock2D *newBlock,size_t 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.");
}
int64_t blockIndex = startIndex / m_vectorsPerBlock;
// Modified data is stored in ManagedWorkspace2D flat file.
if (m_changedBlock[blockIndex])
{
ManagedWorkspace2D::readDataBlock(newBlock,startIndex);
return;
}
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
{
while(static_cast<int>(startIndex) > m_readIndex-m_nmonitorSkipCounter)
Gigg, Martyn Anthony
committed
{
isisRaw->skipData(m_fileRaw,m_readIndex+1);// Adding 1 because we dropped the first spectrum.
++m_readIndex;
if(isMonitor(m_readIndex))
++m_nmonitorSkipCounter;
}
}
else
{
int nwords = 0;
while(static_cast<int>(startIndex)+ m_nmonitorSkipCounter+1 < m_readIndex)
Gigg, Martyn Anthony
committed
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
{
if(isMonitor(m_readIndex))
--m_nmonitorSkipCounter;
--m_readIndex;
nwords += 4*isisRaw->ddes[m_readIndex+1].nwords;
}
if (fseek(m_fileRaw,-nwords,SEEK_CUR) != 0)
{
fclose(m_fileRaw);
removeTempFile();
g_log.error("Error reading RAW file.");
throw std::runtime_error("ManagedRawFileWorkspace2D: Error reading RAW file.");
}
}
int64_t endIndex = startIndex+m_vectorsPerBlock < m_noVectors?startIndex+m_vectorsPerBlock:m_noVectors;
if (endIndex >= static_cast<int64_t>(m_noVectors)) endIndex = static_cast<int64_t>(m_noVectors);
int64_t index=startIndex;
while(index<endIndex)
{
if(isMonitor(m_readIndex))
{ isisRaw->skipData(m_fileRaw,m_readIndex+1);
//g_log.error()<<"skipData called for monitor index"<<m_readIndex<<std::endl;
++m_nmonitorSkipCounter;
++m_readIndex;
}
else
{
isisRaw->readData(m_fileRaw,m_readIndex+1);
//g_log.error()<<"readData called for spectrum index"<<m_readIndex<< " and wsIndex is "<<index<< std::endl;
if( m_readIndex == static_cast<int64_t>(m_noVectors+m_monitorList.size()) )
break;
// The managed histogram we are modifying
ManagedHistogram1D * spec = dynamic_cast<ManagedHistogram1D *>(newBlock->getSpectrum(index));
MantidVec& y = spec->directDataY();
Gigg, Martyn Anthony
committed
y.assign(isisRaw->dat1 + 1, isisRaw->dat1 + m_numberOfBinBoundaries);
//g_log.error()<<"readData called for m_readIndex"<<m_readIndex<< " and wsIndex is "<<index<< "Y value at 0 column is "<<y[0]<<std::endl;
MantidVec& e = spec->directDataE();
e.resize(y.size(), 0);
Gigg, Martyn Anthony
committed
std::transform(y.begin(), y.end(), e.begin(), dblSqrt);
if (m_timeChannels.size() == 1)
spec->directSetX(m_timeChannels[0]);
Gigg, Martyn Anthony
committed
else
{
// std::map<int,int>::const_iterator regime = m_specTimeRegimes.find(index+1);
std::map<int64_t,int64_t>::const_iterator regime = m_specTimeRegimes.find(m_readIndex+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();
}
spec->directSetX(m_timeChannels[(*regime).second-1]);
Gigg, Martyn Anthony
committed
}
spec->setLoaded(true);
Gigg, Martyn Anthony
committed
++index;
++m_readIndex;
}
}
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
{
Gigg, Martyn Anthony
committed
{
isisRaw->skipData(m_fileRaw,m_readIndex+1);// Adding 1 because we dropped the first spectrum.
++m_readIndex;
}
}
else
{
int nwords = 0;
Gigg, Martyn Anthony
committed
{
--m_readIndex;
nwords += 4*isisRaw->ddes[m_readIndex+1].nwords;
}
if (fseek(m_fileRaw,-nwords,SEEK_CUR) != 0)
{
fclose(m_fileRaw);
removeTempFile();
g_log.error("Error reading RAW file.");
throw std::runtime_error("ManagedRawFileWorkspace2D: Error reading RAW file.");
}
}
int64_t endIndex = startIndex+m_vectorsPerBlock < m_noVectors?startIndex+m_vectorsPerBlock:m_noVectors;
if (endIndex >= static_cast<int64_t>(m_noVectors)) endIndex = m_noVectors;
Gigg, Martyn Anthony
committed
for(int64_t index = startIndex;index<endIndex;index++,m_readIndex++)
{
isisRaw->readData(m_fileRaw,m_readIndex+1);
// g_log.error()<<"counter is "<<counter<<std::endl;
// The managed histogram we are modifying
ManagedHistogram1D * spec = dynamic_cast<ManagedHistogram1D *>(newBlock->getSpectrum(index));
MantidVec& y = spec->directDataY();
Gigg, Martyn Anthony
committed
y.assign(isisRaw->dat1 + 1, isisRaw->dat1 + m_numberOfBinBoundaries);
MantidVec& e = spec->directDataE();
e.resize(y.size(), 0);
Gigg, Martyn Anthony
committed
std::transform(y.begin(), y.end(), e.begin(), dblSqrt);
if (m_timeChannels.size() == 1)
spec->directSetX(m_timeChannels[0]);
Gigg, Martyn Anthony
committed
else
{
std::map<int64_t,int64_t>::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();
}
spec->directSetX(m_timeChannels[(*regime).second-1]);
Gigg, Martyn Anthony
committed
}
spec->setLoaded(true);
Gigg, Martyn Anthony
committed
}
}
newBlock->hasChanges(false);
newBlock->setLoaded(true);
}
/** This method checks given spectrum is a monitor
* @param readIndex :: a spectrum index
* @return true if it's a monitor ,otherwise false
*/
bool ManagedRawFileWorkspace2D::isMonitor(const specid_t readIndex)const
{
std::vector<specid_t>::const_iterator itr;
for(itr=m_monitorList.begin();itr!=m_monitorList.end();++itr)
{
Gigg, Martyn Anthony
committed
if((*itr)==readIndex)
return true;
Roman Tolchenov
committed
Russell Taylor
committed
void ManagedRawFileWorkspace2D::writeDataBlock(DataObjects::ManagedDataBlock2D *toWrite) const
Roman Tolchenov
committed
{
Poco::ScopedLock<Poco::FastMutex> mutex(m_mutex);
// ManagedWorkspace2D resets the hasChanges flag but we need to make sure we keep track of it here as well
const bool blockHasChanged = toWrite->hasChanges();
ManagedWorkspace2D::writeDataBlock(toWrite);
int blockIndex = static_cast<int>(toWrite->minIndex() / m_vectorsPerBlock);
m_changedBlock[blockIndex] = blockHasChanged;
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
Gigg, Martyn Anthony
committed
return Kernel::ConfigService::Instance().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() )
{
Gigg, Martyn Anthony
committed
path = Mantid::Kernel::ConfigService::Instance().getUserPropertiesDir();
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
}
Gigg, Martyn Anthony
committed
Roman Tolchenov
committed
} // namespace DataHandling
} //NamespaceMantid