Files
musrfit/src/external/nexus/PNeXus.cpp

1940 lines
81 KiB
C++

/***************************************************************************
PNeXus.cpp
Author: Andreas Suter
e-mail: andreas.suter@psi.ch
$Id$
***************************************************************************/
/***************************************************************************
* Copyright (C) 2007-2011 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. *
***************************************************************************/
#include <cstdio>
#include <cstring>
#include "PNeXus.h"
#ifndef SIZE_FLOAT32
# define SIZE_FLOAT32 4
# define SIZE_FLOAT64 8
# define SIZE_INT8 1
# define SIZE_UINT8 1
# define SIZE_INT16 2
# define SIZE_UINT16 2
# define SIZE_INT32 4
# define SIZE_UINT32 4
# define SIZE_INT64 8
# define SIZE_UINT64 8
# define SIZE_CHAR8 1
# define SIZE_CHAR 1
# define SIZE_UCHAR8 1
# define SIZE_UCHAR 1
# define SIZE_CHAR16 2
# define SIZE_UCHAR16 2
#endif /* SIZE_FLOAT32 */
//-----------------------------------------------------------------------------------------------------
// PNeXus constructor
//-----------------------------------------------------------------------------------------------------
/**
*
*/
PNeXus::PNeXus()
{
Init();
}
//-----------------------------------------------------------------------------------------------------
// PNeXus constructor
//-----------------------------------------------------------------------------------------------------
/**
*
*
* \param fileName
*/
PNeXus::PNeXus(const char* fileName)
{
Init();
fFileName = fileName;
if (ReadFile(fileName) != NX_OK) {
cerr << endl << fErrorMsg << " (error code=" << fErrorCode << ")" << endl << endl;
} else {
fIsValid = true;
}
}
//-----------------------------------------------------------------------------------------------------
// PNeXus destructor
//-----------------------------------------------------------------------------------------------------
/**
*
*/
PNeXus::~PNeXus()
{
CleanUp();
}
//-----------------------------------------------------------------------------------------------------
// ReadFile (public)
//-----------------------------------------------------------------------------------------------------
/**
* <p>
*
* <b>return:</b>
* - NX_OK on successfull reading
* - NX_ERROR on error. The error code/message will give the details.
*
* \param fileName
*/
int PNeXus::ReadFile(const char *fileName)
{
int status, ival;
float fval;
string str("");
// open file
status = NXopen(fileName, NXACC_READ, &fFileHandle);
if (status != NX_OK) {
fErrorCode = PNEXUS_FILE_OPEN_ERROR;
fErrorMsg = "PNeXus::ReadFile() **ERROR** Couldn't open file "+string(fileName)+"!";
return NX_ERROR;
}
// open group
status = NXopengroup(fFileHandle, "run", "NXentry");
if (status != NX_OK) {
fErrorCode = PNEXUS_GROUP_OPEN_ERROR;
fErrorMsg = "PNeXus::ReadFile() **ERROR** Couldn't open NeXus group run!";
return NX_ERROR;
}
// IDF
if (NXopendata(fFileHandle, "idf_version") != NX_OK) {
if (NXopendata(fFileHandle, "IDF_version") != NX_OK) {
fErrorCode = PNEXUS_OPEN_DATA_ERROR;
fErrorMsg = "PNeXus::ReadFile() **ERROR** couldn't open 'IDF_version' nor 'idf_version' data!!";
return NX_ERROR;
}
}
if (!ErrorHandler(NXgetdata(fFileHandle, &fIDFVersion), PNEXUS_GET_DATA_ERROR, "couldn't read 'IDF_version' data!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'IDF_version' data")) return NX_ERROR;
// program_name
if (!ErrorHandler(NXopendata(fFileHandle, "program_name"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'program_name' data!")) return NX_ERROR;
if (!ErrorHandler(GetStringData(fProgramName), PNEXUS_GET_DATA_ERROR, "couldn't read 'program_name' data!")) return NX_ERROR;
if (!ErrorHandler(GetStringAttr("version", fProgramVersion), PNEXUS_GET_ATTR_ERROR, "couldn't read program_name attribute!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'program_name' data")) return NX_ERROR;
// run number
if (!ErrorHandler(NXopendata(fFileHandle, "number"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'number' data!")) return NX_ERROR;
if (!ErrorHandler(NXgetdata(fFileHandle, &fRunNumber), PNEXUS_GET_DATA_ERROR, "couldn't read 'number' data!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'number' data")) return NX_ERROR;
// title
if (!ErrorHandler(NXopendata(fFileHandle, "title"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'title' data!")) return NX_ERROR;
if (!ErrorHandler(GetStringData(fRunTitle), PNEXUS_GET_DATA_ERROR, "couldn't read 'title' data!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'title' data")) return NX_ERROR;
// notes
if (!ErrorHandler(NXopendata(fFileHandle, "notes"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'notes' data!")) return NX_ERROR;
if (!ErrorHandler(GetStringData(fNotes), PNEXUS_GET_DATA_ERROR, "couldn't read 'notes' data!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'notes' data")) return NX_ERROR;
// analysis tag
if (!ErrorHandler(NXopendata(fFileHandle, "analysis"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'analysis' data!")) return NX_ERROR;
if (!ErrorHandler(GetStringData(fAnalysisTag), PNEXUS_GET_DATA_ERROR, "couldn't read 'analysis' data!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'analysis' data")) return NX_ERROR;
// lab
if (!ErrorHandler(NXopendata(fFileHandle, "lab"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'lab' data!")) return NX_ERROR;
if (!ErrorHandler(GetStringData(fLab), PNEXUS_GET_DATA_ERROR, "couldn't read 'lab' data!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'lab' data")) return NX_ERROR;
// beamline
if (!ErrorHandler(NXopendata(fFileHandle, "beamline"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'beamline' data!")) return NX_ERROR;
if (!ErrorHandler(GetStringData(fBeamLine), PNEXUS_GET_DATA_ERROR, "couldn't read 'beamline' data!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'beamline' data")) return NX_ERROR;
// start time
if (!ErrorHandler(NXopendata(fFileHandle, "start_time"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'start_time' data!")) return NX_ERROR;
if (!ErrorHandler(GetStringData(str), PNEXUS_GET_DATA_ERROR, "couldn't read 'start_time' data!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'start_time' data")) return NX_ERROR;
size_t pos, pos1, pos2;
pos1 = str.find("T");
pos2 = str.find(" ");
if ((pos1 == string::npos) && (pos2 == string::npos)) {
fErrorCode = PNEXUS_GET_DATA_ERROR;
fErrorMsg = "PNeXus::ReadFile() **ERROR** Wrong start date-time found (" + str + ")!";
return NX_ERROR;
}
if (pos1 != string::npos)
pos = pos1;
else
pos = pos2;
fStartDate = str.substr(0, pos);
fStartTime = str.substr(pos+1, str.length());
// stop time
if (!ErrorHandler(NXopendata(fFileHandle, "stop_time"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'start_time' data!")) return NX_ERROR;
if (!ErrorHandler(GetStringData(str), PNEXUS_GET_DATA_ERROR, "couldn't read 'start_time' data!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'start_time' data")) return NX_ERROR;
pos1 = str.find("T");
pos2 = str.find(" ");
if ((pos1 == string::npos) && (pos2 == string::npos)) {
fErrorCode = PNEXUS_GET_DATA_ERROR;
fErrorMsg = "PNeXus::ReadFile() **ERROR** Wrong stop date-time found (" + str + ")!";
return NX_ERROR;
}
if (pos1 != string::npos)
pos = pos1;
else
pos = pos2;
fStopDate = str.substr(0, pos);
fStopTime = str.substr(pos+1, str.length());
// switching state (red/green mode)
if (!ErrorHandler(NXopendata(fFileHandle, "switching_states"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'switching_states' data!")) return NX_ERROR;
if (!ErrorHandler(NXgetdata(fFileHandle, &fSwitchingState), PNEXUS_GET_DATA_ERROR, "couldn't read 'switching_states' data!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'switching_states' data")) return NX_ERROR;
// open subgroup NXuser
if (!ErrorHandler(NXopengroup(fFileHandle, "user", "NXuser"), PNEXUS_GROUP_OPEN_ERROR, "couldn't open NeXus subgroup user!")) return NX_ERROR;
// change to subgroup
if (!ErrorHandler(NXinitgroupdir(fFileHandle), PNEXUS_INIT_GROUPDIR_ERROR, "couldn't init group directory")) return NX_ERROR;
int numItems = 0;
NXname groupName, className;
if (!ErrorHandler(NXgetgroupinfo(fFileHandle, &numItems, groupName, className), PNEXUS_GET_GROUP_INFO_ERROR, "couldn't get user group info")) return NX_ERROR;
// get all the user info
// initialize the user data set
fUser.fUserName = "";
fUser.fExperimentNumber = "";
// go through the user list and filter out the required items
NXname nx_label;
int nx_dataType;
for (int i=0; i<numItems; i++) {
if (!ErrorHandler(NXgetnextentry(fFileHandle, nx_label, className, &nx_dataType), PNEXUS_GET_NEXT_ENTRY_ERROR, "couldn't get next entry")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, nx_label), PNEXUS_OPEN_DATA_ERROR, "couldn't open data")) return NX_ERROR;
if (!strcmp(nx_label, "name")) {
if (!ErrorHandler(GetStringData(str), PNEXUS_GET_DATA_ERROR, "couldn't get user name")) return NX_ERROR;
fUser.fUserName = str;
}
if (!strcmp(nx_label, "experiment_number")) {
if (!ErrorHandler(GetStringData(str), PNEXUS_GET_DATA_ERROR, "couldn't get user name")) return NX_ERROR;
fUser.fExperimentNumber = str;
}
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close data")) return NX_ERROR;
}
// close subgroup NXuser
NXclosegroup(fFileHandle);
// open subgroup NXsample
if (!ErrorHandler(NXopengroup(fFileHandle, "sample", "NXSample"), PNEXUS_GROUP_OPEN_ERROR, "couldn't open NeXus subgroup sample!")) return NX_ERROR;
// read sample name
if (!ErrorHandler(NXopendata(fFileHandle, "name"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'name' data in sample group!")) return NX_ERROR;
if (!ErrorHandler(GetStringData(str), PNEXUS_GET_DATA_ERROR, "couldn't read 'name' data in sample group!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'name' data in sample group")) return NX_ERROR;
fSample.fName = str;
// read sample temperature
if (!ErrorHandler(NXopendata(fFileHandle, "temperature"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'temperature' data in sample group!")) return NX_ERROR;
if (!ErrorHandler(NXgetdata(fFileHandle, &fval), PNEXUS_GET_DATA_ERROR, "couldn't read 'temperature' data in sample group!")) return NX_ERROR;
fSample.fTemperature = (double)fval;
if (!ErrorHandler(GetStringAttr("units", str), PNEXUS_GET_ATTR_ERROR, "couldn't read temperature units!")) return NX_ERROR;
fSample.fTemperatureUnit = str;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'temperature' data in sample group")) return NX_ERROR;
// read sample magnetic field
if (!ErrorHandler(NXopendata(fFileHandle, "magnetic_field"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'magnetic_field' data in sample group!")) return NX_ERROR;
if (!ErrorHandler(NXgetdata(fFileHandle, &fval), PNEXUS_GET_DATA_ERROR, "couldn't read 'magnetic_field' data in sample group!")) return NX_ERROR;
fSample.fMagneticField = (double)fval;
if (!ErrorHandler(GetStringAttr("units", str), PNEXUS_GET_ATTR_ERROR, "couldn't read magnetic field units!")) return NX_ERROR;
fSample.fMagneticFieldUnit = str;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'temperature' data in sample group")) return NX_ERROR;
// read sample shape, e.g. powder, single crystal, etc.
if (!ErrorHandler(NXopendata(fFileHandle, "shape"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'shape' data in sample group!")) return NX_ERROR;
if (!ErrorHandler(GetStringData(str), PNEXUS_GET_DATA_ERROR, "couldn't read 'shape' data in sample group!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'shape' data in sample group")) return NX_ERROR;
fSample.fShape = str;
// read magnetic field state, e.g. TF, LF, ZF
if (!ErrorHandler(NXopendata(fFileHandle, "magnetic_field_state"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'magnetic_field_state' data in sample group!")) return NX_ERROR;
if (!ErrorHandler(GetStringData(str), PNEXUS_GET_DATA_ERROR, "couldn't read 'magnetic_field_state' data in sample group!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'magnetic_field_state' data in sample group")) return NX_ERROR;
fSample.fMagneticFieldState = str;
// read 'magnetic_field_vector' and 'coordinate_system' attribute
if (!ErrorHandler(NXopendata(fFileHandle, "magnetic_field_vector"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'magnetic_field_vector' data in sample group!")) return NX_ERROR;
int attLen = SIZE_INT32, attType = NX_INT32;
if (!ErrorHandler(NXgetattr(fFileHandle, "available", &fSample.fMagneticFieldVectorAvailable, &attLen, &attType), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'magnetic_field_vector available' data in sample group!")) return NX_ERROR;
if (fSample.fMagneticFieldVectorAvailable) {
if (!ErrorHandler(GetDoubleVectorData(fSample.fMagneticFieldVector), PNEXUS_GET_DATA_ERROR, "couldn't get 'magnetic_field_vector' data!")) return NX_ERROR;
}
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'magnetic_field_vector' data in sample group")) return NX_ERROR;
// read sample environment, e.g. CCR, LowTemp-2, etc.
if (!ErrorHandler(NXopendata(fFileHandle, "environment"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'environment' data in sample group!")) return NX_ERROR;
if (!ErrorHandler(GetStringData(str), PNEXUS_GET_DATA_ERROR, "couldn't read 'environment' data in sample group!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'environment' data in sample group")) return NX_ERROR;
fSample.fEnvironment = str;
// close subgroup NXsample
NXclosegroup(fFileHandle);
// get required instrument information
// open subgroup NXinstrument with subgroups detector, collimator, beam
if (!ErrorHandler(NXopengroup(fFileHandle, "instrument", "NXinstrument"), PNEXUS_GROUP_OPEN_ERROR, "couldn't open NeXus subgroup instrument!")) return NX_ERROR;
// get instrument name
if (!ErrorHandler(NXopendata(fFileHandle, "name"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'name' data in instrument group!")) return NX_ERROR;
if (!ErrorHandler(GetStringData(str), PNEXUS_GET_DATA_ERROR, "couldn't read 'name' data in instrument group!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'name' data in instrument group")) return NX_ERROR;
fInstrument.name = str;
// open subgroup NXdetector
if (!ErrorHandler(NXopengroup(fFileHandle, "detector", "NXdetector"), PNEXUS_GROUP_OPEN_ERROR, "couldn't open NeXus subgroup detector!")) return NX_ERROR;
// get number of detectors
if (!ErrorHandler(NXopendata(fFileHandle, "number"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'number' data in detector group!")) return NX_ERROR;
if (!ErrorHandler(NXgetdata(fFileHandle, &ival), PNEXUS_GET_DATA_ERROR, "couldn't read 'number' data in detector group!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'number' data in detector group")) return NX_ERROR;
fInstrument.detector.number = ival;
// close subgroup NXdetector
NXclosegroup(fFileHandle);
// open subgroup NXcollimator
if (!ErrorHandler(NXopengroup(fFileHandle, "collimator", "NXcollimator"), PNEXUS_GROUP_OPEN_ERROR, "couldn't open NeXus subgroup collimator!")) return NX_ERROR;
// get collimator type
if (!ErrorHandler(NXopendata(fFileHandle, "type"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'type' data in collimator group!")) return NX_ERROR;
if (!ErrorHandler(GetStringData(str), PNEXUS_GET_DATA_ERROR, "couldn't read 'type' data in collimator group!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'type' data in collimator group")) return NX_ERROR;
fInstrument.collimator.type = str;
// close subgroup NXcollimator
NXclosegroup(fFileHandle);
// open subgroup NXbeam
if (!ErrorHandler(NXopengroup(fFileHandle, "beam", "NXbeam"), PNEXUS_GROUP_OPEN_ERROR, "couldn't open NeXus subgroup beam!")) return NX_ERROR;
// get the total counts
if (!ErrorHandler(NXopendata(fFileHandle, "total_counts"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'total_counts' data in beam group!")) return NX_ERROR;
if (!ErrorHandler(NXgetdata(fFileHandle, &fval), PNEXUS_GET_DATA_ERROR, "couldn't read 'total_counts' data in beam group!")) return NX_ERROR;
fInstrument.beam.total_counts = (double)fval;
if (!ErrorHandler(GetStringAttr("units", str), PNEXUS_GET_ATTR_ERROR, "couldn't read total_counts units!")) return NX_ERROR;
fInstrument.beam.total_counts_units = str;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'total_counts' data in beam group")) return NX_ERROR;
// close subgroup NXbeam
NXclosegroup(fFileHandle);
// close subgroup NXinstrument
NXclosegroup(fFileHandle);
// open subgroup NXdata (this is for Version 1, only and is subject to change in the near future!)
if (!ErrorHandler(NXopengroup(fFileHandle, "histogram_data_1", "NXdata"), PNEXUS_GROUP_OPEN_ERROR, "couldn't open NeXus subgroup histogram_data_1!")) return NX_ERROR;
// get time resolution
if (!ErrorHandler(NXopendata(fFileHandle, "resolution"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'resolution' data in histogram_data_1 group!")) return NX_ERROR;
if (!ErrorHandler(NXgetdata(fFileHandle, &ival), PNEXUS_GET_DATA_ERROR, "couldn't read 'resolution' data in histogram_data_1 group!")) return NX_ERROR;
if (!ErrorHandler(GetStringAttr("units", str), PNEXUS_GET_ATTR_ERROR, "couldn't read 'resolution'' units!")) return NX_ERROR;
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'resolution' data in histogram_data_1 group")) return NX_ERROR;
if (!strcmp(str.data(), "picoseconds")) {
fData.fTimeResolution = (double)ival/1000.0; // time resolution in (ns)
}
// get data, t0, first good bin, last good bin, data
if (!ErrorHandler(NXopendata(fFileHandle, "counts"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'counts' data in histogram_data_1 group!")) return NX_ERROR;
int histoLength=0;
// get number of histos
attLen = SIZE_INT32;
attType = NX_INT32;
if (!ErrorHandler(NXgetattr(fFileHandle, "number", &fData.fNumberOfHistos, &attLen, &attType), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'number' data in histogram_data_1 group!")) return NX_ERROR;
// get histo length
attLen = SIZE_INT32;
attType = NX_INT32;
if (!ErrorHandler(NXgetattr(fFileHandle, "length", &histoLength, &attLen, &attType), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'number' data in histogram_data_1 group!")) return NX_ERROR;
// get t0
attLen = SIZE_INT32;
attType = NX_INT32;
if (!ErrorHandler(NXgetattr(fFileHandle, "t0_bin", &ival, &attLen, &attType), PNEXUS_OPEN_DATA_ERROR, "couldn't open 't0_bin' data in histogram_data_1 group!")) return NX_ERROR;
fData.fT0.push_back(ival);
// get first good bin
attLen = SIZE_INT32;
attType = NX_INT32;
if (!ErrorHandler(NXgetattr(fFileHandle, "first_good_bin", &ival, &attLen, &attType), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'first_good_bin' data in histogram_data_1 group!")) return NX_ERROR;
fData.fFirstGoodBin.push_back(ival);
// get last good bin
attLen = SIZE_INT32;
attType = NX_INT32;
if (!ErrorHandler(NXgetattr(fFileHandle, "last_good_bin", &ival, &attLen, &attType), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'last_good_bin' data in histogram_data_1 group!")) return NX_ERROR;
fData.fLastGoodBin.push_back(ival);
// get data
// get information of the current nexus entity
int rank, type, dims[32], size, noOfElements;
if (!ErrorHandler(NXgetinfo(fFileHandle, &rank, dims, &type), PNEXUS_GET_META_INFO_ERROR, "couldn't get data info!")) return NX_ERROR;
// calculate the needed size
size = dims[0];
for (int i=1; i<rank; i++)
size *= dims[i];
noOfElements = size;
size *= GetDataSize(type);
// allocate locale memory to get the data
char *data_ptr = new char[size];
if (data_ptr == 0) {
return NX_ERROR;
}
// get the data
int *i_data_ptr = (int*) data_ptr;
status = NXgetdata(fFileHandle, i_data_ptr);
if (status != NX_OK) {
return NX_ERROR;
}
// check that the amount of data is consistent with the attribute information
if (noOfElements != (int)fData.fNumberOfHistos * histoLength) {
fErrorCode = PNEXUS_HISTO_ERROR;
fErrorMsg = "inconsistent histogram info!";
return NX_ERROR;
}
// copy the data into the vector
fData.fHisto.clear();
vector<unsigned int> data;
for (int i=0; i<noOfElements; i++) {
if ((i % histoLength == 0) && (i>0)) {
fData.fHisto.push_back(data);
data.clear();
data.push_back(*(i_data_ptr+i));
} else {
data.push_back(*(i_data_ptr+i));
}
}
fData.fHisto.push_back(data);
data.clear();
// clean up
if (data_ptr) {
delete [] data_ptr;
}
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'counts' data in histogram_data_1 group")) return NX_ERROR;
// get grouping
if (!ErrorHandler(NXopendata(fFileHandle, "grouping"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'grouping' data in histogram_data_1 group!")) return NX_ERROR;
attLen = SIZE_INT32;
attType = NX_INT32;
if (!ErrorHandler(NXgetattr(fFileHandle, "available", &ival, &attLen, &attType), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'grouping available' data in histogram_data_1 group!")) return NX_ERROR;
if (ival) {
vector<int> grouping;
if (!ErrorHandler(GetIntVectorData(grouping), PNEXUS_GET_DATA_ERROR, "couldn't read 'grouping' data in histogram_data_1 group!")) return NX_ERROR;
for (unsigned int i=0; i<grouping.size(); i++)
fData.fGrouping.push_back(grouping[i]);
grouping.clear();
}
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'grouping' data in histogram_data_1 group")) return NX_ERROR;
// get alpha
if (!ErrorHandler(NXopendata(fFileHandle, "alpha"), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'alpha' data in histogram_data_1 group!")) return NX_ERROR;
attLen = SIZE_INT32;
attType = NX_INT32;
if (!ErrorHandler(NXgetattr(fFileHandle, "available", &ival, &attLen, &attType), PNEXUS_OPEN_DATA_ERROR, "couldn't open 'alpha available' data in histogram_data_1 group!")) return NX_ERROR;
if (ival) {
if (!ErrorHandler(NXgetinfo(fFileHandle, &rank, dims, &type), PNEXUS_GET_META_INFO_ERROR, "couldn't get alpha info!")) return NX_ERROR;
// calculate the needed size
size = dims[0];
for (int i=1; i<rank; i++)
size *= dims[i];
noOfElements = size;
size *= GetDataSize(type);
// check that noOfElements is a multiple of 3: grp_1, grp_2, alpha_12, etc.
if ((3*(noOfElements/3)-noOfElements) != 0) {
fErrorCode = PNEXUS_GET_META_INFO_ERROR;
fErrorMsg = "PNeXus::ReadFile(): **ERROR** alpha NeXus structure (grp_1, grp_2, alpha_12, etc.) violation.";
return NX_ERROR;
}
// allocate locale memory to get the data
char *data_ptr = new char[size];
if (data_ptr == 0) {
return NX_ERROR;
}
// get the data
float *f_data_ptr = (float*) data_ptr;
status = NXgetdata(fFileHandle, f_data_ptr);
if (status != NX_OK) {
return NX_ERROR;
}
// copy the data into the vector
fData.fAlpha.clear();
PNeXusAlpha alpha;
for (int i=0; i<noOfElements; i+=3) {
fval = *(f_data_ptr+i);
alpha.fGroupFirst = (unsigned int) fval;
fval = *(f_data_ptr+i+1);
alpha.fGroupSecond = (unsigned int) fval;
alpha.fAlphaVal = *(f_data_ptr+i+2);
fData.fAlpha.push_back(alpha);
}
// clean up
if (data_ptr) {
delete [] data_ptr;
}
}
if (!ErrorHandler(NXclosedata(fFileHandle), PNEXUS_CLOSE_DATA_ERROR, "couldn't close 'alpha' data in histogram_data_1 group")) return NX_ERROR;
// close subgroup NXdata
NXclosegroup(fFileHandle);
// close group run
NXclosegroup(fFileHandle);
// close file
NXclose(&fFileHandle);
GroupHistoData();
fIsValid = true;
return true;
}
//-----------------------------------------------------------------------------------------------------
// WriteFile (public)
//-----------------------------------------------------------------------------------------------------
/**
* <p>
*
* <b>return:</b>
* - NX_OK on successfull writing
* - NX_ERROR on error. The error code/message will give the details.
*
* \param fileName
* \param fileType, allowed types are: hdf4, hdf5, xml
*/
int PNeXus::WriteFile(const char *fileName, const char *fileType)
{
char str[256];
int size, idata;
float fdata;
NXaccess access=NXACC_CREATE4;
if (!strcmp(fileType, "hdf4"))
access=NXACC_CREATE4;
else if (!strcmp(fileType, "hdf5"))
access=NXACC_CREATE5;
else if (!strcmp(fileType, "xml"))
access=NXACC_CREATEXML;
else
access=NXACC_CREATE4;
sprintf(str, "couldn't open file '%s' for writing", fileName);
if (!ErrorHandler(NXopen(fileName, access, &fFileHandle), PNEXUS_FILE_OPEN_ERROR, str)) return NX_ERROR;
// write NXfile attributes (NeXus_version, user)
strncpy(str, fUser.fUserName.data(), sizeof(str));
if (!ErrorHandler(NXputattr(fFileHandle, "user", str, strlen(str), NX_CHAR), PNEXUS_SET_ATTR_ERROR, "couldn't set NXfile attributes")) return NX_ERROR;
// make group 'run'
if (!ErrorHandler(NXmakegroup(fFileHandle, "run", "NXentry"), PNEXUS_CREATE_GROUP_ERROR, "couldn't create group 'run'.")) return NX_ERROR;
// open group 'run'
if (!ErrorHandler(NXopengroup(fFileHandle, "run", "NXentry"), PNEXUS_GROUP_OPEN_ERROR, "couldn't open group 'run' for writting.")) return NX_ERROR;
// write IDF_version
size = 1;
if (!ErrorHandler(NXmakedata(fFileHandle, "IDF_version", NX_INT32, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'IDF_version'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "IDF_version"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'IDF_version' for writting.")) return NX_ERROR;
idata = fIDFVersion;
if (!ErrorHandler(NXputdata(fFileHandle, &idata), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'IDF_version'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// write program_name, and attribute version
size = fProgramName.length();
if (!ErrorHandler(NXmakedata(fFileHandle, "program_name", NX_CHAR, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'program_name'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "program_name"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'program_name' for writting.")) return NX_ERROR;
strncpy(str, fProgramName.data(), sizeof(str));
if (!ErrorHandler(NXputdata(fFileHandle, str), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'program_name'.")) return NX_ERROR;
strncpy(str, fProgramVersion.data(), sizeof(str));
if (!ErrorHandler(NXputattr(fFileHandle, "version", str, strlen(str), NX_CHAR), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'version' for 'program_name'")) return NX_ERROR;
NXclosedata(fFileHandle);
// write run 'number'
size = 1;
if (!ErrorHandler(NXmakedata(fFileHandle, "number", NX_INT32, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'number'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "number"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'number' for writting.")) return NX_ERROR;
idata = fRunNumber;
if (!ErrorHandler(NXputdata(fFileHandle, &idata), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'number'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// write run 'title'
size = fRunTitle.length();
if (!ErrorHandler(NXmakedata(fFileHandle, "title", NX_CHAR, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'title'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "title"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'title' for writting.")) return NX_ERROR;
strncpy(str, fRunTitle.data(), sizeof(str));
if (!ErrorHandler(NXputdata(fFileHandle, str), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'title'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// write run 'notes'
size = fNotes.length();
if (!ErrorHandler(NXmakedata(fFileHandle, "notes", NX_CHAR, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'notes'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "notes"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'notes' for writting.")) return NX_ERROR;
strncpy(str, fNotes.data(), sizeof(str));
if (!ErrorHandler(NXputdata(fFileHandle, str), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'notes'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// write run 'analysis'
size = fAnalysisTag.length();
if (!ErrorHandler(NXmakedata(fFileHandle, "analysis", NX_CHAR, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'analysis'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "analysis"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'analysis' for writting.")) return NX_ERROR;
strncpy(str, fAnalysisTag.data(), sizeof(str));
if (!ErrorHandler(NXputdata(fFileHandle, str), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'analysis'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// write run 'lab'
size = fLab.length();
if (!ErrorHandler(NXmakedata(fFileHandle, "lab", NX_CHAR, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'lab'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "lab"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'lab' for writting.")) return NX_ERROR;
strncpy(str, fLab.data(), sizeof(str));
if (!ErrorHandler(NXputdata(fFileHandle, str), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'lab'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// write run 'beamline'
size = fBeamLine.length();
if (!ErrorHandler(NXmakedata(fFileHandle, "beamline", NX_CHAR, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'beamline'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "beamline"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'beamline' for writting.")) return NX_ERROR;
strncpy(str, fBeamLine.data(), sizeof(str));
if (!ErrorHandler(NXputdata(fFileHandle, str), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'beamline'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// write run 'start_time'
snprintf(str, sizeof(str), "%s %s", fStartDate.data(), fStartTime.data());
size = strlen(str);
if (!ErrorHandler(NXmakedata(fFileHandle, "start_time", NX_CHAR, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'start_time'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "start_time"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'start_time' for writting.")) return NX_ERROR;
if (!ErrorHandler(NXputdata(fFileHandle, str), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'start_time'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// write run 'end_time'
snprintf(str, sizeof(str), "%s %s", fStopDate.data(), fStopTime.data());
size = strlen(str);
if (!ErrorHandler(NXmakedata(fFileHandle, "end_time", NX_CHAR, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'end_time'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "end_time"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'end_time' for writting.")) return NX_ERROR;
if (!ErrorHandler(NXputdata(fFileHandle, str), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'end_time'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// write run 'switching_states'
size = 1;
if (!ErrorHandler(NXmakedata(fFileHandle, "switching_states", NX_INT32, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'switching_states'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "switching_states"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'switching_states' for writting.")) return NX_ERROR;
idata = fSwitchingState;
if (!ErrorHandler(NXputdata(fFileHandle, &idata), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'switching_states'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// make group 'user'
if (!ErrorHandler(NXmakegroup(fFileHandle, "user", "NXuser"), PNEXUS_CREATE_GROUP_ERROR, "couldn't create group 'user'.")) return NX_ERROR;
// open group 'user'
if (!ErrorHandler(NXopengroup(fFileHandle, "user", "NXuser"), PNEXUS_GROUP_OPEN_ERROR, "couldn't open group 'user' for writting.")) return NX_ERROR;
// write user 'name'
size = fUser.fUserName.length();
if (!ErrorHandler(NXmakedata(fFileHandle, "name", NX_CHAR, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'name'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "name"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'name' for writting.")) return NX_ERROR;
strncpy(str, fUser.fUserName.data(), sizeof(str));
if (!ErrorHandler(NXputdata(fFileHandle, str), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'name'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// write user 'experiment_number'
size = fUser.fExperimentNumber.length();
if (!ErrorHandler(NXmakedata(fFileHandle, "experiment_number", NX_CHAR, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'experiment_number'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "experiment_number"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'experiment_number' for writting.")) return NX_ERROR;
strncpy(str, fUser.fExperimentNumber.data(), sizeof(str));
if (!ErrorHandler(NXputdata(fFileHandle, str), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'experiment_number'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// close group 'user'
NXclosegroup(fFileHandle);
// make group 'sample'
if (!ErrorHandler(NXmakegroup(fFileHandle, "sample", "NXuser"), PNEXUS_CREATE_GROUP_ERROR, "couldn't create group 'sample'.")) return NX_ERROR;
// open group 'sample'
if (!ErrorHandler(NXopengroup(fFileHandle, "sample", "NXuser"), PNEXUS_GROUP_OPEN_ERROR, "couldn't open group 'sample' for writting.")) return NX_ERROR;
// write sample 'name'
size = fSample.fName.length();
if (!ErrorHandler(NXmakedata(fFileHandle, "name", NX_CHAR, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'name'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "name"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'name' for writting.")) return NX_ERROR;
strncpy(str, fSample.fName.data(), sizeof(str));
if (!ErrorHandler(NXputdata(fFileHandle, str), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'name'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// write sample 'temperature'
size = 1;
if (!ErrorHandler(NXmakedata(fFileHandle, "temperature", NX_FLOAT32, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'temperature'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "temperature"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'temperature' for writting.")) return NX_ERROR;
fdata = fSample.fTemperature;
if (!ErrorHandler(NXputdata(fFileHandle, &fdata), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'temperature'.")) return NX_ERROR;
strncpy(str, fSample.fTemperatureUnit.data(), sizeof(str));
if (!ErrorHandler(NXputattr(fFileHandle, "units", str, strlen(str), NX_CHAR), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'units' for 'temperature'")) return NX_ERROR;
NXclosedata(fFileHandle);
// write sample 'magnetic_field'
size = 1;
if (!ErrorHandler(NXmakedata(fFileHandle, "magnetic_field", NX_FLOAT32, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'magnetic_field'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "magnetic_field"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'magnetic_field' for writting.")) return NX_ERROR;
fdata = fSample.fMagneticField;
if (!ErrorHandler(NXputdata(fFileHandle, &fdata), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'magnetic_field'.")) return NX_ERROR;
strncpy(str, fSample.fMagneticFieldUnit.data(), sizeof(str));
if (!ErrorHandler(NXputattr(fFileHandle, "units", str, strlen(str), NX_CHAR), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'units' for 'magnetic_field'")) return NX_ERROR;
NXclosedata(fFileHandle);
// write sample 'shape'
size = fSample.fShape.length();
if (!ErrorHandler(NXmakedata(fFileHandle, "shape", NX_CHAR, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'shape'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "shape"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'shape' for writting.")) return NX_ERROR;
strncpy(str, fSample.fShape.data(), sizeof(str));
if (!ErrorHandler(NXputdata(fFileHandle, str), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'shape'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// write sample 'magnetic_field_state'
size = fSample.fMagneticFieldState.length();
if (!ErrorHandler(NXmakedata(fFileHandle, "magnetic_field_state", NX_CHAR, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'magnetic_field_state'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "magnetic_field_state"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'magnetic_field_state' for writting.")) return NX_ERROR;
strncpy(str, fSample.fMagneticFieldState.data(), sizeof(str));
if (!ErrorHandler(NXputdata(fFileHandle, str), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'magnetic_field_state'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// write sample 'magnetic_field_vector'
// !! TO BE DONE !!
// write sample 'environment'
size = fSample.fEnvironment.length();
if (!ErrorHandler(NXmakedata(fFileHandle, "environment", NX_CHAR, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'environment'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "environment"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'environment' for writting.")) return NX_ERROR;
strncpy(str, fSample.fEnvironment.data(), sizeof(str));
if (!ErrorHandler(NXputdata(fFileHandle, str), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'environment'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// close group 'sample'
NXclosegroup(fFileHandle);
// make group 'instrument'
if (!ErrorHandler(NXmakegroup(fFileHandle, "instrument", "NXinstrument"), PNEXUS_CREATE_GROUP_ERROR, "couldn't create group 'instrument'.")) return NX_ERROR;
// open group 'instrument'
if (!ErrorHandler(NXopengroup(fFileHandle, "instrument", "NXinstrument"), PNEXUS_GROUP_OPEN_ERROR, "couldn't open group 'instrument' for writting.")) return NX_ERROR;
// write instrument 'name'
size = fInstrument.name.length();
if (!ErrorHandler(NXmakedata(fFileHandle, "name", NX_CHAR, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'name'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "name"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'name' for writting.")) return NX_ERROR;
strncpy(str, fInstrument.name.data(), sizeof(str));
if (!ErrorHandler(NXputdata(fFileHandle, str), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'name'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// make group 'detector'
if (!ErrorHandler(NXmakegroup(fFileHandle, "detector", "NXdetector"), PNEXUS_CREATE_GROUP_ERROR, "couldn't create group 'detector'.")) return NX_ERROR;
// open group 'detector'
if (!ErrorHandler(NXopengroup(fFileHandle, "detector", "NXdetector"), PNEXUS_GROUP_OPEN_ERROR, "couldn't open group 'detector' for writting.")) return NX_ERROR;
// write detector 'number'
size = 1;
if (!ErrorHandler(NXmakedata(fFileHandle, "number", NX_INT32, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'number'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "number"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'number' for writting.")) return NX_ERROR;
idata = fInstrument.detector.number;
if (!ErrorHandler(NXputdata(fFileHandle, &idata), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'number'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// close group 'detector'
NXclosegroup(fFileHandle);
// make group 'collimator'
if (!ErrorHandler(NXmakegroup(fFileHandle, "collimator", "NXcollimator"), PNEXUS_CREATE_GROUP_ERROR, "couldn't create group 'collimator'.")) return NX_ERROR;
// open group 'collimator'
if (!ErrorHandler(NXopengroup(fFileHandle, "collimator", "NXcollimator"), PNEXUS_GROUP_OPEN_ERROR, "couldn't open group 'collimator' for writting.")) return NX_ERROR;
// write collimator 'type'
size = fInstrument.collimator.type.length();
if (!ErrorHandler(NXmakedata(fFileHandle, "type", NX_CHAR, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'type'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "type"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'type' for writting.")) return NX_ERROR;
strncpy(str, fInstrument.collimator.type.data(), sizeof(str));
if (!ErrorHandler(NXputdata(fFileHandle, str), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'type'.")) return NX_ERROR;
NXclosedata(fFileHandle);
// close group 'collimator'
NXclosegroup(fFileHandle);
// make group 'beam'
if (!ErrorHandler(NXmakegroup(fFileHandle, "beam", "NXbeam"), PNEXUS_CREATE_GROUP_ERROR, "couldn't create group 'beam'.")) return NX_ERROR;
// open group 'beam'
if (!ErrorHandler(NXopengroup(fFileHandle, "beam", "NXbeam"), PNEXUS_GROUP_OPEN_ERROR, "couldn't open group 'beam' for writting.")) return NX_ERROR;
size = 1;
if (!ErrorHandler(NXmakedata(fFileHandle, "total_counts", NX_FLOAT32, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'total_counts'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "total_counts"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'total_counts' for writting.")) return NX_ERROR;
fdata = fInstrument.beam.total_counts;
if (!ErrorHandler(NXputdata(fFileHandle, &fdata), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'total_counts'.")) return NX_ERROR;
strncpy(str, fInstrument.beam.total_counts_units.data(), sizeof(str));
if (!ErrorHandler(NXputattr(fFileHandle, "units", str, strlen(str), NX_CHAR), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'units' for 'total_counts'")) return NX_ERROR;
NXclosedata(fFileHandle);
// close group 'beam'
NXclosegroup(fFileHandle);
// close group 'instrument'
NXclosegroup(fFileHandle);
// make group 'histogram_data_1'
if (!ErrorHandler(NXmakegroup(fFileHandle, "histogram_data_1", "NXdata"), PNEXUS_CREATE_GROUP_ERROR, "couldn't create group 'histogram_data_1'.")) return NX_ERROR;
// open group 'histogram_data_1'
if (!ErrorHandler(NXopengroup(fFileHandle, "histogram_data_1", "NXdata"), PNEXUS_GROUP_OPEN_ERROR, "couldn't open group 'histogram_data_1' for writting.")) return NX_ERROR;
// write data 'counts'
int *histo_data=0;
int histo_size[2];
if (fData.fHisto.size() == 0) {
histo_data = new int[1];
histo_data[0] = -1;
histo_size[0] = 1;
histo_size[1] = 1;
} else {
histo_data = new int[fData.fHisto.size()*fData.fHisto[0].size()];
for (unsigned int i=0; i<fData.fHisto.size(); i++)
for (unsigned int j=0; j<fData.fHisto[0].size(); j++)
histo_data[i*fData.fHisto[0].size()+j] = fData.fHisto[i][j];
histo_size[0] = fData.fHisto.size();
histo_size[1] = fData.fHisto[0].size();
}
if (!ErrorHandler(NXmakedata(fFileHandle, "counts", NX_INT32, 2, histo_size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'counts'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "counts"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'counts' for writting.")) return NX_ERROR;
if (!ErrorHandler(NXputdata(fFileHandle, (void*)histo_data), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'counts'.")) return NX_ERROR;
strncpy(str, "counts", sizeof(str));
if (!ErrorHandler(NXputattr(fFileHandle, "units", str, strlen(str), NX_CHAR), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'units' for 'counts'")) return NX_ERROR;
idata = 1;
if (!ErrorHandler(NXputattr(fFileHandle, "signal", &idata, 1, NX_INT32), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'signal' for 'counts'")) return NX_ERROR;
idata = fData.fHisto.size();
if (!ErrorHandler(NXputattr(fFileHandle, "number", &idata, 1, NX_INT32), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'number' for 'counts'")) return NX_ERROR;
idata = fData.fT0[0];
if (!ErrorHandler(NXputattr(fFileHandle, "T0_bin", &idata, 1, NX_INT32), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'T0_bin' for 'counts'")) return NX_ERROR;
idata = fData.fFirstGoodBin[0];
if (!ErrorHandler(NXputattr(fFileHandle, "first_good_bin", &idata, 1, NX_INT32), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'first_good_bin' for 'counts'")) return NX_ERROR;
idata = fData.fLastGoodBin[0];
if (!ErrorHandler(NXputattr(fFileHandle, "last_good_bin", &idata, 1, NX_INT32), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'last_good_bin' for 'counts'")) return NX_ERROR;
fdata = 1.0e3*fData.fTimeResolution/2.0;
if (!ErrorHandler(NXputattr(fFileHandle, "offset", &fdata, 1, NX_FLOAT32), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'offset' for 'counts'")) return NX_ERROR;
if (histo_data) {
delete [] histo_data;
}
NXclosedata(fFileHandle);
// write data 'histogram_resolution'
if (!ErrorHandler(NXmakedata(fFileHandle, "histogram_resolution", NX_FLOAT32, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'histogram_resolution'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "histogram_resolution"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'histogram_resolution' for writting.")) return NX_ERROR;
fdata = fData.fTimeResolution * 1.0e3; // ns -> ps
if (!ErrorHandler(NXputdata(fFileHandle, &fdata), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'histogram_resolution'.")) return NX_ERROR;
strncpy(str, "picoseconds", sizeof(str));
if (!ErrorHandler(NXputattr(fFileHandle, "units", str, strlen(str), NX_CHAR), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'units' for 'histogram_resolution'")) return NX_ERROR;
NXclosedata(fFileHandle);
// write data 'time_zero' always set to 0 since the T0_bin attribute of counts is relevant only
if (!ErrorHandler(NXmakedata(fFileHandle, "time_zero", NX_FLOAT32, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'time_zero'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "time_zero"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'time_zero' for writting.")) return NX_ERROR;
fdata = 0.0;
if (!ErrorHandler(NXputdata(fFileHandle, &fdata), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'time_zero'.")) return NX_ERROR;
strncpy(str, "microseconds", sizeof(str));
if (!ErrorHandler(NXputattr(fFileHandle, "units", str, strlen(str), NX_CHAR), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'units' for 'time_zero'")) return NX_ERROR;
idata = 0;
if (!ErrorHandler(NXputattr(fFileHandle, "available", &idata, 1, NX_INT32), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'available' for 'time_zero'")) return NX_ERROR;
NXclosedata(fFileHandle);
// write data 'raw_time'
if (fData.fHisto.size() == 0) {
fErrorCode = PNEXUS_HISTO_ERROR;
fErrorMsg = "no data for writing present.";
return NX_ERROR;
}
float *raw_time = new float[fData.fHisto[0].size()-1];
for (unsigned int i=0; i<fData.fHisto[0].size()-1; i++) {
raw_time[i] = fData.fTimeResolution * (float)i / 1.0e3; // raw time in (us)
}
size = fData.fHisto[0].size()-1;
if (!ErrorHandler(NXmakedata(fFileHandle, "raw_time", NX_FLOAT32, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'raw_time'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "raw_time"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'raw_time' for writting.")) return NX_ERROR;
if (!ErrorHandler(NXputdata(fFileHandle, raw_time), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'raw_time'.")) return NX_ERROR;
idata = 1;
if (!ErrorHandler(NXputattr(fFileHandle, "axis", &idata, 1, NX_INT32), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'axis' for 'raw_time'")) return NX_ERROR;
idata = 1;
if (!ErrorHandler(NXputattr(fFileHandle, "primary", &idata, 1, NX_INT32), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'primary' for 'raw_time'")) return NX_ERROR;
strncpy(str, "microseconds", sizeof(str));
if (!ErrorHandler(NXputattr(fFileHandle, "units", str, strlen(str), NX_CHAR), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'units' for 'raw_time'")) return NX_ERROR;
NXclosedata(fFileHandle);
if (raw_time) {
delete [] raw_time;
raw_time = 0;
}
// write data 'corrected_time'
float *corrected_time = new float[fData.fHisto[0].size()-1];
for (unsigned int i=0; i<fData.fHisto[0].size()-1; i++) {
corrected_time[i] = fData.fTimeResolution * (float)((int)i-(int)fData.fT0[0]+1) / 1.0e3; // raw time in (us)
}
size = fData.fHisto[0].size()-1;
if (!ErrorHandler(NXmakedata(fFileHandle, "corrected_time", NX_FLOAT32, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'corrected_time'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "corrected_time"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'corrected_time' for writting.")) return NX_ERROR;
if (!ErrorHandler(NXputdata(fFileHandle, corrected_time), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'corrected_time'.")) return NX_ERROR;
idata = 1;
if (!ErrorHandler(NXputattr(fFileHandle, "axis", &idata, 1, NX_INT32), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'axis' for 'corrected_time'")) return NX_ERROR;
strncpy(str, "microseconds", sizeof(str));
if (!ErrorHandler(NXputattr(fFileHandle, "units", str, strlen(str), NX_CHAR), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'units' for 'corrected_time'")) return NX_ERROR;
NXclosedata(fFileHandle);
if (corrected_time) {
delete [] corrected_time;
corrected_time = 0;
}
// write data 'grouping'
int *grouping = new int[fData.fHisto.size()];
vector<int> groupNo; // keep the number of different groupings
if (fData.fHisto.size() == fData.fGrouping.size()) { // grouping vector seems to be properly defined
bool found;
groupNo.push_back(fData.fGrouping[0]);
for (unsigned int i=0; i<fData.fHisto.size(); i++) {
grouping[i] = fData.fGrouping[i];
found = false;
for (unsigned int j=0; j<groupNo.size(); j++) {
if ((int)fData.fGrouping[i] == groupNo[j]) {
found = true;
break;
}
}
if (!found) {
groupNo.push_back(fData.fGrouping[i]);
}
}
} else { // grouping vector not available
for (unsigned int i=0; i<fData.fHisto.size(); i++) {
grouping[i] = 0;
}
}
size = fData.fHisto.size();
if (!ErrorHandler(NXmakedata(fFileHandle, "grouping", NX_INT32, 1, &size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'grouping'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "grouping"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'grouping' for writting.")) return NX_ERROR;
if (!ErrorHandler(NXputdata(fFileHandle, grouping), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'grouping'.")) return NX_ERROR;
idata = groupNo.size();
if (!ErrorHandler(NXputattr(fFileHandle, "available", &idata, 1, NX_INT32), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'available' for 'grouping'")) return NX_ERROR;
NXclosedata(fFileHandle);
if (grouping) {
delete [] grouping;
grouping = 0;
}
groupNo.clear();
// write data 'alpha'
float *alpha;
int array_size[2];
if (fData.fAlpha.size() == 0) {
alpha = new float[3];
alpha[0] = -1.0;
alpha[1] = -1.0;
alpha[2] = -1.0;
array_size[0] = 1;
array_size[1] = 3;
} else {
alpha = new float[fData.fAlpha.size()*3];
for (unsigned int i=0; i<fData.fAlpha.size(); i++) {
alpha[i] = (float)fData.fAlpha[i].fGroupFirst;
alpha[i+1] = (float)fData.fAlpha[i].fGroupSecond;
alpha[i+2] = (float)fData.fAlpha[i].fAlphaVal;
}
array_size[0] = fData.fAlpha.size();
array_size[1] = 3;
}
if (!ErrorHandler(NXmakedata(fFileHandle, "alpha", NX_FLOAT32, 2, array_size), PNEXUS_MAKE_DATA_ERROR, "couldn't create data entry 'alpha'.")) return NX_ERROR;
if (!ErrorHandler(NXopendata(fFileHandle, "alpha"), PNEXUS_OPEN_DATA_ERROR, "couldn't open data 'alpha' for writting.")) return NX_ERROR;
if (!ErrorHandler(NXputdata(fFileHandle, (void*)alpha), PNEXUS_PUT_DATA_ERROR, "couldn't put data 'alpha'.")) return NX_ERROR;
idata = fData.fAlpha.size();
if (!ErrorHandler(NXputattr(fFileHandle, "available", &idata, 1, NX_INT32), PNEXUS_PUT_ATTR_ERROR, "couldn't put attribute 'available' for 'alpha'")) return NX_ERROR;
if (alpha) {
delete [] alpha;
}
// close group 'histogram_data_1'
NXclosegroup(fFileHandle);
// close group 'run'
NXclosegroup(fFileHandle);
NXclose(&fFileHandle);
return NX_OK;
}
//-----------------------------------------------------------------------------------------------------
// WriteFile (public)
//-----------------------------------------------------------------------------------------------------
/**
* <p>Dump read data to the standard output.
*/
void PNeXus::Dump()
{
cout << endl << "-----------------------------";
cout << endl << " NeXus Dump";
cout << endl << "-----------------------------";
cout << endl;
cout << endl << "file name : " << fFileName;
cout << endl << "IDF version : " << fIDFVersion;
cout << endl << "program name : " << fProgramName << ", version : " << fProgramVersion;
cout << endl << "run number : " << fRunNumber;
cout << endl << "run title : " << fRunTitle;
cout << endl << "run notes : " << fNotes;
cout << endl << "analysis : " << fAnalysisTag;
cout << endl << "lab : " << fLab;
cout << endl << "beamline : " << fBeamLine;
cout << endl << "start date/time : " << fStartDate << "/" << fStartTime;
cout << endl << "stop date/time : " << fStopDate << "/" << fStopTime;
cout << endl << "switching state : " << fSwitchingState << " (red/green mode)";
cout << endl << "-----------------------------";
cout << endl << "user info";
cout << endl << "user : " << fUser.fUserName;
cout << endl << "exp. number : " << fUser.fExperimentNumber;
cout << endl << "-----------------------------";
cout << endl << "sample info";
cout << endl << "sample name : " << fSample.fName;
cout << endl << "temperature : " << fSample.fTemperature << " (" << fSample.fTemperatureUnit << ")";
cout << endl << "magnetic state : " << fSample.fMagneticFieldState;
cout << endl << "magnetic field : " << fSample.fMagneticField << " (" << fSample.fMagneticFieldUnit << ")";
cout << endl << "mag. vector : ";
if (fSample.fMagneticFieldVectorAvailable) {
for (unsigned int i=0; i<fSample.fMagneticFieldVector.size(); i++) {
cout << fSample.fMagneticFieldVector[i] << ", ";
}
cout << "(" << fSample.fMagneticFieldVectorUnits << "), coord.system: " << fSample.fMagneticFieldVectorCoordinateSystem;
} else {
cout << "not available.";
}
cout << endl << "shape : " << fSample.fShape;
cout << endl << "environment : " << fSample.fEnvironment;
cout << endl << "-----------------------------";
cout << endl << "instrument info";
cout << endl << "instrument name : " << fInstrument.name;
cout << endl << " detector info";
cout << endl << " detector number : " << fInstrument.detector.number;
cout << endl << " -----------------------------";
cout << endl << " collimator info";
cout << endl << " collimator type : " << fInstrument.collimator.type;
cout << endl << " -----------------------------";
cout << endl << " beam info";
cout << endl << " beam total number of counts : " << fInstrument.beam.total_counts << " " << fInstrument.beam.total_counts_units;
cout << endl << "-----------------------------";
cout << endl << "run data";
cout << endl << "time resolution : " << fData.fTimeResolution << " (ns)";
cout << endl << "number of histos: " << fData.fNumberOfHistos;
if (fData.fAlpha.size() != 0) {
cout << endl << "alpha : ";
for (unsigned int i=0; i<fData.fAlpha.size(); i++) {
cout << "(" << fData.fAlpha[i].fGroupFirst << "/" << fData.fAlpha[i].fGroupSecond << "/" << fData.fAlpha[i].fAlphaVal << "), ";
}
} else {
cout << endl << "alpha : not available";
}
if (fData.fGrouping.size() != 0) {
cout << endl << "grouping : ";
for (unsigned int i=0; i<fData.fGrouping.size(); i++) {
cout << "(" << i << "/" << fData.fGrouping[i] << "), ";
}
} else {
cout << endl << "grouping : not available";
}
cout << endl << "t0 : " << fData.fT0[0];
cout << endl << "first good bin : " << fData.fFirstGoodBin[0];
cout << endl << "last good bin : " << fData.fLastGoodBin[0];
cout << endl << "histograms : +++++++++++";
for (unsigned int i=0; i<fData.fHisto.size(); i++) {
cout << endl << "histo " << i+1 << ": ";
for (unsigned int j=0; j<15; j++) {
cout << fData.fHisto[i][j] << ", ";
}
cout << "...";
}
cout << endl << "-----------------------------";
cout << endl << "grouped histograms : ++++++++";
for (unsigned int i=0; i<fGroupedData.size(); i++) {
cout << endl << "grouped histo " << i+1 << ": ";
for (unsigned int j=0; j<15; j++) {
cout << fGroupedData[i][j] << ", ";
}
cout << "...";
}
cout << endl << "-----------------------------";
cout << endl << "done.";
cout << endl << endl;
}
//-----------------------------------------------------------------------------------------------------
// SetStartDate (public)
//-----------------------------------------------------------------------------------------------------
/**
* <p>The date should look like yyyy-mm-dd.
*
* <b>return:</b>
* - true on date string has proper format
* - false on error. The error code/message will give the details.
*
* \param date
*/
bool PNeXus::SetStartDate(const char *date)
{
string strDate = date;
return SetStartDate(strDate);
}
//-----------------------------------------------------------------------------------------------------
// SetStartDate (public)
//-----------------------------------------------------------------------------------------------------
/**
* <p>The date should look like yyyy-mm-dd.
*
* <b>return:</b>
* - true on date string has proper format
* - false on error. The error code/message will give the details.
*
* \param date
*/
bool PNeXus::SetStartDate(string date)
{
bool ok=false;
string str = TransformDate(date, ok);
if (!ok)
return false;
fStartDate = str;
return true;
}
//-----------------------------------------------------------------------------------------------------
// SetStartTime (public)
//-----------------------------------------------------------------------------------------------------
/**
* <p>The time should look like hh:mm:ss.
*
* <b>return:</b>
* - true on time string has proper format
* - false on error. The error code/message will give the details.
*
* \param time
*/
bool PNeXus::SetStartTime(const char *time)
{
string strTime = time;
return SetStartTime(strTime);
}
//-----------------------------------------------------------------------------------------------------
// SetStartTime (public)
//-----------------------------------------------------------------------------------------------------
/**
* <p>The time should look like hh:mm:ss.
*
* <b>return:</b>
* - true on time string has proper format
* - false on error. The error code/message will give the details.
*
* \param time
*/
bool PNeXus::SetStartTime(string time)
{
if (time.length() != 8) {
fErrorCode = PNEXUS_WRONG_TIME_FORMAT;
fErrorMsg = "PNeXus::SetStartTime **ERROR** given time="+time+", is not of the required form hh:mm:ss!";
return false;
}
if ((time[2] != ':') || (time[5] != ':')) {
fErrorCode = PNEXUS_WRONG_TIME_FORMAT;
fErrorMsg = "PNeXus::SetStartTime **ERROR** given time="+time+", is not of the required form hh:mm:ss!";
return false;
}
fStartTime = time;
return true;
}
//-----------------------------------------------------------------------------------------------------
// SetStopDate (public)
//-----------------------------------------------------------------------------------------------------
/**
* <p>
*
* <b>return:</b>
* - true on date string has proper format
* - false on error. The error code/message will give the details.
*
* \param date
*/
bool PNeXus::SetStopDate(const char *date)
{
string strDate = date;
return SetStopDate(strDate);
}
//-----------------------------------------------------------------------------------------------------
// SetStopDate (public)
//-----------------------------------------------------------------------------------------------------
/**
* <p>
*
* <b>return:</b>
* - true on date string has proper format
* - false on error. The error code/message will give the details.
*
* \param date
*/
bool PNeXus::SetStopDate(string date)
{
bool ok=false;
string str = TransformDate(date, ok);
if (!ok)
return false;
fStopDate = str;
return true;
}
//-----------------------------------------------------------------------------------------------------
// SetStopTime (public)
//-----------------------------------------------------------------------------------------------------
/**
* <p>
*
* <b>return:</b>
* - true on time string has proper format
* - false on error. The error code/message will give the details.
*
* \param time
*/
bool PNeXus::SetStopTime(const char *time)
{
string strTime = time;
return SetStopTime(strTime);
}
//-----------------------------------------------------------------------------------------------------
// SetStopTime (public)
//-----------------------------------------------------------------------------------------------------
/**
* <p>
*
* <b>return:</b>
* - true on time string has proper format
* - false on error. The error code/message will give the details.
*
* \param time
*/
bool PNeXus::SetStopTime(string time)
{
if (time.length() != 8) {
fErrorCode = PNEXUS_WRONG_TIME_FORMAT;
fErrorMsg = "PNeXus::SetStopTime **ERROR** given time="+time+", is not of the required form hh:mm:ss!";
return false;
}
if ((time[2] != ':') || (time[5] != ':')) {
fErrorCode = PNEXUS_WRONG_TIME_FORMAT;
fErrorMsg = "PNeXus::SetStopTime **ERROR** given time="+time+", is not of the required form hh:mm:ss!";
return false;
}
fStopTime = time;
return true;
}
//-----------------------------------------------------------------------------------------------------
// CleanUp (private)
//-----------------------------------------------------------------------------------------------------
/**
*
*/
void PNeXus::CleanUp()
{
fData.fTimeResolution = 0.0;
fData.fNumberOfHistos = 0;
fData.fAlpha.clear();
fData.fGrouping.clear();
fData.fFirstGoodBin.clear();
fData.fLastGoodBin.clear();
fData.fT0.clear();
fData.fHistoName.clear();
for (unsigned int i=0; i<fData.fHisto.size(); i++)
fData.fHisto[i].clear();
fData.fHisto.clear();
}
//-----------------------------------------------------------------------------------------------------
// Init (private)
//-----------------------------------------------------------------------------------------------------
/**
*
*/
void PNeXus::Init()
{
fIsValid = false;
fFileName = "n/a";
fFileHandle = 0;
fErrorMsg = "No Data available!";
fErrorCode = -1;
fIDFVersion = -1;
fProgramName = "n/a";
fProgramVersion = "n/a";
fRunNumber = -1;
fRunTitle = "n/a";
fNotes = "n/a";
fAnalysisTag = "n/a";
fLab = "n/a";
fBeamLine = "n/a";
fStartDate = "n/a";
fStartTime = "n/a";
fStopDate = "n/a";
fStopTime = "n/a";
fSwitchingState = -1;
fSample.fEnvironment = "n/a";
fSample.fMagneticField = 9.9e17;
fSample.fMagneticFieldUnit = "n/a";
fSample.fMagneticFieldState = "n/a";
fSample.fName = "n/a";
fSample.fShape = "n/a";
fSample.fTemperature = 9.9e17;
fSample.fTemperatureUnit = "n/a";
fInstrument.name = "n/a";
fInstrument.detector.number = 0;
fInstrument.collimator.type = "n/a";
fInstrument.beam.total_counts = 0;
fInstrument.beam.total_counts_units = "n/a";
fData.fNumberOfHistos = 0;
fData.fTimeResolution = 0.0;
fData.fAlpha.clear();
fData.fFirstGoodBin.clear();
fData.fLastGoodBin.clear();
fData.fHistoName.clear();
fData.fGrouping.clear();
fData.fT0.clear();
}
//-----------------------------------------------------------------------------------------------------
// ErrorHandler (private)
//-----------------------------------------------------------------------------------------------------
/**
* <p>
*
* <b>return:</b>
* - true of no error occurred
* - false on error
*
* \param status of the calling routine
* \param errCode will set the fErrorCode of the class
* \param errMsg will set the fErrorMsg of the class
*/
bool PNeXus::ErrorHandler(NXstatus status, int errCode, string errMsg)
{
if (status != NX_OK) {
fErrorCode = errCode;
fErrorMsg = errMsg;
if (fFileHandle != 0) {
CleanUp();
NXclose(&fFileHandle);
}
return false;
}
return true;
}
//-----------------------------------------------------------------------------------------------------
// GetStringData (private)
//-----------------------------------------------------------------------------------------------------
/**
* <p>
*
* <b>return:</b>
* - NX_OK on success
* - NX_ERROR otherwiese
*
* \param str string to be fed
*/
NXstatus PNeXus::GetStringData(string &str)
{
int i, status, rank, type, dims[32];
char cstr[VGNAMELENMAX];
NXname data_value;
status = NXgetinfo(fFileHandle, &rank, dims, &type);
if (status != NX_OK) {
fErrorCode = PNEXUS_GET_META_INFO_ERROR;
fErrorMsg = "PNeXus::GetStringData() **ERROR** couldn't get meta info!";
return NX_ERROR;
}
if ((type != NX_CHAR) || (rank > 1) || (dims[0] >= VGNAMELENMAX)) {
fErrorCode = PNEXUS_WRONG_META_INFO;
fErrorMsg = "PNeXus::GetStringData() **ERROR** found wrong meta info!";
return NX_ERROR;
}
status = NXgetdata(fFileHandle, data_value);
if (status != NX_OK) {
fErrorCode = PNEXUS_GET_DATA_ERROR;
fErrorMsg = "PNeXus::GetStringData() **ERROR** couldn't get data!";
return NX_ERROR;
}
for (i = 0; i < dims[0]; i++)
cstr[i] = *(data_value + i);
cstr[i] = '\0';
str = cstr;
return NX_OK;
}
//-----------------------------------------------------------------------------------------------------
// GetStringAttr (private)
//-----------------------------------------------------------------------------------------------------
/**
* <p>
*
* <b>return:</b>
* - NX_OK on success
* - NX_ERROR otherwiese
*
* \param attr attribute tag
* \param str string to be fed
*/
NXstatus PNeXus::GetStringAttr(string attr, string &str)
{
int i, status, attlen, atttype;
char cstr[VGNAMELENMAX];
NXname data_value;
attlen = VGNAMELENMAX - 1;
atttype = NX_CHAR;
status = NXgetattr(fFileHandle, (char *)attr.c_str(), data_value, &attlen, &atttype);
if (status != NX_OK) {
cerr << endl << "**ERROR** in routine NXMgetstringattr: couldn't get attribute!" << endl << endl;
fErrorCode = PNEXUS_GET_ATTR_ERROR;
fErrorMsg = "PNeXus::GetStringAttr() **ERROR** couldn't get string attribute data!";
return NX_ERROR;
}
for (i = 0; i < attlen; i++)
cstr[i] = *(data_value + i);
cstr[i] = '\0';
str = cstr;
return NX_OK;
}
//-----------------------------------------------------------------------------------------------------
// GetDataSize (private)
//-----------------------------------------------------------------------------------------------------
/**
* <p>
*
* <b>return:</b>
* - size in bytes of the given type
* - 0 if the type is not recognized
*
* \param type
*/
int PNeXus::GetDataSize(int type)
{
int size;
switch (type) {
case NX_CHAR:
size = SIZE_CHAR8;
break;
case NX_FLOAT32:
size = SIZE_FLOAT32;
break;
case NX_FLOAT64:
size = SIZE_FLOAT64;
break;
case NX_INT8:
size = SIZE_INT8;
break;
case NX_UINT8:
size = SIZE_UINT8;
break;
case NX_INT16:
size = SIZE_INT16;
break;
case NX_UINT16:
size = SIZE_UINT16;
break;
case NX_INT32:
size = SIZE_INT32;
break;
case NX_UINT32:
size = SIZE_UINT32;
break;
default:
size = 0;
break;
}
return size;
}
//-----------------------------------------------------------------------------------------------------
// GetDoubleVectorData (private)
//-----------------------------------------------------------------------------------------------------
/**
* <p>
*
* <b>return:</b>
* - NX_OK on success
* - NX_ERROR otherwiese
*
* \param data
*/
NXstatus PNeXus::GetDoubleVectorData(vector<double> &data)
{
// get information of the current nexus entity
int rank, type, dims[32], size, noOfElements;
if (!ErrorHandler(NXgetinfo(fFileHandle, &rank, dims, &type), PNEXUS_GET_META_INFO_ERROR, "couldn't get data info!"))
return NX_ERROR;
// calculate the needed size
size = dims[0];
for (int i=1; i<rank; i++)
size *= dims[i];
noOfElements = size;
size *= GetDataSize(type);
// allocate locale memory to get the data
char *data_ptr = new char[size];
if (data_ptr == 0) {
return NX_ERROR;
}
// get the data
float *f_data_ptr = (float*) data_ptr;
int status = NXgetdata(fFileHandle, f_data_ptr);
if (status != NX_OK) {
return NX_ERROR;
}
// copy the data into the vector
data.clear();
for (int i=0; i<noOfElements; i++) {
data.push_back(*(f_data_ptr+i));
}
// clean up
if (data_ptr) {
delete [] data_ptr;
}
return NX_OK;
}
//-----------------------------------------------------------------------------------------------------
// GetIntVectorData (private)
//-----------------------------------------------------------------------------------------------------
/**
* <p>
*
* <b>return:</b>
* - NX_OK on success
* - NX_ERROR otherwiese
*
* \param data
*/
NXstatus PNeXus::GetIntVectorData(vector<int> &data)
{
// get information of the current nexus entity
int rank, type, dims[32], size, noOfElements;
if (!ErrorHandler(NXgetinfo(fFileHandle, &rank, dims, &type), PNEXUS_GET_META_INFO_ERROR, "couldn't get data info!"))
return NX_ERROR;
// calculate the needed size
size = dims[0];
for (int i=1; i<rank; i++)
size *= dims[i];
noOfElements = size;
size *= GetDataSize(type);
// allocate locale memory to get the data
char *data_ptr = new char[size];
if (data_ptr == 0) {
return NX_ERROR;
}
// get the data
int *i_data_ptr = (int*) data_ptr;
int status = NXgetdata(fFileHandle, i_data_ptr);
if (status != NX_OK) {
return NX_ERROR;
}
// copy the data into the vector
data.clear();
for (int i=0; i<noOfElements; i++) {
data.push_back(*(i_data_ptr+i));
}
// clean up
if (data_ptr) {
delete [] data_ptr;
}
return NX_OK;
}
//-----------------------------------------------------------------------------------------------------
// SetT0 (public)
//-----------------------------------------------------------------------------------------------------
/**
* <p>Sets t0. The current muSR NeXus implementation has only a single t0 for all detectors since it was
* tailored for pulsed muon sources (ISIS). This eventually needs to be changed.
*
* \param t0 to be set
* \param idx index of t0
*/
void PNeXus::SetT0(unsigned int t0, unsigned idx)
{
if (idx >= fData.fT0.size())
fData.fT0.resize(idx+1);
fData.fT0[idx] = t0;
}
//-----------------------------------------------------------------------------------------------------
// SetFirstGoodBin (public)
//-----------------------------------------------------------------------------------------------------
/**
* <p>Sets first good bin. The current muSR NeXus implementation has only a single first good bin for all detectors since it was
* tailored for pulsed muon sources (ISIS). This eventually needs to be changed.
*
* \param fgb first good bin to be set
* \param idx index of t0
*/
void PNeXus::SetFirstGoodBin(unsigned int fgb, unsigned int idx)
{
if (idx >= fData.fFirstGoodBin.size())
fData.fFirstGoodBin.resize(idx+1);
fData.fFirstGoodBin[idx] = fgb;
}
//-----------------------------------------------------------------------------------------------------
// SetLastGoodBin (public)
//-----------------------------------------------------------------------------------------------------
/**
* <p>Sets last good bin. The current muSR NeXus implementation has only a single last good bin for all detectors since it was
* tailored for pulsed muon sources (ISIS). This eventually needs to be changed.
*
* \param lgb to be set
* \param idx index of t0
*/
void PNeXus::SetLastGoodBin(unsigned int lgb, unsigned int idx)
{
if (idx >= fData.fLastGoodBin.size())
fData.fLastGoodBin.resize(idx+1);
fData.fLastGoodBin[idx] = lgb;
}
//-----------------------------------------------------------------------------------------------------
// SetHisto (public)
//-----------------------------------------------------------------------------------------------------
/**
* <p>
*
* \param histoNo histogram number (start counting from 0)
* \param data histogram data vector to be set
*/
void PNeXus::SetHisto(unsigned int histoNo, vector<unsigned int> &data)
{
if (histoNo >= fData.fHisto.size())
fData.fHisto.resize(histoNo+1);
fData.fHisto[histoNo] = data;
}
//-----------------------------------------------------------------------------------------------------
// GroupHistoData (private)
//-----------------------------------------------------------------------------------------------------
/**
* <p>Feed the grouped histo data, based on the grouping vector and the raw histo data.
*/
NXstatus PNeXus::GroupHistoData()
{
// check if NO grouping is whished, in which case fData.fHisto == fGroupedData
if (fData.fGrouping.size() == 0) {
for (unsigned int i=0; i<fData.fHisto.size(); i++)
fGroupedData.push_back(fData.fHisto[i]);
return NX_OK;
}
// check that the grouping size is equal to the number of histograms
if (fData.fGrouping.size() != fData.fHisto.size()) {
fErrorCode = PNEXUS_HISTO_ERROR;
fErrorMsg = "PNeXus::GroupHistoData() **ERROR** grouping vector size is unequal to the number of histos present!";
return NX_ERROR;
}
// make a vector of all grouping present
vector<unsigned int> groupingValue;
bool newGroup = true;
for (unsigned int i=0; i<fData.fGrouping.size(); i++) {
newGroup = true;
for (unsigned int j=0; j<groupingValue.size(); j++) {
if (groupingValue[j] == fData.fGrouping[i]) {
newGroup = false;
break;
}
}
if (newGroup)
groupingValue.push_back(fData.fGrouping[i]);
}
// check that none of the grouping values is outside of the valid range
for (unsigned int i=0; i<groupingValue.size(); i++) {
if (groupingValue[i]-1 > fData.fHisto.size()) {
fErrorCode = PNEXUS_HISTO_ERROR;
fErrorMsg = "PNeXus::GroupHistoData() **ERROR** grouping values out of range";
return NX_ERROR;
}
}
// set fGroupedData to the proper size
fGroupedData.clear();
fGroupedData.resize(groupingValue.size());
for (unsigned int i=0; i<fGroupedData.size(); i++) {
fGroupedData[i].resize(fData.fHisto[0].size());
}
for (unsigned int i=0; i<fData.fHisto.size(); i++) {
for (unsigned int j=0; j<fData.fHisto[i].size(); j++) {
fGroupedData[fData.fGrouping[i]-1][j] += fData.fHisto[i][j];
}
}
// cleanup
groupingValue.clear();
return NX_OK;
}
//-----------------------------------------------------------------------------------------------------
// TransformDate (private)
//-----------------------------------------------------------------------------------------------------
/**
* <p>Transformed a given date to the form yyyy-mm-dd if possible. Allowed input dates are yyyy-mm-dd,
* yy-mm-dd, yyyy-MMM-dd, or yy-MMM-dd, where mm is the month as number and MMM the month as string, e.g. APR
*
* <p><b>return:</b> transformed date
*
* \param date
* \param ok
*/
string PNeXus::TransformDate(string date, bool &ok)
{
string result = date;
string str;
char cstr[128];
int status, yy, mm, dd;
ok = true;
switch(date.length()) {
case 8: // yy-mm-dd
if ((date[2] != '-') || (date[5] != '-')) {
ok = false;
} else {
status = sscanf(date.c_str(), "%d-%d-%d", &yy, &mm, &dd);
if (status != 3) {
ok = false;
} else {
if (yy >= 70) // i.e. 1970
result = "19"+date;
else // i.e. 20YY
result = "20"+date;
}
}
break;
case 9: // yy-MMM-dd
if ((date[2] != '-') || (date[6] != '-')) {
ok = false;
} else {
str = date.substr(0,2); // yy
status = sscanf(str.c_str(), "%d", &yy);
if (status != 1)
ok = false;
str = date.substr(3,3); // MMM
mm = GetMonth(str);
if (mm == 0)
ok = false;
str = date.substr(7,2); // dd
status = sscanf(str.c_str(), "%d", &dd);
if (status != 1)
ok = false;
if (ok) {
if (yy >= 70) // i.e. 1970
yy += 1900;
else
yy += 2000;
snprintf(cstr, sizeof(cstr), "%04d-%02d-%02d", yy, mm, dd);
result = cstr;
}
}
break;
case 10: // yyyy-mm-dd
if ((date[4] != '-') || (date[7] != '-')) {
ok = false;
} else {
status = sscanf(date.c_str(), "%04d-%02d-%02d", &yy, &mm, &dd);
if (status != 3) {
ok = false;
} else {
ok = true;
}
}
break;
case 11: // yyyy-MMM-dd
if ((date[4] != '-') || (date[8] != '-')) {
ok = false;
} else {
str = date.substr(0,4); // yyyy
status = sscanf(str.c_str(), "%d", &yy);
if (status != 1)
ok = false;
str = date.substr(5,3); // MMM
mm = GetMonth(str);
if (mm == 0)
ok = false;
str = date.substr(9,2); // dd
status = sscanf(str.c_str(), "%d", &dd);
if (status != 1)
ok = false;
if (ok) {
snprintf(cstr, sizeof(cstr), "%04d-%02d-%02d", yy, mm, dd);
result = cstr;
}
}
break;
default:
ok = false;
break;
}
if (!ok) {
fErrorCode = PNEXUS_WRONG_DATE_FORMAT;
fErrorMsg = "PNeXus::TransformDate **ERROR** given date="+date+", is not of any of the the required forms!";
}
return result;
}
//-----------------------------------------------------------------------------------------------------
// GetMonth (private)
//-----------------------------------------------------------------------------------------------------
/**
* <p>For a month string MMM (e.g. APR) return the month number
*
* <p><b>return:</b> month number
*
* \param month string of the form MMM, e.g. APR
*/
int PNeXus::GetMonth(const string month)
{
int result = 0;
if (!month.compare("jan") || !month.compare("Jan") || !month.compare("JAN"))
result = 1;
else if (!month.compare("feb") || !month.compare("Feb") || !month.compare("FEB"))
result = 2;
else if (!month.compare("mar") || !month.compare("Mar") || !month.compare("MAR"))
result = 3;
else if (!month.compare("apr") || !month.compare("Apr") || !month.compare("APR"))
result = 4;
else if (!month.compare("may") || !month.compare("May") || !month.compare("MAY"))
result = 5;
else if (!month.compare("jun") || !month.compare("Jun") || !month.compare("JUN"))
result = 6;
else if (!month.compare("jul") || !month.compare("Jul") || !month.compare("JUL"))
result = 7;
else if (!month.compare("aug") || !month.compare("Aug") || !month.compare("AUG"))
result = 8;
else if (!month.compare("sep") || !month.compare("Sep") || !month.compare("SEP"))
result = 9;
else if (!month.compare("oct") || !month.compare("Oct") || !month.compare("OCT"))
result = 10;
else if (!month.compare("nov") || !month.compare("Nov") || !month.compare("NOV"))
result = 11;
else if (!month.compare("dec") || !month.compare("Dec") || !month.compare("DEC"))
result = 12;
else
result = 0;
return result;
}
//-----------------------------------------------------------------------------------------------------
// end
//-----------------------------------------------------------------------------------------------------