diff --git a/src/external/nexus/PNeXus.cpp b/src/external/nexus/PNeXus.cpp new file mode 100644 index 000000000..4336273c3 --- /dev/null +++ b/src/external/nexus/PNeXus.cpp @@ -0,0 +1,1729 @@ +/*************************************************************************** + + 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 "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) +//----------------------------------------------------------------------------------------------------- +/** + *

+ * + * return: + * - 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 data; + for (int i=0; i0)) { + 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 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 + * + * return: + * - 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 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 groupNo; // keep the number of different groupings + bool found; + groupNo.push_back(fData.fGrouping[0]); + for (unsigned int i=0; iDump 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; iThe date should look like yyyy-mm-dd. + * + * return: + * - 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) +//----------------------------------------------------------------------------------------------------- +/** + *

The date should look like yyyy-mm-dd. + * + * return: + * - 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) +{ + if (date.length() != 10) { + fErrorCode = PNEXUS_WRONG_DATE_FORMAT; + fErrorMsg = "PNeXus::SetStartDate **ERROR** given date="+date+", is not of the required form yyyy-mm-dd!"; + return false; + } + + if ((date[4] != '-') || (date[7] != '-')) { + fErrorCode = PNEXUS_WRONG_DATE_FORMAT; + fErrorMsg = "PNeXus::SetStartDate **ERROR** given date="+date+", is not of the required form yyyy-mm-dd!"; + return false; + } + + fStartDate = date; + + return true; +} + +//----------------------------------------------------------------------------------------------------- +// SetStartTime (public) +//----------------------------------------------------------------------------------------------------- +/** + *

The time should look like hh:mm:ss. + * + * return: + * - 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) +//----------------------------------------------------------------------------------------------------- +/** + *

The time should look like hh:mm:ss. + * + * return: + * - 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) +//----------------------------------------------------------------------------------------------------- +/** + *

+ * + * return: + * - 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) +//----------------------------------------------------------------------------------------------------- +/** + *

+ * + * return: + * - 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) +{ + if (date.length() != 10) { + fErrorCode = PNEXUS_WRONG_DATE_FORMAT; + fErrorMsg = "PNeXus::SetStopDate **ERROR** given date="+date+", is not of the required form yyyy-mm-dd!"; + return false; + } + + if ((date[4] != '-') || (date[7] != '-')) { + fErrorCode = PNEXUS_WRONG_DATE_FORMAT; + fErrorMsg = "PNeXus::SetStopDate **ERROR** given date="+date+", is not of the required form yyyy-mm-dd!"; + return false; + } + + fStopDate = date; + + return true; +} + +//----------------------------------------------------------------------------------------------------- +// SetStopTime (public) +//----------------------------------------------------------------------------------------------------- +/** + *

+ * + * return: + * - 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) +//----------------------------------------------------------------------------------------------------- +/** + *

+ * + * return: + * - 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 + * + * return: + * - 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) +//----------------------------------------------------------------------------------------------------- +/** + *

+ * + * return: + * - 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) +//----------------------------------------------------------------------------------------------------- +/** + *

+ * + * return: + * - 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) +//----------------------------------------------------------------------------------------------------- +/** + *

+ * + * return: + * - 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) +//----------------------------------------------------------------------------------------------------- +/** + *

+ * + * return: + * - NX_OK on success + * - NX_ERROR otherwiese + * + * \param data + */ +NXstatus PNeXus::GetDoubleVectorData(vector &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 + * + * return: + * - NX_OK on success + * - NX_ERROR otherwiese + * + * \param data + */ +NXstatus PNeXus::GetIntVectorData(vector &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 + * + * \param histoNo histogram number (start counting from 0) + * \param data histogram data vector to be set + */ +void PNeXus::SetHisto(unsigned int histoNo, vector &data) +{ + if (histoNo > fData.fHisto.size()) + fData.fHisto.resize(histoNo+1); + + fData.fHisto[histoNo] = data; +} + +//----------------------------------------------------------------------------------------------------- +// GroupHistoData (public) +//----------------------------------------------------------------------------------------------------- +/** + *

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 groupingValue; + bool newGroup = true; + for (unsigned int i=0; i 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 +#include +#include +using namespace std; + +#include "napi.h" + +#ifndef VGNAMELENMAX +#define VGNAMELENMAX 64 +#endif /* VGNAMELENMAX */ + +#define PNEXUS_FILE_OPEN_ERROR 0 +#define PNEXUS_GROUP_OPEN_ERROR 1 +#define PNEXUS_OPEN_DATA_ERROR 2 +#define PNEXUS_GET_DATA_ERROR 3 +#define PNEXUS_GET_ATTR_ERROR 4 +#define PNEXUS_CLOSE_DATA_ERROR 5 +#define PNEXUS_GET_META_INFO_ERROR 6 +#define PNEXUS_WRONG_META_INFO 7 +#define PNEXUS_WRONG_DATE_FORMAT 8 +#define PNEXUS_WRONG_TIME_FORMAT 9 +#define PNEXUS_INIT_GROUPDIR_ERROR 10 +#define PNEXUS_GET_GROUP_INFO_ERROR 11 +#define PNEXUS_GET_NEXT_ENTRY_ERROR 12 +#define PNEXUS_HISTO_ERROR 13 +#define PNEXUS_SET_ATTR_ERROR 14 +#define PNEXUS_CREATE_GROUP_ERROR 15 +#define PNEXUS_MAKE_DATA_ERROR 16 +#define PNEXUS_PUT_DATA_ERROR 17 +#define PNEXUS_PUT_ATTR_ERROR 18 + +//----------------------------------------------------------------------------- +/** + * + */ +typedef struct { + string fUserName; + string fExperimentNumber; +} PNeXusUser; + +//----------------------------------------------------------------------------- +/** + * + */ +typedef struct { + string fName; + double fTemperature; + string fTemperatureUnit; + double fMagneticField; + string fMagneticFieldUnit; + string fShape; + string fMagneticFieldState; ///< ZF, TF, LF + int fMagneticFieldVectorAvailable; + vector fMagneticFieldVector; + string fMagneticFieldVectorUnits; + string fMagneticFieldVectorCoordinateSystem; + string fEnvironment; +} PNeXusSample; + +//----------------------------------------------------------------------------- +/** + *

currently only put in the requiered ones. + */ +typedef struct { + int number; +} PNeXusDetector; + +//----------------------------------------------------------------------------- +/** + *

currently only put in the requiered ones. + */ +typedef struct { + string type; +} PNeXusCollimator; + +//----------------------------------------------------------------------------- +/** + *

currently only put in the requiered ones. + */ +typedef struct { + double total_counts; + string total_counts_units; +} PNeXusBeam; + +//----------------------------------------------------------------------------- +/** + * + */ +typedef struct { + string name; + PNeXusDetector detector; + PNeXusCollimator collimator; + PNeXusBeam beam; +} PNeXusInstrument; + +//----------------------------------------------------------------------------- +/** + * + */ +typedef struct { + unsigned int fGroupFirst; + unsigned int fGroupSecond; + double fAlphaVal; +} PNeXusAlpha; + +//----------------------------------------------------------------------------- +/** + * + */ +typedef struct { + double fTimeResolution; ///< time resolution in (ns) + unsigned int fNumberOfHistos; + vector fT0; + vector fFirstGoodBin; + vector fLastGoodBin; + vector fHistoName; + vector< vector > fHisto; + vector fGrouping; + vector fAlpha; +} PNeXusData; + +//----------------------------------------------------------------------------- +/** + * + */ +class PNeXus { + public: + PNeXus(); + PNeXus(const char* fileName); + virtual ~PNeXus(); + + virtual bool IsValid() { return fIsValid; } + + virtual int ReadFile(const char *fileName); + virtual int WriteFile(const char *fileName, const char *fileType="hdf4"); + + virtual void Dump(); + + virtual int GetErrorCode() { return fErrorCode; } + virtual string GetErrorMsg() { return fErrorMsg; } + virtual string GetFileName() { return fFileName; } + virtual int GetIDFVersion() { return fIDFVersion; } + virtual string GetProgramName() { return fProgramName; } + virtual string GetProgramVersion() { return fProgramVersion; } + + virtual int GetRunNumber() { return fRunNumber; } + virtual string GetRunTitle() { return fRunTitle; } + virtual string GetRunNotes() { return fNotes; } + virtual string GetAnalysisTag() { return fAnalysisTag; } + virtual string GetLab() { return fLab; } + virtual string GetBeamline() { return fBeamLine; } + virtual string GetStartDate() { return fStartDate; } + virtual string GetStartTime() { return fStartTime; } + virtual string GetStopDate() { return fStopDate; } + virtual string GetStopTime() { return fStopTime; } + virtual int GetSwitchingState() { return fSwitchingState; } + virtual string GetUser() { return fUser.fUserName; } + virtual string GetExperimentNumber() { return fUser.fExperimentNumber; } + virtual string GetSampleName() { return fSample.fName; } + virtual double GetSampleTemperature() { return fSample.fTemperature; } + virtual string GetSampleTemperartureUnits() { return fSample.fTemperatureUnit; } + virtual double GetMagneticField() { return fSample.fMagneticField; } + virtual string GetMagneticFieldUnits() { return fSample.fMagneticFieldUnit; } + virtual string GetMagneticFieldState() { return fSample.fMagneticFieldState; } + virtual int IsMagneticFieldVectorAvailable() { return fSample.fMagneticFieldVectorAvailable; } + virtual vector& GetMagneticFieldVector() { return fSample.fMagneticFieldVector; } + virtual string GetMagneticFieldVectorCoordSystem() { return fSample.fMagneticFieldVectorCoordinateSystem; } + virtual string GetMagneticFieldVectorUnits() { return fSample.fMagneticFieldVectorUnits; } + virtual string GetSampleEnvironment() { return fSample.fEnvironment; } + virtual string GetSampleShape() { return fSample.fShape; } + virtual string GetExperimentName() { return fInstrument.name; } + virtual int GetNoDetectors() { return fInstrument.detector.number; } + virtual string GetCollimatorType() { return fInstrument.collimator.type; } + virtual double GetTotalNoEvents() { return fInstrument.beam.total_counts; } + virtual string GetTotalNoEventsUnits() { return fInstrument.beam.total_counts_units; } + virtual double GetTimeResolution() { return fData.fTimeResolution; } + virtual int GetNoHistos() { return fData.fNumberOfHistos; } + virtual int IsAlphaAvailable() { return fData.fAlpha.size(); } + virtual vector *GetAlpha() { if (fData.fAlpha.size()) return &fData.fAlpha; else return 0; } + virtual unsigned int GetT0() { if (fData.fT0.size()) return fData.fT0[0]; else return 0; } + virtual unsigned int GetFirstGoodBin() { if (fData.fFirstGoodBin.size()) return fData.fFirstGoodBin[0]; else return 0; } + virtual unsigned int GetLastGoodBin() { if (fData.fLastGoodBin.size()) return fData.fLastGoodBin[0]; else return 0; } + virtual vector *GetHisto(unsigned int histoNo) { if (fData.fHisto.size() > histoNo) return &fData.fHisto[histoNo]; else return 0;} + virtual vector *GetGroupedHisto(unsigned int histoNo) { if (fGroupedData.size() > histoNo) return &fGroupedData[histoNo]; else return 0; } + + virtual void SetFileName(const char* fileName) { fFileName = fileName; } + virtual void SetFileName(string fileName) { fFileName = fileName; } + virtual void SetIDFVersion(int idfVersion) { fIDFVersion = idfVersion; } + virtual void SetProgramName(const char* progName) { fProgramName = progName; } + virtual void SetProgramName(string progName) { fProgramName = progName; } + virtual void SetProgramVersion(int progVersion) { fProgramVersion = progVersion; } + virtual void SetRunNumber(int runNumber) { fRunNumber = runNumber; } + virtual void SetRunTitle(const char* runTitle) { fRunTitle = runTitle; } + virtual void SetRunTitle(string runTitle) { fRunTitle = runTitle; } + virtual void SetRunNotes(const char* notes) { fNotes = notes; } + virtual void SetRunNotes(string notes) { fNotes = notes; } + virtual void SetAnalysisTag(const char* analysisTag) { fAnalysisTag = analysisTag; } + virtual void SetAnalysisTag(string analysisTag) { fAnalysisTag = analysisTag; } + virtual void SetLab(const char *lab) { fLab = fLab; } + virtual void SetLab(string lab) { fLab = fLab; } + virtual void SetBeamline(const char *beamline) { fBeamLine = beamline; } + virtual void SetBeamline(string beamline) { fBeamLine = beamline; } + virtual bool SetStartDate(const char *date); + virtual bool SetStartDate(string date); + virtual bool SetStartTime(const char *time); + virtual bool SetStartTime(string time); + virtual bool SetStopDate(const char *date); + virtual bool SetStopDate(string date); + virtual bool SetStopTime(const char *time); + virtual bool SetStopTime(string time); + virtual void SetSwitchingState(int state) { fSwitchingState=state; } + virtual void SetUser(string user) { fUser.fUserName = user; } + virtual void SetExperimentNumber(string number) { fUser.fExperimentNumber = number; } + virtual void SetSampleName(string name) { fSample.fName = name; } + virtual void SetSampleTemperature(double temp) { fSample.fTemperature = temp; } + virtual void SetSampleTemperatureUints(string units) { fSample.fTemperatureUnit = units; } + virtual void SetMagneticField(double field) { fSample.fMagneticField = field; } + virtual void SetMagneticFieldUnits(string units) { fSample.fMagneticFieldUnit = units; } + virtual void SetMagneticFieldState(string state) { fSample.fMagneticFieldState = state; } + virtual void SetSampleEnvironment(string env) { fSample.fEnvironment = env; } + virtual void SetSampleShape(string shape) { fSample.fShape = shape; } + virtual void SetMagneticFieldVectorAvailable(int available) { fSample.fMagneticFieldVectorAvailable = available; } + virtual void SetMagneticFieldVector(vector& vec) {fSample.fMagneticFieldVectorAvailable = 1; fSample.fMagneticFieldVector = vec;} + virtual void SetMagneticFieldVectorCoordSystem(string coord) { fSample.fMagneticFieldVectorCoordinateSystem = coord; } + virtual void SetMagneticFieldVectorUnits(string units) { fSample.fMagneticFieldVectorUnits = units; } + virtual void SetExperimentName(string name) { fInstrument.name = name; } + virtual void SetNoDetectors(unsigned int no) { fInstrument.detector.number = no; } + virtual void SetCollimatorType(string type) { fInstrument.collimator.type = type; } + virtual void SetTimeResolution(double timeResolution) { fData.fTimeResolution = timeResolution; } // given in ns + virtual void SetT0(unsigned int t0) { fData.fT0.clear(); fData.fT0.push_back(t0); } + virtual void SetFirstGoodBin(unsigned int fgb) { fData.fFirstGoodBin.clear(); fData.fFirstGoodBin.push_back(fgb); } + virtual void SetLastGoodBin(unsigned int lgb) { fData.fLastGoodBin.clear(); fData.fLastGoodBin.push_back(lgb); } + virtual void SetHisto(unsigned int histoNo, vector &data); + + private: + bool fIsValid; + string fFileName; ///< read/write file name + NXhandle fFileHandle; ///< nexus file handle + + string fErrorMsg; ///< stores the current error message + int fErrorCode; ///< indicates the current error code + + int fIDFVersion; + string fProgramName; + string fProgramVersion; + + int fRunNumber; + string fRunTitle; + string fNotes; + string fAnalysisTag; ///< type of muon experiment + string fLab; + string fBeamLine; + string fStartDate; + string fStartTime; + string fStopDate; + string fStopTime; + int fSwitchingState; ///< red/green mode + + PNeXusUser fUser; + PNeXusSample fSample; + PNeXusInstrument fInstrument; + PNeXusData fData; + vector< vector > fGroupedData; + + virtual void Init(); + virtual void CleanUp(); + virtual bool ErrorHandler(NXstatus status, int errCode, string errMsg); + virtual NXstatus GetStringData(string &str); + virtual NXstatus GetStringAttr(string attr, string &str); + virtual int GetDataSize(int type); + virtual NXstatus GetDoubleVectorData(vector &data); + virtual NXstatus GetIntVectorData(vector &data); + virtual NXstatus GroupHistoData(); +}; + +#endif // _PNEXUS_H_ diff --git a/src/tests/CheckMusrfitInstall/data/32482.NXS b/src/tests/CheckMusrfitInstall/data/32482.NXS new file mode 100644 index 000000000..b977af648 Binary files /dev/null and b/src/tests/CheckMusrfitInstall/data/32482.NXS differ diff --git a/src/tests/nexus/30000.NXS b/src/tests/nexus/30000.NXS new file mode 100644 index 000000000..36454d339 Binary files /dev/null and b/src/tests/nexus/30000.NXS differ diff --git a/src/tests/nexus/32482.NXS b/src/tests/nexus/32482.NXS new file mode 100644 index 000000000..b977af648 Binary files /dev/null and b/src/tests/nexus/32482.NXS differ diff --git a/src/tests/nexus/37000.NXS b/src/tests/nexus/37000.NXS new file mode 100644 index 000000000..eefd7cd76 Binary files /dev/null and b/src/tests/nexus/37000.NXS differ diff --git a/src/tests/nexus/71545.NXS b/src/tests/nexus/71545.NXS new file mode 100644 index 000000000..257289fae Binary files /dev/null and b/src/tests/nexus/71545.NXS differ diff --git a/src/tests/nexus/MUSR00002100.NXS b/src/tests/nexus/MUSR00002100.NXS new file mode 100644 index 000000000..932474e2c Binary files /dev/null and b/src/tests/nexus/MUSR00002100.NXS differ diff --git a/src/tests/nexus/Makefile b/src/tests/nexus/Makefile new file mode 100644 index 000000000..992870b18 --- /dev/null +++ b/src/tests/nexus/Makefile @@ -0,0 +1,32 @@ +# Makefile for nexus_read_test.cpp +# $Id$ + +NEXUS_CLASS = PNeXus +NEXUS_CLASS_DIR = ../../external/nexus + +CXX = g++ +CXXFLAGS = -g -Wall -fPIC +INCLUDES = -I /usr/local/include -I $(NEXUS_CLASS_DIR) +LD = g++ +LDFLAGS = -g + +LIBS = -L /usr/local/lib -lNeXus +LIBS += -L /usr/local/hdf5/lib -lhdf5 + +EXEC = nexus_read_test + +all: $(EXEC) + +$(EXEC): $(NEXUS_CLASS).o $(EXEC).o + $(LD) $(LDFLAGS) $(NEXUS_CLASS).o $(EXEC).o -o $(EXEC) $(LIBS) + +$(EXEC).o: $(EXEC).cpp + $(CXX) -c $(INCLUDES) $(CXXFLAGS) $(EXEC).cpp + +$(NEXUS_CLASS).o: $(NEXUS_CLASS_DIR)/$(NEXUS_CLASS).cpp + $(CXX) -c $(INCLUDES) $(CXXFLAGS) $(NEXUS_CLASS_DIR)/$(NEXUS_CLASS).cpp + +clean: + @rm -f *.o + + diff --git a/src/tests/nexus/c_nexus_reader.zip b/src/tests/nexus/c_nexus_reader.zip new file mode 100644 index 000000000..37db56488 Binary files /dev/null and b/src/tests/nexus/c_nexus_reader.zip differ diff --git a/src/tests/nexus/nexus_read_test.cpp b/src/tests/nexus/nexus_read_test.cpp new file mode 100644 index 000000000..96a42ea70 --- /dev/null +++ b/src/tests/nexus/nexus_read_test.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + + nexus_read_test.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 + +#include +#include +#include +using namespace std; + +#include "napi.h" + +#include "PNeXus.h" + +//--------------------------------------------------------------------------------------- + +void nexus_read_test_syntax() +{ + cout << endl << ">>---------------------------------------------------------------------------------------"; + cout << endl << ">> usage: nexus_read_test "; + cout << endl << ">> This will try to read a nexus-files and send the relevant"; + cout << endl << ">> information to the standard output."; + cout << endl << ">> At the same time the read file is written back to , where"; + cout << endl << ">> the extension will be added based on the ."; + cout << endl << ">> : hdf4, hdf5, xml"; + cout << endl << ">>---------------------------------------------------------------------------------------"; + cout << endl << endl; +} + +//--------------------------------------------------------------------------------------- + +int main(int argc, char *argv[]) +{ + if (argc != 4) { + nexus_read_test_syntax(); + return -1; + } + + PNeXus *nxs_file = new PNeXus(argv[1]); + + if (nxs_file->IsValid()) { + nxs_file->Dump(); + + char filename[128]; + if (strstr(argv[3], "hdf") || strstr(argv[3], "xml")) { + snprintf(filename, sizeof(filename), "%s.%s", argv[2], argv[3]); + } else { + cerr << endl << "**ERROR** unkown nexus write format found" << endl; + nexus_read_test_syntax(); + return -1; + } + + if (nxs_file->WriteFile(filename, argv[3]) != NX_OK) { + cerr << endl << nxs_file->GetErrorMsg() << " (" << nxs_file->GetErrorCode() << ")" << endl << endl; + } else { + cout << endl << "file " << filename << " written successfully." << endl << endl; + } + } + + return 0; +}