6168 lines
207 KiB
C++
6168 lines
207 KiB
C++
/***************************************************************************
|
|
|
|
PRunDataHandler.cpp
|
|
|
|
Author: Andreas Suter
|
|
e-mail: andreas.suter@psi.ch
|
|
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* Copyright (C) 2007-2014 by Andreas Suter *
|
|
* andreas.suter@psi.ch *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
***************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <cstdio>
|
|
#include <ctime>
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <fstream>
|
|
#include <string>
|
|
#include <sstream>
|
|
using namespace std;
|
|
|
|
#include <TROOT.h>
|
|
#include <TSystem.h>
|
|
#include <TString.h>
|
|
#include <TObjArray.h>
|
|
#include <TObjString.h>
|
|
#include <TFile.h>
|
|
#include <TFolder.h>
|
|
#include <TH1F.h>
|
|
#include <TDatime.h>
|
|
|
|
#include "TMusrRunHeader.h"
|
|
#include "TLemRunHeader.h"
|
|
#include "MuSR_td_PSI_bin.h"
|
|
#include "mud.h"
|
|
|
|
#ifdef PNEXUS_ENABLED
|
|
#include "PNeXus.h"
|
|
#endif
|
|
|
|
#include "PRunDataHandler.h"
|
|
|
|
#define PRH_MUSR_ROOT 0
|
|
#define PRH_LEM_ROOT 1
|
|
|
|
#define PRH_NPP_OFFSET 0
|
|
#define PRH_PPC_OFFSET 20
|
|
|
|
#define A2M_UNDEFINED 0
|
|
#define A2M_ROOT 1
|
|
#define A2M_MUSR_ROOT 2
|
|
#define A2M_PSIBIN 3
|
|
#define A2M_PSIMDU 4
|
|
#define A2M_MUD 5
|
|
#define A2M_NEXUS 6
|
|
#define A2M_WKM 7
|
|
#define A2M_ASCII 8
|
|
|
|
#define PHR_INIT_ALL 0
|
|
#define PHR_INIT_MSR 1
|
|
#define PHR_INIT_ANY2MANY 2
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Empty Constructor
|
|
*/
|
|
PRunDataHandler::PRunDataHandler()
|
|
{
|
|
Init();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Constructor which just reads a single muSR data file.
|
|
*
|
|
* \param fileName
|
|
* \param fileFormat
|
|
*/
|
|
PRunDataHandler::PRunDataHandler(TString fileName, const TString fileFormat) : fFileFormat(fileFormat)
|
|
{
|
|
Init();
|
|
|
|
FileExistsCheck(fileName);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Constructor which just reads a single muSR data file.
|
|
*
|
|
* \param fileName
|
|
* \param fileFormat
|
|
* \param dataPath
|
|
*/
|
|
PRunDataHandler::PRunDataHandler(TString fileName, const TString fileFormat, const PStringVector dataPath) : fDataPath(dataPath), fFileFormat(fileFormat)
|
|
{
|
|
Init();
|
|
|
|
FileExistsCheck(fileName);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Constructor which just writes a single muSR data file.
|
|
*
|
|
* \param fileName
|
|
* \param fileFormat
|
|
* \param dataPath
|
|
* \param runData
|
|
*/
|
|
PRunDataHandler::PRunDataHandler(TString fileName, const TString fileFormat, const TString dataPath, PRawRunData &runData)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Constructor, reading the data histogramm files.
|
|
*
|
|
* \param msrInfo pointer to the msr-file handler
|
|
*/
|
|
PRunDataHandler::PRunDataHandler(PAny2ManyInfo *any2ManyInfo) : fAny2ManyInfo(any2ManyInfo)
|
|
{
|
|
Init(PHR_INIT_ANY2MANY);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Constructor, reading the data histogramm files.
|
|
*
|
|
* \param any2ManyInfo pointer to the PAny2ManyInfo structure needed to convert data
|
|
* \param dataPath contains all data search paths.
|
|
*/
|
|
PRunDataHandler::PRunDataHandler(PAny2ManyInfo *any2ManyInfo, const PStringVector dataPath) :
|
|
fAny2ManyInfo(any2ManyInfo), fDataPath(dataPath)
|
|
{
|
|
Init(PHR_INIT_ANY2MANY);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Constructor, reading the data histogramm files.
|
|
*
|
|
* \param msrInfo pointer to the msr-file handler
|
|
*/
|
|
PRunDataHandler::PRunDataHandler(PMsrHandler *msrInfo) : fMsrInfo(msrInfo)
|
|
{
|
|
Init(PHR_INIT_MSR);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Constructor, reading the data histogramm files, and keeping a copy
|
|
* of potential search paths.
|
|
*
|
|
* \param msrInfo pointer to the msr-file handler
|
|
* \param dataPath vector containing search paths where to find raw data files.
|
|
*/
|
|
PRunDataHandler::PRunDataHandler(PMsrHandler *msrInfo, const PStringVector dataPath) :
|
|
fMsrInfo(msrInfo), fDataPath(dataPath)
|
|
{
|
|
Init(PHR_INIT_MSR);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Destructor
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Destructor.
|
|
*/
|
|
PRunDataHandler::~PRunDataHandler()
|
|
{
|
|
fDataPath.clear();
|
|
fData.clear();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// GetRunData
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Checks if runName is found, and if so return these data.
|
|
*
|
|
* <b>return:</b>
|
|
* - if data are found: pointer to the data.
|
|
* - otherwise the null pointer will be returned.
|
|
*
|
|
* \param runName run name, e.g. 2009/lem09_his_1234
|
|
*/
|
|
PRawRunData* PRunDataHandler::GetRunData(const TString &runName)
|
|
{
|
|
UInt_t i;
|
|
|
|
for (i=0; i<fData.size(); i++) {
|
|
if (!fData[i].GetRunName()->CompareTo(runName)) // run found
|
|
break;
|
|
}
|
|
|
|
if (i == fData.size())
|
|
return 0;
|
|
else
|
|
return &fData[i];
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// ReadData
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Read data. Used to read data, either msr-file triggered, or a single
|
|
* explicit data file should be read.
|
|
*/
|
|
void PRunDataHandler::ReadData()
|
|
{
|
|
if (fMsrInfo) { // i.e. msr-file triggered
|
|
if (!ReadFilesMsr()) // couldn't read file
|
|
fAllDataAvailable = false;
|
|
else
|
|
fAllDataAvailable = true;
|
|
} else if (!fRunPathName.IsWhitespace()) { // i.e. file name triggered
|
|
if ((fFileFormat == "MusrRoot") || (fFileFormat == "musrroot")) {
|
|
fAllDataAvailable = ReadRootFile();
|
|
} else if ((fFileFormat == "NeXus") || (fFileFormat == "nexus")) {
|
|
fAllDataAvailable = ReadNexusFile();
|
|
} else if ((fFileFormat == "PsiBin") || (fFileFormat == "psibin")) {
|
|
fAllDataAvailable = ReadPsiBinFile();
|
|
} else if ((fFileFormat == "Mud") || (fFileFormat == "mud")) {
|
|
fAllDataAvailable = ReadMudFile();
|
|
} else if ((fFileFormat == "Wkm") || (fFileFormat == "wkm")) {
|
|
fAllDataAvailable = ReadWkmFile();
|
|
} else {
|
|
cerr << endl << ">> PRunDataHandler::ReadData(): **ERROR** unkown file format \"" << fFileFormat << "\" found." << endl;
|
|
fAllDataAvailable = false;
|
|
}
|
|
} else {
|
|
cerr << endl << ">> PRunDataHandler::ReadData(): **ERROR** Couldn't read files." << endl;
|
|
fAllDataAvailable = false;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// ConvertData
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Read data and convert it. This routine is used by any2many.
|
|
*/
|
|
void PRunDataHandler::ConvertData()
|
|
{
|
|
if (!ReadWriteFilesList()) // couldn't read file
|
|
fAllDataAvailable = false;
|
|
else
|
|
fAllDataAvailable = true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// WriteData
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Write data. This routine is used to write a single file.
|
|
*/
|
|
void PRunDataHandler::WriteData()
|
|
{
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Init (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Common initializer.
|
|
*/
|
|
void PRunDataHandler::Init(const Int_t tag)
|
|
{
|
|
if ((tag==PHR_INIT_ALL) || (tag==PHR_INIT_ANY2MANY))
|
|
fMsrInfo = 0;
|
|
if ((tag==PHR_INIT_ALL) || (tag==PHR_INIT_MSR))
|
|
fAny2ManyInfo = 0;
|
|
fAllDataAvailable = false;
|
|
if (tag!=PHR_INIT_ALL)
|
|
fFileFormat = TString("");
|
|
fRunName = TString("");
|
|
fRunPathName = TString("");
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// ReadFilesMsr (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> The main read file routine which is filtering what read sub-routine
|
|
* needs to be called. Called when the input is a msr-file.
|
|
*
|
|
* <b>return:</b>
|
|
* - true if reading was successful,
|
|
* - false if reading failed.
|
|
*/
|
|
Bool_t PRunDataHandler::ReadFilesMsr()
|
|
{
|
|
Bool_t success = true;
|
|
|
|
// loop over the full RUN list to see what needs to be read
|
|
PMsrRunList *runList = 0;
|
|
runList = fMsrInfo->GetMsrRunList();
|
|
if (runList == 0) {
|
|
cerr << endl << ">> PRunDataHandler::ReadFilesMsr(): **ERROR** Couldn't obtain run list from PMsrHandler: something VERY fishy";
|
|
cerr << endl;
|
|
return false;
|
|
}
|
|
|
|
for (UInt_t i=0; i<runList->size(); i++) {
|
|
for (UInt_t j=0; j<runList->at(i).GetRunNameSize(); j++) {
|
|
fRunName = *(runList->at(i).GetRunName(j));
|
|
// check if file actually exists
|
|
if (!FileExistsCheck(runList->at(i), j))
|
|
return false;
|
|
|
|
// check special case for ROOT-NPP/ROOT-PPC (LEM)
|
|
if (!runList->at(i).GetFileFormat(j)->CompareTo("root-npp")) { // not post pile up corrected histos
|
|
// check if forward/backward histoNo are within proper bounds, i.e. < PRH_PPC_OFFSET
|
|
for (UInt_t k=0; k<runList->at(i).GetForwardHistoNoSize(); k++) {
|
|
if (runList->at(i).GetForwardHistoNo(k) > PRH_PPC_OFFSET)
|
|
runList->at(i).SetForwardHistoNo(runList->at(i).GetForwardHistoNo(k)-PRH_PPC_OFFSET, k);
|
|
}
|
|
for (UInt_t k=0; k<runList->at(i).GetBackwardHistoNoSize(); k++) {
|
|
if (runList->at(i).GetBackwardHistoNo(k) > PRH_PPC_OFFSET)
|
|
runList->at(i).SetBackwardHistoNo(runList->at(i).GetBackwardHistoNo(k)-PRH_PPC_OFFSET, k);
|
|
}
|
|
} else if (!runList->at(i).GetFileFormat(j)->CompareTo("root-ppc")) { // post pile up corrected histos
|
|
// check if forward/backward histoNo are within proper bounds, i.e. > PRH_PPC_OFFSET
|
|
for (UInt_t k=0; k<runList->at(i).GetForwardHistoNoSize(); k++) {
|
|
if (runList->at(i).GetForwardHistoNo(k) < PRH_PPC_OFFSET)
|
|
runList->at(i).SetForwardHistoNo(runList->at(i).GetForwardHistoNo(k)+PRH_PPC_OFFSET, k);
|
|
}
|
|
for (UInt_t k=0; k<runList->at(i).GetBackwardHistoNoSize(); k++) {
|
|
if (runList->at(i).GetBackwardHistoNo(k) < PRH_PPC_OFFSET)
|
|
runList->at(i).SetBackwardHistoNo(runList->at(i).GetBackwardHistoNo(k)+PRH_PPC_OFFSET, k);
|
|
}
|
|
}
|
|
|
|
// check is file is already read
|
|
if (FileAlreadyRead(*(runList->at(i).GetRunName(j))))
|
|
continue;
|
|
// everything looks fine, hence try to read the data file
|
|
if (!runList->at(i).GetFileFormat(j)->CompareTo("root-npp")) { // not post pile up corrected histos
|
|
success = ReadRootFile();
|
|
} else if (!runList->at(i).GetFileFormat(j)->CompareTo("root-ppc")) { // post pile up corrected histos
|
|
success = ReadRootFile();
|
|
} else if (!runList->at(i).GetFileFormat(j)->CompareTo("musr-root")) { // MusrRoot style file
|
|
success = ReadRootFile();
|
|
} else if (!runList->at(i).GetFileFormat(j)->CompareTo("nexus")) {
|
|
success = ReadNexusFile();
|
|
} else if (!runList->at(i).GetFileFormat(j)->CompareTo("psi-bin")) {
|
|
success = ReadPsiBinFile();
|
|
} else if (!runList->at(i).GetFileFormat(j)->CompareTo("psi-mdu")) {
|
|
success = ReadPsiBinFile();
|
|
} else if (!runList->at(i).GetFileFormat(j)->CompareTo("mud")) {
|
|
success = ReadMudFile();
|
|
} else if (!runList->at(i).GetFileFormat(j)->CompareTo("wkm")) {
|
|
success = ReadWkmFile();
|
|
} else if (!runList->at(i).GetFileFormat(j)->CompareTo("mdu-ascii")) {
|
|
success = ReadMduAsciiFile();
|
|
} else if (!runList->at(i).GetFileFormat(j)->CompareTo("ascii")) {
|
|
success = ReadAsciiFile();
|
|
} else if (!runList->at(i).GetFileFormat(j)->CompareTo("db")) {
|
|
success = ReadDBFile();
|
|
} else {
|
|
success = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// ReadWriteFilesList (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> The main read file routine which is filtering what read sub-routine
|
|
* needs to be called. Called when the input is a list of runs. Used with
|
|
* any2many. If the input data file is successfully read, it will write the
|
|
* converted data file.
|
|
*
|
|
* <b>return:</b>
|
|
* - true if reading was successful,
|
|
* - false if reading failed.
|
|
*/
|
|
Bool_t PRunDataHandler::ReadWriteFilesList()
|
|
{
|
|
if ((fAny2ManyInfo->inFileName.size() == 0) && (fAny2ManyInfo->runList.size() == 0)) {
|
|
cerr << endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't obtain run list from fAny2ManyInfo: something VERY fishy";
|
|
cerr << endl;
|
|
return false;
|
|
}
|
|
|
|
// get input file format tag
|
|
Int_t inTag = A2M_UNDEFINED;
|
|
if (!fAny2ManyInfo->inFormat.CompareTo("root", TString::kIgnoreCase))
|
|
inTag = A2M_ROOT;
|
|
else if (!fAny2ManyInfo->inFormat.CompareTo("musrroot", TString::kIgnoreCase))
|
|
inTag = A2M_MUSR_ROOT;
|
|
else if (!fAny2ManyInfo->inFormat.CompareTo("psi-bin", TString::kIgnoreCase))
|
|
inTag = A2M_PSIBIN;
|
|
else if (!fAny2ManyInfo->inFormat.CompareTo("psi-mdu", TString::kIgnoreCase))
|
|
inTag = A2M_PSIMDU;
|
|
else if (!fAny2ManyInfo->inFormat.CompareTo("mud", TString::kIgnoreCase))
|
|
inTag = A2M_MUD;
|
|
else if (!fAny2ManyInfo->inFormat.CompareTo("nexus", TString::kIgnoreCase))
|
|
inTag = A2M_NEXUS;
|
|
else if (!fAny2ManyInfo->inFormat.CompareTo("wkm", TString::kIgnoreCase))
|
|
inTag = A2M_WKM;
|
|
else
|
|
inTag = A2M_UNDEFINED;
|
|
|
|
if (inTag == A2M_UNDEFINED) {
|
|
cerr << endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** no valid input data file format found: '" << fAny2ManyInfo->inFormat.Data() << "'" << endl;
|
|
return false;
|
|
}
|
|
|
|
// get output file format tag
|
|
Int_t outTag = A2M_UNDEFINED;
|
|
if (!fAny2ManyInfo->outFormat.CompareTo("root", TString::kIgnoreCase))
|
|
outTag = A2M_ROOT;
|
|
else if (!fAny2ManyInfo->outFormat.CompareTo("musrroot", TString::kIgnoreCase))
|
|
outTag = A2M_MUSR_ROOT;
|
|
else if (!fAny2ManyInfo->outFormat.CompareTo("psi-bin", TString::kIgnoreCase))
|
|
outTag = A2M_PSIBIN;
|
|
else if (!fAny2ManyInfo->outFormat.CompareTo("mud",TString::kIgnoreCase))
|
|
outTag = A2M_MUD;
|
|
else if (fAny2ManyInfo->outFormat.BeginsWith("nexus", TString::kIgnoreCase))
|
|
outTag = A2M_NEXUS;
|
|
else if (!fAny2ManyInfo->outFormat.CompareTo("wkm", TString::kIgnoreCase))
|
|
outTag = A2M_WKM;
|
|
else if (!fAny2ManyInfo->outFormat.CompareTo("ascii", TString::kIgnoreCase))
|
|
outTag = A2M_ASCII;
|
|
else
|
|
outTag = A2M_UNDEFINED;
|
|
|
|
if (outTag == A2M_UNDEFINED) {
|
|
cerr << endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** no valid output data file format found: '" << fAny2ManyInfo->outFormat.Data() << "'" << endl;
|
|
return false;
|
|
}
|
|
|
|
if (fAny2ManyInfo->inFileName.size() != 0) { // file name list given
|
|
|
|
// loop over all runs of the run list
|
|
for (UInt_t i=0; i<fAny2ManyInfo->inFileName.size(); i++) {
|
|
if (!FileExistsCheck(true, i)) {
|
|
cerr << endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't find file " << fAny2ManyInfo->inFileName[i].Data() << endl;
|
|
return false;
|
|
}
|
|
|
|
// read input file
|
|
Bool_t success = false;
|
|
switch (inTag) {
|
|
case A2M_ROOT:
|
|
case A2M_MUSR_ROOT:
|
|
success = ReadRootFile();
|
|
break;
|
|
case A2M_PSIBIN:
|
|
case A2M_PSIMDU:
|
|
success = ReadPsiBinFile();
|
|
break;
|
|
case A2M_NEXUS:
|
|
success = ReadNexusFile();
|
|
break;
|
|
case A2M_MUD:
|
|
success = ReadMudFile();
|
|
break;
|
|
case A2M_WKM:
|
|
success = ReadWkmFile();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (!success) {
|
|
cerr << endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't read file " << fAny2ManyInfo->inFileName[i].Data() << endl;
|
|
return false;
|
|
}
|
|
|
|
// write 'converted' output data file
|
|
success = false;
|
|
switch (outTag) {
|
|
case A2M_ROOT:
|
|
if (fAny2ManyInfo->outFileName.Length() == 0)
|
|
success = WriteRootFile();
|
|
else
|
|
success = WriteRootFile(fAny2ManyInfo->outFileName);
|
|
break;
|
|
case A2M_MUSR_ROOT:
|
|
if (fAny2ManyInfo->outFileName.Length() == 0)
|
|
success = WriteMusrRootFile();
|
|
else
|
|
success = WriteMusrRootFile(fAny2ManyInfo->outFileName);
|
|
break;
|
|
break;
|
|
case A2M_PSIBIN:
|
|
if (fAny2ManyInfo->outFileName.Length() == 0)
|
|
success = WritePsiBinFile();
|
|
else
|
|
success = WritePsiBinFile(fAny2ManyInfo->outFileName);
|
|
break;
|
|
case A2M_PSIMDU:
|
|
if (fAny2ManyInfo->outFileName.Length() == 0)
|
|
success = WritePsiBinFile();
|
|
else
|
|
success = WritePsiBinFile(fAny2ManyInfo->outFileName);
|
|
break;
|
|
case A2M_NEXUS:
|
|
if (fAny2ManyInfo->outFileName.Length() == 0)
|
|
success = WriteNexusFile();
|
|
else
|
|
success = WriteNexusFile(fAny2ManyInfo->outFileName);
|
|
break;
|
|
case A2M_MUD:
|
|
if (fAny2ManyInfo->outFileName.Length() == 0)
|
|
success = WriteMudFile();
|
|
else
|
|
success = WriteMudFile(fAny2ManyInfo->outFileName);
|
|
break;
|
|
case A2M_WKM:
|
|
if (fAny2ManyInfo->outFileName.Length() == 0)
|
|
success = WriteWkmFile();
|
|
else
|
|
success = WriteWkmFile(fAny2ManyInfo->outFileName);
|
|
break;
|
|
case A2M_ASCII:
|
|
if (fAny2ManyInfo->outFileName.Length() == 0)
|
|
success = WriteAsciiFile();
|
|
else
|
|
success = WriteAsciiFile(fAny2ManyInfo->outFileName);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (success == false) {
|
|
cerr << endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't write converted output file." << endl;
|
|
return false;
|
|
}
|
|
|
|
// throw away the current data set
|
|
fData.clear();
|
|
}
|
|
}
|
|
|
|
if (fAny2ManyInfo->runList.size() != 0) { // run list given
|
|
|
|
// loop over all runs of the run list
|
|
for (UInt_t i=0; i<fAny2ManyInfo->runList.size(); i++) {
|
|
if (!FileExistsCheck(false, i)) {
|
|
cerr << endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't find run " << fAny2ManyInfo->runList[i] << endl;
|
|
return false;
|
|
}
|
|
|
|
// read input file
|
|
Bool_t success = false;
|
|
switch (inTag) {
|
|
case A2M_ROOT:
|
|
case A2M_MUSR_ROOT:
|
|
success = ReadRootFile();
|
|
break;
|
|
case A2M_PSIBIN:
|
|
case A2M_PSIMDU:
|
|
success = ReadPsiBinFile();
|
|
break;
|
|
case A2M_NEXUS:
|
|
success = ReadNexusFile();
|
|
break;
|
|
case A2M_MUD:
|
|
success = ReadMudFile();
|
|
break;
|
|
case A2M_WKM:
|
|
success = ReadWkmFile();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (!success) {
|
|
cerr << endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't read file " << fRunPathName.Data() << endl;
|
|
return false;
|
|
}
|
|
|
|
TString year("");
|
|
TDatime dt;
|
|
year += dt.GetYear();
|
|
if (fAny2ManyInfo->year.Length() > 0)
|
|
year = fAny2ManyInfo->year;
|
|
Bool_t ok;
|
|
TString fln = FileNameFromTemplate(fAny2ManyInfo->outTemplate, fAny2ManyInfo->runList[i], year, ok);
|
|
if (!ok) {
|
|
cerr << endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't create necessary output file name." << endl;
|
|
return false;
|
|
}
|
|
|
|
// write 'converted' output data file
|
|
success = false;
|
|
switch (outTag) {
|
|
case A2M_ROOT:
|
|
success = WriteRootFile(fln);
|
|
break;
|
|
case A2M_MUSR_ROOT:
|
|
success = WriteMusrRootFile(fln);
|
|
break;
|
|
case A2M_PSIBIN:
|
|
success = WritePsiBinFile(fln);
|
|
break;
|
|
case A2M_PSIMDU:
|
|
success = WritePsiBinFile(fln);
|
|
break;
|
|
case A2M_NEXUS:
|
|
success = WriteNexusFile(fln);
|
|
break;
|
|
case A2M_MUD:
|
|
success = WriteMudFile(fln);
|
|
break;
|
|
case A2M_WKM:
|
|
success = WriteWkmFile(fln);
|
|
break;
|
|
case A2M_ASCII:
|
|
success = WriteAsciiFile(fln);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (success == false) {
|
|
cerr << endl << ">> PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't write converted output file." << endl;
|
|
return false;
|
|
}
|
|
|
|
// throw away the current data set
|
|
fData.clear();
|
|
}
|
|
|
|
}
|
|
|
|
// check if compression is wished
|
|
if (fAny2ManyInfo->compressionTag > 0) {
|
|
TString fln = fAny2ManyInfo->outPath + fAny2ManyInfo->compressFileName;
|
|
|
|
// currently system call is used, which means this is only running under Linux and Mac OS X but not under Windows
|
|
char cmd[256];
|
|
if (fAny2ManyInfo->outPathFileName.size() == 1) {
|
|
if (fAny2ManyInfo->compressionTag == 1) // gzip
|
|
fln += TString(".tar.gz");
|
|
else // bzip2
|
|
fln += TString(".tar.bz2");
|
|
if (fAny2ManyInfo->compressionTag == 1) // gzip
|
|
sprintf(cmd, "tar -zcf %s %s", fln.Data(), fAny2ManyInfo->outPathFileName[0].Data());
|
|
else // bzip2
|
|
sprintf(cmd, "tar -jcf %s %s", fln.Data(), fAny2ManyInfo->outPathFileName[0].Data());
|
|
system(cmd);
|
|
} else {
|
|
fln += TString(".tar");
|
|
for (UInt_t i=0; i<fAny2ManyInfo->outPathFileName.size(); i++) {
|
|
if (i==0) {
|
|
sprintf(cmd, "tar -cf %s %s", fln.Data(), fAny2ManyInfo->outPathFileName[i].Data());
|
|
} else {
|
|
sprintf(cmd, "tar -rf %s %s", fln.Data(), fAny2ManyInfo->outPathFileName[i].Data());
|
|
}
|
|
system(cmd);
|
|
}
|
|
if (fAny2ManyInfo->compressionTag == 1) { // gzip
|
|
sprintf(cmd, "gzip %s", fln.Data());
|
|
fln += ".gz";
|
|
} else {
|
|
sprintf(cmd, "bzip2 -z %s", fln.Data());
|
|
fln += ".bz2";
|
|
}
|
|
system(cmd);
|
|
}
|
|
|
|
// check if the compressed file shall be streamed to the stdout
|
|
if (fAny2ManyInfo->useStandardOutput) {
|
|
// stream file to stdout
|
|
ifstream is;
|
|
int length=1024;
|
|
char *buffer;
|
|
|
|
is.open(fln.Data(), ios::binary);
|
|
if (!is.is_open()) {
|
|
cerr << endl << "PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't open the file for streaming." << endl;
|
|
remove(fln.Data());
|
|
return false;
|
|
}
|
|
|
|
// get length of file
|
|
is.seekg(0, ios::end);
|
|
length = is.tellg();
|
|
is.seekg(0, ios::beg);
|
|
|
|
if (length == -1) {
|
|
cerr << endl << "PRunDataHandler::ReadWriteFilesList(): **ERROR** Couldn't determine the file size." << endl;
|
|
remove(fln.Data());
|
|
return false;
|
|
}
|
|
|
|
// allocate memory
|
|
buffer = new char [length];
|
|
|
|
// read data as a block
|
|
while (!is.eof()) {
|
|
is.read(buffer, length);
|
|
cout.write(buffer, length);
|
|
}
|
|
|
|
is.close();
|
|
|
|
delete [] buffer;
|
|
|
|
// delete temporary root file
|
|
remove(fln.Data());
|
|
}
|
|
|
|
// remove all the converted files
|
|
for (UInt_t i=0; i<fAny2ManyInfo->outPathFileName.size(); i++)
|
|
remove(fAny2ManyInfo->outPathFileName[i].Data());
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// FileAlreadyRead (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Checks if a file has been already read in order to prevent multiple
|
|
* reading of data files.
|
|
*
|
|
* <b>return:</b>
|
|
* - true if the file has been read before,
|
|
* - otherwise false.
|
|
*
|
|
* \param runName run name to be check if the corresponding file is already read.
|
|
*/
|
|
Bool_t PRunDataHandler::FileAlreadyRead(TString runName)
|
|
{
|
|
for (UInt_t i=0; i<fData.size(); i++) {
|
|
if (!fData[i].GetRunName()->CompareTo(runName)) { // run alread read
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// TestFileName (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Tests if a file exists (with or without given extension).
|
|
* The given file-name string will be modified to show the found file name or an empty string if no file is found.
|
|
*
|
|
* \param runName run name with full path to be checked
|
|
* \param ext extension to be checked
|
|
*/
|
|
void PRunDataHandler::TestFileName(TString &runName, const TString &ext)
|
|
{
|
|
TString tmpStr(runName), tmpExt(ext);
|
|
|
|
// check first if the file exists with the default extension which is not given with the run name
|
|
tmpStr += TString(".") + ext;
|
|
if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
|
|
runName = tmpStr;
|
|
return;
|
|
}
|
|
|
|
// test if the file exists with the given run name but an only upper-case extension which is not included in the file name
|
|
tmpStr = runName;
|
|
tmpExt.ToUpper();
|
|
tmpStr += TString(".") + tmpExt;
|
|
if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
|
|
runName = tmpStr;
|
|
return;
|
|
}
|
|
|
|
// test if the file exists with the given run name but an only lower-case extension which is not included in the file name
|
|
tmpStr = runName;
|
|
tmpExt.ToLower();
|
|
tmpStr += TString(".") + tmpExt;
|
|
if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
|
|
runName = tmpStr;
|
|
return;
|
|
}
|
|
|
|
// test if the file exists with only upper-case letters
|
|
tmpStr = runName + TString(".") + tmpExt;
|
|
tmpStr.ToUpper();
|
|
if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
|
|
runName = tmpStr;
|
|
return;
|
|
}
|
|
|
|
// test if the file exists with only lower-case letters
|
|
tmpStr.ToLower();
|
|
if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
|
|
runName = tmpStr;
|
|
return;
|
|
}
|
|
|
|
tmpStr = runName;
|
|
|
|
// the extension is already part of the file name, therefore, do not append it
|
|
if (tmpStr.EndsWith(ext.Data(), TString::kIgnoreCase)) {
|
|
if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
|
|
runName = tmpStr;
|
|
return;
|
|
}
|
|
|
|
// assume some extension is part of the given file name but the real data file ends with an lower-case extension
|
|
tmpExt.ToLower();
|
|
tmpStr = tmpStr.Replace(static_cast<Ssiz_t>(tmpStr.Length()-tmpExt.Length()), tmpExt.Length(), tmpExt);
|
|
if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
|
|
runName = tmpStr;
|
|
return;
|
|
}
|
|
|
|
// assume some extension is part of the given file name but the real data file ends with an upper-case extension
|
|
tmpExt.ToUpper();
|
|
tmpStr = runName;
|
|
tmpStr = tmpStr.Replace(static_cast<Ssiz_t>(tmpStr.Length()-tmpExt.Length()), tmpExt.Length(), tmpExt);
|
|
if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
|
|
runName = tmpStr;
|
|
return;
|
|
}
|
|
|
|
// test if the file exists with only lower-case letters and the extension already included in the file name
|
|
tmpStr = runName;
|
|
tmpStr.ToLower();
|
|
if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
|
|
runName = tmpStr;
|
|
return;
|
|
}
|
|
|
|
// test if the file exists with only upper-case letters and the extension already included in the file name
|
|
tmpStr = runName;
|
|
tmpStr.ToUpper();
|
|
if (gSystem->AccessPathName(tmpStr.Data()) != true) { // found
|
|
runName = tmpStr;
|
|
return;
|
|
}
|
|
}
|
|
|
|
// if the file has not been found, set the run name to be empty
|
|
runName = "";
|
|
|
|
return;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// FileExistsCheck (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Checks if a given data file exists.
|
|
*
|
|
* <b>return:</b>
|
|
* - true if data file exists,
|
|
* - otherwise false.
|
|
*
|
|
* \param runInfo reference to the msr-run-structure
|
|
* \param idx index of the run (needed for ADDRUN feature).
|
|
*/
|
|
Bool_t PRunDataHandler::FileExistsCheck(PMsrRunBlock &runInfo, const UInt_t idx)
|
|
{
|
|
Bool_t success = true;
|
|
|
|
// local init
|
|
TROOT root("PRunBase", "PRunBase", 0);
|
|
TString pathName = "???";
|
|
TString str, *pstr;
|
|
TString ext;
|
|
|
|
pstr = runInfo.GetBeamline(idx);
|
|
if (pstr == 0) {
|
|
cerr << endl << ">> PRunDataHandler::FileExistsCheck: **ERROR** Couldn't obtain beamline data." << endl;
|
|
assert(0);
|
|
}
|
|
pstr->ToLower();
|
|
runInfo.SetBeamline(*pstr, idx);
|
|
pstr = runInfo.GetInstitute(idx);
|
|
if (pstr == 0) {
|
|
cerr << endl << ">> PRunDataHandler::FileExistsCheck: **ERROR** Couldn't obtain institute data." << endl;
|
|
assert(0);
|
|
}
|
|
pstr->ToLower();
|
|
runInfo.SetInstitute(*pstr, idx);
|
|
pstr = runInfo.GetFileFormat(idx);
|
|
if (pstr == 0) {
|
|
cerr << endl << ">> PRunDataHandler::FileExistsCheck: **ERROR** Couldn't obtain file format data." << endl;
|
|
assert(0);
|
|
}
|
|
pstr->ToLower();
|
|
runInfo.SetFileFormat(*pstr, idx);
|
|
|
|
// file extensions for the various formats
|
|
if (!runInfo.GetFileFormat(idx)->CompareTo("root-npp")) // not post pile up corrected histos
|
|
ext = TString("root");
|
|
else if (!runInfo.GetFileFormat(idx)->CompareTo("root-ppc")) // post pile up corrected histos
|
|
ext = TString("root");
|
|
else if (!runInfo.GetFileFormat(idx)->CompareTo("musr-root")) // post pile up corrected histos
|
|
ext = TString("root");
|
|
else if (!runInfo.GetFileFormat(idx)->CompareTo("nexus"))
|
|
ext = TString("NXS");
|
|
else if (!runInfo.GetFileFormat(idx)->CompareTo("psi-bin"))
|
|
ext = TString("bin");
|
|
else if (!runInfo.GetFileFormat(idx)->CompareTo("psi-mdu"))
|
|
ext = TString("mdu");
|
|
else if (!runInfo.GetFileFormat(idx)->CompareTo("mud"))
|
|
ext = TString("msr");
|
|
else if (!runInfo.GetFileFormat(idx)->CompareTo("wkm")) {
|
|
if (!runInfo.GetBeamline(idx)->CompareTo("mue4"))
|
|
ext = TString("nemu");
|
|
else
|
|
ext = *runInfo.GetBeamline(idx);
|
|
}
|
|
else if (!runInfo.GetFileFormat(idx)->CompareTo("mdu-ascii"))
|
|
ext = TString("mdua");
|
|
else if (!runInfo.GetFileFormat(idx)->CompareTo("ascii"))
|
|
ext = TString("dat");
|
|
else if (!runInfo.GetFileFormat(idx)->CompareTo("db"))
|
|
ext = TString("db");
|
|
else
|
|
success = false;
|
|
|
|
// unkown file format found
|
|
if (!success) {
|
|
pstr = runInfo.GetFileFormat(idx);
|
|
if (pstr == 0) {
|
|
cerr << endl << ">> PRunDataHandler::FileExistsCheck: **ERROR** Couldn't obtain file format data." << endl;
|
|
assert(0);
|
|
}
|
|
pstr->ToUpper();
|
|
cerr << endl << ">> PRunDataHandler::FileExistsCheck: **ERROR** File Format '" << pstr->Data() << "' unsupported.";
|
|
cerr << endl << ">> support file formats are:";
|
|
cerr << endl << ">> ROOT-NPP -> root not post pileup corrected for lem";
|
|
cerr << endl << ">> ROOT-PPC -> root post pileup corrected for lem";
|
|
cerr << endl << ">> MUSR-ROOT -> MusrRoot file format";
|
|
cerr << endl << ">> NEXUS -> nexus file format, HDF4, HDF5, or XML";
|
|
cerr << endl << ">> PSI-BIN -> psi bin file format";
|
|
cerr << endl << ">> PSI-MDU -> psi mdu file format (see also MDU-ASCII)";
|
|
cerr << endl << ">> MUD -> triumf mud file format";
|
|
cerr << endl << ">> WKM -> wkm ascii file format";
|
|
cerr << endl << ">> MDU-ASCII -> psi mdu ascii file format";
|
|
cerr << endl << ">> ASCII -> column like file format";
|
|
cerr << endl << ">> DB -> triumf db file \"format\"";
|
|
cerr << endl;
|
|
return success;
|
|
}
|
|
|
|
// check if the file is in the local directory
|
|
str = *runInfo.GetRunName(idx);
|
|
TestFileName(str, ext);
|
|
if (!str.IsNull()) {
|
|
pathName = str;
|
|
}
|
|
|
|
// check if the file is found in the <msr-file-directory>
|
|
if (pathName.CompareTo("???") == 0) { // not found in local directory search
|
|
str = *fMsrInfo->GetMsrFileDirectoryPath() + *runInfo.GetRunName(idx);
|
|
TestFileName(str, ext);
|
|
if (!str.IsNull()) {
|
|
pathName = str;
|
|
}
|
|
}
|
|
|
|
// check if the file is found in the directory given in the startup file
|
|
if (pathName.CompareTo("???") == 0) { // not found in local directory search and not found in the <msr-file-directory> search
|
|
for (UInt_t i=0; i<fDataPath.size(); i++) {
|
|
str = fDataPath[i] + TString("/") + *runInfo.GetRunName(idx);
|
|
TestFileName(str, ext);
|
|
if (!str.IsNull()) {
|
|
pathName = str;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// check if the file is found in the directories given by MUSRFULLDATAPATH
|
|
const Char_t *musrpath = gSystem->Getenv("MUSRFULLDATAPATH");
|
|
if (pathName.CompareTo("???") == 0) { // not found in local directory and xml path
|
|
str = TString(musrpath);
|
|
// MUSRFULLDATAPATH has the structure: path_1:path_2:...:path_n
|
|
TObjArray *tokens = str.Tokenize(":");
|
|
TObjString *ostr;
|
|
for (Int_t i=0; i<tokens->GetEntries(); i++) {
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(i));
|
|
str = ostr->GetString() + TString("/") + *runInfo.GetRunName(idx);
|
|
TestFileName(str, ext);
|
|
if (!str.IsNull()) {
|
|
pathName = str;
|
|
break;
|
|
}
|
|
}
|
|
// cleanup
|
|
if (tokens) {
|
|
delete tokens;
|
|
tokens = 0;
|
|
}
|
|
}
|
|
|
|
// check if the file is found in the generated default path
|
|
if (pathName.CompareTo("???") == 0) { // not found in MUSRFULLDATAPATH search
|
|
str = TString(musrpath);
|
|
// MUSRFULLDATAPATH has the structure: path_1:path_2:...:path_n
|
|
TObjArray *tokens = str.Tokenize(":");
|
|
TObjString *ostr;
|
|
pstr = runInfo.GetInstitute(idx);
|
|
if (pstr == 0) {
|
|
cerr << endl << ">> PRunDataHandler::FileExistsCheck: **ERROR** Couldn't obtain institute data." << endl;
|
|
assert(0);
|
|
}
|
|
pstr->ToUpper();
|
|
runInfo.SetInstitute(*pstr, idx);
|
|
pstr = runInfo.GetBeamline(idx);
|
|
if (pstr == 0) {
|
|
cerr << endl << ">> PRunDataHandler::FileExistsCheck: **ERROR** Couldn't obtain beamline data." << endl;
|
|
assert(0);
|
|
}
|
|
pstr->ToUpper();
|
|
runInfo.SetBeamline(*pstr, idx);
|
|
for (Int_t i=0; i<tokens->GetEntries(); i++) {
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(i));
|
|
str = ostr->GetString() + TString("/DATA/") +
|
|
*runInfo.GetInstitute(idx) + TString("/") +
|
|
*runInfo.GetBeamline(idx) + TString("/") +
|
|
*runInfo.GetRunName(idx);
|
|
TestFileName(str, ext);
|
|
if (!str.IsNull()) { // found
|
|
pathName = str;
|
|
break;
|
|
}
|
|
}
|
|
// clean up
|
|
if (tokens) {
|
|
delete tokens;
|
|
tokens = 0;
|
|
}
|
|
}
|
|
|
|
// no proper path name found
|
|
if (pathName.CompareTo("???") == 0) {
|
|
cerr << endl << ">> PRunDataHandler::FileExistsCheck(): **ERROR** Couldn't find '" << runInfo.GetRunName(idx)->Data() << "' in any standard path.";
|
|
cerr << endl << ">> standard search pathes are:";
|
|
cerr << endl << ">> 1. the local directory";
|
|
cerr << endl << ">> 2. the data directory given in the startup XML file";
|
|
cerr << endl << ">> 3. the directories listed in MUSRFULLDATAPATH";
|
|
cerr << endl << ">> 4. default path construct which is described in the manual";
|
|
return false;
|
|
}
|
|
|
|
fRunPathName = pathName;
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// FileExistsCheck (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Checks if a given data file exists. Used for the any2many program.
|
|
*
|
|
* <b>return:</b>
|
|
* - true if data file exists,
|
|
* - otherwise false.
|
|
*
|
|
* \param fileName flag showing if a file name shall be handled or a run number
|
|
* \param idx index of the run. idx == -1 means that a single input data file name is given.
|
|
*/
|
|
Bool_t PRunDataHandler::FileExistsCheck(const Bool_t fileName, const Int_t idx)
|
|
{
|
|
TString pathName("???");
|
|
TString str("");
|
|
TString fln("");
|
|
|
|
if (fileName) { // single input file name
|
|
if (idx >= (Int_t)fAny2ManyInfo->inFileName.size()) {
|
|
cerr << endl << ">> PRunDataHandler::FileExistsCheck(): **ERROR** idx=" << idx << " out of range. (inFileName.size()==" << fAny2ManyInfo->inFileName.size() << ")" << endl;
|
|
return false;
|
|
}
|
|
fln = fAny2ManyInfo->inFileName[idx];
|
|
} else { // run file list entry shall be handled
|
|
if (idx >= (Int_t)fAny2ManyInfo->runList.size()) {
|
|
cerr << endl << ">> PRunDataHandler::FileExistsCheck(): **ERROR** idx=" << idx << " out of range. (inFileName.size()==" << fAny2ManyInfo->runList.size() << ")" << endl;
|
|
return false;
|
|
}
|
|
// check for input/output templates
|
|
if ((fAny2ManyInfo->inTemplate.Length() == 0) || (fAny2ManyInfo->outTemplate.Length() == 0)) {
|
|
cerr << endl << ">> PRunDataHandler::FileExistsCheck(): **ERROR** when using run lists, input/output templates are needed as well." << endl;
|
|
return false;
|
|
}
|
|
// make the input file name according to the input template
|
|
TString year("");
|
|
TDatime dt;
|
|
year += dt.GetYear();
|
|
if (fAny2ManyInfo->year.Length() > 0)
|
|
year = fAny2ManyInfo->year;
|
|
Bool_t ok;
|
|
fln = FileNameFromTemplate(fAny2ManyInfo->inTemplate, fAny2ManyInfo->runList[idx], year, ok);
|
|
if (!ok)
|
|
return false;
|
|
}
|
|
|
|
// check if the file is in the local directory
|
|
if (gSystem->AccessPathName(fln) != true) { // found in the local dir
|
|
pathName = fln;
|
|
}
|
|
// check if the file is found in the directory given in the startup file
|
|
if (pathName.CompareTo("???") == 0) { // not found in local directory search
|
|
for (UInt_t i=0; i<fDataPath.size(); i++) {
|
|
str = fDataPath[i] + TString("/") + fln;
|
|
if (gSystem->AccessPathName(str.Data())!=true) { // found
|
|
pathName = str;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// check if the file is found in the directories given by MUSRFULLDATAPATH
|
|
const Char_t *musrpath = gSystem->Getenv("MUSRFULLDATAPATH");
|
|
if (pathName.CompareTo("???") == 0) { // not found in local directory and xml path
|
|
str = TString(musrpath);
|
|
// MUSRFULLDATAPATH has the structure: path_1:path_2:...:path_n
|
|
TObjArray *tokens = str.Tokenize(":");
|
|
TObjString *ostr;
|
|
for (Int_t i=0; i<tokens->GetEntries(); i++) {
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(i));
|
|
str = ostr->GetString() + TString("/") + fln;
|
|
if (gSystem->AccessPathName(str.Data())!=true) { // found
|
|
pathName = str;
|
|
break;
|
|
}
|
|
}
|
|
// cleanup
|
|
if (tokens) {
|
|
delete tokens;
|
|
tokens = 0;
|
|
}
|
|
}
|
|
// no proper path name found
|
|
if (pathName.CompareTo("???") == 0) {
|
|
cerr << endl << ">> PRunDataHandler::FileExistsCheck(): **ERROR** Couldn't find '" << fln.Data() << "' in any standard path.";
|
|
cerr << endl << ">> standard search pathes are:";
|
|
cerr << endl << ">> 1. the local directory";
|
|
cerr << endl << ">> 2. the data directory given in the startup XML file";
|
|
cerr << endl << ">> 3. the directories listed in MUSRFULLDATAPATH";
|
|
return false;
|
|
}
|
|
|
|
fRunPathName = pathName;
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// FileExistsCheck (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Checks if a given data file exists. Used for the any2many program.
|
|
*
|
|
* <b>return:</b>
|
|
* - true if data file exists,
|
|
* - otherwise false.
|
|
*
|
|
* \param fileName file name
|
|
*/
|
|
Bool_t PRunDataHandler::FileExistsCheck(const TString fileName)
|
|
{
|
|
TString pathName("???");
|
|
TString str("");
|
|
|
|
// check if the file is in the local directory
|
|
if (gSystem->AccessPathName(fileName) != true) { // found in the local dir
|
|
pathName = fileName;
|
|
}
|
|
// check if the file is found in the directory given in the startup file
|
|
if (pathName.CompareTo("???") == 0) { // not found in local directory search
|
|
for (UInt_t i=0; i<fDataPath.size(); i++) {
|
|
str = fDataPath[i] + TString("/") + fileName;
|
|
if (gSystem->AccessPathName(str.Data())!=true) { // found
|
|
pathName = str;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// check if the file is found in the directories given by MUSRFULLDATAPATH
|
|
const Char_t *musrpath = gSystem->Getenv("MUSRFULLDATAPATH");
|
|
if (pathName.CompareTo("???") == 0) { // not found in local directory and xml path
|
|
str = TString(musrpath);
|
|
// MUSRFULLDATAPATH has the structure: path_1:path_2:...:path_n
|
|
TObjArray *tokens = str.Tokenize(":");
|
|
TObjString *ostr;
|
|
for (Int_t i=0; i<tokens->GetEntries(); i++) {
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(i));
|
|
str = ostr->GetString() + TString("/") + fileName;
|
|
if (gSystem->AccessPathName(str.Data())!=true) { // found
|
|
pathName = str;
|
|
break;
|
|
}
|
|
}
|
|
// cleanup
|
|
if (tokens) {
|
|
delete tokens;
|
|
tokens = 0;
|
|
}
|
|
}
|
|
// no proper path name found
|
|
if (pathName.CompareTo("???") == 0) {
|
|
cerr << endl << ">> PRunDataHandler::FileExistsCheck(): **ERROR** Couldn't find '" << fileName.Data() << "' in any standard path.";
|
|
cerr << endl << ">> standard search pathes are:";
|
|
cerr << endl << ">> 1. the local directory";
|
|
cerr << endl << ">> 2. the data directory given in the startup XML file";
|
|
cerr << endl << ">> 3. the directories listed in MUSRFULLDATAPATH";
|
|
return false;
|
|
}
|
|
|
|
fRunPathName = pathName;
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// ReadRootFile (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Reads both, the "old" LEM-data ROOT-files with TLemRunHeader, and the more general
|
|
* new MusrRoot file.
|
|
*
|
|
* <b>return:</b>
|
|
* - true at successful reading,
|
|
* - otherwise false.
|
|
*/
|
|
Bool_t PRunDataHandler::ReadRootFile()
|
|
{
|
|
PDoubleVector histoData;
|
|
PRawRunData runData;
|
|
PRawRunDataSet dataSet;
|
|
|
|
TFile f(fRunPathName.Data());
|
|
if (f.IsZombie()) {
|
|
return false;
|
|
}
|
|
|
|
UInt_t fileType = PRH_MUSR_ROOT;
|
|
|
|
TFolder *folder;
|
|
f.GetObject("RunInfo", folder); // try first LEM-ROOT style file (used until 2011).
|
|
if (!folder) { // either something is wrong, or it is a MusrRoot file
|
|
f.GetObject("RunHeader", folder);
|
|
if (!folder) { // something is wrong!!
|
|
cerr << endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't neither obtain RunInfo (LEM),";
|
|
cerr << endl << " nor RunHeader (MusrRoot) from " << fRunPathName.Data() << endl;
|
|
f.Close();
|
|
return false;
|
|
} else {
|
|
fileType = PRH_MUSR_ROOT;
|
|
}
|
|
} else {
|
|
fileType = PRH_LEM_ROOT;
|
|
}
|
|
|
|
if (fileType == PRH_LEM_ROOT) {
|
|
// read header and check if some missing run info need to be fed
|
|
TLemRunHeader *runHeader = dynamic_cast<TLemRunHeader*>(folder->FindObjectAny("TLemRunHeader"));
|
|
|
|
// check if run header is valid
|
|
if (!runHeader) {
|
|
cerr << endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't obtain run header info from ROOT file " << fRunPathName.Data() << endl;
|
|
f.Close();
|
|
return false;
|
|
}
|
|
|
|
// set laboratory / beamline / instrument
|
|
runData.SetLaboratory("PSI");
|
|
runData.SetBeamline("muE4");
|
|
runData.SetInstrument("LEM");
|
|
runData.SetMuonSource("low energy muon source");
|
|
runData.SetMuonSpecies("positive muons");
|
|
|
|
// get run title
|
|
TObjString ostr = runHeader->GetRunTitle();
|
|
runData.SetRunTitle(ostr.GetString());
|
|
|
|
// get run number
|
|
runData.SetRunNumber((Int_t)runHeader->GetRunNumber());
|
|
|
|
// get temperature
|
|
runData.ClearTemperature();
|
|
runData.SetTemperature(0, runHeader->GetSampleTemperature(), runHeader->GetSampleTemperatureError());
|
|
|
|
// get field
|
|
runData.SetField(runHeader->GetSampleBField());
|
|
|
|
// get implantation energy
|
|
runData.SetEnergy(runHeader->GetImpEnergy());
|
|
|
|
// get moderator HV
|
|
runData.SetTransport(runHeader->GetModeratorHV());
|
|
|
|
// get setup
|
|
runData.SetSetup(runHeader->GetLemSetup().GetString());
|
|
|
|
// get start time/date
|
|
// start date
|
|
time_t idt = (time_t)runHeader->GetStartTime();
|
|
runData.SetStartDateTime(idt);
|
|
struct tm *dt = localtime(&idt);
|
|
char str[128];
|
|
strftime(str, sizeof(str), "%F", dt);
|
|
TString stime(str);
|
|
runData.SetStartDate(stime);
|
|
// start time
|
|
memset(str, 0, sizeof(str));
|
|
strftime(str, sizeof(str), "%T", dt);
|
|
stime = str;
|
|
runData.SetStartTime(stime);
|
|
|
|
// get stop time/date
|
|
// stop date
|
|
idt = (time_t)runHeader->GetStopTime();
|
|
runData.SetStopDateTime(idt);
|
|
dt = localtime(&idt);
|
|
memset(str, 0, sizeof(str));
|
|
strftime(str, sizeof(str), "%F", dt);
|
|
stime = str;
|
|
runData.SetStopDate(stime);
|
|
// stop time
|
|
memset(str, 0, sizeof(str));
|
|
strftime(str, sizeof(str), "%T", dt);
|
|
stime = str;
|
|
runData.SetStopTime(stime);
|
|
|
|
// get time resolution
|
|
runData.SetTimeResolution(runHeader->GetTimeResolution());
|
|
|
|
// get number of histogramms
|
|
Int_t noOfHistos = runHeader->GetNHist();
|
|
|
|
// get t0's there will be handled together with the data
|
|
Double_t *t0 = runHeader->GetTimeZero();
|
|
|
|
// read run summary to obtain ring anode HV values
|
|
TObjArray *runSummary = dynamic_cast<TObjArray*>(folder->FindObjectAny("RunSummary"));
|
|
|
|
// check if run summary is valid
|
|
if (!runSummary) {
|
|
cout << endl << "**INFO** Couldn't obtain run summary info from ROOT file " << fRunPathName.Data() << endl;
|
|
// this is not fatal... only RA-HV values are not available
|
|
} else { // it follows a (at least) little bit strange extraction of the RA values from Thomas' TObjArray...
|
|
//streaming of a ASCII-file would be more easy
|
|
TString s;
|
|
TObjArrayIter summIter(runSummary);
|
|
TObjString *os(dynamic_cast<TObjString*>(summIter.Next()));
|
|
TObjArray *oa(0);
|
|
TObjString *objTok(0);
|
|
while (os != 0) {
|
|
s = os->GetString();
|
|
// will put four parallel if's since it may be that more than one RA-values are on one line
|
|
if (s.Contains("RA-L")) {
|
|
oa = s.Tokenize(" ");
|
|
TObjArrayIter lineIter(oa);
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next());
|
|
while (objTok != 0) {
|
|
if (!objTok->GetString().CompareTo("RA-L")) {
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // "="
|
|
if (objTok != 0 && !objTok->GetString().CompareTo("=")) {
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // HV value
|
|
runData.SetRingAnode(0, objTok->GetString().Atof()); // fill RA-R value into the runData structure
|
|
break;
|
|
}
|
|
}
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // next token...
|
|
}
|
|
// clean up
|
|
if (oa) {
|
|
delete oa;
|
|
oa = 0;
|
|
}
|
|
}
|
|
|
|
if (s.Contains("RA-R")) {
|
|
oa = s.Tokenize(" ");
|
|
TObjArrayIter lineIter(oa);
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next());
|
|
while (objTok != 0){
|
|
if (!objTok->GetString().CompareTo("RA-R")) {
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // "="
|
|
if (objTok != 0 && !objTok->GetString().CompareTo("=")) {
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // HV value
|
|
runData.SetRingAnode(1, objTok->GetString().Atof()); // fill RA-R value into the runData structure
|
|
break;
|
|
}
|
|
}
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // next token...
|
|
}
|
|
// clean up
|
|
if (oa) {
|
|
delete oa;
|
|
oa = 0;
|
|
}
|
|
}
|
|
|
|
if (s.Contains("RA-T")) {
|
|
oa = s.Tokenize(" ");
|
|
TObjArrayIter lineIter(oa);
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next());
|
|
while (objTok != 0){
|
|
if (!objTok->GetString().CompareTo("RA-T")) {
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // "="
|
|
if (objTok != 0 && !objTok->GetString().CompareTo("=")) {
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // HV value
|
|
runData.SetRingAnode(2, objTok->GetString().Atof()); // fill RA-T value into the runData structure
|
|
break;
|
|
}
|
|
}
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // next token...
|
|
}
|
|
// clean up
|
|
if (oa) {
|
|
delete oa;
|
|
oa = 0;
|
|
}
|
|
}
|
|
|
|
if (s.Contains("RA-B")) {
|
|
oa = s.Tokenize(" ");
|
|
TObjArrayIter lineIter(oa);
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next());
|
|
while (objTok != 0){
|
|
if (!objTok->GetString().CompareTo("RA-B")) {
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // "="
|
|
if (objTok != 0 && !objTok->GetString().CompareTo("=")) {
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // HV value
|
|
runData.SetRingAnode(3, objTok->GetString().Atof()); // fill RA-B value into the runData structure
|
|
break;
|
|
}
|
|
}
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // next token...
|
|
}
|
|
// clean up
|
|
if (oa) {
|
|
delete oa;
|
|
oa = 0;
|
|
}
|
|
}
|
|
|
|
os = dynamic_cast<TObjString*>(summIter.Next()); // next summary line...
|
|
}
|
|
}
|
|
|
|
// read data ---------------------------------------------------------
|
|
|
|
// check if histos folder is found
|
|
f.GetObject("histos", folder);
|
|
if (!folder) {
|
|
cerr << endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't obtain histos from " << fRunPathName.Data() << endl;
|
|
f.Close();
|
|
return false;
|
|
}
|
|
|
|
// get all the data
|
|
Char_t histoName[32];
|
|
for (Int_t i=0; i<noOfHistos; i++) {
|
|
sprintf(histoName, "hDecay%02d", i);
|
|
TH1F *histo = dynamic_cast<TH1F*>(folder->FindObjectAny(histoName));
|
|
if (!histo) {
|
|
cerr << endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't get histo " << histoName;
|
|
cerr << endl;
|
|
f.Close();
|
|
return false;
|
|
}
|
|
|
|
// fill data
|
|
for (Int_t j=1; j<=histo->GetNbinsX(); j++) {
|
|
histoData.push_back(histo->GetBinContent(j));
|
|
}
|
|
|
|
// fill the data set
|
|
dataSet.Clear();
|
|
dataSet.SetName(histo->GetTitle());
|
|
dataSet.SetHistoNo(i+1);
|
|
dataSet.SetTimeZeroBin(t0[i]);
|
|
dataSet.SetTimeZeroBinEstimated(histo->GetMaximumBin());
|
|
dataSet.SetFirstGoodBin((Int_t)t0[i]);
|
|
dataSet.SetLastGoodBin(histo->GetNbinsX()-1);
|
|
dataSet.SetData(histoData);
|
|
runData.SetDataSet(dataSet);
|
|
|
|
// clear histoData for the next histo
|
|
histoData.clear();
|
|
}
|
|
// check if any post pileup histos are present at all (this is not the case for LEM data 2006 and earlier)
|
|
sprintf(histoName, "hDecay%02d", POST_PILEUP_HISTO_OFFSET);
|
|
if (!folder->FindObjectAny(histoName)) {
|
|
cerr << endl << ">> PRunDataHandler::ReadRootFile: **WARNING** Couldn't get histo " << histoName;
|
|
cerr << endl << ">> most probably this is an old (2006 or earlier) LEM file without post pileup histos.";
|
|
cerr << endl;
|
|
} else {
|
|
for (Int_t i=0; i<noOfHistos; i++) {
|
|
sprintf(histoName, "hDecay%02d", i+POST_PILEUP_HISTO_OFFSET);
|
|
TH1F *histo = dynamic_cast<TH1F*>(folder->FindObjectAny(histoName));
|
|
if (!histo) {
|
|
cerr << endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't get histo " << histoName;
|
|
cerr << endl;
|
|
f.Close();
|
|
return false;
|
|
}
|
|
|
|
// fill data
|
|
for (Int_t j=1; j<=histo->GetNbinsX(); j++)
|
|
histoData.push_back(histo->GetBinContent(j));
|
|
|
|
// fill the data set
|
|
dataSet.Clear();
|
|
dataSet.SetName(histo->GetTitle());
|
|
dataSet.SetHistoNo(i+1+POST_PILEUP_HISTO_OFFSET);
|
|
dataSet.SetTimeZeroBin(t0[i]);
|
|
dataSet.SetTimeZeroBinEstimated(histo->GetMaximumBin());
|
|
dataSet.SetFirstGoodBin((Int_t)t0[i]);
|
|
dataSet.SetLastGoodBin(histo->GetNbinsX()-1);
|
|
dataSet.SetData(histoData);
|
|
runData.SetDataSet(dataSet);
|
|
|
|
// clear histoData for the next histo
|
|
histoData.clear();
|
|
}
|
|
}
|
|
} else { // MusrRoot file
|
|
// invoke the MusrRoot header object
|
|
TMusrRunHeader *header = new TMusrRunHeader(true); // read quite
|
|
if (header == 0) {
|
|
cerr << endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't invoke MusrRoot RunHeader in file:" << fRunPathName;
|
|
cerr << endl;
|
|
f.Close();
|
|
return false;
|
|
}
|
|
|
|
// try to populate the MusrRoot header object
|
|
if (!header->ExtractAll(folder)) {
|
|
cerr << endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't invoke MusrRoot RunHeader in file:" << fRunPathName;
|
|
cerr << endl;
|
|
f.Close();
|
|
return false;
|
|
}
|
|
|
|
// get all the header information
|
|
Bool_t ok;
|
|
TString str, path, pathName;
|
|
Int_t ival, noOfHistos=0;
|
|
Double_t dval;
|
|
TMusrRunPhysicalQuantity prop;
|
|
PIntVector ivec, redGreenOffsets;
|
|
|
|
header->Get("RunInfo/Version", str, ok);
|
|
if (ok)
|
|
runData.SetVersion(str);
|
|
|
|
header->Get("RunInfo/Generic Validator URL", str, ok);
|
|
if (ok)
|
|
runData.SetGenericValidatorUrl(str);
|
|
|
|
header->Get("RunInfo/Specific Validator URL", str, ok);
|
|
if (ok)
|
|
runData.SetSpecificValidatorUrl(str);
|
|
|
|
header->Get("RunInfo/Generator", str, ok);
|
|
if (ok)
|
|
runData.SetGenerator(str);
|
|
|
|
header->Get("RunInfo/File Name", str, ok);
|
|
if (ok)
|
|
runData.SetFileName(str);
|
|
|
|
header->Get("RunInfo/Run Title", str, ok);
|
|
if (ok)
|
|
runData.SetRunTitle(str);
|
|
|
|
header->Get("RunInfo/Run Number", ival, ok);
|
|
if (ok)
|
|
runData.SetRunNumber(ival);
|
|
|
|
header->Get("RunInfo/Run Start Time", str, ok);
|
|
if (ok) {
|
|
Ssiz_t pos = str.Index(' ');
|
|
TString substr = str;
|
|
substr.Remove(pos, str.Length());
|
|
runData.SetStartDate(substr);
|
|
substr = str;
|
|
substr.Remove(0, pos+1);
|
|
runData.SetStartTime(substr);
|
|
}
|
|
|
|
header->Get("RunInfo/Run Stop Time", str, ok);
|
|
if (ok) {
|
|
Ssiz_t pos = str.Index(' ');
|
|
TString substr = str;
|
|
substr.Remove(pos, str.Length());
|
|
runData.SetStopDate(substr);
|
|
substr = str;
|
|
substr.Remove(0, pos+1);
|
|
runData.SetStopTime(substr);
|
|
}
|
|
|
|
header->Get("RunInfo/Laboratory", str, ok);
|
|
if (ok)
|
|
runData.SetLaboratory(str);
|
|
|
|
header->Get("RunInfo/Instrument", str, ok);
|
|
if (ok)
|
|
runData.SetInstrument(str);
|
|
|
|
header->Get("RunInfo/Muon Beam Momentum", prop, ok);
|
|
if (ok) {
|
|
if (!prop.GetUnit().CompareTo("MeV/c"))
|
|
runData.SetMuonBeamMomentum(prop.GetValue());
|
|
}
|
|
|
|
header->Get("RunInfo/Muon Species", str, ok);
|
|
if (ok)
|
|
runData.SetMuonSpecies(str);
|
|
|
|
header->Get("RunInfo/Muon Source", str, ok);
|
|
if (ok)
|
|
runData.SetMuonSource(str);
|
|
|
|
header->Get("RunInfo/Muon Spin Angle", prop, ok);
|
|
if (ok) {
|
|
runData.SetMuonSpinAngle(prop.GetValue());
|
|
}
|
|
|
|
header->Get("RunInfo/Setup", str, ok);
|
|
if (ok)
|
|
runData.SetSetup(str);
|
|
|
|
header->Get("RunInfo/Comment", str, ok);
|
|
if (ok)
|
|
runData.SetComment(str);
|
|
|
|
header->Get("RunInfo/Sample Name", str, ok);
|
|
if (ok)
|
|
runData.SetSample(str);
|
|
|
|
header->Get("RunInfo/Sample Temperature", prop, ok);
|
|
if (ok)
|
|
runData.SetTemperature(0, prop.GetValue(), prop.GetError());
|
|
|
|
header->Get("RunInfo/Sample Magnetic Field", prop, ok);
|
|
if (ok) {
|
|
dval = MRH_UNDEFINED;
|
|
if (!prop.GetUnit().CompareTo("G") || !prop.GetUnit().CompareTo("Gauss"))
|
|
dval = prop.GetValue();
|
|
else if (!prop.GetUnit().CompareTo("T") || !prop.GetUnit().CompareTo("Tesla"))
|
|
dval = prop.GetValue() * 1.0e4;
|
|
runData.SetField(dval);
|
|
}
|
|
|
|
header->Get("RunInfo/No of Histos", ival, ok);
|
|
if (ok) {
|
|
noOfHistos = ival;
|
|
}
|
|
|
|
header->Get("RunInfo/Time Resolution", prop, ok);
|
|
if (ok) {
|
|
dval = -1.0;
|
|
if (!prop.GetUnit().CompareTo("ps") || !prop.GetUnit().CompareTo("picosec"))
|
|
dval = prop.GetValue()/1.0e3;
|
|
else if (!prop.GetUnit().CompareTo("ns") || !prop.GetUnit().CompareTo("nanosec"))
|
|
dval = prop.GetValue();
|
|
else if (!prop.GetUnit().CompareTo("us") || !prop.GetUnit().CompareTo("microsec"))
|
|
dval = prop.GetValue()*1.0e3;
|
|
else
|
|
cerr << endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Found unrecognized Time Resolution unit: " << prop.GetUnit() << endl;
|
|
runData.SetTimeResolution(dval);
|
|
}
|
|
|
|
header->Get("RunInfo/RedGreen Offsets", ivec, ok);
|
|
if (ok) {
|
|
redGreenOffsets = ivec;
|
|
runData.SetRedGreenOffset(ivec);
|
|
}
|
|
|
|
// check further for LEM specific stuff in RunInfo
|
|
|
|
header->Get("RunInfo/Moderator HV", prop, ok);
|
|
if (ok)
|
|
runData.SetTransport(prop.GetValue());
|
|
|
|
header->Get("RunInfo/Implantation Energy", prop, ok);
|
|
if (ok)
|
|
runData.SetEnergy(prop.GetValue());
|
|
|
|
// read the SampleEnvironmentInfo
|
|
|
|
header->Get("SampleEnvironmentInfo/Cryo", str, ok);
|
|
if (ok)
|
|
runData.SetCryoName(str);
|
|
|
|
// read the MagneticFieldEnvironmentInfo
|
|
|
|
header->Get("MagneticFieldEnvironmentInfo/Magnet Name", str, ok);
|
|
if (ok)
|
|
runData.SetMagnetName(str);
|
|
|
|
// read the BeamlineInfo
|
|
|
|
header->Get("BeamlineInfo/Name", str, ok);
|
|
if (ok)
|
|
runData.SetBeamline(str);
|
|
|
|
// read run summary to obtain ring anode HV values
|
|
TObjArray *runSummary = dynamic_cast<TObjArray*>(folder->FindObjectAny("RunSummary"));
|
|
|
|
// check if run summary is valid
|
|
if (!runSummary) {
|
|
cout << endl << "**INFO** Couldn't obtain run summary info from ROOT file " << fRunPathName.Data() << endl;
|
|
// this is not fatal... only RA-HV values are not available
|
|
} else { // it follows a (at least) little bit strange extraction of the RA values from Thomas' TObjArray...
|
|
//streaming of a ASCII-file would be more easy
|
|
TString s;
|
|
TObjArrayIter summIter(runSummary);
|
|
TObjString *os(dynamic_cast<TObjString*>(summIter.Next()));
|
|
TObjArray *oa(0);
|
|
TObjString *objTok(0);
|
|
while (os != 0) {
|
|
s = os->GetString();
|
|
// will put four parallel if's since it may be that more than one RA-values are on one line
|
|
if (s.Contains("RA-L")) {
|
|
oa = s.Tokenize(" ");
|
|
TObjArrayIter lineIter(oa);
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next());
|
|
while (objTok != 0) {
|
|
if (!objTok->GetString().CompareTo("RA-L")) {
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // "="
|
|
if (objTok != 0 && !objTok->GetString().CompareTo("=")) {
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // HV value
|
|
runData.SetRingAnode(0, objTok->GetString().Atof()); // fill RA-R value into the runData structure
|
|
break;
|
|
}
|
|
}
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // next token...
|
|
}
|
|
// clean up
|
|
if (oa) {
|
|
delete oa;
|
|
oa = 0;
|
|
}
|
|
}
|
|
|
|
if (s.Contains("RA-R")) {
|
|
oa = s.Tokenize(" ");
|
|
TObjArrayIter lineIter(oa);
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next());
|
|
while (objTok != 0){
|
|
if (!objTok->GetString().CompareTo("RA-R")) {
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // "="
|
|
if (objTok != 0 && !objTok->GetString().CompareTo("=")) {
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // HV value
|
|
runData.SetRingAnode(1, objTok->GetString().Atof()); // fill RA-R value into the runData structure
|
|
break;
|
|
}
|
|
}
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // next token...
|
|
}
|
|
// clean up
|
|
if (oa) {
|
|
delete oa;
|
|
oa = 0;
|
|
}
|
|
}
|
|
|
|
if (s.Contains("RA-T")) {
|
|
oa = s.Tokenize(" ");
|
|
TObjArrayIter lineIter(oa);
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next());
|
|
while (objTok != 0){
|
|
if (!objTok->GetString().CompareTo("RA-T")) {
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // "="
|
|
if (objTok != 0 && !objTok->GetString().CompareTo("=")) {
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // HV value
|
|
runData.SetRingAnode(2, objTok->GetString().Atof()); // fill RA-T value into the runData structure
|
|
break;
|
|
}
|
|
}
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // next token...
|
|
}
|
|
// clean up
|
|
if (oa) {
|
|
delete oa;
|
|
oa = 0;
|
|
}
|
|
}
|
|
|
|
if (s.Contains("RA-B")) {
|
|
oa = s.Tokenize(" ");
|
|
TObjArrayIter lineIter(oa);
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next());
|
|
while (objTok != 0){
|
|
if (!objTok->GetString().CompareTo("RA-B")) {
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // "="
|
|
if (objTok != 0 && !objTok->GetString().CompareTo("=")) {
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // HV value
|
|
runData.SetRingAnode(3, objTok->GetString().Atof()); // fill RA-B value into the runData structure
|
|
break;
|
|
}
|
|
}
|
|
objTok = dynamic_cast<TObjString*>(lineIter.Next()); // next token...
|
|
}
|
|
// clean up
|
|
if (oa) {
|
|
delete oa;
|
|
oa = 0;
|
|
}
|
|
}
|
|
|
|
os = dynamic_cast<TObjString*>(summIter.Next()); // next summary line...
|
|
}
|
|
}
|
|
|
|
// read data ---------------------------------------------------------
|
|
|
|
// check if histos folder is found
|
|
f.GetObject("histos", folder);
|
|
if (!folder) {
|
|
cerr << endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't obtain histos from " << fRunPathName.Data() << endl;
|
|
f.Close();
|
|
return false;
|
|
}
|
|
|
|
// get all the data
|
|
for (UInt_t i=0; i<redGreenOffsets.size(); i++) {
|
|
for (Int_t j=0; j<noOfHistos; j++) {
|
|
str.Form("hDecay%03d", redGreenOffsets[i]+j+1);
|
|
TH1F *histo = dynamic_cast<TH1F*>(folder->FindObjectAny(str.Data()));
|
|
if (!histo) {
|
|
cerr << endl << ">> PRunDataHandler::ReadRootFile: **ERROR** Couldn't get histo " << str;
|
|
cerr << endl;
|
|
f.Close();
|
|
return false;
|
|
}
|
|
|
|
dataSet.Clear();
|
|
dataSet.SetName(histo->GetTitle());
|
|
dataSet.SetHistoNo(redGreenOffsets[i]+j+1);
|
|
|
|
// get detector info
|
|
path.Form("DetectorInfo/Detector%03d/", redGreenOffsets[i]+j+1);
|
|
pathName = path + "Time Zero Bin";
|
|
header->Get(pathName, dval, ok);
|
|
if (ok)
|
|
dataSet.SetTimeZeroBin(dval);
|
|
pathName = path + "First Good Bin";
|
|
header->Get(pathName, ival, ok);
|
|
if (ok)
|
|
dataSet.SetFirstGoodBin(ival);
|
|
pathName = path + "Last Good Bin";
|
|
header->Get(pathName, ival, ok);
|
|
if (ok)
|
|
dataSet.SetLastGoodBin(ival);
|
|
dataSet.SetTimeZeroBinEstimated(histo->GetMaximumBin());
|
|
|
|
// fill data
|
|
for (Int_t j=1; j<=histo->GetNbinsX(); j++) {
|
|
histoData.push_back(histo->GetBinContent(j));
|
|
}
|
|
dataSet.SetData(histoData);
|
|
runData.SetDataSet(dataSet);
|
|
|
|
// clear histoData for the next histo
|
|
histoData.clear();
|
|
}
|
|
}
|
|
|
|
// clean up
|
|
if (header) {
|
|
delete header;
|
|
header=0;
|
|
}
|
|
}
|
|
|
|
f.Close();
|
|
|
|
// keep run name
|
|
runData.SetRunName(fRunName);
|
|
|
|
// add run to the run list
|
|
fData.push_back(runData);
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// ReadNexusFile (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Will read the NeXuS File Format as soon as PSI will have an implementation.
|
|
*
|
|
* <b>return:</b>
|
|
* - true at successful reading,
|
|
* - otherwise false.
|
|
*/
|
|
Bool_t PRunDataHandler::ReadNexusFile()
|
|
{
|
|
#ifdef PNEXUS_ENABLED
|
|
cout << endl << ">> PRunDataHandler::ReadNexusFile(): Will read nexus file " << fRunPathName.Data() << " ...";
|
|
|
|
PDoubleVector histoData;
|
|
PRawRunData runData;
|
|
PRawRunDataSet dataSet;
|
|
TString str;
|
|
string sstr;
|
|
Double_t dval;
|
|
bool ok;
|
|
|
|
PNeXus *nxs_file = new PNeXus(fRunPathName.Data());
|
|
if (!nxs_file->IsValid()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadNexusFile(): Not a valid NeXus file.";
|
|
cerr << endl << ">> Error Message: " << nxs_file->GetErrorMsg().data() << endl;
|
|
return false;
|
|
}
|
|
|
|
if (nxs_file->GetIdfVersion() == 1) {
|
|
if (!nxs_file->IsValid()) {
|
|
cout << endl << "**ERROR** invalid NeXus IDF 2 version file found." << endl;
|
|
return false;
|
|
}
|
|
|
|
// get header information
|
|
|
|
// get/set laboratory
|
|
str = TString(nxs_file->GetEntryIdf1()->GetLaboratory());
|
|
runData.SetLaboratory(str);
|
|
|
|
// get/set beamline
|
|
str = TString(nxs_file->GetEntryIdf1()->GetBeamline());
|
|
runData.SetBeamline(str);
|
|
|
|
// get/set instrument
|
|
str = TString(nxs_file->GetEntryIdf1()->GetInstrument()->GetName());
|
|
runData.SetInstrument(str);
|
|
|
|
// get/set run title
|
|
str = TString(nxs_file->GetEntryIdf1()->GetTitle());
|
|
runData.SetRunTitle(str);
|
|
|
|
// get/set run number
|
|
runData.SetRunNumber(nxs_file->GetEntryIdf1()->GetRunNumber());
|
|
|
|
// get/set temperature
|
|
dval = nxs_file->GetEntryIdf1()->GetSample()->GetPhysPropValue("temperature", ok);
|
|
if (ok)
|
|
runData.SetTemperature(0, dval, 0.0);
|
|
|
|
// get/set field
|
|
dval = nxs_file->GetEntryIdf1()->GetSample()->GetPhysPropValue("magnetic_field", ok);
|
|
nxs_file->GetEntryIdf1()->GetSample()->GetPhysPropUnit("magnetic_field", sstr, ok);
|
|
str = sstr;
|
|
// since field has to be given in Gauss, check the units
|
|
Double_t factor=1.0;
|
|
if (!str.CompareTo("gauss", TString::kIgnoreCase))
|
|
factor=1.0;
|
|
else if (!str.CompareTo("tesla", TString::kIgnoreCase))
|
|
factor=1.0e4;
|
|
else
|
|
factor=1.0;
|
|
runData.SetField(factor*dval);
|
|
|
|
// get/set implantation energy
|
|
runData.SetEnergy(PMUSR_UNDEFINED);
|
|
|
|
// get/set moderator HV
|
|
runData.SetTransport(PMUSR_UNDEFINED);
|
|
|
|
// get/set RA HV's (LEM specific)
|
|
for (UInt_t i=0; i<4; i++)
|
|
runData.SetRingAnode(i, PMUSR_UNDEFINED);
|
|
|
|
// get/set setup
|
|
runData.SetSetup(nxs_file->GetEntryIdf1()->GetNotes());
|
|
|
|
// get/set sample
|
|
runData.SetSample(nxs_file->GetEntryIdf1()->GetSample()->GetName());
|
|
|
|
// get/set orientation
|
|
runData.SetOrientation("??");
|
|
|
|
// get/set time resolution (ns)
|
|
runData.SetTimeResolution(nxs_file->GetEntryIdf1()->GetData()->GetTimeResolution("ns"));
|
|
|
|
// get/set start/stop time
|
|
sstr = nxs_file->GetEntryIdf1()->GetStartTime();
|
|
str = sstr;
|
|
TString date, time;
|
|
SplitTimeDate(str, time, date, ok);
|
|
if (ok) {
|
|
runData.SetStartTime(time);
|
|
runData.SetStartDate(date);
|
|
}
|
|
|
|
sstr = nxs_file->GetEntryIdf1()->GetStopTime();
|
|
str = sstr;
|
|
SplitTimeDate(str, time, date, ok);
|
|
if (ok) {
|
|
runData.SetStopTime(time);
|
|
runData.SetStopDate(date);
|
|
}
|
|
|
|
// get/set t0, firstGoodBin, lastGoodBin
|
|
vector<unsigned int> *t0 = nxs_file->GetEntryIdf1()->GetData()->GetT0s();
|
|
vector<unsigned int> *fgb = nxs_file->GetEntryIdf1()->GetData()->GetFirstGoodBins();
|
|
vector<unsigned int> *lgb = nxs_file->GetEntryIdf1()->GetData()->GetLastGoodBins();
|
|
|
|
// get/set data
|
|
vector<unsigned int> *pdata;
|
|
unsigned int max=0, binMax=0;
|
|
PDoubleVector data;
|
|
for (UInt_t i=0; i<nxs_file->GetEntryIdf1()->GetData()->GetNoOfHistos(); i++) {
|
|
pdata = nxs_file->GetEntryIdf1()->GetData()->GetHisto(i);
|
|
for (UInt_t j=0; j<pdata->size(); j++) {
|
|
data.push_back(pdata->at(j));
|
|
if (pdata->at(j) > max) {
|
|
max = pdata->at(j);
|
|
binMax = j;
|
|
}
|
|
}
|
|
|
|
// fill data set
|
|
dataSet.Clear();
|
|
dataSet.SetHistoNo(i+1); // i.e. histo numbers start with 1
|
|
// set time zero bin
|
|
if (i<t0->size())
|
|
dataSet.SetTimeZeroBin(t0->at(i));
|
|
else
|
|
dataSet.SetTimeZeroBin(t0->at(0));
|
|
// set time zero bin estimate
|
|
dataSet.SetTimeZeroBinEstimated(binMax);
|
|
// set first good bin
|
|
if (i<fgb->size())
|
|
dataSet.SetFirstGoodBin(fgb->at(i));
|
|
else
|
|
dataSet.SetFirstGoodBin(fgb->at(0));
|
|
// set last good bin
|
|
if (i<lgb->size())
|
|
dataSet.SetFirstGoodBin(lgb->at(i));
|
|
else
|
|
dataSet.SetFirstGoodBin(lgb->at(0));
|
|
dataSet.SetData(data);
|
|
|
|
runData.SetDataSet(dataSet);
|
|
data.clear();
|
|
}
|
|
|
|
// keep run name from the msr-file
|
|
runData.SetRunName(fRunName);
|
|
|
|
// keep the information
|
|
fData.push_back(runData);
|
|
} else if (nxs_file->GetIdfVersion() == 2) {
|
|
if (!nxs_file->IsValid()) {
|
|
cout << endl << "**ERROR** invalid NeXus IDF 2 version file found." << endl;
|
|
return false;
|
|
}
|
|
// get header information
|
|
|
|
// get/set laboratory
|
|
str = TString(nxs_file->GetEntryIdf2()->GetInstrument()->GetSource()->GetName());
|
|
runData.SetLaboratory(str);
|
|
|
|
// get/set beamline
|
|
str = TString(nxs_file->GetEntryIdf2()->GetInstrument()->GetName());
|
|
runData.SetBeamline(str);
|
|
|
|
// get/set instrument
|
|
str = TString(nxs_file->GetEntryIdf2()->GetInstrument()->GetName());
|
|
runData.SetInstrument(str);
|
|
|
|
// get/set muon source
|
|
str = TString(nxs_file->GetEntryIdf2()->GetInstrument()->GetSource()->GetType());
|
|
runData.SetMuonSource(str);
|
|
|
|
// get/set muon species
|
|
str = TString(nxs_file->GetEntryIdf2()->GetInstrument()->GetSource()->GetProbe());
|
|
runData.SetMuonSpecies(str);
|
|
|
|
// get/set run title
|
|
str = TString(nxs_file->GetEntryIdf2()->GetTitle());
|
|
runData.SetRunTitle(str);
|
|
|
|
// get/set run number
|
|
runData.SetRunNumber(nxs_file->GetEntryIdf2()->GetRunNumber());
|
|
|
|
// get/set temperature
|
|
dval = nxs_file->GetEntryIdf2()->GetSample()->GetPhysPropValue("temperature", ok);
|
|
if (ok)
|
|
runData.SetTemperature(0, dval, 0.0);
|
|
|
|
// get/set field
|
|
dval = nxs_file->GetEntryIdf2()->GetSample()->GetPhysPropValue("magnetic_field", ok);
|
|
nxs_file->GetEntryIdf2()->GetSample()->GetPhysPropUnit("magnetic_field", sstr, ok);
|
|
str = sstr;
|
|
// since field has to be given in Gauss, check the units
|
|
Double_t factor=1.0;
|
|
if (!str.CompareTo("gauss", TString::kIgnoreCase))
|
|
factor=1.0;
|
|
else if (!str.CompareTo("tesla", TString::kIgnoreCase))
|
|
factor=1.0e4;
|
|
else
|
|
factor=1.0;
|
|
runData.SetField(factor*dval);
|
|
|
|
// get/set implantation energy
|
|
runData.SetEnergy(PMUSR_UNDEFINED);
|
|
|
|
// get/set moderator HV
|
|
runData.SetTransport(PMUSR_UNDEFINED);
|
|
|
|
// get/set RA HV's (LEM specific)
|
|
for (UInt_t i=0; i<4; i++)
|
|
runData.SetRingAnode(i, PMUSR_UNDEFINED);
|
|
|
|
// get/set setup take NXsample/temperature_1_env and NXsample/magnetic_field_1_env
|
|
sstr = nxs_file->GetEntryIdf2()->GetSample()->GetEnvironmentTemp() + string("/");
|
|
sstr += nxs_file->GetEntryIdf2()->GetSample()->GetEnvironmentField();
|
|
str = sstr;
|
|
runData.SetSetup(str);
|
|
|
|
// get/set sample
|
|
runData.SetSample(nxs_file->GetEntryIdf2()->GetSample()->GetName());
|
|
|
|
// get/set orientation
|
|
runData.SetOrientation("??");
|
|
|
|
// get/set time resolution (ns)
|
|
runData.SetTimeResolution(nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetTimeResolution("ns"));
|
|
|
|
// get/set start/stop time
|
|
sstr = nxs_file->GetEntryIdf2()->GetStartTime();
|
|
str = sstr;
|
|
TString date, time;
|
|
SplitTimeDate(str, time, date, ok);
|
|
if (ok) {
|
|
runData.SetStartTime(time);
|
|
runData.SetStartDate(date);
|
|
}
|
|
|
|
sstr = nxs_file->GetEntryIdf2()->GetStopTime();
|
|
str = sstr;
|
|
SplitTimeDate(str, time, date, ok);
|
|
if (ok) {
|
|
runData.SetStopTime(time);
|
|
runData.SetStopDate(date);
|
|
}
|
|
|
|
// get/set data, t0, fgb, lgb
|
|
PDoubleVector data;
|
|
PRawRunDataSet dataSet;
|
|
UInt_t histoNo = 0;
|
|
Int_t ival;
|
|
int *histos = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetHistos();
|
|
if (nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfPeriods() > 0) { // counts[][][]
|
|
for (int i=0; i<nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfPeriods(); i++) {
|
|
for (int j=0; j<nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra(); j++) {
|
|
for (int k=0; k<nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfBins(); k++) {
|
|
data.push_back(*(histos+i*nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra()+j*nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfBins()+k));
|
|
}
|
|
dataSet.Clear();
|
|
dataSet.SetHistoNo(++histoNo); // i.e. histo numbers start with 1
|
|
// get t0
|
|
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetT0(i,j);
|
|
if (ival == -1) // i.e. single value only
|
|
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetT0();
|
|
dataSet.SetTimeZeroBin(ival);
|
|
// get first good bin
|
|
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetFirstGoodBin(i,j);
|
|
if (ival == -1) // i.e. single value only
|
|
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetFirstGoodBin();
|
|
dataSet.SetFirstGoodBin(ival);
|
|
// get last good bin
|
|
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetLastGoodBin(i,j);
|
|
if (ival == -1) // i.e. single value only
|
|
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetLastGoodBin();
|
|
dataSet.SetLastGoodBin(ival);
|
|
|
|
dataSet.SetData(data);
|
|
runData.SetDataSet(dataSet);
|
|
data.clear();
|
|
}
|
|
}
|
|
} else {
|
|
if (nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra() > 0) { // counts[][]
|
|
for (int i=0; i<nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra(); i++) {
|
|
for (int j=0; j<nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfBins(); j++) {
|
|
data.push_back(*(histos+i*nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfBins()+j));
|
|
}
|
|
dataSet.Clear();
|
|
dataSet.SetHistoNo(++histoNo); // i.e. histo numbers start with 1
|
|
// get t0
|
|
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetT0(-1,i);
|
|
if (ival == -1) // i.e. single value only
|
|
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetT0();
|
|
dataSet.SetTimeZeroBin(ival);
|
|
// get first good bin
|
|
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetFirstGoodBin(-1,i);
|
|
if (ival == -1) // i.e. single value only
|
|
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetFirstGoodBin();
|
|
dataSet.SetFirstGoodBin(ival);
|
|
// get last good bin
|
|
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetLastGoodBin(-1,i);
|
|
if (ival == -1) // i.e. single value only
|
|
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetLastGoodBin();
|
|
dataSet.SetLastGoodBin(ival);
|
|
|
|
dataSet.SetData(data);
|
|
runData.SetDataSet(dataSet);
|
|
data.clear();
|
|
}
|
|
} else { // counts[]
|
|
for (int i=0; i<nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfBins(); i++) {
|
|
data.push_back(*(histos+i));
|
|
}
|
|
dataSet.Clear();
|
|
dataSet.SetHistoNo(++histoNo); // i.e. histo numbers start with 1
|
|
// get t0
|
|
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetT0();
|
|
dataSet.SetTimeZeroBin(ival);
|
|
// get first good bin
|
|
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetFirstGoodBin();
|
|
dataSet.SetFirstGoodBin(ival);
|
|
// get last good bin
|
|
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetLastGoodBin();
|
|
dataSet.SetLastGoodBin(ival);
|
|
|
|
dataSet.SetData(data);
|
|
runData.SetDataSet(dataSet);
|
|
data.clear();
|
|
}
|
|
}
|
|
|
|
// keep run name from the msr-file
|
|
runData.SetRunName(fRunName);
|
|
|
|
// keep the information
|
|
fData.push_back(runData);
|
|
} else {
|
|
cout << endl << ">> PRunDataHandler::ReadNexusFile(): IDF version " << nxs_file->GetIdfVersion() << ", not implemented." << endl;
|
|
}
|
|
|
|
// clean up
|
|
if (nxs_file) {
|
|
delete nxs_file;
|
|
nxs_file = 0;
|
|
}
|
|
#else
|
|
cout << endl << ">> PRunDataHandler::ReadNexusFile(): Sorry, not enabled at configuration level, i.e. --enable-NeXus when executing configure" << endl << endl;
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// ReadWkmFile (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Reads, for backwards compatibility, the ascii-wkm-file data format.
|
|
* The routine is clever enough to distinguish the different wkm-flavours (argh).
|
|
*
|
|
* <b>return:</b>
|
|
* - true at successful reading,
|
|
* - otherwise false.
|
|
*/
|
|
Bool_t PRunDataHandler::ReadWkmFile()
|
|
{
|
|
PDoubleVector histoData;
|
|
PRawRunData runData;
|
|
|
|
// open file
|
|
ifstream f;
|
|
|
|
// open wkm-file
|
|
f.open(fRunPathName.Data(), ifstream::in);
|
|
if (!f.is_open()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadWkmFile: **ERROR** Couldn't open run data (" << fRunPathName.Data() << ") file for reading, sorry ...";
|
|
cerr << endl;
|
|
return false;
|
|
}
|
|
|
|
// read header
|
|
Bool_t headerInfo = true;
|
|
Char_t instr[512];
|
|
TString line, linecp;
|
|
Double_t dval;
|
|
Int_t ival;
|
|
Bool_t ok;
|
|
Int_t groups = 0, channels = 0;
|
|
|
|
// skip leading empty lines
|
|
do {
|
|
f.getline(instr, sizeof(instr));
|
|
line = TString(instr);
|
|
if (!line.IsWhitespace())
|
|
break;
|
|
} while (!f.eof());
|
|
|
|
// real header data should start here
|
|
Ssiz_t idx;
|
|
do {
|
|
line = TString(instr);
|
|
if (line.IsDigit()) { // end of header reached
|
|
headerInfo = false;
|
|
} else { // real stuff, hence filter data
|
|
if (line.Contains("Title") || line.Contains("Titel")) {
|
|
idx = line.Index(":");
|
|
line.Replace(0, idx+1, 0, 0); // remove 'Title:'
|
|
StripWhitespace(line);
|
|
runData.SetRunTitle(line);
|
|
} else if (line.Contains("Run:")) {
|
|
idx = line.Index(":");
|
|
line.Replace(0, idx+1, 0, 0); // remove 'Run:'
|
|
StripWhitespace(line);
|
|
ival = ToInt(line, ok);
|
|
if (ok)
|
|
runData.SetRunNumber(ival);
|
|
} else if (line.Contains("Field")) {
|
|
idx = line.Index(":");
|
|
line.Replace(0, idx+1, 0, 0); // remove 'Field:'
|
|
StripWhitespace(line);
|
|
idx = line.Index("G"); // check if unit is given
|
|
if (idx > 0) // unit is indeed given
|
|
line.Resize(idx);
|
|
dval = ToDouble(line, ok);
|
|
if (ok)
|
|
runData.SetField(dval);
|
|
} else if (line.Contains("Setup")) {
|
|
idx = line.Index(":");
|
|
line.Replace(0, idx+1, 0, 0); // remove 'Setup:'
|
|
StripWhitespace(line);
|
|
runData.SetSetup(line);
|
|
} else if (line.Contains("Temp:") || line.Contains("Temp(meas1):")) {
|
|
linecp = line;
|
|
idx = line.Index(":");
|
|
line.Replace(0, idx+1, 0, 0); // remove 'Temp:'
|
|
StripWhitespace(line);
|
|
idx = line.Index("+/-"); // remove "+/- ..." part
|
|
if (idx > 0)
|
|
line.Resize(idx);
|
|
idx = line.Index("K"); // remove "K ..." part
|
|
if (idx > 0)
|
|
line.Resize(idx);
|
|
dval = ToDouble(line, ok);
|
|
if (ok) {
|
|
runData.SetTemperature(0, dval, 0.0);
|
|
}
|
|
idx = linecp.Index("+/-"); // get the error
|
|
linecp.Replace(0, idx+3, 0, 0);
|
|
StripWhitespace(linecp);
|
|
dval = ToDouble(linecp, ok);
|
|
if (ok) {
|
|
runData.SetTempError(0, dval);
|
|
}
|
|
} else if (line.Contains("Temp(meas2):")) {
|
|
linecp = line;
|
|
idx = line.Index(":");
|
|
line.Replace(0, idx+1, 0, 0); // remove 'Temp(meas2):'
|
|
StripWhitespace(line);
|
|
idx = line.Index("+/-"); // remove "+/- ..." part
|
|
if (idx > 0)
|
|
line.Resize(idx);
|
|
idx = line.Index("K"); // remove "K ..." part
|
|
if (idx > 0)
|
|
line.Resize(idx);
|
|
dval = ToDouble(line, ok);
|
|
if (ok) {
|
|
runData.SetTemperature(1, dval, 0.0);
|
|
}
|
|
idx = linecp.Index("+/-"); // get the error
|
|
linecp.Replace(0, idx+3, 0, 0);
|
|
StripWhitespace(linecp);
|
|
dval = ToDouble(linecp, ok);
|
|
if (ok) {
|
|
runData.SetTempError(1, dval);
|
|
}
|
|
} else if (line.Contains("Groups")) {
|
|
idx = line.Index(":");
|
|
line.Replace(0, idx+1, 0, 0); // remove 'Groups:'
|
|
StripWhitespace(line);
|
|
ival = ToInt(line, ok);
|
|
if (ok)
|
|
groups = ival;
|
|
} else if (line.Contains("Channels")) {
|
|
idx = line.Index(":");
|
|
line.Replace(0, idx+1, 0, 0); // remove 'Channels:'
|
|
StripWhitespace(line);
|
|
ival = ToInt(line, ok);
|
|
if (ok)
|
|
channels = ival;
|
|
} else if (line.Contains("Resolution")) {
|
|
idx = line.Index(":");
|
|
line.Replace(0, idx+1, 0, 0); // remove 'Resolution:'
|
|
StripWhitespace(line);
|
|
dval = ToDouble(line, ok);
|
|
if (ok)
|
|
runData.SetTimeResolution(dval*1.0e3); // us -> ns
|
|
}
|
|
}
|
|
|
|
if (headerInfo)
|
|
f.getline(instr, sizeof(instr));
|
|
} while (headerInfo && !f.eof());
|
|
|
|
if ((groups == 0) || (channels == 0) || runData.GetTimeResolution() == 0.0) {
|
|
cerr << endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR** essential header informations are missing!";
|
|
cerr << endl << ">> groups = " << groups;
|
|
cerr << endl << ">> channels = " << channels;
|
|
cerr << endl << ">> time resolution = " << runData.GetTimeResolution();
|
|
cerr << endl;
|
|
f.close();
|
|
return false;
|
|
}
|
|
|
|
// read data ---------------------------------------------------------
|
|
UInt_t group_counter = 0;
|
|
Int_t val;
|
|
TObjArray *tokens;
|
|
TObjString *ostr;
|
|
TString str;
|
|
UInt_t histoNo = 0;
|
|
PRawRunDataSet dataSet;
|
|
do {
|
|
// check if empty line, i.e. new group
|
|
if (IsWhitespace(instr)) {
|
|
dataSet.Clear();
|
|
dataSet.SetHistoNo(++histoNo);
|
|
dataSet.SetData(histoData);
|
|
|
|
// get a T0 estimate
|
|
Double_t maxVal = 0.0;
|
|
Int_t maxBin = 0;
|
|
for (UInt_t i=0; i<histoData.size(); i++) {
|
|
if (histoData[i] > maxVal) {
|
|
maxVal = histoData[i];
|
|
maxBin = i;
|
|
}
|
|
}
|
|
dataSet.SetTimeZeroBinEstimated(maxBin);
|
|
|
|
runData.SetDataSet(dataSet);
|
|
|
|
histoData.clear();
|
|
group_counter++;
|
|
} else {
|
|
// extract values
|
|
line = TString(instr);
|
|
// check if line starts with character. Needed for RAL WKM format
|
|
if (!line.IsDigit()) {
|
|
f.getline(instr, sizeof(instr));
|
|
continue;
|
|
}
|
|
tokens = line.Tokenize(" ");
|
|
|
|
if (!tokens) { // no tokens found
|
|
cerr << endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR** while reading data: coulnd't tokenize run data.";
|
|
return false;
|
|
}
|
|
for (Int_t i=0; i<tokens->GetEntries(); i++) {
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(i));
|
|
str = ostr->GetString();
|
|
val = ToInt(str, ok);
|
|
if (ok) {
|
|
histoData.push_back(val);
|
|
} else {
|
|
cerr << endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR** while reading data: data line contains non-integer values.";
|
|
// clean up
|
|
delete tokens;
|
|
return false;
|
|
}
|
|
}
|
|
// clean up
|
|
if (tokens) {
|
|
delete tokens;
|
|
tokens = 0;
|
|
}
|
|
}
|
|
|
|
f.getline(instr, sizeof(instr));
|
|
|
|
} while (!f.eof());
|
|
|
|
// handle last line if present
|
|
if (strlen(instr) != 0) {
|
|
// extract values
|
|
line = TString(instr);
|
|
tokens = line.Tokenize(" ");
|
|
if (!tokens) { // no tokens found
|
|
cerr << endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR** while reading data: coulnd't tokenize run data.";
|
|
return false;
|
|
}
|
|
for (Int_t i=0; i<tokens->GetEntries(); i++) {
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(i));
|
|
str = ostr->GetString();
|
|
val = ToInt(str, ok);
|
|
if (ok) {
|
|
histoData.push_back(val);
|
|
} else {
|
|
cerr << endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR** while reading data: data line contains non-integer values.";
|
|
// clean up
|
|
delete tokens;
|
|
return false;
|
|
}
|
|
}
|
|
// clean up
|
|
if (tokens) {
|
|
delete tokens;
|
|
tokens = 0;
|
|
}
|
|
}
|
|
|
|
// save the last histo if not empty
|
|
if (histoData.size() > 0) {
|
|
dataSet.Clear();
|
|
dataSet.SetHistoNo(++histoNo);
|
|
dataSet.SetData(histoData);
|
|
|
|
// get a T0 estimate
|
|
Double_t maxVal = 0.0;
|
|
Int_t maxBin = 0;
|
|
for (UInt_t i=0; i<histoData.size(); i++) {
|
|
if (histoData[i] > maxVal) {
|
|
maxVal = histoData[i];
|
|
maxBin = i;
|
|
}
|
|
}
|
|
dataSet.SetTimeZeroBinEstimated(maxBin);
|
|
|
|
runData.SetDataSet(dataSet);
|
|
histoData.clear();
|
|
}
|
|
|
|
// close file
|
|
f.close();
|
|
|
|
// check if all groups are found
|
|
if ((Int_t) runData.GetNoOfHistos() != groups) {
|
|
cerr << endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR**";
|
|
cerr << endl << ">> expected " << groups << " histos, but found " << runData.GetNoOfHistos();
|
|
return false;
|
|
}
|
|
|
|
// check if all groups have enough channels
|
|
for (UInt_t i=0; i<runData.GetNoOfHistos(); i++) {
|
|
if ((Int_t) runData.GetDataBin(i+1)->size() != channels) {
|
|
cerr << endl << ">> PRunDataHandler::ReadWkmFile(): **ERROR**";
|
|
cerr << endl << ">> expected " << channels << " bins in histo " << i+1 << ", but found " << runData.GetDataBin(i)->size();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// keep run name
|
|
runData.SetRunName(fRunName);
|
|
|
|
// add run to the run list
|
|
fData.push_back(runData);
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// ReadPsiBinFile (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Reads the old-fashioned PSI-BIN data-files. The MuSR_td_PSI_bin class
|
|
* of Alex Amato is used. In case of problems, please contact alex.amato@psi.ch.
|
|
*
|
|
* <b>return:</b>
|
|
* - true at successful reading,
|
|
* - otherwise false.
|
|
*/
|
|
Bool_t PRunDataHandler::ReadPsiBinFile()
|
|
{
|
|
MuSR_td_PSI_bin psiBin;
|
|
Int_t status;
|
|
Bool_t success;
|
|
|
|
// read psi bin file
|
|
status = psiBin.read(fRunPathName.Data());
|
|
switch (status) {
|
|
case 0: // everything perfect
|
|
success = true;
|
|
break;
|
|
case 1: // couldn't open file, or failed while reading the header
|
|
cerr << endl << ">> **ERROR** couldn't open psi-bin file, or failed while reading the header";
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
case 2: // unsupported version of the data
|
|
cerr << endl << ">> **ERROR** psi-bin file: unsupported version of the data";
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
case 3: // error when allocating data buffer
|
|
cerr << endl << ">> **ERROR** psi-bin file: error when allocating data buffer";
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
case 4: // number of histograms/record not equals 1
|
|
cerr << endl << ">> **ERROR** psi-bin file: number of histograms/record not equals 1";
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
default: // you never should have reached this point
|
|
success = false;
|
|
break;
|
|
}
|
|
|
|
// if any reading error happend, get out of here
|
|
if (!success)
|
|
return success;
|
|
|
|
// fill necessary header informations
|
|
PRawRunData runData;
|
|
Double_t dval;
|
|
|
|
// set file name
|
|
Ssiz_t pos = fRunPathName.Last('/');
|
|
TString fln(fRunPathName);
|
|
fln.Remove(0, pos+1);
|
|
runData.SetFileName(fln);
|
|
|
|
// set laboratory
|
|
runData.SetLaboratory("PSI");
|
|
|
|
// filter from the file name the instrument
|
|
TString instrument("n/a"), beamline("n/a");
|
|
TString muonSource("n/a"), muonSpecies("n/a");
|
|
if (fRunPathName.Contains("_gps_", TString::kIgnoreCase)) {
|
|
instrument = "GPS";
|
|
beamline = "piM3.2";
|
|
muonSource = "continuous surface muon source";
|
|
muonSpecies = "positive muons";
|
|
} else if (fRunPathName.Contains("_ltf_", TString::kIgnoreCase)) {
|
|
instrument = "LTF";
|
|
beamline = "piM3.3";
|
|
muonSource = "continuous surface muon source";
|
|
muonSpecies = "positive muons";
|
|
} else if (fRunPathName.Contains("_gpd_", TString::kIgnoreCase)) {
|
|
instrument = "GPD";
|
|
beamline = "muE1";
|
|
muonSource = "continuous decay channel muon source";
|
|
muonSpecies = "positive muons";
|
|
} else if (fRunPathName.Contains("_dolly_", TString::kIgnoreCase)) {
|
|
instrument = "DOLLY";
|
|
beamline = "piE1";
|
|
muonSource = "continuous surface muon source";
|
|
muonSpecies = "positive muons";
|
|
} else if (fRunPathName.Contains("_alc_", TString::kIgnoreCase)) {
|
|
instrument = "ALC";
|
|
beamline = "piE3";
|
|
muonSource = "continuous surface muon source";
|
|
muonSpecies = "positive muons";
|
|
} else if (fRunPathName.Contains("_hifi_", TString::kIgnoreCase)) {
|
|
instrument = "HIFI";
|
|
beamline = "piE3";
|
|
muonSource = "continuous surface muon source";
|
|
muonSpecies = "positive muons";
|
|
}
|
|
runData.SetInstrument(instrument);
|
|
runData.SetBeamline(beamline);
|
|
runData.SetMuonSource(muonSource);
|
|
runData.SetMuonSpecies(muonSpecies);
|
|
|
|
// keep run name
|
|
runData.SetRunName(fRunName);
|
|
// get run title
|
|
runData.SetRunTitle(TString(psiBin.get_comment().c_str())); // run title
|
|
// get run number
|
|
runData.SetRunNumber(psiBin.get_runNumber_int());
|
|
// get setup
|
|
runData.SetSetup(TString(psiBin.get_comment().c_str()));
|
|
// get sample
|
|
runData.SetSample(TString(psiBin.get_sample().c_str()));
|
|
// get orientation
|
|
runData.SetOrientation(TString(psiBin.get_orient().c_str()));
|
|
// get comment
|
|
runData.SetComment(TString(psiBin.get_comment().c_str()));
|
|
// set LEM specific information to default value since it is not in the file and not used...
|
|
runData.SetEnergy(PMUSR_UNDEFINED);
|
|
runData.SetTransport(PMUSR_UNDEFINED);
|
|
// get field
|
|
Double_t scale = 0.0;
|
|
if (psiBin.get_field().rfind("G") != string::npos)
|
|
scale = 1.0;
|
|
if (psiBin.get_field().rfind("T") != string::npos)
|
|
scale = 1.0e4;
|
|
status = sscanf(psiBin.get_field().c_str(), "%lf", &dval);
|
|
if (status == 1)
|
|
runData.SetField(scale*dval);
|
|
// get temperature
|
|
PDoubleVector tempVec(psiBin.get_temperatures_vector());
|
|
PDoubleVector tempDevVec(psiBin.get_devTemperatures_vector());
|
|
if ((tempVec.size() > 1) && (tempDevVec.size() > 1) && tempVec[0] && tempVec[1]) {
|
|
// take only the first two values for now...
|
|
//maybe that's not enough - e.g. in older GPD data I saw the "correct values in the second and third entry..."
|
|
for (UInt_t i(0); i<2; i++) {
|
|
runData.SetTemperature(i, tempVec[i], tempDevVec[i]);
|
|
}
|
|
tempVec.clear();
|
|
tempDevVec.clear();
|
|
} else {
|
|
status = sscanf(psiBin.get_temp().c_str(), "%lfK", &dval);
|
|
if (status == 1)
|
|
runData.SetTemperature(0, dval, 0.0);
|
|
}
|
|
|
|
// get time resolution (ns)
|
|
runData.SetTimeResolution(psiBin.get_binWidth_ns());
|
|
|
|
// get start/stop time
|
|
vector<string> sDateTime = psiBin.get_timeStart_vector();
|
|
if (sDateTime.size() < 2) {
|
|
cerr << endl << ">> **WARNING** psi-bin file: couldn't obtain run start date/time" << endl;
|
|
}
|
|
string date("");
|
|
if (DateToISO8601(sDateTime[0], date)) {
|
|
runData.SetStartDate(date);
|
|
} else {
|
|
cerr << endl << ">> **WARNING** failed to convert start date: " << sDateTime[0] << " into ISO 8601 date." << endl;
|
|
runData.SetStartDate(sDateTime[0]);
|
|
}
|
|
runData.SetStartTime(sDateTime[1]);
|
|
sDateTime.clear();
|
|
|
|
sDateTime = psiBin.get_timeStop_vector();
|
|
if (sDateTime.size() < 2) {
|
|
cerr << endl << ">> **WARNING** psi-bin file: couldn't obtain run stop date/time" << endl;
|
|
}
|
|
date = string("");
|
|
if (DateToISO8601(sDateTime[0], date)) {
|
|
runData.SetStopDate(date);
|
|
} else {
|
|
cerr << endl << ">> **WARNING** failed to convert stop date: " << sDateTime[0] << " into ISO 8601 date." << endl;
|
|
runData.SetStopDate(sDateTime[0]);
|
|
}
|
|
runData.SetStopTime(sDateTime[1]);
|
|
sDateTime.clear();
|
|
|
|
// get t0's
|
|
PIntVector t0 = psiBin.get_t0_vector();
|
|
|
|
if (t0.empty()) {
|
|
cerr << endl << ">> **ERROR** psi-bin file: couldn't obtain any t0's";
|
|
cerr << endl;
|
|
return false;
|
|
}
|
|
|
|
// get first good bin
|
|
PIntVector fgb = psiBin.get_firstGood_vector();
|
|
if (fgb.empty()) {
|
|
cerr << endl << ">> **ERROR** psi-bin file: couldn't obtain any fgb's";
|
|
cerr << endl;
|
|
return false;
|
|
}
|
|
|
|
// get last good bin
|
|
PIntVector lgb = psiBin.get_lastGood_vector();
|
|
if (lgb.empty()) {
|
|
cerr << endl << ">> **ERROR** psi-bin file: couldn't obtain any lgb's";
|
|
cerr << endl;
|
|
return false;
|
|
}
|
|
|
|
// fill raw data
|
|
PRawRunDataSet dataSet;
|
|
PDoubleVector histoData;
|
|
Int_t *histo;
|
|
for (Int_t i=0; i<psiBin.get_numberHisto_int(); i++) {
|
|
histo = psiBin.get_histo_array_int(i);
|
|
for (Int_t j=0; j<psiBin.get_histoLength_bin(); j++) {
|
|
histoData.push_back(histo[j]);
|
|
}
|
|
delete[] histo;
|
|
|
|
// estimate T0 from maximum of the data
|
|
Double_t maxVal = 0.0;
|
|
Int_t maxBin = 0;
|
|
for (UInt_t j=0; j<histoData.size(); j++) {
|
|
if (histoData[j] > maxVal) {
|
|
maxVal = histoData[j];
|
|
maxBin = j;
|
|
}
|
|
}
|
|
|
|
dataSet.Clear();
|
|
dataSet.SetName(psiBin.get_nameHisto(i).c_str());
|
|
dataSet.SetHistoNo(i+1); // i.e. hist numbering starts at 1
|
|
if (i < (Int_t)t0.size())
|
|
dataSet.SetTimeZeroBin(t0[i]);
|
|
dataSet.SetTimeZeroBinEstimated(maxBin);
|
|
if (i < (Int_t)fgb.size())
|
|
dataSet.SetFirstGoodBin(fgb[i]);
|
|
if (i < (Int_t)lgb.size())
|
|
dataSet.SetLastGoodBin(lgb[i]);
|
|
dataSet.SetData(histoData);
|
|
|
|
runData.SetDataSet(dataSet);
|
|
|
|
histoData.clear();
|
|
}
|
|
|
|
// add run to the run list
|
|
fData.push_back(runData);
|
|
|
|
return success;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// ReadMudFile (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Reads the triumf mud-file format.
|
|
*
|
|
* <b>return:</b>
|
|
* - true at successful reading,
|
|
* - otherwise false.
|
|
*/
|
|
Bool_t PRunDataHandler::ReadMudFile()
|
|
{
|
|
Int_t fh;
|
|
UINT32 type, val;
|
|
Int_t success;
|
|
Char_t str[1024];
|
|
Double_t dval;
|
|
|
|
PRawRunData runData;
|
|
|
|
fh = MUD_openRead((Char_t *)fRunPathName.Data(), &type);
|
|
if (fh == -1) {
|
|
cerr << endl << ">> **ERROR** Couldn't open mud-file " << fRunPathName.Data() << ", sorry.";
|
|
cerr << endl;
|
|
return false;
|
|
}
|
|
|
|
// read necessary header information
|
|
|
|
// keep run name
|
|
runData.SetRunName(fRunName);
|
|
|
|
// get/set the lab
|
|
success = MUD_getLab( fh, str, sizeof(str) );
|
|
if ( !success ) {
|
|
cerr << endl << ">> **WARNING** Couldn't obtain the laboratory name of run " << fRunName.Data();
|
|
cerr << endl;
|
|
strcpy(str, "n/a");
|
|
}
|
|
runData.SetLaboratory(TString(str));
|
|
|
|
// get/set the beamline
|
|
success = MUD_getArea( fh, str, sizeof(str) );
|
|
if ( !success ) {
|
|
cerr << endl << ">> **WARNING** Couldn't obtain the beamline of run " << fRunName.Data();
|
|
cerr << endl;
|
|
strcpy(str, "n/a");
|
|
}
|
|
runData.SetBeamline(TString(str));
|
|
|
|
// get/set the instrument
|
|
success = MUD_getApparatus( fh, str, sizeof(str) );
|
|
if ( !success ) {
|
|
cerr << endl << ">> **WARNING** Couldn't obtain the instrument name of run " << fRunName.Data();
|
|
cerr << endl;
|
|
strcpy(str, "n/a");
|
|
}
|
|
runData.SetInstrument(TString(str));
|
|
|
|
// get run title
|
|
success = MUD_getTitle( fh, str, sizeof(str) );
|
|
if ( !success ) {
|
|
cerr << endl << ">> **WARNING** Couldn't obtain the run title of run " << fRunName.Data();
|
|
cerr << endl;
|
|
}
|
|
runData.SetRunTitle(TString(str));
|
|
|
|
// get run number
|
|
success = MUD_getRunNumber( fh, &val );
|
|
if (success) {
|
|
runData.SetRunNumber((Int_t)val);
|
|
}
|
|
|
|
// get start/stop time of the run
|
|
time_t tval;
|
|
struct tm *dt;
|
|
TString stime("");
|
|
success = MUD_getTimeBegin( fh, (UINT32*)&tval );
|
|
if (success) {
|
|
runData.SetStartDateTime((const time_t)tval);
|
|
dt = localtime((const time_t*)&tval);
|
|
assert(dt);
|
|
|
|
// start date
|
|
strftime(str, sizeof(str), "%F", dt);
|
|
stime = str;
|
|
runData.SetStartDate(stime);
|
|
// start time
|
|
memset(str, 0, sizeof(str));
|
|
strftime(str, sizeof(str), "%T", dt);
|
|
stime = str;
|
|
runData.SetStartTime(stime);
|
|
}
|
|
|
|
stime = TString("");
|
|
success = MUD_getTimeEnd( fh, (UINT32*)&tval );
|
|
if (success) {
|
|
runData.SetStopDateTime((const time_t)tval);
|
|
dt = localtime((const time_t*)&tval);
|
|
assert(dt);
|
|
|
|
// stop date
|
|
strftime(str, sizeof(str), "%F", dt);
|
|
stime = str;
|
|
runData.SetStopDate(stime);
|
|
// stop time
|
|
memset(str, 0, sizeof(str));
|
|
strftime(str, sizeof(str), "%T", dt);
|
|
stime = str;
|
|
runData.SetStopTime(stime);
|
|
}
|
|
|
|
// get setup
|
|
TString setup;
|
|
success = MUD_getLab( fh, str, sizeof(str) );
|
|
if (success) {
|
|
setup = TString(str) + TString("/");
|
|
}
|
|
success = MUD_getArea( fh, str, sizeof(str) );
|
|
if (success) {
|
|
setup += TString(str) + TString("/");
|
|
}
|
|
success = MUD_getApparatus( fh, str, sizeof(str) );
|
|
if (success) {
|
|
setup += TString(str) + TString("/");
|
|
}
|
|
success = MUD_getSample( fh, str, sizeof(str) );
|
|
if (success) {
|
|
setup += TString(str);
|
|
runData.SetSample(str);
|
|
}
|
|
runData.SetSetup(setup);
|
|
|
|
// set LEM specific information to default value since it is not in the file and not used...
|
|
runData.SetEnergy(PMUSR_UNDEFINED);
|
|
runData.SetTransport(PMUSR_UNDEFINED);
|
|
|
|
// get field
|
|
success = MUD_getField( fh, str, sizeof(str) );
|
|
if (success) {
|
|
success = sscanf(str, "%lf G", &dval);
|
|
if (success == 1) {
|
|
runData.SetField(dval);
|
|
} else {
|
|
runData.SetField(PMUSR_UNDEFINED);
|
|
}
|
|
} else {
|
|
runData.SetField(PMUSR_UNDEFINED);
|
|
}
|
|
|
|
// get temperature
|
|
success = MUD_getTemperature( fh, str, sizeof(str) );
|
|
if (success) {
|
|
success = sscanf(str, "%lf K", &dval);
|
|
if (success == 1) {
|
|
runData.SetTemperature(0, dval, 0.0);
|
|
} else {
|
|
runData.SetTemperature(0, PMUSR_UNDEFINED, 0.0);
|
|
}
|
|
} else {
|
|
runData.SetTemperature(0, PMUSR_UNDEFINED, 0.0);
|
|
}
|
|
|
|
// get number of histogramms
|
|
success = MUD_getHists(fh, &type, &val);
|
|
if ( !success ) {
|
|
cerr << endl << ">> **ERROR** Couldn't obtain the number of histograms of run " << fRunName.Data();
|
|
cerr << endl;
|
|
MUD_closeRead(fh);
|
|
return false;
|
|
}
|
|
Int_t noOfHistos = (Int_t)val;
|
|
|
|
// get time resolution (ns)
|
|
// check that time resolution is identical for all histograms
|
|
// >> currently it is not forseen to handle histos with different time resolutions <<
|
|
// >> perhaps this needs to be reconsidered later on <<
|
|
REAL64 timeResolution = 0.0; // in seconds!!
|
|
REAL64 lrval = 0.0;
|
|
for (Int_t i=1; i<=noOfHistos; i++) {
|
|
success = MUD_getHistSecondsPerBin( fh, i, &lrval );
|
|
if (!success) {
|
|
cerr << endl << ">> **ERROR** Couldn't obtain the time resolution of run " << fRunName.Data();
|
|
cerr << endl << ">> which is fatal, sorry.";
|
|
cerr << endl;
|
|
MUD_closeRead(fh);
|
|
return false;
|
|
}
|
|
if (i==1) {
|
|
timeResolution = lrval;
|
|
} else {
|
|
if (lrval != timeResolution) {
|
|
cerr << endl << ">> **ERROR** various time resolutions found in run " << fRunName.Data();
|
|
cerr << endl << ">> this is currently not supported, sorry.";
|
|
cerr << endl;
|
|
MUD_closeRead(fh);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
runData.SetTimeResolution((Double_t)timeResolution * 1.0e9); // s -> ns
|
|
|
|
// read histograms
|
|
UINT32 *pData; // histo memory
|
|
pData = NULL;
|
|
PDoubleVector histoData;
|
|
PRawRunDataSet dataSet;
|
|
UInt_t noOfBins;
|
|
|
|
for (Int_t i=1; i<=noOfHistos; i++) {
|
|
dataSet.Clear();
|
|
|
|
dataSet.SetHistoNo(i);
|
|
|
|
// get t0's
|
|
success = MUD_getHistT0_Bin( fh, i, &val );
|
|
if ( !success ) {
|
|
cerr << endl << ">> **WARNING** Couldn't get t0 of histo " << i << " of run " << fRunName.Data();
|
|
cerr << endl;
|
|
}
|
|
dataSet.SetTimeZeroBin((Double_t)val);
|
|
|
|
// get bkg bins
|
|
success = MUD_getHistBkgd1( fh, i, &val );
|
|
if ( !success ) {
|
|
cerr << endl << ">> **WARNING** Couldn't get bkg bin 1 of histo " << i << " of run " << fRunName.Data();
|
|
cerr << endl;
|
|
val = 0;
|
|
}
|
|
dataSet.SetFirstBkgBin((Int_t)val);
|
|
|
|
success = MUD_getHistBkgd2( fh, i, &val );
|
|
if ( !success ) {
|
|
cerr << endl << ">> **WARNING** Couldn't get bkg bin 2 of histo " << i << " of run " << fRunName.Data();
|
|
cerr << endl;
|
|
val = 0;
|
|
}
|
|
dataSet.SetLastBkgBin((Int_t)val);
|
|
|
|
// get good data bins
|
|
success = MUD_getHistGoodBin1( fh, i, &val );
|
|
if ( !success ) {
|
|
cerr << endl << ">> **WARNING** Couldn't get good bin 1 of histo " << i << " of run " << fRunName.Data();
|
|
cerr << endl;
|
|
val = 0;
|
|
}
|
|
dataSet.SetFirstGoodBin((Int_t)val);
|
|
|
|
success = MUD_getHistGoodBin2( fh, i, &val );
|
|
if ( !success ) {
|
|
cerr << endl << ">> **WARNING** Couldn't get good bin 2 of histo " << i << " of run " << fRunName.Data();
|
|
cerr << endl;
|
|
val = 0;
|
|
}
|
|
dataSet.SetLastGoodBin((Int_t)val);
|
|
|
|
// get number of bins
|
|
success = MUD_getHistNumBins( fh, i, &val );
|
|
if ( !success ) {
|
|
cerr << endl << ">> **ERROR** Couldn't get the number of bins of histo " << i << ".";
|
|
cerr << endl << ">> This is fatal, sorry.";
|
|
cerr << endl;
|
|
MUD_closeRead( fh );
|
|
return false;
|
|
}
|
|
noOfBins = (UInt_t)val;
|
|
|
|
pData = (UINT32*)malloc(noOfBins*sizeof(pData));
|
|
if (pData == NULL) {
|
|
cerr << endl << ">> **ERROR** Couldn't allocate memory for data.";
|
|
cerr << endl << ">> This is fatal, sorry.";
|
|
cerr << endl;
|
|
MUD_closeRead( fh );
|
|
return false;
|
|
}
|
|
|
|
// get histogram
|
|
success = MUD_getHistData( fh, i, pData );
|
|
if ( !success ) {
|
|
cerr << endl << ">> **ERROR** Couldn't get histo no " << i << ".";
|
|
cerr << endl << ">> This is fatal, sorry.";
|
|
cerr << endl;
|
|
MUD_closeRead( fh );
|
|
return false;
|
|
}
|
|
|
|
for (UInt_t j=0; j<noOfBins; j++) {
|
|
histoData.push_back(pData[j]);
|
|
}
|
|
dataSet.SetData(histoData);
|
|
|
|
// estimate T0 from maximum of the data
|
|
Double_t maxVal = 0.0;
|
|
Int_t maxBin = 0;
|
|
for (UInt_t j=0; j<histoData.size(); j++) {
|
|
if (histoData[j] > maxVal) {
|
|
maxVal = histoData[j];
|
|
maxBin = j;
|
|
}
|
|
}
|
|
dataSet.SetTimeZeroBinEstimated(maxBin);
|
|
|
|
runData.SetDataSet(dataSet);
|
|
|
|
histoData.clear();
|
|
|
|
free(pData);
|
|
}
|
|
|
|
MUD_closeRead(fh);
|
|
|
|
// add run to the run list
|
|
fData.push_back(runData);
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// ReadMduAsciiFile (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Reads the mdu ascii files (PSI). Needed to work around PSI-BIN limitations.
|
|
*
|
|
* <p>Lines starting with '#' or '%' are considered as comment lines. The file has
|
|
* the following structure:
|
|
* \verbatim
|
|
* HEADER
|
|
* TITLE: title-string
|
|
* SETUP: setup-string
|
|
* FIELD: val-string (G) or (T) (e.g. 123456 (G))
|
|
* TEMP: val-string (K)
|
|
* GROUPS: # of histograms written
|
|
* CHANNELS: # of bins per histogram written
|
|
* RESOLUTION: timeresolution (fs) or (ps) or (ns) or (us)
|
|
* \endverbatim
|
|
* followed by the data, which are written in column format, starting with the DATA
|
|
* tag, i.e.
|
|
* \verbatim
|
|
* DATA
|
|
*
|
|
* \endverbatim
|
|
*
|
|
* <b>return:</b>
|
|
* - true at successful reading,
|
|
* - otherwise false.
|
|
*/
|
|
Bool_t PRunDataHandler::ReadMduAsciiFile()
|
|
{
|
|
Bool_t success = true;
|
|
|
|
// open file
|
|
ifstream f;
|
|
|
|
// open data-file
|
|
f.open(fRunPathName.Data(), ifstream::in);
|
|
if (!f.is_open()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** Couldn't open data file (" << fRunPathName.Data() << ") for reading, sorry ...";
|
|
cerr << endl;
|
|
return false;
|
|
}
|
|
|
|
PRawRunData runData;
|
|
|
|
// keep run name
|
|
runData.SetRunName(fRunName);
|
|
|
|
Int_t lineNo = 0;
|
|
Char_t instr[512];
|
|
TString line, workStr;
|
|
Bool_t headerTag = false;
|
|
Bool_t dataTag = false;
|
|
Int_t dataLineCounter = 0;
|
|
TObjString *ostr;
|
|
TObjArray *tokens = 0;
|
|
TString str;
|
|
Int_t groups = 0;
|
|
Int_t channels = 0;
|
|
Double_t dval = 0.0, unitScaling = 0.0;
|
|
vector<PDoubleVector> data;
|
|
|
|
while (!f.eof()) {
|
|
f.getline(instr, sizeof(instr));
|
|
line = TString(instr);
|
|
lineNo++;
|
|
|
|
// ignore comment lines
|
|
if (line.BeginsWith("#") || line.BeginsWith("%"))
|
|
continue;
|
|
|
|
// ignore empty lines
|
|
if (line.IsWhitespace())
|
|
continue;
|
|
|
|
// check if header tag
|
|
workStr = line;
|
|
workStr.Remove(TString::kLeading, ' '); // remove spaces from the begining
|
|
if (workStr.BeginsWith("header", TString::kIgnoreCase)) {
|
|
headerTag = true;
|
|
dataTag = false;
|
|
continue;
|
|
}
|
|
|
|
// check if data tag
|
|
workStr = line;
|
|
workStr.Remove(TString::kLeading, ' '); // remove spaces from the beining
|
|
if (workStr.BeginsWith("data", TString::kIgnoreCase)) {
|
|
headerTag = false;
|
|
dataTag = true;
|
|
continue;
|
|
}
|
|
|
|
if (headerTag) {
|
|
workStr = line;
|
|
workStr.Remove(TString::kLeading, ' '); // remove spaces from the beining
|
|
if (workStr.BeginsWith("title:", TString::kIgnoreCase)) {
|
|
runData.SetRunTitle(TString(workStr.Data()+workStr.First(":")+2));
|
|
} else if (workStr.BeginsWith("field:", TString::kIgnoreCase)) {
|
|
tokens = workStr.Tokenize(":("); // field: val (units)
|
|
// check if expected number of tokens present
|
|
if (tokens->GetEntries() != 3) {
|
|
cerr << endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", invalid field entry in header.";
|
|
cerr << endl << ">> " << line.Data();
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
// check if field value is a number
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(1));
|
|
if (ostr->GetString().IsFloat()) {
|
|
dval = ostr->GetString().Atof();
|
|
} else {
|
|
cerr << endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", field value is not float/doulbe.";
|
|
cerr << endl << ">> " << line.Data();
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
// check units, accept (G), (T)
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(2));
|
|
if (ostr->GetString().Contains("G"))
|
|
unitScaling = 1.0;
|
|
else if (ostr->GetString().Contains("T"))
|
|
unitScaling = 1.0e4;
|
|
else {
|
|
cerr << endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", unkown field units.";
|
|
cerr << endl << ">> " << line.Data();
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
runData.SetField(dval*unitScaling);
|
|
|
|
// clean up tokens
|
|
if (tokens) {
|
|
delete tokens;
|
|
tokens = 0;
|
|
}
|
|
} else if (workStr.BeginsWith("temp:", TString::kIgnoreCase)) {
|
|
tokens = workStr.Tokenize(":("); // temp: val (units)
|
|
// check if expected number of tokens present
|
|
if (tokens->GetEntries() != 3) {
|
|
cerr << endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", invalid temperatue entry in header.";
|
|
cerr << endl << ">> " << line.Data();
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
// check if field value is a number
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(1));
|
|
if (ostr->GetString().IsFloat()) {
|
|
dval = ostr->GetString().Atof();
|
|
} else {
|
|
cerr << endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", temperature value is not float/doulbe.";
|
|
cerr << endl << ">> " << line.Data();
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
runData.SetTemperature(0, dval, 0.0);
|
|
|
|
// clean up tokens
|
|
if (tokens) {
|
|
delete tokens;
|
|
tokens = 0;
|
|
}
|
|
} else if (workStr.BeginsWith("setup:", TString::kIgnoreCase)) {
|
|
runData.SetSetup(TString(workStr.Data()+workStr.First(":")+2));
|
|
} else if (workStr.BeginsWith("groups:", TString::kIgnoreCase)) {
|
|
workStr = TString(workStr.Data()+workStr.First(":")+2);
|
|
groups = workStr.Atoi();
|
|
if (groups == 0) {
|
|
cerr << endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", groups is not a number or 0.";
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
data.resize(groups);
|
|
} else if (workStr.BeginsWith("channels:", TString::kIgnoreCase)) {
|
|
workStr = TString(workStr.Data()+workStr.First(":")+2);
|
|
channels = workStr.Atoi();
|
|
if (channels == 0) {
|
|
cerr << endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", channels is not a number or 0.";
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
} else if (workStr.BeginsWith("resolution:", TString::kIgnoreCase)) {
|
|
tokens = workStr.Tokenize(":("); // resolution: val (units)
|
|
// check if expected number of tokens present
|
|
if (tokens->GetEntries() != 3) {
|
|
cerr << endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", invalid time resolution entry in header.";
|
|
cerr << endl << line.Data();
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
// check if timeresolution value is a number
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(1));
|
|
if (ostr->GetString().IsFloat()) {
|
|
dval = ostr->GetString().Atof();
|
|
} else {
|
|
cerr << endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", time resolution value is not float/doulbe.";
|
|
cerr << endl << ">> " << line.Data();
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
// check units, accept (fs), (ps), (ns), (us)
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(2));
|
|
if (ostr->GetString().Contains("fs"))
|
|
unitScaling = 1.0e-6;
|
|
else if (ostr->GetString().Contains("ps"))
|
|
unitScaling = 1.0e-3;
|
|
else if (ostr->GetString().Contains("ns"))
|
|
unitScaling = 1.0;
|
|
else if (ostr->GetString().Contains("us"))
|
|
unitScaling = 1.0e3;
|
|
else {
|
|
cerr << endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", unkown time resolution units.";
|
|
cerr << endl << ">> " << line.Data();
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
runData.SetTimeResolution(dval*unitScaling);
|
|
|
|
// clean up tokens
|
|
if (tokens) {
|
|
delete tokens;
|
|
tokens = 0;
|
|
}
|
|
} else { // error
|
|
cerr << endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** line no " << lineNo << ", illegal header line.";
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
} else if (dataTag) {
|
|
dataLineCounter++;
|
|
tokens = line.Tokenize(" ,\t");
|
|
// check if the number of data line entries is correct
|
|
if (tokens->GetEntries() != groups+1) {
|
|
cerr << endl << ">> PRunDataHandler::ReadMduAsciiFile **ERROR** found data line with a wrong data format, cannot be handled (line no " << lineNo << ")";
|
|
cerr << endl << ">> line:";
|
|
cerr << endl << ">> " << line.Data();
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
|
|
for (Int_t i=1; i<tokens->GetEntries(); i++) {
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(i));
|
|
data[i-1].push_back(ostr->GetString().Atof());
|
|
}
|
|
|
|
// clean up tokens
|
|
if (tokens) {
|
|
delete tokens;
|
|
tokens = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
f.close();
|
|
|
|
// keep data
|
|
PRawRunDataSet dataSet;
|
|
for (UInt_t i=0; i<data.size(); i++) {
|
|
dataSet.Clear();
|
|
dataSet.SetHistoNo(i);
|
|
dataSet.SetData(data[i]);
|
|
|
|
// estimate T0 from maximum of the data
|
|
Double_t maxVal = 0.0;
|
|
Int_t maxBin = 0;
|
|
for (UInt_t j=0; j<data[i].size(); j++) {
|
|
if (data[i][j] > maxVal) {
|
|
maxVal = data[i][j];
|
|
maxBin = j;
|
|
}
|
|
}
|
|
dataSet.SetTimeZeroBinEstimated(maxBin);
|
|
runData.SetDataSet(dataSet);
|
|
}
|
|
|
|
// clean up
|
|
for (UInt_t i=0; i<data.size(); i++)
|
|
data[i].clear();
|
|
data.clear();
|
|
|
|
if (dataLineCounter != channels) {
|
|
cerr << endl << ">> PRunDataHandler::ReadMduAsciiFile **WARNING** found " << dataLineCounter << " data bins,";
|
|
cerr << endl << ">> expected " << channels << " according to the header." << endl;
|
|
}
|
|
|
|
fData.push_back(runData);
|
|
|
|
return success;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// ReadAsciiFile (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Reads ascii files. Intended for the nonMuSR data.
|
|
*
|
|
* The file format definition is:
|
|
* Comment lines start with a '#' or '%' character.
|
|
* The file can start with some header info. The header is optional, as all its tags, but
|
|
* if present it has the following format:
|
|
*
|
|
* \verbatim
|
|
* HEADER
|
|
* TITLE: title
|
|
* X-AXIS-TITLE: x-axis title
|
|
* Y-AXIS-TITLE: y-axis title
|
|
* SETUP: setup
|
|
* FIELD: field
|
|
* TEMP: temperature
|
|
* ENERGY: energy
|
|
* \endverbatim
|
|
*
|
|
* field is assumed to be given in (G), the temperature in (K), the energy in (keV)
|
|
*
|
|
* The data are read column like and start with the data tag DATA, followed by the
|
|
* data columns, i.e.:
|
|
*
|
|
* \verbatim
|
|
* DATA
|
|
* x, y [, error y]
|
|
* \endverbatim
|
|
*
|
|
* where spaces, column, are a tab are possible separations.
|
|
* If no error in y is present, the weighting in the fit will be equal.
|
|
*
|
|
* <b>return:</b>
|
|
* - true at successful reading,
|
|
* - otherwise false.
|
|
*/
|
|
Bool_t PRunDataHandler::ReadAsciiFile()
|
|
{
|
|
Bool_t success = true;
|
|
|
|
// open file
|
|
ifstream f;
|
|
|
|
// open data-file
|
|
f.open(fRunPathName.Data(), ifstream::in);
|
|
if (!f.is_open()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** Couldn't open data file (" << fRunPathName.Data() << ") for reading, sorry ...";
|
|
cerr << endl;
|
|
return false;
|
|
}
|
|
|
|
PRawRunData runData;
|
|
|
|
// init some stuff
|
|
runData.fDataNonMusr.SetFromAscii(true);
|
|
runData.fDataNonMusr.AppendLabel("??"); // x default label
|
|
runData.fDataNonMusr.AppendLabel("??"); // y default label
|
|
|
|
runData.SetRunName(fRunName); // keep the run name
|
|
|
|
Int_t lineNo = 0;
|
|
Char_t instr[512];
|
|
TString line, workStr;
|
|
Bool_t headerTag = false;
|
|
Bool_t dataTag = false;
|
|
Double_t x, y, ey;
|
|
PDoubleVector xVec, exVec, yVec, eyVec;
|
|
|
|
while (!f.eof()) {
|
|
f.getline(instr, sizeof(instr));
|
|
line = TString(instr);
|
|
lineNo++;
|
|
|
|
// check if comment line
|
|
if (line.BeginsWith("#") || line.BeginsWith("%"))
|
|
continue;
|
|
|
|
// check if header tag
|
|
workStr = line;
|
|
workStr.Remove(TString::kLeading, ' '); // remove spaces from the begining
|
|
if (workStr.BeginsWith("header", TString::kIgnoreCase)) {
|
|
headerTag = true;
|
|
dataTag = false;
|
|
continue;
|
|
}
|
|
|
|
// check if data tag
|
|
workStr = line;
|
|
workStr.Remove(TString::kLeading, ' '); // remove spaces from the beining
|
|
if (workStr.BeginsWith("data", TString::kIgnoreCase)) {
|
|
headerTag = false;
|
|
dataTag = true;
|
|
continue;
|
|
}
|
|
|
|
if (headerTag) {
|
|
if (line.IsWhitespace()) // ignore empty lines
|
|
continue;
|
|
workStr = line;
|
|
workStr.Remove(TString::kLeading, ' '); // remove spaces from the beining
|
|
if (workStr.BeginsWith("title:", TString::kIgnoreCase)) {
|
|
runData.SetRunTitle(TString(workStr.Data()+workStr.First(":")+2));
|
|
} else if (workStr.BeginsWith("setup:", TString::kIgnoreCase)) {
|
|
runData.SetSetup(TString(workStr.Data()+workStr.First(":")+2));
|
|
} else if (workStr.BeginsWith("field:", TString::kIgnoreCase)) {
|
|
workStr = TString(workStr.Data()+workStr.First(":")+2);
|
|
if (!workStr.IsFloat()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ", field is not a number.";
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
runData.SetField(workStr.Atof());
|
|
} else if (workStr.BeginsWith("x-axis-title:", TString::kIgnoreCase)) {
|
|
runData.fDataNonMusr.SetLabel(0, TString(workStr.Data()+workStr.First(":")+2));
|
|
} else if (workStr.BeginsWith("y-axis-title:", TString::kIgnoreCase)) {
|
|
runData.fDataNonMusr.SetLabel(1, TString(workStr.Data()+workStr.First(":")+2));
|
|
} else if (workStr.BeginsWith("temp:", TString::kIgnoreCase)) {
|
|
workStr = TString(workStr.Data()+workStr.First(":")+2);
|
|
if (!workStr.IsFloat()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ", temperature is not a number.";
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
runData.SetTemperature(0, workStr.Atof(), 0.0);
|
|
} else if (workStr.BeginsWith("energy:", TString::kIgnoreCase)) {
|
|
workStr = TString(workStr.Data()+workStr.First(":")+2);
|
|
if (!workStr.IsFloat()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ", energy is not a number.";
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
runData.SetEnergy(workStr.Atof());
|
|
runData.SetTransport(PMUSR_UNDEFINED); // just to initialize the variables to some "meaningful" value
|
|
} else { // error
|
|
cerr << endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ", illegal header line.";
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
} else if (dataTag) {
|
|
if (line.IsWhitespace()) // ignore empty lines
|
|
continue;
|
|
TObjString *ostr;
|
|
TObjArray *tokens;
|
|
|
|
// Remove trailing end of line
|
|
line.Remove(TString::kTrailing, '\r');
|
|
|
|
// check if data have x, y [, error y] structure, and that x, y, and error y are numbers
|
|
tokens = line.Tokenize(" ,\t");
|
|
// check if the number of data line entries is 2 or 3
|
|
if ((tokens->GetEntries() != 2) && (tokens->GetEntries() != 3)) {
|
|
cerr << endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** found data line with a structure different than \"x, y [, error y]\", cannot be handled (line no " << lineNo << ")";
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
|
|
// get x
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(0));
|
|
if (!ostr->GetString().IsFloat()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ": x = " << ostr->GetString().Data() << " is not a number, sorry.";
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
x = ostr->GetString().Atof();
|
|
|
|
// get y
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(1));
|
|
if (!ostr->GetString().IsFloat()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ": y = " << ostr->GetString().Data() << " is not a number, sorry.";
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
y = ostr->GetString().Atof();
|
|
|
|
// get error y if present
|
|
if (tokens->GetEntries() == 3) {
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(2));
|
|
if (!ostr->GetString().IsFloat()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << ": error y = " << ostr->GetString().Data() << " is not a number, sorry.";
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
ey = ostr->GetString().Atof();
|
|
} else {
|
|
ey = 1.0;
|
|
}
|
|
|
|
// clean up tokens
|
|
if (tokens) {
|
|
delete tokens;
|
|
tokens = 0;
|
|
}
|
|
|
|
// keep values
|
|
xVec.push_back(x);
|
|
exVec.push_back(1.0);
|
|
yVec.push_back(y);
|
|
eyVec.push_back(ey);
|
|
|
|
} else {
|
|
cerr << endl << ">> PRunDataHandler::ReadAsciiFile **ERROR** line no " << lineNo << " neither header nor data line. No idea how to handle it!";
|
|
cerr << endl;
|
|
success = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
f.close();
|
|
|
|
// keep values
|
|
runData.fDataNonMusr.AppendData(xVec);
|
|
runData.fDataNonMusr.AppendErrData(exVec);
|
|
runData.fDataNonMusr.AppendData(yVec);
|
|
runData.fDataNonMusr.AppendErrData(eyVec);
|
|
|
|
fData.push_back(runData);
|
|
|
|
// clean up
|
|
xVec.clear();
|
|
exVec.clear();
|
|
yVec.clear();
|
|
eyVec.clear();
|
|
|
|
return success;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// ReadDBFile (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Reads triumf db-files. Intended for the nonMuSR data.
|
|
*
|
|
* <p>The file format definition is:
|
|
* The following is a description of the features of the TRIUMF .db file format that are
|
|
* currently recognized by musrfit/musrview. The available commands include: title, abstract,
|
|
* comments, labels, and data.
|
|
*
|
|
* \verbatim
|
|
* TITLE
|
|
* The following line must contain the title.
|
|
*
|
|
*
|
|
* ABSTRACT
|
|
* The abstract is read in starting with the following line until an empty line is reached.
|
|
*
|
|
* COMMENTS
|
|
* The comments are read in starting with the following line until an empty line is reached.
|
|
*
|
|
*
|
|
* LABELS
|
|
* One label must occupy each subsequent line until an empty line is reached. The number
|
|
* of labels should preferably match the number of variables in the data.
|
|
*
|
|
* DATA
|
|
* On the same line as the DATA command, there must appear a comma-delimited list of variable
|
|
* names. These names should be kept short (some applications truncate to 4 characters). The
|
|
* numerical data is read in beginning with the following line until an empty line is reached.
|
|
*
|
|
* In every line, there must appear exactly 3 comma-delimited fields for each specified name.
|
|
* The first field is the value, the second is the positive error, and the third is the negative
|
|
* error. If you leave the last field blank (the comma is still required), then the positive error
|
|
* will be interpreted as a symmetric error. If you include only the value, then the errors will be
|
|
* set to zero.
|
|
*
|
|
* To reiterate, if you provide a DATA command with 2 names, e.g. "DATA 1st, 2nd", then every subsequent
|
|
* line must contain 2*3 - 1 = 5 commas. If you give 3 names, then there must be 3*3 - 1 = 8 commas.
|
|
*
|
|
* Example
|
|
* TITLE
|
|
* Most Excellent Fake Data
|
|
*
|
|
* ABSTRACT
|
|
* This data was collected over
|
|
* many minutes of light work
|
|
* that was required to make it up.
|
|
*
|
|
* COMMENTS
|
|
* This data was generated using C++.
|
|
* The file was formatted with Emacs.
|
|
*
|
|
* LABEL
|
|
* Randomized Linear
|
|
* Randomized Gaussian
|
|
* Randomized Lorentzian
|
|
* Run
|
|
*
|
|
* DATA line, gauss, lrntz, run
|
|
* -1.966, -0.168, -0.106, 0.048, 0.002, 0.005, 0.184, 0.010, 0.017, 1001, , , run 1001 title
|
|
* -1.895, -0.151, -0.128, 0.014, 0.001, 0.001, 0.259, 0.017, 0.015, 1002, , , run 1002 title
|
|
* -1.836, -0.127, -0.184, 0.013, 0.001, 0.001, 0.202, 0.017, 0.020, 1003, , , run 1003 title
|
|
* -1.739, -0.064, -0.166, 0.057, 0.003, 0.004, 0.237, 0.016, 0.018, 1004, , , run 1004 title
|
|
* -1.601, -0.062, -0.147, 0.104, 0.008, 0.006, 0.271, 0.012, 0.025, 1005, , , run 1005 title
|
|
* . . . . . . . . .
|
|
* . . . . . . . . .
|
|
* . . . . . . . . .
|
|
* Alternatively, the data often utilizes the continuation character ('\') and is labelled like
|
|
* DATA line, gauss, lrntz
|
|
* linear = -1.966, -0.168, -0.106, \
|
|
* gaussn = 0.048, 0.002, 0.005, \
|
|
* lorntz = 0.184, 0.010, 0.017, \
|
|
* 1001,,, run 1001 title
|
|
* linear = -1.895, -0.151, -0.128, \
|
|
* gaussn = 0.014, 0.001, 0.001, \
|
|
* lorntz = 0.259, 0.017, 0.015, |
|
|
* 1002,,, run 1002 title
|
|
* linear = -1.836, -0.127, -0.184, \
|
|
* gaussn = 0.013, 0.001, 0.001, \
|
|
* lorntz = 0.202, 0.017, 0.020, |
|
|
* 1003,,, run 1003 title
|
|
* . . . .
|
|
* . . . .
|
|
* . . . .
|
|
* If there is a run line as in the above examples, it must be at the end of the data and given
|
|
* in this just slight odd manner (do not blame me, I haven't invented this format ;-) ).
|
|
* \endverbatim
|
|
*
|
|
* <p><b>WARNING:</b>For the row like data representation (the top DATA representation shown)
|
|
* it is essential that there are always at least one space inbetween commas (the reason is that
|
|
* I am too lazy to write my own tokenizer), e.g.
|
|
*
|
|
* \verbatim
|
|
* -1.966, -0.168, , 0.048, , , 0.184, 0.010, 0.017, 1001, , , run 1001 title
|
|
* \endverbatim
|
|
*
|
|
* <p>which is ok, but
|
|
*
|
|
* \verbatim
|
|
* -1.966, -0.168,, 0.048,,, 0.184, 0.010, 0.017, 1001,,, run 1001 title
|
|
* \endverbatim
|
|
*
|
|
* <p>will <b>not</b> work!
|
|
*
|
|
* <p>Some db-files do have a '\\-e' or '\\e' label just between the DATA tag line and the real data.
|
|
* This tag will just be ignored.
|
|
*
|
|
* <b>return:</b>
|
|
* - true at successful reading,
|
|
* - otherwise false.
|
|
*/
|
|
Bool_t PRunDataHandler::ReadDBFile()
|
|
{
|
|
Bool_t success = true;
|
|
|
|
// open file
|
|
ifstream f;
|
|
|
|
// open db-file
|
|
f.open(fRunPathName.Data(), ifstream::in);
|
|
if (!f.is_open()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadDBFile **ERROR** Couldn't open data file (" << fRunPathName.Data() << ") for reading, sorry ...";
|
|
cerr << endl;
|
|
return false;
|
|
}
|
|
|
|
PRawRunData runData;
|
|
|
|
runData.fDataNonMusr.SetFromAscii(false);
|
|
|
|
Int_t lineNo = 0;
|
|
Int_t idx;
|
|
Int_t dbTag = -1;
|
|
Char_t instr[512];
|
|
TString line, workStr;
|
|
Double_t val;
|
|
Bool_t firstData = true; // needed as a switch to check in which format the data are given.
|
|
Bool_t labelledFormat = true; // flag showing if the data are given in row format, or as labelled format (see description above, default is labelled format)
|
|
Bool_t dataTagsRead = false; // flag showing if the data tags are alread read
|
|
|
|
// variables needed to tokenize strings
|
|
TString tstr;
|
|
TObjString *ostr;
|
|
TObjArray *tokens = 0;
|
|
|
|
while (!f.eof()) {
|
|
// get next line from file
|
|
f.getline(instr, sizeof(instr));
|
|
line = TString(instr);
|
|
lineNo++;
|
|
|
|
// check if comment line
|
|
if (line.BeginsWith("#") || line.BeginsWith("%"))
|
|
continue;
|
|
|
|
// ignore empty lines
|
|
if (line.IsWhitespace())
|
|
continue;
|
|
|
|
// check for db specific tags
|
|
workStr = line;
|
|
workStr.Remove(TString::kLeading, ' '); // remove spaces from the begining
|
|
if (workStr.BeginsWith("title", TString::kIgnoreCase)) {
|
|
dbTag = 0;
|
|
continue;
|
|
} else if (workStr.BeginsWith("abstract", TString::kIgnoreCase)) {
|
|
dbTag = 1;
|
|
continue;
|
|
} else if (workStr.BeginsWith("comments", TString::kIgnoreCase)) {
|
|
dbTag = 2;
|
|
continue;
|
|
} else if (workStr.BeginsWith("label", TString::kIgnoreCase)) {
|
|
dbTag = 3;
|
|
continue;
|
|
} else if (workStr.BeginsWith("data", TString::kIgnoreCase) && !dataTagsRead) {
|
|
dataTagsRead = true;
|
|
dbTag = 4;
|
|
|
|
// filter out all data tags
|
|
tokens = workStr.Tokenize(" ,\t");
|
|
for (Int_t i=1; i<tokens->GetEntries(); i++) {
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(i));
|
|
runData.fDataNonMusr.AppendDataTag(ostr->GetString());
|
|
}
|
|
|
|
// clean up tokens
|
|
if (tokens) {
|
|
delete tokens;
|
|
tokens = 0;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
switch (dbTag) {
|
|
case 0: // TITLE
|
|
runData.SetRunTitle(workStr);
|
|
break;
|
|
case 1: // ABSTRACT
|
|
// nothing to be done for now
|
|
break;
|
|
case 2: // COMMENTS
|
|
// nothing to be done for now
|
|
break;
|
|
case 3: // LABEL
|
|
runData.fDataNonMusr.AppendLabel(workStr);
|
|
break;
|
|
case 4: // DATA
|
|
// filter out potential start data tag
|
|
if (workStr.BeginsWith("\\-e", TString::kIgnoreCase) ||
|
|
workStr.BeginsWith("\\e", TString::kIgnoreCase) ||
|
|
workStr.BeginsWith("/-e", TString::kIgnoreCase) ||
|
|
workStr.BeginsWith("/e", TString::kIgnoreCase)) {
|
|
continue;
|
|
}
|
|
|
|
// check if first real data line
|
|
if (firstData) {
|
|
// check if data are given just as rows are as labelled columns (see description above)
|
|
tokens = workStr.Tokenize(",");
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(0));
|
|
if (!ostr->GetString().IsFloat()) {
|
|
labelledFormat = true;
|
|
} else {
|
|
labelledFormat = false;
|
|
}
|
|
// clean up tokens
|
|
if (tokens) {
|
|
delete tokens;
|
|
tokens = 0;
|
|
}
|
|
|
|
// prepare data vector for use
|
|
PDoubleVector dummy;
|
|
for (UInt_t i=0; i<runData.fDataNonMusr.GetDataTags()->size(); i++) {
|
|
runData.fDataNonMusr.AppendData(dummy);
|
|
runData.fDataNonMusr.AppendErrData(dummy);
|
|
}
|
|
|
|
firstData = false;
|
|
}
|
|
|
|
if (labelledFormat) { // handle labelled formated data
|
|
// check if run line
|
|
const Char_t *str = workStr.Data();
|
|
if (isdigit(str[0])) { // run line
|
|
TString run("run");
|
|
idx = GetDataTagIndex(run, runData.fDataNonMusr.GetDataTags());
|
|
if (idx == -1) {
|
|
cerr << endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
|
|
cerr << endl << ">> " << workStr.Data();
|
|
cerr << endl << ">> found potential run data line without run data tag.";
|
|
return false;
|
|
}
|
|
// split string in tokens
|
|
tokens = workStr.Tokenize(","); // line has structure: runNo,,, runTitle
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(0));
|
|
tstr = ostr->GetString();
|
|
if (!tstr.IsFloat()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
|
|
cerr << endl << ">> " << workStr.Data();
|
|
cerr << endl << ">> Expected db-data line with structure: runNo,,, runTitle";
|
|
cerr << endl << ">> runNo = " << tstr.Data() << ", seems to be not a number.";
|
|
delete tokens;
|
|
return false;
|
|
}
|
|
val = tstr.Atof();
|
|
runData.fDataNonMusr.AppendSubData(idx, val);
|
|
runData.fDataNonMusr.AppendSubErrData(idx, 1.0);
|
|
} else { // tag = data line
|
|
// remove all possible spaces
|
|
workStr.ReplaceAll(" ", "");
|
|
// split string in tokens
|
|
tokens = workStr.Tokenize("=,"); // line has structure: tag = val,err1,err2,
|
|
if (tokens->GetEntries() < 3) {
|
|
cerr << endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
|
|
cerr << endl << ">> " << workStr.Data();
|
|
cerr << endl << ">> Expected db-data line with structure: tag = val,err1,err2,\\";
|
|
delete tokens;
|
|
return false;
|
|
}
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(0));
|
|
tstr = ostr->GetString();
|
|
idx = GetDataTagIndex(tstr, runData.fDataNonMusr.GetDataTags());
|
|
if (idx == -1) {
|
|
cerr << endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
|
|
cerr << endl << ">> " << workStr.Data();
|
|
cerr << endl << ">> data tag error: " << tstr.Data() << " seems not present in the data tag list";
|
|
delete tokens;
|
|
return false;
|
|
}
|
|
|
|
switch (tokens->GetEntries()) {
|
|
case 3: // tag = val,,,
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(1));
|
|
tstr = ostr->GetString();
|
|
if (!tstr.IsFloat()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
|
|
cerr << endl << ">> " << workStr.Data();
|
|
cerr << endl << ">> Expected db-data line with structure: tag = val,err1,err2,\\";
|
|
cerr << endl << ">> val = " << tstr.Data() << ", seems to be not a number.";
|
|
delete tokens;
|
|
return false;
|
|
}
|
|
val = tstr.Atof();
|
|
runData.fDataNonMusr.AppendSubData(idx, val);
|
|
runData.fDataNonMusr.AppendSubErrData(idx, 1.0);
|
|
break;
|
|
case 4: // tag = val,err,,
|
|
case 5: // tag = val,err1,err2,
|
|
// handle val
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(1));
|
|
tstr = ostr->GetString();
|
|
if (!tstr.IsFloat()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
|
|
cerr << endl << ">> " << workStr.Data();
|
|
cerr << endl << ">> Expected db-data line with structure: tag = val,err1,err2,\\";
|
|
cerr << endl << ">> val = " << tstr.Data() << ", seems to be not a number.";
|
|
delete tokens;
|
|
return false;
|
|
}
|
|
val = tstr.Atof();
|
|
runData.fDataNonMusr.AppendSubData(idx, val);
|
|
// handle err1 (err2 will be ignored for the time being)
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(2));
|
|
tstr = ostr->GetString();
|
|
if (!tstr.IsFloat()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
|
|
cerr << endl << ">> " << workStr.Data();
|
|
cerr << endl << ">> Expected db-data line with structure: tag = val,err1,err2,\\";
|
|
cerr << endl << ">> err1 = " << tstr.Data() << ", seems to be not a number.";
|
|
delete tokens;
|
|
return false;
|
|
}
|
|
val = tstr.Atof();
|
|
runData.fDataNonMusr.AppendSubErrData(idx, val);
|
|
break;
|
|
default:
|
|
cerr << endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
|
|
cerr << endl << ">> " << workStr.Data();
|
|
cerr << endl << ">> Expected db-data line with structure: tag = val,err1,err2,\\";
|
|
delete tokens;
|
|
return false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
} else { // handle row formated data
|
|
// split string in tokens
|
|
tokens = workStr.Tokenize(","); // line has structure: val1, err11, err12, ..., valn, errn1, errn2, runNo, , , , runTitle
|
|
if (tokens->GetEntries() != (Int_t)(3*runData.fDataNonMusr.GetDataTags()->size()+1)) {
|
|
cerr << endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
|
|
cerr << endl << ">> " << workStr.Data();
|
|
cerr << endl << ">> Expected db-data line with structure: val1, err11, err12, ..., valn, errn1, errn2, runNo, , , , runTitle";
|
|
cerr << endl << ">> found = " << tokens->GetEntries() << " tokens, however expected " << 3*runData.fDataNonMusr.GetDataTags()->size()+1;
|
|
cerr << endl << ">> Perhaps there are commas without space inbetween, like 12.3,, 3.2,...";
|
|
delete tokens;
|
|
return false;
|
|
}
|
|
// extract data
|
|
Int_t j=0;
|
|
for (Int_t i=0; i<tokens->GetEntries()-1; i+=3) {
|
|
// handle value
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(i));
|
|
tstr = ostr->GetString();
|
|
if (!tstr.IsFloat()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
|
|
cerr << endl << ">> " << workStr.Data();
|
|
cerr << endl << ">> Expected db-data line with structure: val1, err11, err12, ..., valn, errn1, errn2, runNo, , , , runTitle";
|
|
cerr << endl << ">> value=" << tstr.Data() << " seems not to be a number";
|
|
delete tokens;
|
|
return false;
|
|
}
|
|
runData.fDataNonMusr.AppendSubData(j, tstr.Atof());
|
|
|
|
// handle 1st error if present (2nd will be ignored for now)
|
|
ostr = dynamic_cast<TObjString*>(tokens->At(i+1));
|
|
tstr = ostr->GetString();
|
|
if (tstr.IsWhitespace()) {
|
|
runData.fDataNonMusr.AppendSubErrData(j, 1.0);
|
|
} else if (tstr.IsFloat()) {
|
|
runData.fDataNonMusr.AppendSubErrData(j, tstr.Atof());
|
|
} else {
|
|
cerr << endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo << ":";
|
|
cerr << endl << ">> " << workStr.Data();
|
|
cerr << endl << ">> Expected db-data line with structure: val1, err11, err12, ..., valn, errn1, errn2, runNo, , , , runTitle";
|
|
cerr << endl << ">> error1=" << tstr.Data() << " seems not to be a number";
|
|
delete tokens;
|
|
return false;
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
f.close();
|
|
|
|
// check that the number of labels == the number of data tags
|
|
if (runData.fDataNonMusr.GetLabels()->size() != runData.fDataNonMusr.GetDataTags()->size()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadDBFile **ERROR**";
|
|
cerr << endl << ">> number of LABELS found = " << runData.fDataNonMusr.GetLabels()->size();
|
|
cerr << endl << ">> number of Data tags found = " << runData.fDataNonMusr.GetDataTags()->size();
|
|
cerr << endl << ">> They have to be equal!!";
|
|
if (tokens) {
|
|
delete tokens;
|
|
tokens = 0;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// check if all vectors have the same size
|
|
for (UInt_t i=1; i<runData.fDataNonMusr.GetData()->size(); i++) {
|
|
if (runData.fDataNonMusr.GetData()->at(i).size() != runData.fDataNonMusr.GetData()->at(i-1).size()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo;
|
|
cerr << endl << ">> label: " << runData.fDataNonMusr.GetDataTags()->at(i-1).Data() << ", number data elements = " << runData.fDataNonMusr.GetData()->at(i-1).size();
|
|
cerr << endl << ">> label: " << runData.fDataNonMusr.GetDataTags()->at(i).Data() << ", number data elements = " << runData.fDataNonMusr.GetData()->at(i).size();
|
|
cerr << endl << ">> They have to be equal!!";
|
|
success = false;
|
|
break;
|
|
}
|
|
if (runData.fDataNonMusr.GetErrData()->at(i).size() != runData.fDataNonMusr.GetErrData()->at(i-1).size()) {
|
|
cerr << endl << ">> PRunDataHandler::ReadDBFile **ERROR** in line no " << lineNo;
|
|
cerr << endl << ">> label: " << runData.fDataNonMusr.GetDataTags()->at(i-1).Data() << ", number data elements = " << runData.fDataNonMusr.GetData()->at(i-1).size();
|
|
cerr << endl << ">> label: " << runData.fDataNonMusr.GetDataTags()->at(i).Data() << ", number error data elements = " << runData.fDataNonMusr.GetErrData()->at(i).size();
|
|
cerr << endl << ">> They have to be equal!!";
|
|
success = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// clean up tokens
|
|
if (tokens) {
|
|
delete tokens;
|
|
tokens = 0;
|
|
}
|
|
|
|
// keep run name
|
|
runData.SetRunName(fRunName);
|
|
|
|
fData.push_back(runData);
|
|
|
|
return success;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// WriteMusrRootFile (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Write the MusrRoot file format. Only the required entries will be handled.
|
|
*
|
|
* <b>return:</b>
|
|
* - true on successful writting,
|
|
* - otherwise false.
|
|
*
|
|
* \param fln file name. If empty, the routine will try to construct one
|
|
*/
|
|
Bool_t PRunDataHandler::WriteMusrRootFile(TString fln)
|
|
{
|
|
Bool_t ok = false;
|
|
fln = GenerateOutputFileName(fln, ".root", ok);
|
|
if (!ok)
|
|
return false;
|
|
|
|
if (!fAny2ManyInfo->useStandardOutput)
|
|
cout << endl << ">> PRunDataHandler::WriteMusrRootFile(): writing a root data file (" << fln.Data() << ") ... " << endl;
|
|
|
|
// generate data file
|
|
TFolder *histosFolder;
|
|
TFolder *decayAnaModule;
|
|
TFolder *runHeader;
|
|
|
|
histosFolder = gROOT->GetRootFolder()->AddFolder("histos", "Histograms");
|
|
gROOT->GetListOfBrowsables()->Add(histosFolder, "histos");
|
|
decayAnaModule = histosFolder->AddFolder("DecayAnaModule", "muSR decay histograms");
|
|
|
|
runHeader = gROOT->GetRootFolder()->AddFolder("RunHeader", "MusrRoot Run Header Info");
|
|
gROOT->GetListOfBrowsables()->Add(runHeader, "RunHeader");
|
|
TMusrRunHeader *header = new TMusrRunHeader(true);
|
|
gROOT->GetListOfBrowsables()->Add(runHeader, "RunHeader");
|
|
|
|
// feed header info
|
|
TString str, pathName;
|
|
Int_t ival;
|
|
Double_t dval[2];
|
|
TMusrRunPhysicalQuantity prop;
|
|
|
|
// feed RunInfo
|
|
str = fData[0].GetGenericValidatorUrl()->Copy();
|
|
header->Set("RunInfo/Generic Validator URL", str);
|
|
str = fData[0].GetSpecificValidatorUrl()->Copy();
|
|
header->Set("RunInfo/Specific Validator URL", str);
|
|
str = fData[0].GetGenerator()->Copy();
|
|
header->Set("RunInfo/Generator", str);
|
|
str = fData[0].GetFileName()->Copy();
|
|
header->Set("RunInfo/File Name", str);
|
|
str = fData[0].GetRunTitle()->Copy();
|
|
header->Set("RunInfo/Run Title", str);
|
|
header->Set("RunInfo/Run Number", fData[0].GetRunNumber());
|
|
str = fData[0].GetStartDate()->Copy() + " " + fData[0].GetStartTime()->Copy();
|
|
header->Set("RunInfo/Run Start Time", str);
|
|
str = fData[0].GetStopDate()->Copy() + " " + fData[0].GetStopTime()->Copy();
|
|
header->Set("RunInfo/Run Stop Time", str);
|
|
ival = fData[0].GetStopDateTime() - fData[0].GetStartDateTime();
|
|
prop.Set("Run Duration", ival, "sec");
|
|
header->Set("RunInfo/Run Duration", prop);
|
|
str = fData[0].GetLaboratory()->Copy();
|
|
header->Set("RunInfo/Laboratory", str);
|
|
str = fData[0].GetInstrument()->Copy();
|
|
header->Set("RunInfo/Instrument", str);
|
|
dval[0] = fData[0].GetMuonBeamMomentum();
|
|
prop.Set("Muon Beam Momentum", dval[0], "MeV/c");
|
|
header->Set("RunInfo/Muon Beam Momentum", prop);
|
|
str = fData[0].GetMuonSpecies()->Copy();
|
|
header->Set("RunInfo/Muon Species", str);
|
|
str = fData[0].GetMuonSource()->Copy();
|
|
header->Set("RunInfo/Muon Source", str);
|
|
str = fData[0].GetSetup()->Copy();
|
|
header->Set("RunInfo/Setup", str);
|
|
str = fData[0].GetComment()->Copy();
|
|
header->Set("RunInfo/Comment", str);
|
|
str = fData[0].GetSample()->Copy();
|
|
header->Set("RunInfo/Sample Name", str);
|
|
dval[0] = fData[0].GetTemperature(0);
|
|
dval[1] = fData[0].GetTempError(0);
|
|
prop.Set("Sample Temperature", MRH_UNDEFINED, dval[0], dval[1], "K");
|
|
header->Set("RunInfo/Sample Temperature", prop);
|
|
dval[0] = fData[0].GetField();
|
|
prop.Set("Sample Magnetic Field", dval[0], "G");
|
|
header->Set("RunInfo/Sample Magnetic Field", prop);
|
|
header->Set("RunInfo/No of Histos", (Int_t)fData[0].GetNoOfHistos());
|
|
dval[0] = fData[0].GetTimeResolution();
|
|
prop.Set("Time Resolution", dval[0], "ns");
|
|
header->Set("RunInfo/Time Resolution", prop);
|
|
header->Set("RunInfo/RedGreen Offsets", fData[0].GetRedGreenOffset());
|
|
|
|
// feed DetectorInfo
|
|
Int_t histoNo = 0;
|
|
PRawRunDataSet *dataSet;
|
|
UInt_t size = fData[0].GetNoOfHistos();
|
|
for (UInt_t i=0; i<size; i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
if (dataSet == 0) { // something is really wrong
|
|
cerr << endl << ">> PRunDataHandler::WriteMusrRootFile: **ERROR** Couldn't get data set (idx=" << i << ")";
|
|
cerr << endl << ">> something is really wrong!" << endl;
|
|
return false;
|
|
}
|
|
histoNo = dataSet->GetHistoNo();
|
|
pathName.Form("DetectorInfo/Detector%03d/Name", histoNo);
|
|
str = dataSet->GetName();
|
|
if (!str.CompareTo("n/a"))
|
|
str.Form("Detector%3d", histoNo);
|
|
header->Set(pathName, str);
|
|
pathName.Form("DetectorInfo/Detector%03d/Histo Number", histoNo);
|
|
header->Set(pathName, histoNo);
|
|
pathName.Form("DetectorInfo/Detector%03d/Histo Length", histoNo);
|
|
header->Set(pathName, (Int_t)(dataSet->GetData()->size()/fAny2ManyInfo->rebin));
|
|
pathName.Form("DetectorInfo/Detector%03d/Time Zero Bin", histoNo);
|
|
header->Set(pathName, dataSet->GetTimeZeroBin()/fAny2ManyInfo->rebin);
|
|
pathName.Form("DetectorInfo/Detector%03d/First Good Bin", histoNo);
|
|
ival = dataSet->GetFirstGoodBin();
|
|
header->Set(pathName, (Int_t)(ival/fAny2ManyInfo->rebin));
|
|
pathName.Form("DetectorInfo/Detector%03d/Last Good Bin", histoNo);
|
|
ival = dataSet->GetLastGoodBin();
|
|
header->Set(pathName, (Int_t)(ival/fAny2ManyInfo->rebin));
|
|
}
|
|
|
|
// feed SampleEnvironmentInfo
|
|
str = fData[0].GetCryoName()->Copy();
|
|
header->Set("SampleEnvironmentInfo/Cryo", str);
|
|
|
|
// feed MagneticFieldEnvironmentInfo
|
|
str = fData[0].GetMagnetName()->Copy();
|
|
header->Set("MagneticFieldEnvironmentInfo/Magnet Name", str);
|
|
|
|
// feed BeamlineInfo
|
|
str = fData[0].GetBeamline()->Copy();
|
|
header->Set("BeamlineInfo/Name", str);
|
|
|
|
// feed histos
|
|
vector<TH1F*> histos;
|
|
TH1F *histo = 0;
|
|
UInt_t length = 0;
|
|
if (fAny2ManyInfo->rebin == 1) {
|
|
for (UInt_t i=0; i<size; i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
if (dataSet == 0) { // something is really wrong
|
|
cerr << endl << ">> PRunDataHandler::WriteMusrRootFile: **ERROR** Couldn't get data set (idx=" << i << ")";
|
|
cerr << endl << ">> something is really wrong!" << endl;
|
|
return false;
|
|
}
|
|
str.Form("hDecay%03d", dataSet->GetHistoNo());
|
|
length = dataSet->GetData()->size();
|
|
histo = new TH1F(str.Data(), str.Data(), length+1, -0.5, (Double_t)length+0.5);
|
|
for (UInt_t j=0; j<length; j++) {
|
|
histo->SetBinContent(j+1, dataSet->GetData()->at(j));
|
|
}
|
|
histos.push_back(histo);
|
|
}
|
|
} else { // rebin > 1
|
|
UInt_t dataRebin = 0;
|
|
UInt_t dataCount = 0;
|
|
for (UInt_t i=0; i<size; i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
if (dataSet == 0) { // something is really wrong
|
|
cerr << endl << ">> PRunDataHandler::WriteMusrRootFile: **ERROR** Couldn't get data set (idx=" << i << ")";
|
|
cerr << endl << ">> something is really wrong!" << endl;
|
|
return false;
|
|
}
|
|
str.Form("hDecay%03d", dataSet->GetHistoNo());
|
|
length = dataSet->GetData()->size();
|
|
histo = new TH1F(str.Data(), str.Data(), (Int_t)(length/fAny2ManyInfo->rebin)+1, -0.5, (Double_t)((Int_t)(length/fAny2ManyInfo->rebin))+0.5);
|
|
dataCount = 0;
|
|
for (UInt_t j=0; j<length; j++) {
|
|
if ((j > 0) && (j % fAny2ManyInfo->rebin == 0)) {
|
|
dataCount++;
|
|
histo->SetBinContent(dataCount, dataRebin);
|
|
dataRebin = 0;
|
|
}
|
|
dataRebin += static_cast<UInt_t>(dataSet->GetData()->at(j));
|
|
}
|
|
histos.push_back(histo);
|
|
}
|
|
}
|
|
|
|
// add histos to the DecayAnaModule folder
|
|
for (UInt_t i=0; i<histos.size(); i++)
|
|
decayAnaModule->Add(histos[i]);
|
|
|
|
// write file
|
|
TFile *fout = new TFile(fln, "RECREATE", fln);
|
|
if (fout == 0) {
|
|
cerr << endl << "PRunDataHandler::WriteMusrRootFile(): **ERROR** Couldn't create ROOT file '" << fln << "'" << endl;
|
|
return false;
|
|
}
|
|
|
|
fout->cd();
|
|
if (header->FillFolder(runHeader))
|
|
runHeader->Write();
|
|
histosFolder->Write();
|
|
fout->Close();
|
|
|
|
// check if root file shall be streamed to stdout
|
|
if (fAny2ManyInfo->useStandardOutput && (fAny2ManyInfo->compressionTag == 0)) {
|
|
// stream file to stdout
|
|
ifstream is;
|
|
int length=1024;
|
|
char *buffer;
|
|
|
|
is.open(fln.Data(), ios::binary);
|
|
if (!is.is_open()) {
|
|
cerr << endl << "PRunDataHandler::WriteMusrRootFile(): **ERROR** Couldn't open the root-file for streaming." << endl;
|
|
remove(fln.Data());
|
|
return false;
|
|
}
|
|
|
|
// get length of file
|
|
is.seekg(0, ios::end);
|
|
length = is.tellg();
|
|
is.seekg(0, ios::beg);
|
|
|
|
if (length == -1) {
|
|
cerr << endl << "PRunDataHandler::WriteMusrRootFile(): **ERROR** Couldn't determine the root-file size." << endl;
|
|
remove(fln.Data());
|
|
return false;
|
|
}
|
|
|
|
// allocate memory
|
|
buffer = new char [length];
|
|
|
|
// read data as a block
|
|
while (!is.eof()) {
|
|
is.read(buffer, length);
|
|
cout.write(buffer, length);
|
|
}
|
|
|
|
is.close();
|
|
|
|
delete [] buffer;
|
|
|
|
// delete temporary root file
|
|
remove(fln.Data());
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// WriteRootFile (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Write the PSI LEM root-file format.
|
|
*
|
|
* <b>return:</b>
|
|
* - true on successful writting,
|
|
* - otherwise false.
|
|
*
|
|
* \param fln file name. If empty, the routine will try to construct one
|
|
*/
|
|
Bool_t PRunDataHandler::WriteRootFile(TString fln)
|
|
{
|
|
Bool_t ok = false;
|
|
fln = GenerateOutputFileName(fln, ".root", ok);
|
|
if (!ok)
|
|
return false;
|
|
|
|
|
|
if (!fAny2ManyInfo->useStandardOutput)
|
|
cout << endl << ">> PRunDataHandler::WriteRootFile(): writing a root data file (" << fln.Data() << ") ... " << endl;
|
|
|
|
// generate data file
|
|
TFolder *histosFolder;
|
|
TFolder *decayAnaModule;
|
|
TFolder *runInfo;
|
|
|
|
histosFolder = gROOT->GetRootFolder()->AddFolder("histos", "Histograms");
|
|
gROOT->GetListOfBrowsables()->Add(histosFolder, "histos");
|
|
decayAnaModule = histosFolder->AddFolder("DecayAnaModule", "muSR decay histograms");
|
|
|
|
runInfo = gROOT->GetRootFolder()->AddFolder("RunInfo", "LEM RunInfo");
|
|
gROOT->GetListOfBrowsables()->Add(runInfo, "RunInfo");
|
|
TLemRunHeader *header = new TLemRunHeader();
|
|
gROOT->GetListOfBrowsables()->Add(runInfo, "RunInfo");
|
|
|
|
// feed header info
|
|
header->SetRunTitle(fData[0].GetRunTitle()->Data());
|
|
header->SetLemSetup(fData[0].GetSetup()->Data());
|
|
header->SetRunNumber(fData[0].GetRunNumber());
|
|
TString dt = *fData[0].GetStartDate() + "/" + *fData[0].GetStartTime();
|
|
header->SetStartTimeString(dt.Data());
|
|
dt = *fData[0].GetStopDate() + "/" + *fData[0].GetStopTime();
|
|
header->SetStopTimeString(dt.Data());
|
|
header->SetStartTime(fData[0].GetStartDateTime());
|
|
header->SetStopTime(fData[0].GetStopDateTime());
|
|
header->SetModeratorHV(-999.9, 0.0);
|
|
header->SetSampleHV(-999.9, 0.0);
|
|
header->SetImpEnergy(-999.9);
|
|
header->SetSampleTemperature(fData[0].GetTemperature(0), fData[0].GetTempError(0));
|
|
header->SetSampleBField(fData[0].GetField(), 0.0);
|
|
header->SetTimeResolution(fData[0].GetTimeResolution());
|
|
PRawRunDataSet *dataSet = fData[0].GetDataSet(0, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
header->SetNChannels(static_cast<UInt_t>(dataSet->GetData()->size()/fAny2ManyInfo->rebin));
|
|
header->SetNHist(fData[0].GetNoOfHistos());
|
|
header->SetCuts("none");
|
|
header->SetModerator("none");
|
|
|
|
// feed t0's if possible
|
|
UInt_t NoT0s = fData[0].GetNoOfHistos();
|
|
if (fData[0].GetNoOfHistos() > NHIST) {
|
|
cerr << endl << ">> PRunDataHandler::WriteRootFile: **WARNING** found more T0's (" << NoT0s << ") than can be handled (" << NHIST << ").";
|
|
cerr << endl << ">> Will only write the first " << NHIST << " T0s!!" << endl;
|
|
NoT0s = NHIST;
|
|
}
|
|
Double_t *tt0 = new Double_t[NoT0s];
|
|
|
|
for (UInt_t i=0; i<NoT0s; i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
tt0[i] = dataSet->GetTimeZeroBin()/fAny2ManyInfo->rebin;
|
|
}
|
|
header->SetTimeZero(tt0);
|
|
runInfo->Add(header); // add header to RunInfo folder
|
|
|
|
// feed histos
|
|
vector<TH1F*> histos;
|
|
TH1F *histo = 0;
|
|
Char_t str[32];
|
|
UInt_t size = 0;
|
|
if (fAny2ManyInfo->rebin == 1) {
|
|
for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
if (dataSet == 0) { // something is really wrong
|
|
cerr << endl << ">> PRunDataHandler::WriteRootFile: **ERROR** Couldn't get data set (idx=0" << i << ")";
|
|
cerr << endl << ">> something is really wrong!" << endl;
|
|
return false;
|
|
}
|
|
size = dataSet->GetData()->size();
|
|
sprintf(str, "hDecay%02d", (Int_t)i);
|
|
histo = new TH1F(str, str, size+1, -0.5, static_cast<Double_t>(size)+0.5);
|
|
for (UInt_t j=0; j<size; j++) {
|
|
histo->SetBinContent(j+1, dataSet->GetData()->at(j));
|
|
}
|
|
histos.push_back(histo);
|
|
}
|
|
} else { // rebin > 1
|
|
UInt_t dataRebin = 0;
|
|
UInt_t dataCount = 0;
|
|
for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
if (dataSet == 0) { // something is really wrong
|
|
cerr << endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=0" << i << ")";
|
|
cerr << endl << ">> something is really wrong!" << endl;
|
|
return false;
|
|
}
|
|
size = dataSet->GetData()->size();
|
|
sprintf(str, "hDecay%02d", (Int_t)i);
|
|
histo = new TH1F(str, str, (UInt_t)(size/fAny2ManyInfo->rebin)+1, -0.5, (Double_t)size/(Double_t)fAny2ManyInfo->rebin+0.5);
|
|
dataCount = 0;
|
|
for (UInt_t j=0; j<size; j++) {
|
|
if ((j > 0) && (j % fAny2ManyInfo->rebin == 0)) {
|
|
dataCount++;
|
|
histo->SetBinContent(dataCount, dataRebin);
|
|
dataRebin = 0;
|
|
}
|
|
dataRebin += static_cast<UInt_t>(dataSet->GetData()->at(j));
|
|
}
|
|
histos.push_back(histo);
|
|
}
|
|
}
|
|
|
|
// add histos to the DecayAnaModule folder
|
|
for (UInt_t i=0; i<histos.size(); i++)
|
|
decayAnaModule->Add(histos[i]);
|
|
|
|
// write file
|
|
TFile *fout = new TFile(fln, "RECREATE", fln);
|
|
if (fout == 0) {
|
|
cerr << endl << "PRunDataHandler::WriteRootFile(): **ERROR** Couldn't create ROOT file '" << fln << "'" << endl;
|
|
return false;
|
|
}
|
|
|
|
fout->cd();
|
|
runInfo->Write();
|
|
histosFolder->Write();
|
|
fout->Close();
|
|
|
|
// clean up
|
|
for (UInt_t i=0; i<histos.size(); i++) {
|
|
delete histos[i];
|
|
}
|
|
histos.clear();
|
|
delete fout;
|
|
delete [] tt0;
|
|
delete header;
|
|
|
|
// check if root file shall be streamed to stdout
|
|
if (fAny2ManyInfo->useStandardOutput && (fAny2ManyInfo->compressionTag == 0)) {
|
|
// stream file to stdout
|
|
ifstream is;
|
|
int length=1024;
|
|
char *buffer;
|
|
|
|
is.open(fln.Data(), ios::binary);
|
|
if (!is.is_open()) {
|
|
cerr << endl << "PRunDataHandler::WriteRootFile(): **ERROR** Couldn't open the root-file for streaming." << endl;
|
|
remove(fln.Data());
|
|
return false;
|
|
}
|
|
|
|
// get length of file
|
|
is.seekg(0, ios::end);
|
|
length = is.tellg();
|
|
is.seekg(0, ios::beg);
|
|
|
|
if (length == -1) {
|
|
cerr << endl << "PRunDataHandler::WriteRootFile(): **ERROR** Couldn't determine the root-file size." << endl;
|
|
remove(fln.Data());
|
|
return false;
|
|
}
|
|
|
|
// allocate memory
|
|
buffer = new char [length];
|
|
|
|
// read data as a block
|
|
while (!is.eof()) {
|
|
is.read(buffer, length);
|
|
cout.write(buffer, length);
|
|
}
|
|
|
|
is.close();
|
|
|
|
delete [] buffer;
|
|
|
|
// delete temporary root file
|
|
remove(fln.Data());
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// WriteNexusFile (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Write the nexus-file format.
|
|
*
|
|
* <b>return:</b>
|
|
* - true on successful writting,
|
|
* - otherwise false.
|
|
*
|
|
* \param fln file name. If empty, the routine will try to construct one
|
|
*/
|
|
Bool_t PRunDataHandler::WriteNexusFile(TString fln)
|
|
{
|
|
#ifdef PNEXUS_ENABLED
|
|
Bool_t ok = false;
|
|
fln = GenerateOutputFileName(fln, ".nxs", ok);
|
|
if (!ok)
|
|
return false;
|
|
|
|
if (!fAny2ManyInfo->useStandardOutput)
|
|
cout << endl << ">> PRunDataHandler::WriteNexusFile(): writing a NeXus data file (" << fln.Data() << ") ... " << endl;
|
|
|
|
// create NeXus object
|
|
PNeXus *nxs = new PNeXus();
|
|
if (nxs == 0) {
|
|
cerr << endl << ">> PRunDataHandler::WriteNexusFile(): **ERROR** couldn't invoke the NeXus object." << endl;
|
|
return false;
|
|
}
|
|
|
|
// set IDF version
|
|
nxs->SetIdfVersion(fAny2ManyInfo->idf);
|
|
|
|
if (fAny2ManyInfo->idf == 1) {
|
|
// fill necessary data structures
|
|
nxs->SetFileName(fln.Data());
|
|
|
|
// set file creating time
|
|
time_t now;
|
|
struct tm *tm;
|
|
time(&now);
|
|
tm = localtime(&now);
|
|
string str("");
|
|
char cstr[128];
|
|
strftime(cstr, sizeof(cstr), "%FT%T", tm);
|
|
str = string(cstr);
|
|
nxs->SetFileTime(str);
|
|
|
|
nxs->GetEntryIdf1()->SetProgramName("any2many");
|
|
nxs->GetEntryIdf1()->SetProgramVersion("$Id$");
|
|
nxs->GetEntryIdf1()->SetRunNumber(fData[0].GetRunNumber());
|
|
nxs->GetEntryIdf1()->SetTitle(fData[0].GetRunTitle()->Data());
|
|
nxs->GetEntryIdf1()->SetNotes("n/a");
|
|
nxs->GetEntryIdf1()->SetAnalysis("muonTD");
|
|
if (*fData[0].GetLaboratory() != "n/a")
|
|
nxs->GetEntryIdf1()->SetLaboratory(fData[0].GetLaboratory()->Data());
|
|
if (*fData[0].GetBeamline() != "n/a")
|
|
nxs->GetEntryIdf1()->SetBeamline(fData[0].GetBeamline()->Data());
|
|
str = string(fData[0].GetStartDate()->Data()) + string("T") + string(fData[0].GetStartTime()->Data());
|
|
nxs->GetEntryIdf1()->SetStartTime(str);
|
|
str = string(fData[0].GetStopDate()->Data()) + string("T") + string(fData[0].GetStopTime()->Data());
|
|
nxs->GetEntryIdf1()->SetStopTime(str);
|
|
nxs->GetEntryIdf1()->SetSwitchingState(1);
|
|
nxs->GetEntryIdf1()->GetUser()->SetName("n/a");
|
|
nxs->GetEntryIdf1()->GetUser()->SetExperimentNumber("n/a");
|
|
nxs->GetEntryIdf1()->GetSample()->SetName(fData[0].GetSample()->Data());
|
|
nxs->GetEntryIdf1()->GetSample()->SetPhysProp("temperature", fData[0].GetTemperature(0), "Kelvin");
|
|
nxs->GetEntryIdf1()->GetSample()->SetPhysProp("magnetic_field", fData[0].GetField(), "Gauss");
|
|
nxs->GetEntryIdf1()->GetSample()->SetEnvironment(fData[0].GetSetup()->Data());
|
|
nxs->GetEntryIdf1()->GetSample()->SetShape("n/a");
|
|
nxs->GetEntryIdf1()->GetSample()->SetMagneticFieldVectorAvailable(0);
|
|
if (*fData[0].GetInstrument() != "n/a")
|
|
nxs->GetEntryIdf1()->GetInstrument()->SetName(fData[0].GetInstrument()->Data());
|
|
nxs->GetEntryIdf1()->GetInstrument()->GetDetector()->SetNumber(fData[0].GetNoOfHistos());
|
|
nxs->GetEntryIdf1()->GetInstrument()->GetCollimator()->SetType("n/a");
|
|
// calculate the total number of counts
|
|
double total_counts = 0;
|
|
PRawRunDataSet *dataSet = 0;
|
|
for (unsigned int i=0; i<fData[0].GetNoOfHistos(); i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
if (dataSet == 0) { // something is really wrong
|
|
cerr << endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=0" << i << ")";
|
|
cerr << endl << ">> something is really wrong!" << endl;
|
|
return false;
|
|
}
|
|
for (unsigned int j=0; j<dataSet->GetData()->size(); j++)
|
|
total_counts += dataSet->GetData()->at(j);
|
|
}
|
|
double total_counts_mev = (double) total_counts / 1.0e6;
|
|
nxs->GetEntryIdf1()->GetInstrument()->GetBeam()->SetTotalCounts(total_counts_mev);
|
|
nxs->GetEntryIdf1()->GetInstrument()->GetBeam()->SetUnits("Mev");
|
|
|
|
nxs->GetEntryIdf1()->GetData()->SetTimeResolution(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin, "ns");
|
|
|
|
for (unsigned int i=0; i<fData[0].GetNoOfHistos(); i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
nxs->GetEntryIdf1()->GetData()->SetT0((Int_t)(dataSet->GetTimeZeroBin()/fAny2ManyInfo->rebin), i);
|
|
nxs->GetEntryIdf1()->GetData()->SetFirstGoodBin((Int_t)(dataSet->GetFirstGoodBin()/fAny2ManyInfo->rebin), i);
|
|
nxs->GetEntryIdf1()->GetData()->SetLastGoodBin((Int_t)(dataSet->GetLastGoodBin()/fAny2ManyInfo->rebin), i);
|
|
}
|
|
|
|
// feed histos
|
|
PUIntVector data;
|
|
UInt_t size = 0;
|
|
if (fAny2ManyInfo->rebin == 1) {
|
|
for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
if (dataSet == 0) { // something is really wrong
|
|
cerr << endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=" << i << ")";
|
|
cerr << endl << ">> something is really wrong!" << endl;
|
|
return false;
|
|
}
|
|
size = dataSet->GetData()->size();
|
|
for (UInt_t j=0; j<size; j++) {
|
|
data.push_back((UInt_t)dataSet->GetData()->at(j));
|
|
}
|
|
nxs->GetEntryIdf1()->GetData()->SetHisto(data, i);
|
|
data.clear();
|
|
}
|
|
} else { // rebin > 1
|
|
UInt_t dataRebin = 0;
|
|
UInt_t dataCount = 0;
|
|
for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
if (dataSet == 0) { // something is really wrong
|
|
cerr << endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=" << i << ")";
|
|
cerr << endl << ">> something is really wrong!" << endl;
|
|
return false;
|
|
}
|
|
size = dataSet->GetData()->size();
|
|
dataCount = 0;
|
|
for (UInt_t j=0; j<size; j++) {
|
|
if ((j > 0) && (j % fAny2ManyInfo->rebin == 0)) {
|
|
dataCount++;
|
|
data.push_back(dataRebin);
|
|
dataRebin = 0;
|
|
}
|
|
dataRebin += static_cast<UInt_t>(dataSet->GetData()->at(j));
|
|
}
|
|
nxs->GetEntryIdf1()->GetData()->SetHisto(data, i);
|
|
data.clear();
|
|
}
|
|
}
|
|
} else if (fAny2ManyInfo->idf == 2) {
|
|
// fill necessary data structures
|
|
nxs->SetFileName(fln.Data());
|
|
|
|
// set file creating time
|
|
time_t now;
|
|
struct tm *tm;
|
|
time(&now);
|
|
tm = localtime(&now);
|
|
string str("");
|
|
char cstr[128];
|
|
strftime(cstr, sizeof(cstr), "%FT%T", tm);
|
|
str = string(cstr);
|
|
nxs->SetFileTime(str);
|
|
|
|
// NXroot info
|
|
nxs->SetCreator("PSI: any2many");
|
|
|
|
// NXentry info
|
|
nxs->GetEntryIdf2()->SetDefinition("muonTD");
|
|
nxs->GetEntryIdf2()->SetProgramName("any2many");
|
|
nxs->GetEntryIdf2()->SetProgramVersion("$Id$");
|
|
nxs->GetEntryIdf2()->SetRunNumber(fData[0].GetRunNumber());
|
|
nxs->GetEntryIdf2()->SetTitle(fData[0].GetRunTitle()->Data());
|
|
str = string(fData[0].GetStartDate()->Data()) + string("T") + string(fData[0].GetStartTime()->Data());
|
|
nxs->GetEntryIdf2()->SetStartTime(str);
|
|
str = string(fData[0].GetStopDate()->Data()) + string("T") + string(fData[0].GetStopTime()->Data());
|
|
nxs->GetEntryIdf2()->SetStopTime(str);
|
|
|
|
nxs->GetEntryIdf2()->SetExperimentIdentifier("n/a");
|
|
|
|
// NXuser info
|
|
nxs->GetEntryIdf2()->GetUser()->SetName("n/a");
|
|
|
|
// NXsample info
|
|
nxs->GetEntryIdf2()->GetSample()->SetName(fData[0].GetSample()->Data());
|
|
nxs->GetEntryIdf2()->GetSample()->SetDescription("n/a");
|
|
nxs->GetEntryIdf2()->GetSample()->SetPhysProp("temperature_1", fData[0].GetTemperature(0), "Kelvin");
|
|
nxs->GetEntryIdf2()->GetSample()->SetPhysProp("magnetic_field_1", fData[0].GetField(), "Gauss");
|
|
nxs->GetEntryIdf2()->GetSample()->SetEnvironmentTemp(fData[0].GetSetup()->Data());
|
|
nxs->GetEntryIdf2()->GetSample()->SetEnvironmentField("n/a");
|
|
|
|
// here would be the information for NXinstrument. Currently there are not much information to feed this
|
|
nxs->GetEntryIdf2()->GetInstrument()->SetName(fData[0].GetInstrument()->Data());
|
|
|
|
// NXinstrument/NXsource
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetSource()->SetName(fData[0].GetLaboratory()->Data());
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetSource()->SetType(fData[0].GetMuonSource()->Data());
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetSource()->SetProbe(fData[0].GetMuonSpecies()->Data());
|
|
|
|
// NXinstrument/NXbeamline
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetBeamline()->SetName(fData[0].GetBeamline()->Data());
|
|
|
|
// NXinstrument/NXdetector
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetDescription(fData[0].GetInstrument()->Data()); // assume that this should be the instrument name
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetNoOfPeriods(0); // currently red/green is not distinguished
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetNoOfSpectra(fData[0].GetNoOfHistos());
|
|
PRawRunDataSet *dataSet = fData[0].GetDataSet(0, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
if (dataSet == 0) { // something is really wrong
|
|
cerr << endl << ">> PRunDataHandler::WriteNeXusFile: **ERROR** Couldn't get data set (idx=0)";
|
|
cerr << endl << ">> something is really wrong!" << endl;
|
|
return false;
|
|
}
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetNoOfBins((unsigned int)(dataSet->GetData()->size() / fAny2ManyInfo->rebin));
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetTimeResolution(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin, "ns");
|
|
int *histo = 0;
|
|
int idx = 0;
|
|
if (fAny2ManyInfo->rebin == 1) {
|
|
histo = new int[fData[0].GetNoOfHistos()*dataSet->GetData()->size()];
|
|
idx = 0;
|
|
for (int i=0; i<nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra(); i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
if (dataSet == 0) { // something is really wrong
|
|
cerr << endl << ">> PRunDataHandler::WriteNeXusFile: **ERROR** Couldn't get data set (idx=" << i << ")";
|
|
cerr << endl << ">> something is really wrong!" << endl;
|
|
return false;
|
|
}
|
|
for (unsigned int j=0; j<dataSet->GetData()->size(); j++) {
|
|
*(histo+idx++) = (int) dataSet->GetData()->at(j);
|
|
}
|
|
}
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetHistos(histo);
|
|
// clean up
|
|
if (histo) {
|
|
delete [] histo;
|
|
histo = 0;
|
|
}
|
|
} else { // rebin > 1
|
|
histo = new int[fData[0].GetNoOfHistos()*(int)(dataSet->GetData()->size()/fAny2ManyInfo->rebin)];
|
|
int counts = 0;
|
|
idx = 0;
|
|
for (int i=0; i<nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra(); i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
if (dataSet == 0) { // something is really wrong
|
|
cerr << endl << ">> PRunDataHandler::WriteNeXusFile: **ERROR** Couldn't get data set (idx=" << i << ")";
|
|
cerr << endl << ">> something is really wrong!" << endl;
|
|
return false;
|
|
}
|
|
for (unsigned int j=0; j<dataSet->GetData()->size(); j++) {
|
|
if ((j>0) && (j % fAny2ManyInfo->rebin == 0)) {
|
|
*(histo+idx++) = counts;
|
|
counts = 0;
|
|
}
|
|
counts += (int) dataSet->GetData()->at(j);
|
|
}
|
|
}
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetHistos(histo);
|
|
// clean up
|
|
if (histo) {
|
|
delete [] histo;
|
|
histo = 0;
|
|
}
|
|
}
|
|
|
|
// handle spectrum index
|
|
for (int i=0; i<nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra(); i++)
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetSpectrumIndex(i+1);
|
|
|
|
// handle histogram resolution
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetTimeResolution(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin, "ns");
|
|
|
|
// handle raw time
|
|
vector<double> raw_time;
|
|
UInt_t size = (unsigned int)(dataSet->GetData()->size() / fAny2ManyInfo->rebin);
|
|
for (unsigned int i=0; i<size; i++) {
|
|
raw_time.push_back((double)i * fData[0].GetTimeResolution() * fAny2ManyInfo->rebin * 1.0e-3); // since time resolution is given in ns, the factor 1.0e-3 is needed to convert to us
|
|
}
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetRawTime(raw_time);
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetRawTimeUnit("micro.second");
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetRawTimeName("time");
|
|
raw_time.clear();
|
|
|
|
// handle t0
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetT0Tag(2); // i.e. t0[#histo] format
|
|
int *t0 = new int[fData[0].GetNoOfHistos()];
|
|
int *fgb = new int[fData[0].GetNoOfHistos()];
|
|
int *lgb = new int[fData[0].GetNoOfHistos()];
|
|
if ((t0==0) || (fgb==0) || (lgb==0)) {
|
|
cerr << endl << ">> PRunDataHandler::WriteNeXusFile: **ERROR** Couldn't allocate memory for t0, fgb, lgb" << endl;
|
|
return false;
|
|
}
|
|
for (unsigned int i=0; i<fData[0].GetNoOfHistos(); i++) {
|
|
PRawRunDataSet *dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
if (dataSet == 0) { // something is really wrong
|
|
cerr << endl << ">> PRunDataHandler::WriteNeXusFile: **ERROR** Couldn't get data set (idx=0)";
|
|
cerr << endl << ">> something is really wrong!" << endl;
|
|
return false;
|
|
}
|
|
t0[i] = (int)(dataSet->GetTimeZeroBin() / fAny2ManyInfo->rebin);
|
|
fgb[i] = (int)(dataSet->GetFirstGoodBin() / fAny2ManyInfo->rebin);
|
|
lgb[i] = (int)(dataSet->GetLastGoodBin() / fAny2ManyInfo->rebin);
|
|
}
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetT0(t0);
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetFirstGoodBin(fgb);
|
|
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetLastGoodBin(lgb);
|
|
|
|
// clean up
|
|
if (t0) delete [] t0;
|
|
if (fgb) delete [] fgb;
|
|
if (lgb) delete [] lgb;
|
|
} else {
|
|
// clean up
|
|
if (nxs != 0) {
|
|
delete nxs;
|
|
nxs = 0;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// filter out the proper file type, i.e. HDF4, HDF5, or XML
|
|
char fileType[32];
|
|
memset(fileType, '\0', 32);
|
|
if (!fAny2ManyInfo->outFormat.CompareTo("nexus1-hdf4", TString::kIgnoreCase) || !fAny2ManyInfo->outFormat.CompareTo("nexus2-hdf4", TString::kIgnoreCase))
|
|
strncpy(fileType, "hdf4", sizeof(fileType));
|
|
else if (!fAny2ManyInfo->outFormat.CompareTo("nexus1-hdf5", TString::kIgnoreCase) || !fAny2ManyInfo->outFormat.CompareTo("nexus2-hdf5", TString::kIgnoreCase))
|
|
strncpy(fileType, "hdf5", sizeof(fileType));
|
|
else if (!fAny2ManyInfo->outFormat.CompareTo("nexus1-xml", TString::kIgnoreCase) || !fAny2ManyInfo->outFormat.CompareTo("nexus2-xml", TString::kIgnoreCase))
|
|
strncpy(fileType, "xml", sizeof(fileType));
|
|
else {
|
|
cerr << endl << ">> PRunDataHandler::WriteNexusFile(): **ERROR** undefined output NeXus format " << fAny2ManyInfo->outFormat.Data() << " found.";
|
|
cerr << endl << ">> Allowed are: hdf4, hdf5, xml" << endl;
|
|
if (nxs != 0) {
|
|
delete nxs;
|
|
nxs = 0;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// write file
|
|
nxs->WriteFile(fln, fileType, fAny2ManyInfo->idf);
|
|
|
|
if (nxs != 0) {
|
|
delete nxs;
|
|
nxs = 0;
|
|
}
|
|
#else
|
|
cout << endl << ">> PRunDataHandler::WriteNexusFile(): Sorry, not enabled at configuration level, i.e. --enable-NeXus when executing configure" << endl << endl;
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// WriteWkmFile (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Write the wkm-file format.
|
|
*
|
|
* <b>return:</b>
|
|
* - true on successful writting,
|
|
* - otherwise false.
|
|
*
|
|
* \param fln file name. If empty, the routine will try to construct one
|
|
*/
|
|
Bool_t PRunDataHandler::WriteWkmFile(TString fln)
|
|
{
|
|
// check if a LEM nemu file needs to be written
|
|
bool lem_wkm_style = false;
|
|
if (!fData[0].GetBeamline()->CompareTo("mue4", TString::kIgnoreCase))
|
|
lem_wkm_style = true;
|
|
|
|
Bool_t ok = false;
|
|
if (lem_wkm_style)
|
|
fln = GenerateOutputFileName(fln, ".nemu", ok);
|
|
else
|
|
fln = GenerateOutputFileName(fln, ".wkm", ok);
|
|
|
|
if (!ok)
|
|
return false;
|
|
|
|
TString fileName = fln;
|
|
|
|
if (!fAny2ManyInfo->useStandardOutput)
|
|
cout << endl << ">> PRunDataHandler::WriteWkmFile(): writing a wkm data file (" << fln.Data() << ") ... " << endl;
|
|
|
|
// write ascii file
|
|
ofstream fout;
|
|
streambuf* strm_buffer = 0;
|
|
|
|
if (!fAny2ManyInfo->useStandardOutput || (fAny2ManyInfo->compressionTag > 0)) {
|
|
// open data-file
|
|
fout.open(fln.Data(), ofstream::out);
|
|
if (!fout.is_open()) {
|
|
cerr << endl << ">> PRunDataHandler::WriteWkmFile **ERROR** Couldn't open data file (" << fln.Data() << ") for writing, sorry ...";
|
|
cerr << endl;
|
|
return false;
|
|
}
|
|
|
|
// save output buffer of the stream
|
|
strm_buffer = cout.rdbuf();
|
|
|
|
// redirect output into the file
|
|
cout.rdbuf(fout.rdbuf());
|
|
}
|
|
|
|
// write header
|
|
cout << "- WKM data file converted with any2many";
|
|
if (lem_wkm_style) {
|
|
cout << endl << "NEMU_Run: " << fData[0].GetRunNumber();
|
|
cout << endl << "nemu_Run: " << fileName.Data();
|
|
} else {
|
|
cout << endl << "Run: " << fData[0].GetRunNumber();
|
|
}
|
|
cout << endl << "Date: " << fData[0].GetStartTime()->Data() << " " << fData[0].GetStartDate()->Data() << " / " << fData[0].GetStopTime()->Data() << " " << fData[0].GetStopDate()->Data();
|
|
if (fData[0].GetRunTitle()->Length() > 0)
|
|
cout << endl << "Title: " << fData[0].GetRunTitle()->Data();
|
|
if (fData[0].GetField() != PMUSR_UNDEFINED) {
|
|
cout << endl << "Field: " << fData[0].GetField();
|
|
} else {
|
|
cout << endl << "Field: ??";
|
|
}
|
|
cout << endl << "Setup: " << fData[0].GetSetup()->Data();
|
|
if (fData[0].GetNoOfTemperatures() == 1) {
|
|
cout << endl << "Temp: " << fData[0].GetTemperature(0);
|
|
} else if (fData[0].GetNoOfTemperatures() > 1) {
|
|
cout << endl << "Temp(meas1): " << fData[0].GetTemperature(0) << " +- " << fData[0].GetTempError(0);
|
|
cout << endl << "Temp(meas2): " << fData[0].GetTemperature(1) << " +- " << fData[0].GetTempError(1);
|
|
} else {
|
|
cout << endl << "Temp: ??";
|
|
}
|
|
if (lem_wkm_style)
|
|
cout << endl << "TOF(M3S1): nocut";
|
|
cout << endl << "Groups: " << fData[0].GetNoOfHistos();
|
|
cout << endl << "Channels: " << static_cast<UInt_t>(fData[0].GetDataBin(1)->size()/fAny2ManyInfo->rebin);
|
|
cout.precision(10);
|
|
cout << endl << "Resolution: " << fData[0].GetTimeResolution()*fAny2ManyInfo->rebin/1.0e3; // ns->us
|
|
cout.setf(ios::fixed,ios::floatfield); // floatfield set to fixed
|
|
|
|
// write data
|
|
UInt_t no_of_bins_per_line = 16;
|
|
if (lem_wkm_style)
|
|
no_of_bins_per_line = 10;
|
|
|
|
PRawRunDataSet *dataSet;
|
|
|
|
if (fAny2ManyInfo->rebin == 1) {
|
|
for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
|
|
cout << endl << endl;
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
for (UInt_t j=0; j<dataSet->GetData()->size(); j++) {
|
|
if ((j > 0) && (j % no_of_bins_per_line == 0))
|
|
cout << endl;
|
|
if (lem_wkm_style)
|
|
cout << setw(8) << static_cast<Int_t>(dataSet->GetData()->at(j));
|
|
else
|
|
cout << static_cast<Int_t>(dataSet->GetData()->at(j)) << " ";
|
|
}
|
|
}
|
|
} else { // rebin > 1
|
|
Int_t dataRebin = 0;
|
|
UInt_t count = 0;
|
|
for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
|
|
cout << endl << endl;
|
|
count = 0;
|
|
dataRebin = 0; // reset rebin
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
for (UInt_t j=0; j<dataSet->GetData()->size(); j++) {
|
|
if ((j > 0) && (j % fAny2ManyInfo->rebin == 0)) {
|
|
if (lem_wkm_style)
|
|
cout << setw(8) << dataRebin;
|
|
else
|
|
cout << dataRebin << " ";
|
|
count++;
|
|
dataRebin = 0;
|
|
if ((count > 0) && (count % no_of_bins_per_line == 0) && (j != dataSet->GetData()->size()-1))
|
|
cout << endl;
|
|
} else {
|
|
dataRebin += static_cast<Int_t>(dataSet->GetData()->at(j));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!fAny2ManyInfo->useStandardOutput || (fAny2ManyInfo->compressionTag > 0)) {
|
|
// restore old output buffer
|
|
cout.rdbuf(strm_buffer);
|
|
|
|
fout.close();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// WritePsiBinFile (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Write the psi-bin-file format.
|
|
*
|
|
* <b>return:</b>
|
|
* - true on successful writting,
|
|
* - otherwise false.
|
|
*
|
|
* \param fln file name. If empty, the routine will try to construct one
|
|
*/
|
|
Bool_t PRunDataHandler::WritePsiBinFile(TString fln)
|
|
{
|
|
Bool_t ok = false;
|
|
fln = GenerateOutputFileName(fln, ".bin", ok);
|
|
if (!ok)
|
|
return false;
|
|
|
|
if (!fAny2ManyInfo->useStandardOutput)
|
|
cout << endl << ">> PRunDataHandler::WritePsiBinFile(): writing a psi-bin data file (" << fln.Data() << ") ... " << endl;
|
|
|
|
MuSR_td_PSI_bin psibin;
|
|
int status = 0;
|
|
|
|
// fill header information
|
|
// run number
|
|
psibin.put_runNumber_int(fData[0].GetRunNumber());
|
|
// length of histograms
|
|
psibin.put_histoLength_bin((int)(fData[0].GetDataBin(1)->size()/fAny2ManyInfo->rebin));
|
|
// number of histograms
|
|
psibin.put_numberHisto_int((int)fData[0].GetNoOfHistos());
|
|
// run title = sample (10 char) / temp (10 char) / field (10 char) / orientation (10 char)
|
|
char cstr[11];
|
|
// sample
|
|
if (fData[0].GetSample()->Length() > 0)
|
|
strncpy(cstr, fData[0].GetSample()->Data(), 10);
|
|
else
|
|
strcpy(cstr, "??");
|
|
cstr[10] = '\0';
|
|
psibin.put_sample(cstr);
|
|
// temp
|
|
if (fData[0].GetNoOfTemperatures() > 0)
|
|
snprintf(cstr, 10, "%.1f K", fData[0].GetTemperature(0));
|
|
else
|
|
strcpy(cstr, "?? K");
|
|
cstr[10] = '\0';
|
|
psibin.put_temp(cstr);
|
|
// field
|
|
if (fData[0].GetField() > 0)
|
|
snprintf(cstr, 10, "%.1f G", fData[0].GetField());
|
|
else
|
|
strcpy(cstr, "?? G");
|
|
cstr[10] = '\0';
|
|
psibin.put_field(cstr);
|
|
// orientation
|
|
if (fData[0].GetOrientation()->Length() > 0)
|
|
strncpy(cstr, fData[0].GetOrientation()->Data(), 10);
|
|
else
|
|
strcpy(cstr, "??");
|
|
cstr[10] = '\0';
|
|
psibin.put_orient(cstr);
|
|
// setup
|
|
if (fData[0].GetSetup()->Length() > 0)
|
|
strncpy(cstr, fData[0].GetSetup()->Data(), 10);
|
|
else
|
|
strcpy(cstr, "??");
|
|
cstr[10] = '\0';
|
|
psibin.put_setup(cstr);
|
|
|
|
// handle PSI-BIN start/stop Time/Date. PSI-BIN requires: Time -> HH:MM:SS, and Date -> DD-MMM-YY
|
|
// internally given: Time -> HH:MM:SS, and Date -> YYYY-MM-DD
|
|
// run start date
|
|
vector<string> svec;
|
|
TString str, date;
|
|
TDatime dt;
|
|
dt.Set(fData[0].GetStartDateTime());
|
|
date.Form("%02d-", dt.GetDay());
|
|
date.Append(GetMonth(dt.GetMonth()));
|
|
date.Append("-");
|
|
date.Append(GetYear(dt.GetYear()));
|
|
strncpy(cstr, date.Data(), 9);
|
|
cstr[9] = '\0';
|
|
svec.push_back(cstr);
|
|
// run start time
|
|
strncpy(cstr, fData[0].GetStartTime()->Data(), 8);
|
|
cstr[8] = '\0';
|
|
svec.push_back(cstr);
|
|
psibin.put_timeStart_vector(svec);
|
|
svec.clear();
|
|
|
|
// run stop date
|
|
dt.Set(fData[0].GetStopDateTime());
|
|
date.Form("%02d-", dt.GetDay());
|
|
date.Append(GetMonth(dt.GetMonth()));
|
|
date.Append("-");
|
|
date.Append(GetYear(dt.GetYear()));
|
|
strncpy(cstr, date.Data(), 9);
|
|
cstr[9] = '\0';
|
|
svec.push_back(cstr);
|
|
// run stop time
|
|
strncpy(cstr, fData[0].GetStopTime()->Data(), 8);
|
|
cstr[8] = '\0';
|
|
svec.push_back(cstr);
|
|
psibin.put_timeStop_vector(svec);
|
|
svec.clear();
|
|
|
|
// number of measured temperatures
|
|
psibin.put_numberTemperature_int(fData[0].GetNoOfTemperatures());
|
|
|
|
// mean temperatures
|
|
vector<double> dvec;
|
|
for (UInt_t i=0; i<fData[0].GetNoOfTemperatures(); i++)
|
|
dvec.push_back(fData[0].GetTemperature(i));
|
|
psibin.put_temperatures_vector(dvec);
|
|
|
|
// standard deviation of temperatures
|
|
dvec.clear();
|
|
for (UInt_t i=0; i<fData[0].GetNoOfTemperatures(); i++)
|
|
dvec.push_back(fData[0].GetTempError(i));
|
|
psibin.put_devTemperatures_vector(dvec);
|
|
|
|
// write comment
|
|
psibin.put_comment(fData[0].GetRunTitle()->Data());
|
|
|
|
// write time resolution
|
|
psibin.put_binWidth_ns(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin);
|
|
|
|
// write scaler dummies
|
|
psibin.put_numberScaler_int(0);
|
|
|
|
// feed detector related info like, histogram names, t0, fgb, lgb
|
|
Int_t ival = 0;
|
|
PRawRunDataSet *dataSet;
|
|
UInt_t size = fData[0].GetNoOfHistos();
|
|
for (UInt_t i=0; i<size; i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
if (dataSet == 0) { // something is really wrong
|
|
cerr << endl << ">> PRunDataHandler::WritePsiBinFile: **ERROR** Couldn't get data set (idx=" << i << ")";
|
|
cerr << endl << ">> something is really wrong!" << endl;
|
|
return false;
|
|
}
|
|
|
|
// detector name
|
|
str = dataSet->GetName();
|
|
if (!str.CompareTo("n/a"))
|
|
str.Form("Detector%3d", i+1);
|
|
psibin.put_nameHisto(str.Data(), i);
|
|
// time zero bin
|
|
ival = (Int_t)(dataSet->GetTimeZeroBin()/fAny2ManyInfo->rebin);
|
|
psibin.put_t0_int(i, ival);
|
|
// first good bin
|
|
ival = (Int_t)(dataSet->GetFirstGoodBin()/fAny2ManyInfo->rebin);
|
|
psibin.put_firstGood_int(i, ival);
|
|
// last good bin
|
|
ival = (Int_t)(dataSet->GetLastGoodBin()/fAny2ManyInfo->rebin);
|
|
psibin.put_lastGood_int(i, ival);
|
|
}
|
|
|
|
// feed histos
|
|
vector< vector<int> > histos;
|
|
histos.resize(fData[0].GetNoOfHistos());
|
|
UInt_t length = 0;
|
|
if (fAny2ManyInfo->rebin == 1) {
|
|
for (UInt_t i=0; i<size; i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
if (dataSet == 0) { // something is really wrong
|
|
cerr << endl << ">> PRunDataHandler::WritePsiBinFile: **ERROR** Couldn't get data set (idx=" << i << ")";
|
|
cerr << endl << ">> something is really wrong!" << endl;
|
|
return false;
|
|
}
|
|
length = dataSet->GetData()->size();
|
|
histos[i].resize(length);
|
|
for (UInt_t j=0; j<length; j++) {
|
|
histos[i][j] = (Int_t)dataSet->GetData()->at(j);
|
|
}
|
|
}
|
|
} else { // rebin > 1
|
|
UInt_t dataRebin = 0;
|
|
UInt_t dataCount = 0;
|
|
for (UInt_t i=0; i<size; i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
if (dataSet == 0) { // something is really wrong
|
|
cerr << endl << ">> PRunDataHandler::WritePsiBinFile: **ERROR** Couldn't get data set (idx=" << i << ")";
|
|
cerr << endl << ">> something is really wrong!" << endl;
|
|
return false;
|
|
}
|
|
length = dataSet->GetData()->size();
|
|
dataCount = 0;
|
|
for (UInt_t j=0; j<length; j++) {
|
|
if ((j > 0) && (j % fAny2ManyInfo->rebin == 0)) {
|
|
dataCount++;
|
|
histos[i].push_back(dataRebin);
|
|
dataRebin = 0;
|
|
}
|
|
dataRebin += static_cast<UInt_t>(dataSet->GetData()->at(j));
|
|
}
|
|
}
|
|
}
|
|
status = psibin.put_histo_array_int(histos);
|
|
if (status != 0) {
|
|
cerr << endl << ">> PRunDataHandler::WritePsiBinFile(): " << psibin.ConsistencyStatus() << endl;
|
|
return false;
|
|
}
|
|
|
|
if (!psibin.CheckDataConsistency()) {
|
|
cerr << endl << ">> PRunDataHandler::WritePsiBinFile(): " << psibin.ConsistencyStatus() << endl;
|
|
return false;
|
|
}
|
|
|
|
// write data to file
|
|
status = psibin.write(fln.Data());
|
|
|
|
if (status != 0) {
|
|
cerr << endl << ">> PRunDataHandler::WritePsiBinFile(): " << psibin.WriteStatus() << endl;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// WriteMudFile (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Write the mud-file format.
|
|
*
|
|
* <b>return:</b>
|
|
* - true on successful writting,
|
|
* - otherwise false.
|
|
*
|
|
* \param fln file name. If empty, the routine will try to construct one
|
|
*/
|
|
Bool_t PRunDataHandler::WriteMudFile(TString fln)
|
|
{
|
|
Bool_t ok = false;
|
|
fln = GenerateOutputFileName(fln, ".msr", ok);
|
|
if (!ok)
|
|
return false;
|
|
|
|
if (!fAny2ManyInfo->useStandardOutput)
|
|
cout << endl << ">> PRunDataHandler::WriteMudFile(): writing a mud data file (" << fln.Data() << ") ... " << endl;
|
|
|
|
// generate the mud data file
|
|
int fd = MUD_openWrite((char*)fln.Data(), MUD_FMT_TRI_TD_ID);
|
|
if (fd == -1) {
|
|
cerr << endl << ">> PRunDataHandler::WriteMudFile(): **ERROR** couldn't open mud data file for write ..." << endl;
|
|
return false;
|
|
}
|
|
|
|
// generate header information
|
|
char dummy[32], info[128];
|
|
strcpy(dummy, "???");
|
|
MUD_setRunDesc(fd, MUD_SEC_GEN_RUN_DESC_ID);
|
|
MUD_setExptNumber(fd, 0);
|
|
MUD_setRunNumber(fd, fData[0].GetRunNumber());
|
|
Int_t ival = fData[0].GetStopDateTime()-fData[0].GetStartDateTime();
|
|
MUD_setElapsedSec(fd, ival);
|
|
MUD_setTimeBegin(fd, fData[0].GetStartDateTime());
|
|
MUD_setTimeEnd(fd, fData[0].GetStopDateTime());
|
|
MUD_setTitle(fd, (char *)fData[0].GetRunTitle()->Data());
|
|
MUD_setLab(fd, (char *)fData[0].GetLaboratory()->Data());
|
|
MUD_setArea(fd, (char *)fData[0].GetBeamline()->Data());
|
|
MUD_setMethod(fd, (char *)fData[0].GetSetup()->Data());
|
|
MUD_setApparatus(fd, (char *)fData[0].GetInstrument()->Data());
|
|
MUD_setInsert(fd, dummy);
|
|
MUD_setSample(fd, (char *)fData[0].GetSample()->Data());
|
|
MUD_setOrient(fd, (char *)fData[0].GetOrientation()->Data());
|
|
MUD_setDas(fd, dummy);
|
|
MUD_setExperimenter(fd, dummy);
|
|
sprintf(info, "%lf+-%lf (K)", fData[0].GetTemperature(0), fData[0].GetTempError(0));
|
|
MUD_setTemperature(fd, info);
|
|
sprintf(info, "%lf", fData[0].GetField());
|
|
MUD_setField(fd, info);
|
|
|
|
// generate the histograms
|
|
MUD_setHists(fd, MUD_GRP_TRI_TD_HIST_ID, fData[0].GetNoOfHistos());
|
|
|
|
UInt_t *data, dataSize = fData[0].GetDataSet(0, false)->GetData()->size()/fAny2ManyInfo->rebin + 1;
|
|
data = new UInt_t[dataSize];
|
|
if (data == 0) {
|
|
cerr << endl << ">> PRunDataHandler::WriteMudFile(): **ERROR** couldn't allocate memory for the data ..." << endl;
|
|
MUD_closeWrite(fd);
|
|
return false;
|
|
}
|
|
|
|
UInt_t noOfEvents = 0, k = 0;
|
|
ival = 0;
|
|
PRawRunDataSet *dataSet;
|
|
for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
if (dataSet == 0) { // something is really wrong
|
|
cerr << endl << ">> PRunDataHandler::WriteMudFile: **ERROR** Couldn't get data set (idx=" << i << ")";
|
|
cerr << endl << ">> something is really wrong!" << endl;
|
|
return false;
|
|
}
|
|
|
|
// fill data
|
|
for (UInt_t j=0; j<dataSize; j++)
|
|
data[j] = 0;
|
|
noOfEvents = 0;
|
|
k = 0;
|
|
for (UInt_t j=0; j<dataSet->GetData()->size(); j++) {
|
|
if ((j != 0) && (j % fAny2ManyInfo->rebin == 0)) {
|
|
data[k] = ival;
|
|
noOfEvents += ival;
|
|
k++;
|
|
ival = 0;
|
|
}
|
|
ival += static_cast<UInt_t>(dataSet->GetData()->at(j));
|
|
}
|
|
|
|
// feed data relevant information
|
|
// the numbering of the histograms start from '1', hence i+1 needed!!
|
|
MUD_setHistType(fd, i+1, MUD_GRP_TRI_TD_HIST_ID);
|
|
MUD_setHistNumBytes(fd, i+1, sizeof(data));
|
|
MUD_setHistNumBins(fd, i+1, dataSize);
|
|
MUD_setHistBytesPerBin(fd, i+1, 0);
|
|
MUD_setHistFsPerBin(fd, i+1, static_cast<UINT32>(1.0e6*fAny2ManyInfo->rebin*fData[0].GetTimeResolution())); // time resolution is given in (ns)
|
|
MUD_setHistT0_Ps(fd, i+1, static_cast<UINT32>(1.0e3*fData[0].GetTimeResolution()*((dataSet->GetTimeZeroBin()+fAny2ManyInfo->rebin/2)/fAny2ManyInfo->rebin)));
|
|
MUD_setHistT0_Bin(fd, i+1, static_cast<UINT32>(dataSet->GetTimeZeroBin()/fAny2ManyInfo->rebin));
|
|
MUD_setHistGoodBin1(fd, i+1, static_cast<UINT32>(dataSet->GetFirstGoodBin()/fAny2ManyInfo->rebin));
|
|
MUD_setHistGoodBin2(fd, i+1, static_cast<UINT32>(dataSet->GetLastGoodBin()/fAny2ManyInfo->rebin));
|
|
MUD_setHistBkgd1(fd, i+1, 0);
|
|
MUD_setHistBkgd2(fd, i+1, 0);
|
|
MUD_setHistNumEvents(fd, i+1, (UINT32)noOfEvents);
|
|
MUD_setHistTitle(fd, i+1, (char *)dataSet->GetName().Data());
|
|
REAL64 timeResolution = (fAny2ManyInfo->rebin*fData[0].GetTimeResolution())/1.0e9; // ns -> s
|
|
MUD_setHistSecondsPerBin(fd, i+1, timeResolution);
|
|
|
|
MUD_setHistData(fd, i+1, data);
|
|
}
|
|
|
|
MUD_closeWrite(fd);
|
|
|
|
delete [] data;
|
|
|
|
// check if mud file shall be streamed to stdout
|
|
if (fAny2ManyInfo->useStandardOutput && (fAny2ManyInfo->compressionTag == 0)) {
|
|
// stream file to stdout
|
|
ifstream is;
|
|
int length=1024;
|
|
char *buffer;
|
|
|
|
is.open(fln.Data(), ios::binary);
|
|
if (!is.is_open()) {
|
|
cerr << endl << "PRunDataHandler::WriteMudFile(): **ERROR** Couldn't open the mud-file for streaming." << endl;
|
|
remove(fln.Data());
|
|
return false;
|
|
}
|
|
|
|
// get length of file
|
|
is.seekg(0, ios::end);
|
|
length = is.tellg();
|
|
is.seekg(0, ios::beg);
|
|
|
|
if (length == -1) {
|
|
cerr << endl << "PRunDataHandler::WriteMudFile(): **ERROR** Couldn't determine the mud-file size." << endl;
|
|
remove(fln.Data());
|
|
return false;
|
|
}
|
|
|
|
// allocate memory
|
|
buffer = new char [length];
|
|
|
|
// read data as a block
|
|
while (!is.eof()) {
|
|
is.read(buffer, length);
|
|
cout.write(buffer, length);
|
|
}
|
|
|
|
is.close();
|
|
|
|
delete [] buffer;
|
|
|
|
// delete temporary root file
|
|
remove(fln.Data());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// WriteAsciiFile (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Write the ascii-file format.
|
|
*
|
|
* <b>return:</b>
|
|
* - true on successful writting,
|
|
* - otherwise false.
|
|
*
|
|
* \param fln file name. If empty, the routine will try to construct one
|
|
*/
|
|
Bool_t PRunDataHandler::WriteAsciiFile(TString fln)
|
|
{
|
|
Bool_t ok = false;
|
|
fln = GenerateOutputFileName(fln, ".ascii", ok);
|
|
if (!ok)
|
|
return false;
|
|
|
|
TString fileName = fln;
|
|
|
|
if (!fAny2ManyInfo->useStandardOutput)
|
|
cout << endl << ">> PRunDataHandler::WriteAsciiFile(): writing an ascii data file (" << fln.Data() << ") ... " << endl;
|
|
|
|
// write ascii file
|
|
ofstream fout;
|
|
streambuf* strm_buffer = 0;
|
|
|
|
if (!fAny2ManyInfo->useStandardOutput || (fAny2ManyInfo->compressionTag > 0)) {
|
|
// open data-file
|
|
fout.open(fln.Data(), ofstream::out);
|
|
if (!fout.is_open()) {
|
|
cerr << endl << ">> PRunDataHandler::WriteAsciiFile **ERROR** Couldn't open data file (" << fln.Data() << ") for writing, sorry ...";
|
|
cerr << endl;
|
|
return false;
|
|
}
|
|
|
|
// save output buffer of the stream
|
|
strm_buffer = cout.rdbuf();
|
|
|
|
// redirect output into the file
|
|
cout.rdbuf(fout.rdbuf());
|
|
}
|
|
|
|
// write header
|
|
cout << "%*************************************************************************";
|
|
cout << endl << "% file name : " << fileName.Data();
|
|
if (fData[0].GetRunTitle()->Length() > 0)
|
|
cout << endl << "% title : " << fData[0].GetRunTitle()->Data();
|
|
if (fData[0].GetRunNumber() >= 0)
|
|
cout << endl << "% run number : " << fData[0].GetRunNumber();
|
|
if (fData[0].GetSetup()->Length() > 0)
|
|
cout << endl << "% setup : " << fData[0].GetSetup()->Data();
|
|
cout << endl << "% field : " << fData[0].GetField() << " (G)";
|
|
if (fData[0].GetStartTime()->Length() > 0)
|
|
cout << endl << "% date : " << fData[0].GetStartTime()->Data() << " " << fData[0].GetStartDate()->Data() << " / " << fData[0].GetStopTime()->Data() << " " << fData[0].GetStopDate()->Data();
|
|
if (fData[0].GetNoOfTemperatures() > 0) {
|
|
cout << endl << "% temperature : ";
|
|
for (UInt_t i=0; i<fData[0].GetNoOfTemperatures()-1; i++) {
|
|
cout << fData[0].GetTemperature(i) << "+-" << fData[0].GetTempError(i) << "(K) , ";
|
|
}
|
|
cout << fData[0].GetTemperature(fData[0].GetNoOfTemperatures()-1) << "+-" << fData[0].GetTempError(fData[0].GetNoOfTemperatures()-1) << "(K)";
|
|
}
|
|
if (fData[0].GetEnergy() != PMUSR_UNDEFINED)
|
|
cout << endl << "% energy : " << fData[0].GetEnergy() << " (keV)";
|
|
if (fData[0].GetTransport() != PMUSR_UNDEFINED)
|
|
cout << endl << "% transport : " << fData[0].GetTransport() << " (kV)";
|
|
if (fData[0].GetTimeResolution() != PMUSR_UNDEFINED) {
|
|
cout.precision(10);
|
|
cout << endl << "% time resolution : " << fData[0].GetTimeResolution()*fAny2ManyInfo->rebin << " (ns)";
|
|
cout.setf(ios::fixed,ios::floatfield); // floatfield set to fixed
|
|
}
|
|
PRawRunDataSet *dataSet;
|
|
cout << endl << "% t0 : ";
|
|
for (UInt_t i=0; i<fData[0].GetNoOfHistos()-1; i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
cout << static_cast<UInt_t>(dataSet->GetTimeZeroBin()/fAny2ManyInfo->rebin) << ", ";
|
|
}
|
|
dataSet = fData[0].GetDataSet(fData[0].GetNoOfHistos()-1, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
cout << static_cast<UInt_t>(dataSet->GetTimeZeroBin()/fAny2ManyInfo->rebin);
|
|
|
|
cout << endl << "% # histos : " << fData[0].GetNoOfHistos();
|
|
dataSet = fData[0].GetDataSet(0, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
cout << endl << "% # of bins : " << static_cast<UInt_t>(dataSet->GetData()->size()/fAny2ManyInfo->rebin);
|
|
cout << endl << "%*************************************************************************";
|
|
|
|
// write data
|
|
UInt_t length = fData[0].GetDataSet(0,false)->GetData()->size();
|
|
if (fAny2ManyInfo->rebin == 1) {
|
|
for (UInt_t i=0; i<length; i++) {
|
|
cout << endl;
|
|
for (UInt_t j=0; j<fData[0].GetNoOfHistos(); j++) {
|
|
dataSet = fData[0].GetDataSet(j, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
cout.width(8);
|
|
cout << static_cast<Int_t>(dataSet->GetData()->at(i));
|
|
}
|
|
}
|
|
} else {
|
|
PUIntVector dataRebin(fData[0].GetNoOfHistos());
|
|
|
|
// initialize the dataRebin vector
|
|
for (UInt_t i=0; i<dataRebin.size(); i++) {
|
|
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
dataRebin[i] = static_cast<UInt_t>(dataSet->GetData()->at(0));
|
|
}
|
|
|
|
for (UInt_t i=0; i<length; i++) {
|
|
if ((i % fAny2ManyInfo->rebin) == 0) {
|
|
cout << endl;
|
|
for (UInt_t j=0; j<dataRebin.size(); j++) {
|
|
cout.width(8);
|
|
cout << dataRebin[j];
|
|
}
|
|
// initialize the dataRebin vector for the next pack
|
|
for (UInt_t j=0; j<dataRebin.size(); j++) {
|
|
dataSet = fData[0].GetDataSet(j, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
dataRebin[j] = static_cast<UInt_t>(dataSet->GetData()->at(i));
|
|
}
|
|
} else {
|
|
for (UInt_t j=0; j<fData[0].GetNoOfHistos(); j++) {
|
|
dataSet = fData[0].GetDataSet(j, false); // i.e. the false means, that i is the index and NOT the histo number
|
|
dataRebin[j] += static_cast<UInt_t>(dataSet->GetData()->at(i));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
cout << endl;
|
|
|
|
if (!fAny2ManyInfo->useStandardOutput || (fAny2ManyInfo->compressionTag > 0)) {
|
|
// restore old output buffer
|
|
cout.rdbuf(strm_buffer);
|
|
|
|
fout.close();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
// StripWhitespace (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Strip white spaces from a string. The hope is that future TString
|
|
* implementations of ROOT will make this routine obsolate.
|
|
*
|
|
* \param str string to be stripped. It will be modified directly on success.
|
|
*
|
|
* <b>return:</b>
|
|
* - true at successful reading,
|
|
* - otherwise false.
|
|
*/
|
|
Bool_t PRunDataHandler::StripWhitespace(TString &str)
|
|
{
|
|
Char_t *s = 0;
|
|
Char_t *subs = 0;
|
|
Int_t i;
|
|
Int_t start;
|
|
Int_t end;
|
|
Int_t size;
|
|
|
|
size = (Int_t)str.Length();
|
|
s = new Char_t[size+1];
|
|
|
|
if (!s)
|
|
return false;
|
|
|
|
for (Int_t i=0; i<size+1; i++)
|
|
s[i] = str[i];
|
|
s[size] = 0;
|
|
|
|
// check for whitespaces at the beginning of the string
|
|
i = 0;
|
|
while (isblank(s[i]) || iscntrl(s[i])) {
|
|
i++;
|
|
}
|
|
start = i;
|
|
|
|
// check for whitespaces at the end of the string
|
|
i = strlen(s);
|
|
while (isblank(s[i]) || iscntrl(s[i])) {
|
|
i--;
|
|
}
|
|
end = i;
|
|
|
|
if (end < start)
|
|
return false;
|
|
|
|
// make substring
|
|
subs = new Char_t[end-start+2];
|
|
if (!subs)
|
|
return false;
|
|
|
|
strncpy(subs, s+start, end-start+1);
|
|
subs[end-start+1] = '\0';
|
|
|
|
str = TString(subs);
|
|
|
|
// clean up
|
|
if (subs) {
|
|
delete [] subs;
|
|
subs = 0;
|
|
}
|
|
if (s) {
|
|
delete [] s;
|
|
s = 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// IsWhitespace (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Check if a string consists only of white spaces, i.e. spaces and/or
|
|
* ctrl-characters.
|
|
*
|
|
* <b>return:</b>
|
|
* - true at successful reading,
|
|
* - otherwise false.
|
|
*
|
|
* \param str string to be checked
|
|
*/
|
|
Bool_t PRunDataHandler::IsWhitespace(const Char_t *str)
|
|
{
|
|
UInt_t i=0;
|
|
|
|
while (isblank(str[i]) || iscntrl(str[i])) {
|
|
if (str[i] == 0)
|
|
break;
|
|
i++;
|
|
}
|
|
|
|
if (i == strlen(str))
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// ToDouble (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Convert a string to a Double_t.
|
|
*
|
|
* <b>return:</b>
|
|
* - returns the converted string
|
|
* - otherwise 0.0 with ok==false
|
|
*
|
|
* \param str string to be converted
|
|
* \param ok true on success, otherwise false.
|
|
*/
|
|
Double_t PRunDataHandler::ToDouble(TString &str, Bool_t &ok)
|
|
{
|
|
Char_t *s;
|
|
Double_t value;
|
|
Int_t size, status;
|
|
|
|
ok = true;
|
|
|
|
size = (Int_t)str.Length();
|
|
s = new Char_t[size+1];
|
|
|
|
if (!s) {
|
|
ok = false;
|
|
return 0.0;
|
|
}
|
|
|
|
// copy string; stupid way but it works
|
|
for (Int_t i=0; i<size+1; i++)
|
|
s[i] = str[i];
|
|
s[size] = 0;
|
|
|
|
// extract value
|
|
status = sscanf(s, "%lf", &value);
|
|
if (status != 1) {
|
|
ok = false;
|
|
return 0.0;
|
|
}
|
|
|
|
// clean up
|
|
if (s) {
|
|
delete [] s;
|
|
s = 0;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// ToInt (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Convert a string to an Int_t.
|
|
*
|
|
* <b>return:</b>
|
|
* - returns the converted string
|
|
* - otherwise 0.0 with ok==false
|
|
*
|
|
* \param str string to be converted
|
|
* \param ok true on success, otherwise false.
|
|
*/
|
|
Int_t PRunDataHandler::ToInt(TString &str, Bool_t &ok)
|
|
{
|
|
Char_t *s;
|
|
Int_t value;
|
|
Int_t size, status;
|
|
|
|
ok = true;
|
|
|
|
size = (Int_t)str.Length();
|
|
s = new Char_t[size+1];
|
|
|
|
if (!s) {
|
|
ok = false;
|
|
return 0;
|
|
}
|
|
|
|
// copy string; stupid way but it works
|
|
for (Int_t i=0; i<size+1; i++)
|
|
s[i] = str[i];
|
|
s[size] = 0;
|
|
|
|
// extract value
|
|
status = sscanf(s, "%d", &value);
|
|
if (status != 1) {
|
|
ok = false;
|
|
return 0;
|
|
}
|
|
|
|
// clean up
|
|
if (s) {
|
|
delete [] s;
|
|
s = 0;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// GetDataTagIndex (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p> Checks if str is in a list of data tags
|
|
*
|
|
* <b>return:</b>
|
|
* - if found returns the data tag index (from the dataTags vector),
|
|
* - otherwise -1
|
|
*
|
|
* \param str data tag string (see description of nonMusr db-data)
|
|
* \param dataTags vector of all data tags
|
|
*/
|
|
Int_t PRunDataHandler::GetDataTagIndex(TString &str, const PStringVector* dataTags)
|
|
{
|
|
Int_t result = -1;
|
|
|
|
// check all the other possible data tags
|
|
for (UInt_t i=0; i<dataTags->size(); i++) {
|
|
if (!dataTags->at(i).CompareTo(str, TString::kIgnoreCase)) {
|
|
result = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
// GenerateOutputFileName (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Generates the output file name (any2many). It also makes sure that the
|
|
* generated output file name does not coincidentally is identical to an already
|
|
* existing file.
|
|
*
|
|
* <b>return:</b>
|
|
* - constructed file name
|
|
* - empty string
|
|
*
|
|
* \param fileName
|
|
* \param extension if the file name to be constructed
|
|
* \param ok flag which is 'true' if the file name could be constructed, 'false' otherwise
|
|
*/
|
|
TString PRunDataHandler::GenerateOutputFileName(const TString fileName, const TString extension, Bool_t &ok)
|
|
{
|
|
TString fln = fileName;
|
|
ok = true;
|
|
|
|
// generate output file name if needed
|
|
if (!fAny2ManyInfo->useStandardOutput || (fAny2ManyInfo->compressionTag > 0)) {
|
|
if (fln.Length() == 0) {
|
|
ok = false;
|
|
fln = GetFileName(extension, ok);
|
|
if (!ok) {
|
|
fln = "";
|
|
return fln;
|
|
}
|
|
} else {
|
|
fln.Prepend(fAny2ManyInfo->outPath);
|
|
}
|
|
|
|
// make sure that the file name doesn't already exist as a real file
|
|
if (!gSystem->AccessPathName(fln)) { // file name already exists!!
|
|
Int_t count = 1;
|
|
TString newFln;
|
|
do {
|
|
newFln = fln;
|
|
newFln.Insert(newFln.Last('.'), TString::Format(".%d", count++));
|
|
} while (!gSystem->AccessPathName(newFln));
|
|
cerr << endl << ">> PRunDataHandler::GenerateOutputFileName **WARNING** needed to modify output filename to " << newFln << ",";
|
|
cerr << endl << ">> due to potential conflict with already existing files." << endl << endl;
|
|
fln = newFln;
|
|
}
|
|
|
|
// keep the file name if compression is whished
|
|
fAny2ManyInfo->outPathFileName.push_back(fln);
|
|
} else {
|
|
fln = fAny2ManyInfo->outPath + TString("__tmp.") + extension;
|
|
}
|
|
|
|
return fln;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// GetFileName (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Construct the file name based on the any2many request.
|
|
*
|
|
* <b>return:</b>
|
|
* - constructed file name
|
|
* - empty string
|
|
*
|
|
* \param extension if the file name to be constructed
|
|
* \param ok flag which is 'true' if the file name could be constructed, 'false' otherwise
|
|
*/
|
|
TString PRunDataHandler::GetFileName(const TString extension, Bool_t &ok)
|
|
{
|
|
TString fileName = "";
|
|
ok = true;
|
|
|
|
Int_t start = fRunPathName.Last('/');
|
|
Int_t end = fRunPathName.Last('.');
|
|
if (end == -1) {
|
|
cerr << endl << ">> PRunDataHandler::GetFileName(): **ERROR** couldn't generate the output file name ..." << endl;
|
|
ok = false;
|
|
return fileName;
|
|
}
|
|
// cut out the filename (get rid of the extension, and the path)
|
|
Char_t str1[1024], str2[1024];
|
|
strncpy(str1, fRunPathName.Data(), sizeof(str1));
|
|
for (Int_t i=0; i<end-start-1; i++) {
|
|
str2[i] = str1[i+start+1];
|
|
}
|
|
str2[end-start-1] = 0;
|
|
|
|
if (fAny2ManyInfo->inFormat == fAny2ManyInfo->outFormat) { // only rebinning
|
|
TString rebinStr;
|
|
rebinStr += fAny2ManyInfo->rebin;
|
|
fileName = fAny2ManyInfo->outPath + str2 + "_rebin" + rebinStr + extension;
|
|
} else { // real conversion
|
|
fileName = fAny2ManyInfo->outPath + str2 + extension;
|
|
}
|
|
|
|
return fileName;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// FileNameFromTemplate (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>Will, based on the fileNameTemplate construct a file name. The file name template has a run tag
|
|
* and a year tag. The run tag has the form [rrrr], whereas the number of 'r' defines the length of
|
|
* this string part. If the run number is shorter, leading zeros will be filled, e.g. [rrrrrr] and run==123
|
|
* will lead to '000123'. The same is true for the year tag [yy], except that the length must agree.
|
|
* For example: fileNameTemplate = d[yyyy]/deltat_tdc_gps_[rrrr].bin, run = 123, year = 2009 will result
|
|
* in 'd2009/deltat_tdc_gps_0123.bin'.
|
|
*
|
|
* <b>return:</b>
|
|
* - constructed file name from template, run number, and year
|
|
* - empty string
|
|
*
|
|
* \param template template string
|
|
* \param run run number
|
|
* \param year year
|
|
* \param ok true if operation went smooth, otherwise false
|
|
*/
|
|
TString PRunDataHandler::FileNameFromTemplate(TString &fileNameTemplate, Int_t run, TString &year, Bool_t &ok)
|
|
{
|
|
TString result("");
|
|
|
|
TObjArray *tok=0;
|
|
TObjString *ostr;
|
|
TString str;
|
|
|
|
// check year string
|
|
if ((year.Length() != 2) && (year.Length() != 4)) {
|
|
cerr << endl << ">> PRunDataHandler::FileNameFromTemplate: **ERROR** year needs to be of the format";
|
|
cerr << endl << ">> 'yy' or 'yyyy', found " << year << endl;
|
|
return result;
|
|
}
|
|
|
|
// make a short year version 'yy' and a long year version 'yyyy'
|
|
TString yearShort="", yearLong="";
|
|
if (year.Length() == 2) {
|
|
yearShort = year;
|
|
yearLong = "20" ;
|
|
yearLong += year;
|
|
} else {
|
|
yearShort = year[2];
|
|
yearShort += year[3];
|
|
yearLong = year;
|
|
}
|
|
|
|
// tokenize template string
|
|
tok = fileNameTemplate.Tokenize("[]");
|
|
if (tok == 0) {
|
|
cerr << endl << ">> PRunDataHandler::FileNameFromTemplate: **ERROR** couldn't tokenize template!" << endl;
|
|
return result;
|
|
}
|
|
if (tok->GetEntries()==1) {
|
|
cerr << endl << ">> PRunDataHandler::FileNameFromTemplate: **WARNING** template without tags." << endl;
|
|
}
|
|
|
|
// go through the tokens and generate the result string
|
|
for (Int_t i=0; i<tok->GetEntries(); i++) {
|
|
ostr = (TObjString*)tok->At(i);
|
|
str = ostr->GetString();
|
|
|
|
// check tokens
|
|
if (!str.CompareTo("yy", TString::kExact)) { // check for 'yy'
|
|
result += yearShort;
|
|
} else if (!str.CompareTo("yyyy", TString::kExact)) { // check for 'yyyy'
|
|
result += yearLong;
|
|
} else if (str.Contains("rr")) { // check for run
|
|
// make sure ONLY 'r' are present
|
|
Int_t idx;
|
|
for (idx=0; idx<str.Length(); idx++) {
|
|
if (str[idx] != 'r')
|
|
break;
|
|
}
|
|
if (idx == str.Length()) { // 'r' only
|
|
TString runStr("");
|
|
char fmt[128];
|
|
sprintf(fmt , "%%0%dd", str.Length());
|
|
runStr.Form(fmt, run);
|
|
result += runStr;
|
|
} else { // not only 'r'
|
|
result += str;
|
|
}
|
|
} else { // all parts which are NOT tags
|
|
result += str;
|
|
}
|
|
}
|
|
|
|
// clean up
|
|
if (tok)
|
|
delete tok;
|
|
|
|
// everything fine here
|
|
ok = true;
|
|
|
|
return result;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// DateToISO8601 (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>If possible converts a inDate, into a ISO8601 standard date.
|
|
*
|
|
* <p><b>return:</b> true if conversion was successfull otherwise false.
|
|
*
|
|
* \param inDate input date which should be converted to an ISO 8601 date.
|
|
* \param iso8601Date on success the converted iso8601Date, otherwise an empty string
|
|
*/
|
|
bool PRunDataHandler::DateToISO8601(string inDate, string &iso8601Date)
|
|
{
|
|
iso8601Date = string("");
|
|
|
|
struct tm tm;
|
|
|
|
// currently only dates like dd-mmm-yy are handled, where dd day of the month, mmm month as abbrivation, e.g. JAN, and yy as the year
|
|
if (!strptime(inDate.c_str(), "%d-%b-%y", &tm)) // failed
|
|
return false;
|
|
|
|
TString str("");
|
|
str.Form("%04d-%02d-%02d", 1900+tm.tm_year, tm.tm_mon, tm.tm_mday);
|
|
|
|
iso8601Date = str.Data();
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// SplitTimeData (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>splits an ISO 8601 timeDate into seperate time and data. The flag ok
|
|
* shows if it was successfull.
|
|
*
|
|
* \param timeData ISO 8601 timeData
|
|
* \param time part of timeData
|
|
* \param date part of timeData
|
|
* \param ok flag showing if the splitting was successfull
|
|
*/
|
|
void PRunDataHandler::SplitTimeDate(TString timeData, TString &time, TString &date, Bool_t &ok)
|
|
{
|
|
struct tm tm;
|
|
memset(&tm, 0, sizeof(tm));
|
|
strptime(timeData.Data(), "%Y-%m-%d %H:%M:S", &tm);
|
|
if (tm.tm_year == 0)
|
|
strptime(timeData.Data(), "%Y-%m-%dT%H:%M:S", &tm);
|
|
|
|
if (tm.tm_year == 0) {
|
|
ok = false;
|
|
return;
|
|
}
|
|
|
|
time = TString::Format("%02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec);
|
|
date = TString::Format("%04d-%02d-%02d", tm.tm_year+1900, tm.tm_mon, tm.tm_mday);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// GetMonth (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>given the month as number, convert it to a 3 character month.
|
|
* If month is out of range (i.e. not between 1 and 12) a '???' will
|
|
* be returned.
|
|
*
|
|
* \param month as number
|
|
*/
|
|
TString PRunDataHandler::GetMonth(Int_t month)
|
|
{
|
|
TString monthString = "???";
|
|
|
|
switch (month) {
|
|
case 1:
|
|
monthString = "JAN";
|
|
break;
|
|
case 2:
|
|
monthString = "FEB";
|
|
break;
|
|
case 3:
|
|
monthString = "MAR";
|
|
break;
|
|
case 4:
|
|
monthString = "APR";
|
|
break;
|
|
case 5:
|
|
monthString = "MAY";
|
|
break;
|
|
case 6:
|
|
monthString = "JUN";
|
|
break;
|
|
case 7:
|
|
monthString = "JUL";
|
|
break;
|
|
case 8:
|
|
monthString = "AUG";
|
|
break;
|
|
case 9:
|
|
monthString = "SEP";
|
|
break;
|
|
case 10:
|
|
monthString = "OCT";
|
|
break;
|
|
case 11:
|
|
monthString = "NOV";
|
|
break;
|
|
case 12:
|
|
monthString = "DEC";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return monthString;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// GetYear (private)
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* <p>given the year as number, convert it to a 2 character year.
|
|
* If year is out of range '??' will be returned. This routine will
|
|
* break in the year 2100 or later ;-)
|
|
*
|
|
* \param year as number
|
|
*/
|
|
TString PRunDataHandler::GetYear(Int_t year)
|
|
{
|
|
TString yearString = "??";
|
|
Int_t yy=0;
|
|
|
|
if (year < 2000) {
|
|
yy = year - 1900;
|
|
if (yy > 0)
|
|
yearString.Form("%02d", yy);
|
|
} else {
|
|
yy = year - 2000;
|
|
if ((yy >= 0) && (yy <= 99))
|
|
yearString.Form("%02d", yy);
|
|
}
|
|
|
|
return yearString;
|
|
}
|