adopted to new hdf4/5 approach of NeXus.
This commit is contained in:
@@ -248,14 +248,40 @@ if (qt_based_tools)
|
||||
endif (qt_version STREQUAL 3)
|
||||
endif (qt_based_tools)
|
||||
|
||||
#--- if NeXus check also for HDF4, HDF5, and MXML -----------------------------
|
||||
#--- if NeXus check also for HDF4 (optional), HDF5 ----------------------------
|
||||
if (nexus)
|
||||
find_package(HDF5 COMPONENTS CXX REQUIRED)
|
||||
if (HAVE_HDF4)
|
||||
find_package(HDF4 REQUIRED)
|
||||
#--- check for HDF4 -----------------------------------------------------------
|
||||
# Find HDF4 manually (pkg-config often doesn't have hdf4)
|
||||
find_path(HDF4_INCLUDE_DIR
|
||||
NAMES mfhdf.h
|
||||
PATHS /usr/include /usr/include/hdf /usr/local/include
|
||||
PATH_SUFFIXES hdf
|
||||
)
|
||||
|
||||
find_library(HDF4_DF_LIBRARY
|
||||
NAMES df libdf
|
||||
PATHS /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib
|
||||
)
|
||||
|
||||
find_library(HDF4_MFHDF_LIBRARY
|
||||
NAMES mfhdf libmfhdf
|
||||
PATHS /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib
|
||||
)
|
||||
|
||||
if (HDF4_INCLUDE_DIR AND HDF4_DF_LIBRARY AND HDF4_MFHDF_LIBRARY)
|
||||
set(HDF4_FOUND TRUE)
|
||||
set(HDF4_INCLUDE_DIRS ${HDF4_INCLUDE_DIR})
|
||||
set(HDF4_LIBRARIES ${HDF4_MFHDF_LIBRARY} ${HDF4_DF_LIBRARY})
|
||||
message(STATUS "Found HDF4: ${HDF4_INCLUDE_DIR}")
|
||||
message(STATUS " HDF4 libraries: ${HDF4_LIBRARIES}")
|
||||
else()
|
||||
message(FATAL_ERROR "HDF4 library not found. Please install libhdf4-dev or hdf-devel")
|
||||
endif()
|
||||
|
||||
add_definitions(-DHAVE_HDF4)
|
||||
endif (HAVE_HDF4)
|
||||
find_package(NEXUS REQUIRED)
|
||||
add_definitions(-DPNEXUS_ENABLED)
|
||||
endif (nexus)
|
||||
|
||||
@@ -380,7 +406,6 @@ if (nexus)
|
||||
message(" HDF4 not present.")
|
||||
endif (HAVE_HDF4)
|
||||
message(" HDF5 found in ${HDF5_INCLUDE_DIRS}, Version: ${HDF5_VERSION}")
|
||||
message(" NeXus found in ${NEXUS_INCLUDE_DIR}, Version: ${NEXUS_VERSION_STRING}")
|
||||
endif (nexus)
|
||||
|
||||
message("")
|
||||
|
||||
Binary file not shown.
@@ -15,10 +15,10 @@ FITPARAMETER
|
||||
11 BkgR 8.393 -0.050 0.050
|
||||
12 AlphaTB 1.1025 -0.0015 0.0015
|
||||
13 RelPhaseT 269.1 -1.9 1.9 240 300
|
||||
14 BkgT 7.467 -0.049 0.049
|
||||
14 BkgT 7.467 -0.049 0.050
|
||||
15 NormB 393.08 -0.39 0.39
|
||||
16 RelPhaseB 90.7 -2.0 2.0 60 120
|
||||
17 BkgB 7.092 -0.048 0.047
|
||||
17 BkgB 7.092 -0.048 0.048
|
||||
18 One 1 0 none
|
||||
19 Zero 0 0 none
|
||||
|
||||
@@ -36,7 +36,7 @@ FUNCTIONS
|
||||
fun1 = par7 + map1
|
||||
fun2 = par2 * gamma_mu
|
||||
fun3 = map2 * map3
|
||||
fun4 = par4 * cos(pi / 180.0 * (par7 + map1))
|
||||
fun4 = par4 * cos(pi / 180 * (par7 + map1))
|
||||
|
||||
###############################################################
|
||||
GLOBAL
|
||||
@@ -96,5 +96,5 @@ range 0 9 -0.15 0.15
|
||||
view_packing 500
|
||||
|
||||
###############################################################
|
||||
STATISTIC --- 2023-10-25 11:01:10
|
||||
STATISTIC --- 2026-02-13 14:07:06
|
||||
maxLH = 3971.7, NDF = 4001, maxLH/NDF = 0.992678
|
||||
|
||||
@@ -4,7 +4,7 @@ FITPARAMETER
|
||||
# No Name Value Step Pos_Error Boundaries
|
||||
1 phaseL 0 0 none
|
||||
2 field 20.3381 -0.0085 0.0085 0 none
|
||||
3 asym 0.23440 -0.00051 0.00051 0 0.3
|
||||
3 asym 0.23440 -0.00051 0.00052 0 0.3
|
||||
4 rate 0.0234 -0.0041 0.0035 0 100
|
||||
5 Norm_L 1151.30 -0.53 0.53
|
||||
6 BG_L 0 0 none 0 none
|
||||
@@ -38,7 +38,6 @@ norm 5
|
||||
backgr.fit 6
|
||||
map 1 0 0 0 0 0 0 0 0 0
|
||||
forward 1-48
|
||||
#deadtime-cor file
|
||||
|
||||
RUN data/emu00139040 XXXX ISIS NEXUS (name beamline institute data-file-format)
|
||||
norm 7
|
||||
@@ -70,5 +69,8 @@ range 0 20 -0.35 0.35
|
||||
view_packing 10
|
||||
|
||||
###############################################################
|
||||
STATISTIC --- 2026-02-23 13:09:55
|
||||
STATISTIC --- 2026-03-02 13:44:22
|
||||
maxLH = 4228.9, NDF = 3726, maxLH/NDF = 1.134977
|
||||
expected maxLH = 4211.4, NDF = 3726, expected maxLH/NDF = 1.130285
|
||||
run block 1: (NDF/red.maxLH/red.maxLH_e) = (1862/1.170949/1.182735)
|
||||
run block 2: (NDF/red.maxLH/red.maxLH_e) = (1861/1.100817/1.079629)
|
||||
|
||||
@@ -50,7 +50,8 @@ target_compile_options(dump_header BEFORE PRIVATE "-DHAVE_CONFIG_H" "${HAVE_GIT_
|
||||
target_include_directories(dump_header
|
||||
BEFORE PRIVATE
|
||||
$<BUILD_INTERFACE:${Boost_INCLUDE_DIRS}>
|
||||
$<BUILD_INTERFACE:${NEXUS_INCLUDE_DIR}>
|
||||
$<BUILD_INTERFACE:${HDF4_INCLUDE_DIRS}>
|
||||
$<BUILD_INTERFACE:${HDF5_INCLUDE_DIRS}>
|
||||
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/src>
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src/include>
|
||||
|
||||
@@ -6,6 +6,7 @@ set(MUSRFIT_INC ${CMAKE_SOURCE_DIR}/src/include)
|
||||
# Hence, target_include_directories cannot be used here because, targets are
|
||||
# setup only afterwards.
|
||||
include_directories(${MUSRFIT_INC})
|
||||
include_directories(${FFTW3_INC})
|
||||
|
||||
root_generate_dictionary(
|
||||
PFourierCanvasDict
|
||||
@@ -81,7 +82,7 @@ set(prefix "${CMAKE_INSTALL_PREFIX}")
|
||||
set(exec_prefix "\$\{prefix\}")
|
||||
set(libdir "\$\{exec_prefix\}/lib")
|
||||
set(includedir "\$\{prefix\}/include")
|
||||
set(MUSR_VERSION "1.7.0")
|
||||
set(MUSR_VERSION "1.8.0")
|
||||
set(MUSR_LIBRARY_NAME "PMusr")
|
||||
configure_file("PMusr.pc.in" "PMusr.pc" @ONLY)
|
||||
set(USERFCN_LIBRARY_NAME "PUserFcnBase")
|
||||
@@ -132,13 +133,15 @@ target_include_directories(
|
||||
$<BUILD_INTERFACE:${DKS_INCLUDE_DIR}>
|
||||
$<BUILD_INTERFACE:${Boost_INCLUDE_DIRS}>
|
||||
$<BUILD_INTERFACE:${FFTW3_INCLUDE}>
|
||||
$<BUILD_INTERFACE:${NEXUS_INCLUDE_DIR}>
|
||||
$<BUILD_INTERFACE:${HDF4_INCLUDE_DIRS}>
|
||||
$<BUILD_INTERFACE:${HDF5_INCLUDE_DIRS}>
|
||||
$<BUILD_INTERFACE:${MUSRFIT_INC}>
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src/external/MusrRoot>
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src/external/TLemRunHeader>
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src/external/MuSR_software/Class_MuSR_PSI>
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src/external/mud/src>
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src/external/nexus>
|
||||
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}>
|
||||
)
|
||||
|
||||
add_library(PUserFcnBase SHARED
|
||||
@@ -152,6 +155,7 @@ add_library(PRgeHandler SHARED
|
||||
)
|
||||
|
||||
#--- set target properties, e.g. version --------------------------------------
|
||||
target_compile_options(PMusr BEFORE PRIVATE "-DHAVE_CONFIG_H")
|
||||
set_target_properties(PMusr
|
||||
PROPERTIES
|
||||
VERSION ${MUSR_VERSION}
|
||||
|
||||
@@ -814,6 +814,10 @@ Int_t PMsrHandler::WriteMsrLogFile(const Bool_t messages)
|
||||
fout.width(16);
|
||||
fout << std::left << "packing";
|
||||
fout << fGlobal.GetPacking() << std::endl;
|
||||
} else if (sstr.BeginsWith("deadtime-cor")) {
|
||||
fout.width(16);
|
||||
fout << std::left << "deadtime-cor";
|
||||
fout << fGlobal.GetDeadTimeCorrection() << std::endl;
|
||||
} else {
|
||||
fout << str.Data() << std::endl;
|
||||
}
|
||||
@@ -1157,6 +1161,10 @@ Int_t PMsrHandler::WriteMsrLogFile(const Bool_t messages)
|
||||
fout.width(16);
|
||||
fout << std::left << "packing";
|
||||
fout << fRuns[runNo].GetPacking() << std::endl;
|
||||
} else if (sstr.BeginsWith("deadtime-cor")) {
|
||||
fout.width(16);
|
||||
fout << std::left << "deadtime-cor";
|
||||
fout << fRuns[runNo].GetDeadTimeCorrection() << std::endl;
|
||||
} else {
|
||||
fout << str.Data() << std::endl;
|
||||
}
|
||||
@@ -3334,6 +3342,20 @@ Bool_t PMsrHandler::HandleGlobalEntry(PMsrLines &lines)
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
} else if (iter->fLine.BeginsWith("deadtime-cor", TString::kIgnoreCase)) { // deadtime correction
|
||||
if (tokens->GetEntries() < 2) {
|
||||
error = true;
|
||||
} else {
|
||||
ostr = dynamic_cast<TObjString*>(tokens->At(1));
|
||||
str = ostr->GetString();
|
||||
if (!str.CompareTo("no", TString::kIgnoreCase) ||
|
||||
!str.CompareTo("file", TString::kIgnoreCase) ||
|
||||
!str.CompareTo("estimate", TString::kIgnoreCase)) {
|
||||
global.SetDeadTimeCorrection(str);
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clean up
|
||||
@@ -3931,6 +3953,26 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines)
|
||||
}
|
||||
}
|
||||
|
||||
// deadtime-correction -----------------------------------
|
||||
if (iter->fLine.BeginsWith("deadtime-cor", TString::kIgnoreCase)) { // deadtime correction
|
||||
|
||||
runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
|
||||
|
||||
if (tokens->GetEntries() < 2) {
|
||||
error = true;
|
||||
} else {
|
||||
ostr = dynamic_cast<TObjString*>(tokens->At(1));
|
||||
str = ostr->GetString();
|
||||
if (!str.CompareTo("no", TString::kIgnoreCase) ||
|
||||
!str.CompareTo("file", TString::kIgnoreCase) ||
|
||||
!str.CompareTo("estimate", TString::kIgnoreCase)) {
|
||||
param.SetDeadTimeCorrection(str);
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// xy-data -----------------------------------------------
|
||||
if (line.BeginsWith("xy-data", TString::kIgnoreCase)) {
|
||||
|
||||
@@ -6413,10 +6455,6 @@ Bool_t PMsrHandler::CheckMaps()
|
||||
for (UInt_t i=0; i<map->size(); i++)
|
||||
if (map->at(i) != 0)
|
||||
fNoOfMaps++;
|
||||
/*as
|
||||
if (fNoOfMaps == 0)
|
||||
fNoOfMaps = -1;
|
||||
*/
|
||||
}
|
||||
|
||||
// clean up
|
||||
|
||||
@@ -721,6 +721,22 @@ PRawRunDataSet* PRawRunData::GetDataSet(const UInt_t idx, Bool_t wantHistoNo)
|
||||
return fData.GetSet(idx);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// DeadTimeCorrectionReady (public)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Checks if deadtime correction information is sufficient to apply it.
|
||||
* This means that fNumberOfGoodFrames must be present and the deadtime
|
||||
* parameter vector.
|
||||
*
|
||||
* @return true if ready to apply deadtime correctio, false otherwise
|
||||
*/
|
||||
const Bool_t PRawRunData::DeadTimeCorrectionReady()
|
||||
{
|
||||
if ((fNumberOfGoodFrames > 0) && (fDeadTimeParam.size() > 0))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// SetRingAnode (public)
|
||||
|
||||
@@ -408,9 +408,9 @@ Bool_t PRunDataHandler::WriteData(TString fileName)
|
||||
break;
|
||||
case A2M_NEXUS:
|
||||
if (fAny2ManyInfo->outFileName.Length() == 0)
|
||||
success = WriteNexusFile(fileName);
|
||||
success = WriteNexusFile(fAny2ManyInfo->outFormat, fileName);
|
||||
else
|
||||
success = WriteNexusFile(fAny2ManyInfo->outFileName);
|
||||
success = WriteNexusFile(fAny2ManyInfo->outFormat, fAny2ManyInfo->outFileName);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -684,9 +684,9 @@ Bool_t PRunDataHandler::ReadWriteFilesList()
|
||||
break;
|
||||
case A2M_NEXUS:
|
||||
if (fAny2ManyInfo->outFileName.Length() == 0)
|
||||
success = WriteNexusFile();
|
||||
success = WriteNexusFile(fAny2ManyInfo->outFormat);
|
||||
else
|
||||
success = WriteNexusFile(fAny2ManyInfo->outFileName);
|
||||
success = WriteNexusFile(fAny2ManyInfo->outFormat, fAny2ManyInfo->outFileName);
|
||||
break;
|
||||
case A2M_MUD:
|
||||
if (fAny2ManyInfo->outFileName.Length() == 0)
|
||||
@@ -787,7 +787,7 @@ Bool_t PRunDataHandler::ReadWriteFilesList()
|
||||
success = WritePsiBinFile(fln);
|
||||
break;
|
||||
case A2M_NEXUS:
|
||||
success = WriteNexusFile(fln);
|
||||
success = WriteNexusFile(fAny2ManyInfo->outFormat, fln);
|
||||
break;
|
||||
case A2M_MUD:
|
||||
success = WriteMudFile(fln);
|
||||
@@ -2193,348 +2193,98 @@ Bool_t PRunDataHandler::ReadRootFile()
|
||||
Bool_t PRunDataHandler::ReadNexusFile()
|
||||
{
|
||||
#ifdef PNEXUS_ENABLED
|
||||
std::cout << std::endl << ">> PRunDataHandler::ReadNexusFile(): Will read nexus file " << fRunPathName.Data() << " ...";
|
||||
std::cout << std::endl << ">> PRunDataHandler::ReadNexusFile(): Will read nexus file " << fRunPathName.Data() << " ...";
|
||||
|
||||
PDoubleVector histoData;
|
||||
PRawRunData runData;
|
||||
PRawRunDataSet dataSet;
|
||||
TString str;
|
||||
std::string sstr;
|
||||
Double_t dval;
|
||||
bool ok;
|
||||
nxs::HDFType type = nxs::checkHDFType(fRunPathName.Data());
|
||||
|
||||
std::unique_ptr<PNeXus> nxs_file = std::make_unique<PNeXus>(fRunPathName.Data());
|
||||
if (!nxs_file->IsValid()) {
|
||||
std::cerr << std::endl << ">> PRunDataHandler::ReadNexusFile(): Not a valid NeXus file.";
|
||||
std::cerr << std::endl << ">> Error Message: " << nxs_file->GetErrorMsg().data() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nxs_file->GetIdfVersion() == 1) {
|
||||
if (!nxs_file->IsValid()) {
|
||||
std::cout << std::endl << "**ERROR** invalid NeXus IDF 2 version file found." << std::endl;
|
||||
return false;
|
||||
// check for type errors, missing enabled HDF4
|
||||
switch (type) {
|
||||
case nxs::HDFType::HDF4:
|
||||
std::cout << std::endl << ">> PRunDataHandler::ReadNexusFile(): HDF4 file." << std::endl;
|
||||
#ifndef HAVE_HDF4
|
||||
std::cerr << std::endl << ">> PRunDataHandler::ReadNexusFile(): **ERROR**, HDF4 is not enabled." << std::endl;
|
||||
return false;
|
||||
#endif
|
||||
break;
|
||||
case nxs::HDFType::HDF5:
|
||||
std::cout << std::endl << ">> PRunDataHandler::ReadNexusFile(): HDF5 file." << std::endl;
|
||||
break;
|
||||
case nxs::HDFType::Unknown:
|
||||
std::cerr << std::endl << ">> PRunDataHandler::ReadNexusFile(): Not a valid NeXus file." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// get header information
|
||||
|
||||
// get/set laboratory
|
||||
str = TString(nxs_file->GetEntryIdf1()->GetLaboratory());
|
||||
runData.SetLaboratory(str);
|
||||
|
||||
// get/set beamline
|
||||
str = TString(nxs_file->GetEntryIdf1()->GetBeamline());
|
||||
runData.SetBeamline(str);
|
||||
|
||||
// get/set instrument
|
||||
str = TString(nxs_file->GetEntryIdf1()->GetInstrument()->GetName());
|
||||
runData.SetInstrument(str);
|
||||
|
||||
// get/set run title
|
||||
str = TString(nxs_file->GetEntryIdf1()->GetTitle());
|
||||
runData.SetRunTitle(str);
|
||||
|
||||
// get/set run number
|
||||
runData.SetRunNumber(nxs_file->GetEntryIdf1()->GetRunNumber());
|
||||
|
||||
// get/set temperature
|
||||
dval = nxs_file->GetEntryIdf1()->GetSample()->GetPhysPropValue("temperature", ok);
|
||||
if (ok)
|
||||
runData.SetTemperature(0, dval, 0.0);
|
||||
|
||||
// get/set field
|
||||
dval = nxs_file->GetEntryIdf1()->GetSample()->GetPhysPropValue("magnetic_field", ok);
|
||||
nxs_file->GetEntryIdf1()->GetSample()->GetPhysPropUnit("magnetic_field", sstr, ok);
|
||||
str = sstr;
|
||||
// since field has to be given in Gauss, check the units
|
||||
Double_t factor=1.0;
|
||||
if (!str.CompareTo("gauss", TString::kIgnoreCase))
|
||||
factor=1.0;
|
||||
else if (!str.CompareTo("tesla", TString::kIgnoreCase))
|
||||
factor=1.0e4;
|
||||
else
|
||||
factor=1.0;
|
||||
runData.SetField(factor*dval);
|
||||
|
||||
// get/set implantation energy
|
||||
runData.SetEnergy(PMUSR_UNDEFINED);
|
||||
|
||||
// get/set moderator HV
|
||||
runData.SetTransport(PMUSR_UNDEFINED);
|
||||
|
||||
// get/set RA HV's (LEM specific)
|
||||
for (UInt_t i=0; i<4; i++)
|
||||
runData.SetRingAnode(i, PMUSR_UNDEFINED);
|
||||
|
||||
// get/set setup
|
||||
runData.SetSetup(nxs_file->GetEntryIdf1()->GetNotes());
|
||||
|
||||
// get/set sample
|
||||
runData.SetSample(nxs_file->GetEntryIdf1()->GetSample()->GetName());
|
||||
|
||||
// get/set orientation
|
||||
runData.SetOrientation("??");
|
||||
|
||||
// get/set time resolution (ns)
|
||||
runData.SetTimeResolution(nxs_file->GetEntryIdf1()->GetData()->GetTimeResolution("ns"));
|
||||
|
||||
// get/set start/stop time
|
||||
sstr = nxs_file->GetEntryIdf1()->GetStartTime();
|
||||
str = sstr;
|
||||
TString date, time;
|
||||
SplitTimeDate(str, time, date, ok);
|
||||
if (ok) {
|
||||
runData.SetStartTime(time);
|
||||
runData.SetStartDate(date);
|
||||
}
|
||||
|
||||
sstr = nxs_file->GetEntryIdf1()->GetStopTime();
|
||||
str = sstr;
|
||||
SplitTimeDate(str, time, date, ok);
|
||||
if (ok) {
|
||||
runData.SetStopTime(time);
|
||||
runData.SetStopDate(date);
|
||||
}
|
||||
|
||||
// get/set t0, firstGoodBin, lastGoodBin
|
||||
std::vector<unsigned int> *t0 = nxs_file->GetEntryIdf1()->GetData()->GetT0s();
|
||||
std::vector<unsigned int> *fgb = nxs_file->GetEntryIdf1()->GetData()->GetFirstGoodBins();
|
||||
std::vector<unsigned int> *lgb = nxs_file->GetEntryIdf1()->GetData()->GetLastGoodBins();
|
||||
|
||||
// get/set data
|
||||
std::vector<unsigned int> *pdata;
|
||||
unsigned int max=0, binMax=0;
|
||||
PDoubleVector data;
|
||||
for (UInt_t i=0; i<nxs_file->GetEntryIdf1()->GetData()->GetNoOfHistos(); i++) {
|
||||
pdata = nxs_file->GetEntryIdf1()->GetData()->GetHisto(i);
|
||||
for (UInt_t j=0; j<pdata->size(); j++) {
|
||||
data.push_back(pdata->at(j));
|
||||
if (pdata->at(j) > max) {
|
||||
max = pdata->at(j);
|
||||
binMax = j;
|
||||
}
|
||||
}
|
||||
|
||||
// fill data set
|
||||
dataSet.Clear();
|
||||
dataSet.SetHistoNo(i+1); // i.e. histo numbers start with 1
|
||||
// set time zero bin
|
||||
if (i<t0->size())
|
||||
dataSet.SetTimeZeroBin(t0->at(i));
|
||||
else
|
||||
dataSet.SetTimeZeroBin(t0->at(0));
|
||||
// set time zero bin estimate
|
||||
dataSet.SetTimeZeroBinEstimated(binMax);
|
||||
// set first good bin
|
||||
if (i<fgb->size())
|
||||
dataSet.SetFirstGoodBin(fgb->at(i));
|
||||
else
|
||||
dataSet.SetFirstGoodBin(fgb->at(0));
|
||||
// set last good bin
|
||||
if (i<lgb->size())
|
||||
dataSet.SetFirstGoodBin(lgb->at(i));
|
||||
else
|
||||
dataSet.SetFirstGoodBin(lgb->at(0));
|
||||
dataSet.SetData(data);
|
||||
|
||||
runData.SetDataSet(dataSet);
|
||||
data.clear();
|
||||
}
|
||||
|
||||
// keep run name from the msr-file
|
||||
runData.SetRunName(fRunName);
|
||||
|
||||
// keep the information
|
||||
fData.push_back(runData);
|
||||
} else if (nxs_file->GetIdfVersion() == 2) {
|
||||
if (!nxs_file->IsValid()) {
|
||||
std::cout << std::endl << "**ERROR** invalid NeXus IDF 2 version file found." << std::endl;
|
||||
return false;
|
||||
}
|
||||
// get header information
|
||||
|
||||
// get/set laboratory
|
||||
str = TString(nxs_file->GetEntryIdf2()->GetInstrument()->GetSource()->GetName());
|
||||
runData.SetLaboratory(str);
|
||||
|
||||
// get/set beamline
|
||||
str = TString(nxs_file->GetEntryIdf2()->GetInstrument()->GetName());
|
||||
runData.SetBeamline(str);
|
||||
|
||||
// get/set instrument
|
||||
str = TString(nxs_file->GetEntryIdf2()->GetInstrument()->GetName());
|
||||
runData.SetInstrument(str);
|
||||
|
||||
// get/set muon source
|
||||
str = TString(nxs_file->GetEntryIdf2()->GetInstrument()->GetSource()->GetType());
|
||||
runData.SetMuonSource(str);
|
||||
|
||||
// get/set muon species
|
||||
str = TString(nxs_file->GetEntryIdf2()->GetInstrument()->GetSource()->GetProbe());
|
||||
runData.SetMuonSpecies(str);
|
||||
|
||||
// get/set run title
|
||||
str = TString(nxs_file->GetEntryIdf2()->GetTitle());
|
||||
runData.SetRunTitle(str);
|
||||
|
||||
// get/set run number
|
||||
runData.SetRunNumber(nxs_file->GetEntryIdf2()->GetRunNumber());
|
||||
|
||||
// get/set temperature
|
||||
dval = nxs_file->GetEntryIdf2()->GetSample()->GetPhysPropValue("temperature", ok);
|
||||
if (ok)
|
||||
runData.SetTemperature(0, dval, 0.0);
|
||||
|
||||
// get/set field
|
||||
dval = nxs_file->GetEntryIdf2()->GetSample()->GetPhysPropValue("magnetic_field", ok);
|
||||
nxs_file->GetEntryIdf2()->GetSample()->GetPhysPropUnit("magnetic_field", sstr, ok);
|
||||
str = sstr;
|
||||
// since field has to be given in Gauss, check the units
|
||||
Double_t factor=1.0;
|
||||
if (!str.CompareTo("gauss", TString::kIgnoreCase))
|
||||
factor=1.0;
|
||||
else if (!str.CompareTo("tesla", TString::kIgnoreCase))
|
||||
factor=1.0e4;
|
||||
else
|
||||
factor=1.0;
|
||||
runData.SetField(factor*dval);
|
||||
|
||||
// get/set implantation energy
|
||||
runData.SetEnergy(PMUSR_UNDEFINED);
|
||||
|
||||
// get/set moderator HV
|
||||
runData.SetTransport(PMUSR_UNDEFINED);
|
||||
|
||||
// get/set RA HV's (LEM specific)
|
||||
for (UInt_t i=0; i<4; i++)
|
||||
runData.SetRingAnode(i, PMUSR_UNDEFINED);
|
||||
|
||||
// get/set setup take NXsample/temperature_1_env and NXsample/magnetic_field_1_env
|
||||
sstr = nxs_file->GetEntryIdf2()->GetSample()->GetEnvironmentTemp() + std::string("/");
|
||||
sstr += nxs_file->GetEntryIdf2()->GetSample()->GetEnvironmentField();
|
||||
str = sstr;
|
||||
runData.SetSetup(str);
|
||||
|
||||
// get/set sample
|
||||
runData.SetSample(nxs_file->GetEntryIdf2()->GetSample()->GetName());
|
||||
|
||||
// get/set orientation
|
||||
runData.SetOrientation("??");
|
||||
|
||||
// get/set time resolution (ns)
|
||||
runData.SetTimeResolution(nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetTimeResolution("ns"));
|
||||
|
||||
// get/set start/stop time
|
||||
sstr = nxs_file->GetEntryIdf2()->GetStartTime();
|
||||
str = sstr;
|
||||
TString date, time;
|
||||
SplitTimeDate(str, time, date, ok);
|
||||
if (ok) {
|
||||
runData.SetStartTime(time);
|
||||
runData.SetStartDate(date);
|
||||
}
|
||||
|
||||
sstr = nxs_file->GetEntryIdf2()->GetStopTime();
|
||||
str = sstr;
|
||||
SplitTimeDate(str, time, date, ok);
|
||||
if (ok) {
|
||||
runData.SetStopTime(time);
|
||||
runData.SetStopDate(date);
|
||||
}
|
||||
|
||||
// get/set data, t0, fgb, lgb
|
||||
PDoubleVector data;
|
||||
PDoubleVector histoData;
|
||||
PRawRunData runData;
|
||||
PRawRunDataSet dataSet;
|
||||
UInt_t histoNo = 0;
|
||||
Int_t ival;
|
||||
int *histos = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetHistos();
|
||||
if (nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfPeriods() > 0) { // counts[][][]
|
||||
for (int i=0; i<nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfPeriods(); i++) {
|
||||
for (int j=0; j<nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra(); j++) {
|
||||
for (int k=0; k<nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfBins(); k++) {
|
||||
data.push_back(*(histos+i*nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra()+j*nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfBins()+k));
|
||||
}
|
||||
dataSet.Clear();
|
||||
dataSet.SetHistoNo(++histoNo); // i.e. histo numbers start with 1
|
||||
// get t0
|
||||
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetT0(i,j);
|
||||
if (ival == -1) // i.e. single value only
|
||||
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetT0();
|
||||
dataSet.SetTimeZeroBin(ival);
|
||||
// get first good bin
|
||||
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetFirstGoodBin(i,j);
|
||||
if (ival == -1) // i.e. single value only
|
||||
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetFirstGoodBin();
|
||||
dataSet.SetFirstGoodBin(ival);
|
||||
// get last good bin
|
||||
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetLastGoodBin(i,j);
|
||||
if (ival == -1) // i.e. single value only
|
||||
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetLastGoodBin();
|
||||
dataSet.SetLastGoodBin(ival);
|
||||
TString str;
|
||||
std::string sstr;
|
||||
Int_t ival, idf{-1};
|
||||
Double_t dval, factor;
|
||||
bool ok;
|
||||
|
||||
dataSet.SetData(data);
|
||||
runData.SetDataSet(dataSet);
|
||||
data.clear();
|
||||
if (type == nxs::HDFType::HDF4) {
|
||||
#ifdef HAVE_HDF4
|
||||
std::unique_ptr<nxH4::PNeXus> nxs_file = std::make_unique<nxH4::PNeXus>(fRunPathName.Data());
|
||||
if (nxs_file == nullptr) {
|
||||
std::cerr << std::endl << "**ERROR** allocation of nxH4::PNeXus object failed." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
// check for IDF_version
|
||||
if (nxs_file->HasDataset("/run/IDF_version")) {
|
||||
idf = nxs_file->GetDataset<int>("/run/IDF_version").GetData()[0];
|
||||
std::cout << ">> PRunDataHandler::ReadNexusFile(): IDF V" << idf << std::endl;
|
||||
}
|
||||
if (idf == -1) { // IDF_version not found
|
||||
if (nxs_file->HasDataset("/raw_data_1/IDF_version")) {
|
||||
idf = nxs_file->GetDataset<int>("/raw_data_1/IDF_version").GetData()[0];
|
||||
std::cout << ">> PRunDataHandler::ReadNexusFile(): IDF V" << idf << std::endl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra() > 0) { // counts[][]
|
||||
for (int i=0; i<nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra(); i++) {
|
||||
for (int j=0; j<nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfBins(); j++) {
|
||||
data.push_back(*(histos+i*nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfBins()+j));
|
||||
}
|
||||
dataSet.Clear();
|
||||
dataSet.SetHistoNo(++histoNo); // i.e. histo numbers start with 1
|
||||
// get t0
|
||||
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetT0(-1,i);
|
||||
if (ival == -1) // i.e. single value only
|
||||
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetT0();
|
||||
dataSet.SetTimeZeroBin(ival);
|
||||
// get first good bin
|
||||
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetFirstGoodBin(-1,i);
|
||||
if (ival == -1) // i.e. single value only
|
||||
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetFirstGoodBin();
|
||||
dataSet.SetFirstGoodBin(ival);
|
||||
// get last good bin
|
||||
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetLastGoodBin(-1,i);
|
||||
if (ival == -1) // i.e. single value only
|
||||
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetLastGoodBin();
|
||||
dataSet.SetLastGoodBin(ival);
|
||||
if ((idf != 1) && (idf != 2)) {
|
||||
std::cerr << std::endl << ">> PRunDataHandler::ReadNexusFile(): a NeXus file with an invalid IDF V" << idf << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
dataSet.SetData(data);
|
||||
runData.SetDataSet(dataSet);
|
||||
data.clear();
|
||||
}
|
||||
} else { // counts[]
|
||||
for (int i=0; i<nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfBins(); i++) {
|
||||
data.push_back(*(histos+i));
|
||||
}
|
||||
dataSet.Clear();
|
||||
dataSet.SetHistoNo(++histoNo); // i.e. histo numbers start with 1
|
||||
// get t0
|
||||
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetT0();
|
||||
dataSet.SetTimeZeroBin(ival);
|
||||
// get first good bin
|
||||
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetFirstGoodBin();
|
||||
dataSet.SetFirstGoodBin(ival);
|
||||
// get last good bin
|
||||
ival = nxs_file->GetEntryIdf2()->GetInstrument()->GetDetector()->GetLastGoodBin();
|
||||
dataSet.SetLastGoodBin(ival);
|
||||
if (idf == 1) { // HDF4 IDF V1
|
||||
if (!ReadNexusFileIdf1(nxs_file))
|
||||
return false;
|
||||
} else { // HDF4 IDF V2
|
||||
// not yet implemented
|
||||
}
|
||||
#endif
|
||||
} else { // HDF5
|
||||
std::unique_ptr<nxH5::PNeXus> nxs_file = std::make_unique<nxH5::PNeXus>(fRunPathName.Data());
|
||||
if (nxs_file == nullptr) {
|
||||
std::cerr << std::endl << "**ERROR** allocation of nxH5::PNeXus object failed." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
dataSet.SetData(data);
|
||||
runData.SetDataSet(dataSet);
|
||||
data.clear();
|
||||
// check for IDF_version
|
||||
if (nxs_file->HasDataset("/run/IDF_version")) {
|
||||
idf = nxs_file->GetDataset<int>("/run/IDF_version").GetData()[0];
|
||||
std::cout << ">> PRunDataHandler::ReadNexusFile(): IDF V" << idf << std::endl;
|
||||
}
|
||||
if (idf == -1) { // IDF_version not found
|
||||
if (nxs_file->HasDataset("/raw_data_1/IDF_version")) {
|
||||
idf = nxs_file->GetDataset<int>("/raw_data_1/IDF_version").GetData()[0];
|
||||
std::cout << ">> PRunDataHandler::ReadNexusFile(): IDF V" << idf << std::endl;
|
||||
}
|
||||
}
|
||||
if ((idf != 1) && (idf != 2)) {
|
||||
std::cerr << std::endl << ">> PRunDataHandler::ReadNexusFile(): a NeXus file with an invalid IDF V" << idf << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (idf == 1) { // HDF5 IDF V1
|
||||
if (!ReadNexusFileIdf1(nxs_file))
|
||||
return false;
|
||||
} else { // HDF5 IDF V2
|
||||
if (!ReadNexusFileIdf2(nxs_file))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// keep run name from the msr-file
|
||||
runData.SetRunName(fRunName);
|
||||
|
||||
// keep the information
|
||||
fData.push_back(runData);
|
||||
} else {
|
||||
std::cout << std::endl << ">> PRunDataHandler::ReadNexusFile(): IDF version " << nxs_file->GetIdfVersion() << ", not implemented." << std::endl;
|
||||
}
|
||||
#else
|
||||
std::cout << std::endl << ">> PRunDataHandler::ReadNexusFile(): Sorry, not enabled at configuration level, i.e. --enable-NeXus when executing configure" << std::endl << std::endl;
|
||||
#endif
|
||||
@@ -4956,7 +4706,7 @@ Bool_t PRunDataHandler::WriteRootFile(TString fln)
|
||||
for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
|
||||
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
||||
if (dataSet == nullptr) { // something is really wrong
|
||||
std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=0" << i << ")";
|
||||
std::cerr << std::endl << ">> PRunDataHandler::WriteRootFile: **ERROR** Couldn't get data set (idx=0" << i << ")";
|
||||
std::cerr << std::endl << ">> something is really wrong!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
@@ -5050,15 +4800,14 @@ Bool_t PRunDataHandler::WriteRootFile(TString fln)
|
||||
/**
|
||||
* <p> Write the nexus-file format.
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true on successful writting,
|
||||
* - otherwise false.
|
||||
*
|
||||
* \param fln file name. If empty, the routine will try to construct one
|
||||
|
||||
* \return true on successful writting, otherwise false.
|
||||
*/
|
||||
Bool_t PRunDataHandler::WriteNexusFile(TString fln)
|
||||
Bool_t PRunDataHandler::WriteNexusFile(TString format, TString fln)
|
||||
{
|
||||
#ifdef PNEXUS_ENABLED
|
||||
std::string str{""};
|
||||
Bool_t ok = false;
|
||||
fln = GenerateOutputFileName(fln, ".nxs", ok);
|
||||
if (!ok)
|
||||
@@ -5097,9 +4846,9 @@ Bool_t PRunDataHandler::WriteNexusFile(TString fln)
|
||||
// set program name
|
||||
nxs->AddDataset<std::string>("/run/program_name", {"any2many"}, {1}, nxH4::H4DataType::kCHAR8);
|
||||
str="n/a";
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#ifdef HAVE_CONFIG_H
|
||||
str = PACKAGE_VERSION;
|
||||
#endif
|
||||
#endif
|
||||
nxs->AddDatasetAttribute<std::string>("/run/program_name", "version", str);
|
||||
|
||||
// set run number
|
||||
@@ -5471,9 +5220,9 @@ Bool_t PRunDataHandler::WriteNexusFile(TString fln)
|
||||
// set program name
|
||||
nxs->AddDataset<std::string>("/run/program_name", {"any2many"}, {1}, H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
|
||||
str="n/a";
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#ifdef HAVE_CONFIG_H
|
||||
str = PACKAGE_VERSION;
|
||||
#endif
|
||||
#endif
|
||||
nxs->AddDatasetAttribute<std::string>("/run/program_name", "version", str);
|
||||
|
||||
// set run number
|
||||
@@ -5816,302 +5565,9 @@ Bool_t PRunDataHandler::WriteNexusFile(TString fln)
|
||||
}
|
||||
}
|
||||
|
||||
// set IDF version
|
||||
nxs->SetIdfVersion(fAny2ManyInfo->idf);
|
||||
|
||||
if (fAny2ManyInfo->idf == 1) {
|
||||
// fill necessary data structures
|
||||
nxs->SetFileName(fln.Data());
|
||||
|
||||
// set file creating time
|
||||
time_t now;
|
||||
struct tm *tm;
|
||||
time(&now);
|
||||
tm = localtime(&now);
|
||||
std::string str("");
|
||||
char cstr[128];
|
||||
strftime(cstr, sizeof(cstr), "%FT%T", tm);
|
||||
str = std::string(cstr);
|
||||
nxs->SetFileTime(str);
|
||||
|
||||
nxs->GetEntryIdf1()->SetProgramName("any2many");
|
||||
nxs->GetEntryIdf1()->SetProgramVersion("$Id$");
|
||||
nxs->GetEntryIdf1()->SetRunNumber(fData[0].GetRunNumber());
|
||||
nxs->GetEntryIdf1()->SetTitle(fData[0].GetRunTitle()->Data());
|
||||
nxs->GetEntryIdf1()->SetNotes("n/a");
|
||||
nxs->GetEntryIdf1()->SetAnalysis("muonTD");
|
||||
if (*fData[0].GetLaboratory() != "n/a")
|
||||
nxs->GetEntryIdf1()->SetLaboratory(fData[0].GetLaboratory()->Data());
|
||||
if (*fData[0].GetBeamline() != "n/a")
|
||||
nxs->GetEntryIdf1()->SetBeamline(fData[0].GetBeamline()->Data());
|
||||
str = std::string(fData[0].GetStartDate()->Data()) + std::string("T") + std::string(fData[0].GetStartTime()->Data());
|
||||
nxs->GetEntryIdf1()->SetStartTime(str);
|
||||
str = std::string(fData[0].GetStopDate()->Data()) + std::string("T") + std::string(fData[0].GetStopTime()->Data());
|
||||
nxs->GetEntryIdf1()->SetStopTime(str);
|
||||
nxs->GetEntryIdf1()->SetSwitchingState(1);
|
||||
nxs->GetEntryIdf1()->GetUser()->SetName("n/a");
|
||||
nxs->GetEntryIdf1()->GetUser()->SetExperimentNumber("n/a");
|
||||
nxs->GetEntryIdf1()->GetSample()->SetName(fData[0].GetSample()->Data());
|
||||
nxs->GetEntryIdf1()->GetSample()->SetPhysProp("temperature", fData[0].GetTemperature(0), "Kelvin");
|
||||
nxs->GetEntryIdf1()->GetSample()->SetPhysProp("magnetic_field", fData[0].GetField(), "Gauss");
|
||||
nxs->GetEntryIdf1()->GetSample()->SetEnvironment(fData[0].GetSetup()->Data());
|
||||
nxs->GetEntryIdf1()->GetSample()->SetShape("n/a");
|
||||
nxs->GetEntryIdf1()->GetSample()->SetMagneticFieldVectorAvailable(0);
|
||||
if (*fData[0].GetInstrument() != "n/a")
|
||||
nxs->GetEntryIdf1()->GetInstrument()->SetName(fData[0].GetInstrument()->Data());
|
||||
nxs->GetEntryIdf1()->GetInstrument()->GetDetector()->SetNumber(fData[0].GetNoOfHistos());
|
||||
nxs->GetEntryIdf1()->GetInstrument()->GetCollimator()->SetType("n/a");
|
||||
// calculate the total number of counts
|
||||
double total_counts = 0;
|
||||
PRawRunDataSet *dataSet = nullptr;
|
||||
for (unsigned int i=0; i<fData[0].GetNoOfHistos(); i++) {
|
||||
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
||||
if (dataSet == nullptr) { // something is really wrong
|
||||
std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=0" << i << ")";
|
||||
std::cerr << std::endl << ">> something is really wrong!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
for (unsigned int j=0; j<dataSet->GetData()->size(); j++)
|
||||
total_counts += dataSet->GetData()->at(j);
|
||||
}
|
||||
double total_counts_mev = (double) total_counts / 1.0e6;
|
||||
nxs->GetEntryIdf1()->GetInstrument()->GetBeam()->SetTotalCounts(total_counts_mev);
|
||||
nxs->GetEntryIdf1()->GetInstrument()->GetBeam()->SetUnits("Mev");
|
||||
|
||||
nxs->GetEntryIdf1()->GetData()->SetTimeResolution(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin, "ns");
|
||||
|
||||
for (unsigned int i=0; i<fData[0].GetNoOfHistos(); i++) {
|
||||
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
||||
nxs->GetEntryIdf1()->GetData()->SetT0(static_cast<Int_t>(dataSet->GetTimeZeroBin()/fAny2ManyInfo->rebin), i);
|
||||
nxs->GetEntryIdf1()->GetData()->SetFirstGoodBin(static_cast<Int_t>(dataSet->GetFirstGoodBin()/fAny2ManyInfo->rebin), i);
|
||||
nxs->GetEntryIdf1()->GetData()->SetLastGoodBin(static_cast<Int_t>(dataSet->GetLastGoodBin()/fAny2ManyInfo->rebin), i);
|
||||
}
|
||||
|
||||
// feed histos
|
||||
PUIntVector data;
|
||||
UInt_t size = 0;
|
||||
if (fAny2ManyInfo->rebin == 1) {
|
||||
for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
|
||||
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
||||
if (dataSet == nullptr) { // something is really wrong
|
||||
std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=" << i << ")";
|
||||
std::cerr << std::endl << ">> something is really wrong!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
size = dataSet->GetData()->size();
|
||||
for (UInt_t j=0; j<size; j++) {
|
||||
data.push_back((UInt_t)dataSet->GetData()->at(j));
|
||||
}
|
||||
nxs->GetEntryIdf1()->GetData()->SetHisto(data, i);
|
||||
data.clear();
|
||||
}
|
||||
} else { // rebin > 1
|
||||
UInt_t dataRebin = 0;
|
||||
UInt_t dataCount = 0;
|
||||
for (UInt_t i=0; i<fData[0].GetNoOfHistos(); i++) {
|
||||
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
||||
if (dataSet == nullptr) { // something is really wrong
|
||||
std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile: **ERROR** Couldn't get data set (idx=" << i << ")";
|
||||
std::cerr << std::endl << ">> something is really wrong!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
size = dataSet->GetData()->size();
|
||||
dataCount = 0;
|
||||
for (UInt_t j=0; j<size; j++) {
|
||||
if ((j > 0) && (j % fAny2ManyInfo->rebin == 0)) {
|
||||
dataCount++;
|
||||
data.push_back(dataRebin);
|
||||
dataRebin = 0;
|
||||
}
|
||||
dataRebin += static_cast<UInt_t>(dataSet->GetData()->at(j));
|
||||
}
|
||||
nxs->GetEntryIdf1()->GetData()->SetHisto(data, i);
|
||||
data.clear();
|
||||
}
|
||||
}
|
||||
} else if (fAny2ManyInfo->idf == 2) {
|
||||
// fill necessary data structures
|
||||
nxs->SetFileName(fln.Data());
|
||||
|
||||
// set file creating time
|
||||
time_t now;
|
||||
struct tm *tm;
|
||||
time(&now);
|
||||
tm = localtime(&now);
|
||||
std::string str("");
|
||||
char cstr[128];
|
||||
strftime(cstr, sizeof(cstr), "%FT%T", tm);
|
||||
str = std::string(cstr);
|
||||
nxs->SetFileTime(str);
|
||||
|
||||
// NXroot info
|
||||
nxs->SetCreator("PSI: any2many");
|
||||
|
||||
// NXentry info
|
||||
nxs->GetEntryIdf2()->SetDefinition("muonTD");
|
||||
nxs->GetEntryIdf2()->SetProgramName("any2many");
|
||||
nxs->GetEntryIdf2()->SetProgramVersion("$Id$");
|
||||
nxs->GetEntryIdf2()->SetRunNumber(fData[0].GetRunNumber());
|
||||
nxs->GetEntryIdf2()->SetTitle(fData[0].GetRunTitle()->Data());
|
||||
str = std::string(fData[0].GetStartDate()->Data()) + std::string("T") + std::string(fData[0].GetStartTime()->Data());
|
||||
nxs->GetEntryIdf2()->SetStartTime(str);
|
||||
str = std::string(fData[0].GetStopDate()->Data()) + std::string("T") + std::string(fData[0].GetStopTime()->Data());
|
||||
nxs->GetEntryIdf2()->SetStopTime(str);
|
||||
|
||||
nxs->GetEntryIdf2()->SetExperimentIdentifier("n/a");
|
||||
|
||||
// NXuser info
|
||||
nxs->GetEntryIdf2()->GetUser()->SetName("n/a");
|
||||
|
||||
// NXsample info
|
||||
nxs->GetEntryIdf2()->GetSample()->SetName(fData[0].GetSample()->Data());
|
||||
nxs->GetEntryIdf2()->GetSample()->SetDescription("n/a");
|
||||
nxs->GetEntryIdf2()->GetSample()->SetPhysProp("temperature_1", fData[0].GetTemperature(0), "Kelvin");
|
||||
nxs->GetEntryIdf2()->GetSample()->SetPhysProp("magnetic_field_1", fData[0].GetField(), "Gauss");
|
||||
nxs->GetEntryIdf2()->GetSample()->SetEnvironmentTemp(fData[0].GetSetup()->Data());
|
||||
nxs->GetEntryIdf2()->GetSample()->SetEnvironmentField("n/a");
|
||||
|
||||
// here would be the information for NXinstrument. Currently there are not much information to feed this
|
||||
nxs->GetEntryIdf2()->GetInstrument()->SetName(fData[0].GetInstrument()->Data());
|
||||
|
||||
// NXinstrument/NXsource
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetSource()->SetName(fData[0].GetLaboratory()->Data());
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetSource()->SetType(fData[0].GetMuonSource()->Data());
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetSource()->SetProbe(fData[0].GetMuonSpecies()->Data());
|
||||
|
||||
// NXinstrument/NXbeamline
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetBeamline()->SetName(fData[0].GetBeamline()->Data());
|
||||
|
||||
// NXinstrument/NXdetector
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetDescription(fData[0].GetInstrument()->Data()); // assume that this should be the instrument name
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetNoOfPeriods(0); // currently red/green is not distinguished
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetNoOfSpectra(fData[0].GetNoOfHistos());
|
||||
PRawRunDataSet *dataSet = fData[0].GetDataSet(0, false); // i.e. the false means, that i is the index and NOT the histo number
|
||||
if (dataSet == nullptr) { // something is really wrong
|
||||
std::cerr << std::endl << ">> PRunDataHandler::WriteNeXusFile: **ERROR** Couldn't get data set (idx=0)";
|
||||
std::cerr << std::endl << ">> something is really wrong!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetNoOfBins((unsigned int)(dataSet->GetData()->size() / fAny2ManyInfo->rebin));
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetTimeResolution(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin, "ns");
|
||||
int *histo = nullptr;
|
||||
int idx = 0;
|
||||
if (fAny2ManyInfo->rebin == 1) {
|
||||
histo = new int[fData[0].GetNoOfHistos()*dataSet->GetData()->size()];
|
||||
idx = 0;
|
||||
for (int i=0; i<nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra(); i++) {
|
||||
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
||||
if (dataSet == nullptr) { // something is really wrong
|
||||
std::cerr << std::endl << ">> PRunDataHandler::WriteNeXusFile: **ERROR** Couldn't get data set (idx=" << i << ")";
|
||||
std::cerr << std::endl << ">> something is really wrong!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
for (unsigned int j=0; j<dataSet->GetData()->size(); j++) {
|
||||
*(histo+idx++) = (int) dataSet->GetData()->at(j);
|
||||
}
|
||||
}
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetHistos(histo);
|
||||
// clean up
|
||||
if (histo) {
|
||||
delete [] histo;
|
||||
histo = nullptr;
|
||||
}
|
||||
} else { // rebin > 1
|
||||
histo = new int[fData[0].GetNoOfHistos()*(int)(dataSet->GetData()->size()/fAny2ManyInfo->rebin)];
|
||||
int counts = 0;
|
||||
idx = 0;
|
||||
for (int i=0; i<nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra(); i++) {
|
||||
dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
||||
if (dataSet == nullptr) { // something is really wrong
|
||||
std::cerr << std::endl << ">> PRunDataHandler::WriteNeXusFile: **ERROR** Couldn't get data set (idx=" << i << ")";
|
||||
std::cerr << std::endl << ">> something is really wrong!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
for (unsigned int j=0; j<dataSet->GetData()->size(); j++) {
|
||||
if ((j>0) && (j % fAny2ManyInfo->rebin == 0)) {
|
||||
*(histo+idx++) = counts;
|
||||
counts = 0;
|
||||
}
|
||||
counts += (int) dataSet->GetData()->at(j);
|
||||
}
|
||||
}
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetHistos(histo);
|
||||
// clean up
|
||||
if (histo) {
|
||||
delete [] histo;
|
||||
histo = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// handle spectrum index
|
||||
for (int i=0; i<nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->GetNoOfSpectra(); i++)
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetSpectrumIndex(i+1);
|
||||
|
||||
// handle histogram resolution
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetTimeResolution(fData[0].GetTimeResolution()*fAny2ManyInfo->rebin, "ns");
|
||||
|
||||
// handle raw time
|
||||
std::vector<double> raw_time;
|
||||
UInt_t size = (unsigned int)(dataSet->GetData()->size() / fAny2ManyInfo->rebin);
|
||||
for (unsigned int i=0; i<size; i++) {
|
||||
raw_time.push_back((double)i * fData[0].GetTimeResolution() * fAny2ManyInfo->rebin * 1.0e-3); // since time resolution is given in ns, the factor 1.0e-3 is needed to convert to us
|
||||
}
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetRawTime(raw_time);
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetRawTimeUnit("micro.second");
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetRawTimeName("time");
|
||||
raw_time.clear();
|
||||
|
||||
// handle t0
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetT0Tag(2); // i.e. t0[#histo] format
|
||||
int *t0 = new int[fData[0].GetNoOfHistos()];
|
||||
int *fgb = new int[fData[0].GetNoOfHistos()];
|
||||
int *lgb = new int[fData[0].GetNoOfHistos()];
|
||||
if ((t0==0) || (fgb==0) || (lgb==0)) {
|
||||
std::cerr << std::endl << ">> PRunDataHandler::WriteNeXusFile: **ERROR** Couldn't allocate memory for t0, fgb, lgb" << std::endl;
|
||||
return false;
|
||||
}
|
||||
for (unsigned int i=0; i<fData[0].GetNoOfHistos(); i++) {
|
||||
PRawRunDataSet *dataSet = fData[0].GetDataSet(i, false); // i.e. the false means, that i is the index and NOT the histo number
|
||||
if (dataSet == nullptr) { // something is really wrong
|
||||
std::cerr << std::endl << ">> PRunDataHandler::WriteNeXusFile: **ERROR** Couldn't get data set (idx=0)";
|
||||
std::cerr << std::endl << ">> something is really wrong!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
t0[i] = (int)(dataSet->GetTimeZeroBin() / fAny2ManyInfo->rebin);
|
||||
fgb[i] = (int)(dataSet->GetFirstGoodBin() / fAny2ManyInfo->rebin);
|
||||
lgb[i] = (int)(dataSet->GetLastGoodBin() / fAny2ManyInfo->rebin);
|
||||
}
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetT0(t0);
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetFirstGoodBin(fgb);
|
||||
nxs->GetEntryIdf2()->GetInstrument()->GetDetector()->SetLastGoodBin(lgb);
|
||||
|
||||
// clean up
|
||||
if (t0) delete [] t0;
|
||||
if (fgb) delete [] fgb;
|
||||
if (lgb) delete [] lgb;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// filter out the proper file type, i.e. HDF4, HDF5, or XML
|
||||
char fileType[32];
|
||||
memset(fileType, '\0', 32);
|
||||
if (!fAny2ManyInfo->outFormat.CompareTo("nexus1-hdf4", TString::kIgnoreCase) || !fAny2ManyInfo->outFormat.CompareTo("nexus2-hdf4", TString::kIgnoreCase))
|
||||
strncpy(fileType, "hdf4", sizeof(fileType));
|
||||
else if (!fAny2ManyInfo->outFormat.CompareTo("nexus1-hdf5", TString::kIgnoreCase) || !fAny2ManyInfo->outFormat.CompareTo("nexus2-hdf5", TString::kIgnoreCase))
|
||||
strncpy(fileType, "hdf5", sizeof(fileType));
|
||||
else if (!fAny2ManyInfo->outFormat.CompareTo("nexus1-xml", TString::kIgnoreCase) || !fAny2ManyInfo->outFormat.CompareTo("nexus2-xml", TString::kIgnoreCase))
|
||||
strncpy(fileType, "xml", sizeof(fileType));
|
||||
else {
|
||||
std::cerr << std::endl << ">> PRunDataHandler::WriteNexusFile(): **ERROR** undefined output NeXus format " << fAny2ManyInfo->outFormat.Data() << " found.";
|
||||
std::cerr << std::endl << ">> Allowed are: hdf4, hdf5, xml" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// write file
|
||||
nxs->WriteFile(fln, fileType, fAny2ManyInfo->idf);
|
||||
return true;
|
||||
#else
|
||||
std::cout << std::endl << ">> PRunDataHandler::WriteNexusFile(): Sorry, not enabled at configuration level, i.e. --enable-NeXus when executing configure" << std::endl << std::endl;
|
||||
std::cout << std::endl << ">> PRunDataHandler::WriteNexusFile(): Sorry, not enabled at configuration level, i.e. -Dnexus=1 when executing configure" << std::endl << std::endl;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
@@ -365,18 +366,42 @@ int dump_header_root(const std::string fileName, const bool summary, const bool
|
||||
int dump_header_nexus(const std::string fileName, const bool counts) {
|
||||
|
||||
#ifdef PNEXUS_ENABLED
|
||||
std::unique_ptr<PNeXus> nxs_file = std::make_unique<PNeXus>(fileName.c_str());
|
||||
nxs::HDFType type = nxs::checkHDFType(fileName);
|
||||
|
||||
if (nxs_file->IsValid(false)) {
|
||||
nxs_file->Dump(counts);
|
||||
} else {
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "**ERROR** found invalid NeXus file." << std::endl;
|
||||
std::cerr << std::endl;
|
||||
return 1;
|
||||
}
|
||||
// check for type errors, missing enabled HDF4
|
||||
switch (type) {
|
||||
case nxs::HDFType::HDF4:
|
||||
std::cout << std::endl << ">> PRunDataHandler::ReadNexusFile(): HDF4 file." << std::endl;
|
||||
#ifndef HAVE_HDF4
|
||||
std::cerr << std::endl << ">> PRunDataHandler::ReadNexusFile(): **ERROR**, HDF4 is not enabled." << std::endl;
|
||||
return 1;
|
||||
#endif
|
||||
break;
|
||||
case nxs::HDFType::HDF5:
|
||||
std::cout << std::endl << ">> PRunDataHandler::ReadNexusFile(): HDF5 file." << std::endl;
|
||||
break;
|
||||
case nxs::HDFType::Unknown:
|
||||
std::cerr << std::endl << ">> PRunDataHandler::ReadNexusFile(): Not a valid NeXus file." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (type == nxs::HDFType::HDF4) {
|
||||
#ifdef HAVE_HDF4
|
||||
std::unique_ptr<nxH4::PNeXus> nxs_file = std::make_unique<nxH4::PNeXus>(fileName);
|
||||
if (nxs_file == nullptr) {
|
||||
std::cerr << std::endl << "**ERROR** allocation of nxH4::PNeXus object failed." << std::endl;
|
||||
}
|
||||
nxs_file->Dump();
|
||||
#endif
|
||||
} else { // HDF5
|
||||
std::unique_ptr<nxH5::PNeXus> nxs_file = std::make_unique<nxH5::PNeXus>(fileName);
|
||||
if (nxs_file == nullptr) {
|
||||
std::cerr << std::endl << "**ERROR** allocation of nxH5::PNeXus object failed." << std::endl;
|
||||
}
|
||||
nxs_file->Dump();
|
||||
}
|
||||
#else
|
||||
std::cout << std::endl << "NeXus not enabled, hence the header information cannot be dumped." << std::endl << std::endl;
|
||||
std::cout << std::endl << "NeXus not enabled, hence the header information cannot be dumped." << std::endl << std::endl;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
8
src/external/nexus/CMakeLists.txt
vendored
8
src/external/nexus/CMakeLists.txt
vendored
@@ -1,7 +1,5 @@
|
||||
# - PNeXus library ------------------------------------------------------------
|
||||
|
||||
include_directories(${NEXUS_INCLUDE_DIR}) # to get the nexus headers
|
||||
|
||||
#--- create pkg-config info ---------------------------------------------------
|
||||
set(prefix "${CMAKE_INSTALL_PREFIX}")
|
||||
set(exec_prefix "\$\{prefix\}")
|
||||
@@ -24,7 +22,10 @@ set_target_properties(PNeXus
|
||||
|
||||
#--- make sure that the include directory is found ----------------------------
|
||||
target_include_directories(
|
||||
PNeXus BEFORE PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
PNeXus BEFORE PRIVATE
|
||||
$<BUILD_INTERFACE:${HDF4_INCLUDE_DIRS}>
|
||||
$<BUILD_INTERFACE:${HDF5_INCLUDE_DIRS}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
)
|
||||
|
||||
#--- add library dependencies -------------------------------------------------
|
||||
@@ -33,7 +34,6 @@ if (HAVE_HDF4)
|
||||
else (HAVE_HDF4)
|
||||
set(HDF_LIBS ${HDF5_LIBRARIES})
|
||||
endif (HAVE_HDF4)
|
||||
message(STATUS "as35> HDF_LIBS: ${HDF_LIBS}")
|
||||
target_link_libraries(PNeXus PRIVATE ${HDF_LIBS} ${ROOT_LIBRARIES})
|
||||
|
||||
#--- install PNeXus solib -----------------------------------------------------
|
||||
|
||||
@@ -879,6 +879,9 @@ class PRawRunData {
|
||||
virtual const PIntPair GetBkgBin(const UInt_t histoNo) { return fData.GetBkgBin(histoNo); }
|
||||
virtual const PIntPair GetGoodDataBin(const UInt_t histoNo) { return fData.GetGoodDataBin(histoNo); }
|
||||
virtual const PIntVector GetRedGreenOffset() { return fRedGreenOffset; }
|
||||
virtual const Bool_t DeadTimeCorrectionReady();
|
||||
virtual const Int_t GetNumberOfGoodFrames() { return fNumberOfGoodFrames; }
|
||||
virtual const std::vector<float> GetDeadTimeParam() { return fDeadTimeParam; }
|
||||
virtual const UInt_t GetNoOfHistos() { return fData.Size(); }
|
||||
virtual PRawRunDataSet* GetDataSet(const UInt_t idx, Bool_t wantHistoNo = true);
|
||||
virtual const PDoubleVector* GetDataBin(const UInt_t histoNo) { return fData.GetData(histoNo); }
|
||||
@@ -920,6 +923,8 @@ class PRawRunData {
|
||||
virtual void SetRingAnode(const UInt_t idx, const Double_t dval);
|
||||
virtual void SetTimeResolution(const Double_t dval) { fTimeResolution = dval; }
|
||||
virtual void SetRedGreenOffset(PIntVector &ivec) { fRedGreenOffset = ivec; }
|
||||
virtual void SetNumberOfGoodFrames(Int_t ival) { fNumberOfGoodFrames = ival; }
|
||||
virtual void SetDeadTimeParam(std::vector<float> dvec) { fDeadTimeParam = dvec; }
|
||||
virtual void SetDataSet(PRawRunDataSet &dataSet, UInt_t idx=-1) { fData.Set(dataSet, idx); }
|
||||
|
||||
PNonMusrRawRunData fDataNonMusr; ///< keeps all ascii- or db-file info in case of nonMusr fit
|
||||
@@ -959,6 +964,8 @@ class PRawRunData {
|
||||
PDoubleVector fRingAnode; ///< LEM ring anode HVs (L,R[,T,B])
|
||||
Double_t fTimeResolution; ///< time resolution of the run in (ns)
|
||||
PIntVector fRedGreenOffset; ///< keeps the Red/Green offsets
|
||||
std::vector<float> fDeadTimeParam; ///< dead time parameter vector needed for pulsed sources
|
||||
Int_t fNumberOfGoodFrames{0}; ///< needed to correct dead times at pulsed sources
|
||||
|
||||
PRawRunDataVector fData; ///< keeps the histos together with the histo related properties such as T0, first good bin, etc.
|
||||
};
|
||||
@@ -1057,6 +1064,7 @@ class PMsrGlobalBlock {
|
||||
virtual Int_t GetFitRangeOffset(UInt_t idx);
|
||||
virtual Int_t GetPacking() { return fPacking; }
|
||||
virtual Double_t GetEstimatedAlpha() { return fAlpha; }
|
||||
virtual TString GetDeadTimeCorrection() { return fDeadTimeCorrection; }
|
||||
|
||||
virtual void SetGlobalPresent(Bool_t bval) { fGlobalPresent = bval; }
|
||||
virtual void SetRRFFreq(Double_t freq, const char *unit);
|
||||
@@ -1070,6 +1078,7 @@ class PMsrGlobalBlock {
|
||||
virtual void SetFitRange(Double_t dval, UInt_t idx);
|
||||
virtual void SetFitRangeOffset(Int_t ival, UInt_t idx);
|
||||
virtual void SetPacking(Int_t ival) { fPacking = ival; }
|
||||
virtual void SetDeadTimeCorrection(TString str) { fDeadTimeCorrection = str; }
|
||||
|
||||
private:
|
||||
Bool_t fGlobalPresent; ///< flag showing if a GLOBAL block is present at all.
|
||||
@@ -1086,6 +1095,7 @@ class PMsrGlobalBlock {
|
||||
Int_t fFitRangeOffset[2]; ///< if fit range is given in bins it can have the form fit fgb+n0 lgb-n1. This variable holds the n0 and n1.
|
||||
Int_t fPacking; ///< packing/rebinning
|
||||
Double_t fAlpha; ///< estimated alpha value from F/B counts
|
||||
TString fDeadTimeCorrection; ///< tells if deadtime correction (pulsed sources) should be applied. Possible value: 'no' (default), 'file', 'estimate'
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------
|
||||
@@ -1151,6 +1161,7 @@ class PMsrRunBlock {
|
||||
virtual Double_t GetFitRange(UInt_t idx);
|
||||
virtual Int_t GetFitRangeOffset(UInt_t idx);
|
||||
virtual Int_t GetPacking() { return fPacking; }
|
||||
virtual TString GetDeadTimeCorrection() { return fDeadTimeCorrection; }
|
||||
virtual Double_t GetEstimatedAlpha() { return fAlpha; }
|
||||
virtual Int_t GetXDataIndex() { return fXYDataIndex[0]; }
|
||||
virtual Int_t GetYDataIndex() { return fXYDataIndex[1]; }
|
||||
@@ -1184,6 +1195,7 @@ class PMsrRunBlock {
|
||||
virtual void SetFitRange(Double_t dval, UInt_t idx);
|
||||
virtual void SetFitRangeOffset(Int_t ival, UInt_t idx);
|
||||
virtual void SetPacking(Int_t ival) { fPacking = ival; }
|
||||
virtual void SetDeadTimeCorrection(TString str) { fDeadTimeCorrection = str; }
|
||||
virtual void SetXDataIndex(Int_t ival) { fXYDataIndex[0] = ival; }
|
||||
virtual void SetYDataIndex(Int_t ival) { fXYDataIndex[1] = ival; }
|
||||
virtual void SetXDataLabel(TString& str) { fXYDataLabel[0] = str; }
|
||||
@@ -1217,6 +1229,7 @@ class PMsrRunBlock {
|
||||
Int_t fFitRangeOffset[2]; ///< if fit range is given in bins it can have the form fit fgb+n0 lgb-n1. This variable holds the n0 and n1.
|
||||
Double_t fAlpha; ///< estimated alpha value from F/B counts
|
||||
Int_t fPacking; ///< packing/rebinning
|
||||
TString fDeadTimeCorrection; ///< tells if deadtime correction (pulsed sources) should be applied. Possible value: 'no' (default), 'file', 'estimate'
|
||||
Int_t fXYDataIndex[2]; ///< used to get the data indices when using db-files (fit type 8)
|
||||
TString fXYDataLabel[2]; ///< used to get the indices via labels when using db-files (fit type 8)
|
||||
|
||||
|
||||
@@ -30,6 +30,10 @@
|
||||
#ifndef _PRUNDATAHANDLER_H_
|
||||
#define _PRUNDATAHANDLER_H_
|
||||
|
||||
#include <any>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <TString.h>
|
||||
|
||||
#include "PMusr.h"
|
||||
@@ -432,6 +436,8 @@ class PRunDataHandler
|
||||
virtual Bool_t FileExistsCheck(const Bool_t fileName, const Int_t idx);
|
||||
virtual Bool_t FileExistsCheck(const TString fileName);
|
||||
virtual Bool_t ReadRootFile();
|
||||
template <typename T> Bool_t ReadNexusFileIdf1(T& nxs_file);
|
||||
template <typename T> Bool_t ReadNexusFileIdf2(T& nxs_file);
|
||||
virtual Bool_t ReadNexusFile();
|
||||
virtual Bool_t ReadWkmFile();
|
||||
virtual Bool_t ReadPsiBinFile();
|
||||
@@ -443,7 +449,7 @@ class PRunDataHandler
|
||||
|
||||
virtual Bool_t WriteMusrRootFile(Int_t tag=A2M_MUSR_ROOT_DIR, TString fln="");
|
||||
virtual Bool_t WriteRootFile(TString fln="");
|
||||
virtual Bool_t WriteNexusFile(TString fln="");
|
||||
virtual Bool_t WriteNexusFile(TString format, TString fln="");
|
||||
virtual Bool_t WriteWkmFile(TString fln="");
|
||||
virtual Bool_t WritePsiBinFile(TString fln="");
|
||||
virtual Bool_t WriteMudFile(TString fln="");
|
||||
@@ -464,4 +470,417 @@ class PRunDataHandler
|
||||
virtual TString GetYear(Int_t month);
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// ReadNexusFileIdf1 (private)
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Reads a NeXus file with IDF version 1 format.
|
||||
*
|
||||
* <p>Extracts run metadata (laboratory, beamline, instrument, run title,
|
||||
* run number, temperature, field, sample info, time resolution, start/stop
|
||||
* times) and histogram data from the NeXus file structure.
|
||||
*
|
||||
* @tparam T NeXus file handler type (std::unique_ptr<nxH4::PNeXus> and std::unique_ptr<nxH5::PNeXus>)
|
||||
* @param nxs_file reference to the NeXus file handler
|
||||
*
|
||||
* <b>return:</b>
|
||||
* - true at successful reading,
|
||||
* - otherwise false.
|
||||
*/
|
||||
template <typename T>
|
||||
Bool_t PRunDataHandler::ReadNexusFileIdf1(T& nxs_file)
|
||||
{
|
||||
PRawRunData runData;
|
||||
PRawRunDataSet dataSet;
|
||||
TString str;
|
||||
std::string sstr;
|
||||
Int_t ival;
|
||||
Double_t dval, factor;
|
||||
bool ok;
|
||||
|
||||
// get header information
|
||||
|
||||
// get/set laboratory
|
||||
sstr = "n/a";
|
||||
if (nxs_file->HasDataset("/run/lab"))
|
||||
sstr = nxs_file->template GetDataset<std::string>("/run/lab").GetData()[0];
|
||||
runData.SetLaboratory(sstr);
|
||||
|
||||
// get/set beamline
|
||||
sstr = "n/a";
|
||||
if (nxs_file->HasDataset("/run/beamline"))
|
||||
sstr = nxs_file->template GetDataset<std::string>("/run/beamline").GetData()[0];
|
||||
runData.SetBeamline(sstr);
|
||||
|
||||
// get/set instrument
|
||||
sstr = "n/a";
|
||||
if (nxs_file->HasDataset("/run/instrument/name"))
|
||||
sstr = nxs_file->template GetDataset<std::string>("/run/instrument/name").GetData()[0];
|
||||
runData.SetInstrument(sstr);
|
||||
|
||||
// get/set run title
|
||||
str = "n/a";
|
||||
if (nxs_file->HasDataset("/run/title"))
|
||||
sstr = nxs_file->template GetDataset<std::string>("/run/title").GetData()[0];
|
||||
runData.SetRunTitle(sstr);
|
||||
|
||||
// get/set run number
|
||||
ival = -1;
|
||||
if (nxs_file->HasDataset("/run/number"))
|
||||
ival = nxs_file->template GetDataset<int>("/run/number").GetData()[0];
|
||||
runData.SetRunNumber(ival);
|
||||
|
||||
// get/set temperature
|
||||
dval = PMUSR_UNDEFINED;
|
||||
sstr = "n/a";
|
||||
if (nxs_file->HasDataset("/run/sample/temperature")) {
|
||||
auto tmp_ds = nxs_file->template GetDataset<float>("/run/sample/temperature");
|
||||
dval = tmp_ds.GetData()[0];
|
||||
if (tmp_ds.HasAttribute("units"))
|
||||
sstr = std::any_cast<std::string>(tmp_ds.GetAttribute("units"));
|
||||
if (sstr == "Celcius")
|
||||
dval += 273.16;
|
||||
}
|
||||
runData.SetTemperature(0, dval, 0.0);
|
||||
|
||||
// get/set field
|
||||
dval = PMUSR_UNDEFINED;
|
||||
sstr = "n/a";
|
||||
factor = 1.0;
|
||||
if (nxs_file->HasDataset("/run/sample/magnetic_field")) {
|
||||
auto mag_ds = nxs_file->template GetDataset<float>("/run/sample/magnetic_field");
|
||||
dval = mag_ds.GetData()[0];
|
||||
if (mag_ds.HasAttribute("units"))
|
||||
sstr = std::any_cast<std::string>(mag_ds.GetAttribute("units"));
|
||||
if (sstr == "Tesla")
|
||||
factor = 1.0e4;
|
||||
}
|
||||
runData.SetField(dval*factor);
|
||||
|
||||
// get/set implantation energy
|
||||
runData.SetEnergy(PMUSR_UNDEFINED);
|
||||
|
||||
// get/set moderator HV
|
||||
runData.SetTransport(PMUSR_UNDEFINED);
|
||||
|
||||
// get/set RA HV's (LEM specific)
|
||||
for (UInt_t i=0; i<4; i++)
|
||||
runData.SetRingAnode(i, PMUSR_UNDEFINED);
|
||||
|
||||
// get/set setup
|
||||
sstr = "n/a";
|
||||
if (nxs_file->HasDataset("/run/notes"))
|
||||
sstr = nxs_file->template GetDataset<std::string>("/run/notes").GetData()[0];
|
||||
runData.SetSetup(sstr);
|
||||
|
||||
// get/set sample
|
||||
sstr = "n/a";
|
||||
if (nxs_file->HasDataset("/run/sample/name"))
|
||||
sstr = nxs_file->template GetDataset<std::string>("/run/sample/name").GetData()[0];
|
||||
runData.SetSample(sstr);
|
||||
|
||||
// get/set orientation
|
||||
runData.SetOrientation("??");
|
||||
|
||||
// get/set time resolution (ns)
|
||||
dval = PMUSR_UNDEFINED;
|
||||
sstr = "n/a";
|
||||
factor = 1.0;
|
||||
if (nxs_file->HasDataset("/run/histogram_data_1/resolution")) {
|
||||
auto res_ds = nxs_file->template GetDataset<int>("/run/histogram_data_1/resolution");
|
||||
dval = res_ds.GetData()[0];
|
||||
if (res_ds.HasAttribute("units"))
|
||||
sstr = std::any_cast<std::string>(res_ds.GetAttribute("units"));
|
||||
if ((sstr == "picoseconds") || (sstr == "pico.seconds"))
|
||||
factor = 1.0e-3; // ps -> ns
|
||||
}
|
||||
runData.SetTimeResolution(dval*factor);
|
||||
|
||||
// get/set start/stop time
|
||||
sstr = "n/a";
|
||||
TString date{"n/a"}, time{"n/a"};
|
||||
if (nxs_file->HasDataset("/run/start_time"))
|
||||
sstr = nxs_file->template GetDataset<std::string>("/run/start_time").GetData()[0];
|
||||
str = sstr;
|
||||
SplitTimeDate(str, time, date, ok);
|
||||
if (ok) {
|
||||
runData.SetStartTime(time);
|
||||
runData.SetStartDate(date);
|
||||
}
|
||||
|
||||
sstr = "n/a";
|
||||
date = "n/a";
|
||||
time = "n/a";
|
||||
if (nxs_file->HasDataset("/run/stop_time"))
|
||||
sstr = nxs_file->template GetDataset<std::string>("/run/stop_time").GetData()[0];
|
||||
str = sstr;
|
||||
SplitTimeDate(str, time, date, ok);
|
||||
if (ok) {
|
||||
runData.SetStopTime(time);
|
||||
runData.SetStopDate(date);
|
||||
}
|
||||
|
||||
// get/set deadtime relevant parameters
|
||||
if (nxs_file->HasDataset("/run/instrument/detector/deadtimes")) {
|
||||
std::vector<float> dt;
|
||||
dt = nxs_file->template GetDataset<float>("/run/instrument/detector/deadtimes").GetData();
|
||||
runData.SetDeadTimeParam(dt);
|
||||
}
|
||||
if (nxs_file->HasDataset("/run/instrument/beam/frames_good")) {
|
||||
ival = nxs_file->template GetDataset<float>("/run/instrument/beam/frames_good").GetData()[0];
|
||||
runData.SetNumberOfGoodFrames(ival);
|
||||
}
|
||||
|
||||
// data with its metadata
|
||||
if (nxs_file->HasDataset("/run/histogram_data_1/counts")) {
|
||||
int t0_bin{-1}, fgb{-1}, lgb{-1}, noOfHistos{-1}, histoLength{-1};
|
||||
auto count_ds = nxs_file->template GetDataset<int>("/run/histogram_data_1/counts");
|
||||
auto count = count_ds.GetData();
|
||||
// get all necessary attributes
|
||||
if (count_ds.HasAttribute("t0_bin"))
|
||||
t0_bin = std::any_cast<int>(count_ds.GetAttribute("t0_bin"));
|
||||
if (count_ds.HasAttribute("first_good_bin"))
|
||||
fgb = std::any_cast<int>(count_ds.GetAttribute("first_good_bin"));
|
||||
if (count_ds.HasAttribute("last_good_bin"))
|
||||
lgb = std::any_cast<int>(count_ds.GetAttribute("last_good_bin"));
|
||||
if (count_ds.HasAttribute("number"))
|
||||
noOfHistos = std::any_cast<int>(count_ds.GetAttribute("number"));
|
||||
if (count_ds.HasAttribute("length"))
|
||||
histoLength = std::any_cast<int>(count_ds.GetAttribute("length"));
|
||||
if (static_cast<int>(count.size()) != noOfHistos*histoLength) {
|
||||
std::cerr << std::endl << "**ERROR** PNeXus data size error! count.size()=" << count.size() << ", #histos=" << noOfHistos << ", length=" << histoLength << "." << std::endl;
|
||||
return false;
|
||||
}
|
||||
// fill dataSet
|
||||
PDoubleVector data;
|
||||
for (int i=0; i<noOfHistos; i++) {
|
||||
dataSet.Clear();
|
||||
dataSet.SetHistoNo(i+1); // i.e. histo numbers start with 1
|
||||
dataSet.SetTimeZeroBin(t0_bin);
|
||||
dataSet.SetFirstGoodBin(fgb);
|
||||
dataSet.SetLastGoodBin(lgb);
|
||||
for (int j=0; j<histoLength; j++)
|
||||
data.push_back(count[i*histoLength+j]);
|
||||
dataSet.SetData(data);
|
||||
runData.SetDataSet(dataSet);
|
||||
data.clear();
|
||||
}
|
||||
|
||||
// keep run name from the msr-file
|
||||
runData.SetRunName(fRunName);
|
||||
|
||||
// keep the information
|
||||
fData.push_back(runData);
|
||||
} else { // no data found
|
||||
std::cerr << std::endl << "**ERROR** PNeXus couldn't obtain data: '/run/histogram_data_1/counts' is missing." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// ReadNexusFileIdf2 (private)
|
||||
//--------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
Bool_t PRunDataHandler::ReadNexusFileIdf2(T& nxs_file)
|
||||
{
|
||||
PRawRunData runData;
|
||||
PRawRunDataSet dataSet;
|
||||
TString str;
|
||||
std::string sstr;
|
||||
Int_t ival;
|
||||
Double_t dval, factor;
|
||||
bool ok;
|
||||
|
||||
// get header information
|
||||
|
||||
// get/set laboratory
|
||||
sstr = "n/a";
|
||||
if (nxs_file->HasDataset("/raw_data_1/instrument/source/name"))
|
||||
sstr = nxs_file->template GetDataset<std::string>("/raw_data_1/instrument/source/name").GetData()[0];
|
||||
runData.SetLaboratory(sstr);
|
||||
|
||||
// get/set beamline
|
||||
sstr = "n/a";
|
||||
if (nxs_file->HasDataset("/raw_data_1/instrument/name"))
|
||||
sstr = nxs_file->template GetDataset<std::string>("/raw_data_1/instrument/name").GetData()[0];
|
||||
runData.SetBeamline(sstr);
|
||||
runData.SetBeamline(sstr);
|
||||
|
||||
// get/set muon source
|
||||
sstr = "n/a";
|
||||
if (nxs_file->HasDataset("/raw_data_1/instrument/source/type"))
|
||||
sstr = nxs_file->template GetDataset<std::string>("/raw_data_1/instrument/source/type").GetData()[0];
|
||||
runData.SetMuonSource(sstr);
|
||||
|
||||
// get/set muon species
|
||||
sstr = "n/a";
|
||||
if (nxs_file->HasDataset("/raw_data_1/instrument/source/probe"))
|
||||
sstr = nxs_file->template GetDataset<std::string>("/raw_data_1/instrument/source/probe").GetData()[0];
|
||||
runData.SetMuonSpecies(sstr);
|
||||
|
||||
// get/set run title
|
||||
sstr = "n/a";
|
||||
if (nxs_file->HasDataset("/raw_data_1/title"))
|
||||
sstr = nxs_file->template GetDataset<std::string>("/raw_data_1/title").GetData()[0];
|
||||
runData.SetRunTitle(sstr);
|
||||
|
||||
// get/set run number
|
||||
ival = -1;
|
||||
if (nxs_file->HasDataset("/raw_data_1/run_number"))
|
||||
ival = nxs_file->template GetDataset<int>("/raw_data_1/run_number").GetData()[0];
|
||||
runData.SetRunNumber(ival);
|
||||
|
||||
// get/set temperature
|
||||
dval = PMUSR_UNDEFINED;
|
||||
sstr = "n/a";
|
||||
if (nxs_file->HasDataset("/raw_data_1/sample/temperature")) {
|
||||
auto tmp_ds = nxs_file->template GetDataset<float>("/raw_data_1/sample/temperature");
|
||||
dval = tmp_ds.GetData()[0];
|
||||
if (tmp_ds.HasAttribute("units"))
|
||||
sstr = std::any_cast<std::string>(tmp_ds.GetAttribute("units"));
|
||||
if (sstr == "Celcius")
|
||||
dval += 273.16;
|
||||
}
|
||||
runData.SetTemperature(0, dval, 0.0);
|
||||
|
||||
// get/set field
|
||||
dval = PMUSR_UNDEFINED;
|
||||
sstr = "n/a";
|
||||
factor = 1.0;
|
||||
if (nxs_file->HasDataset("/raw_data_1/sample/magnetic_field")) {
|
||||
auto mag_ds = nxs_file->template GetDataset<float>("/raw_data_1/sample/magnetic_field");
|
||||
dval = mag_ds.GetData()[0];
|
||||
if (mag_ds.HasAttribute("units"))
|
||||
sstr = std::any_cast<std::string>(mag_ds.GetAttribute("units"));
|
||||
if (sstr == "Tesla")
|
||||
factor = 1.0e4;
|
||||
}
|
||||
runData.SetField(dval*factor);
|
||||
|
||||
// get/set implantation energy
|
||||
runData.SetEnergy(PMUSR_UNDEFINED);
|
||||
|
||||
// get/set implantation energy
|
||||
runData.SetEnergy(PMUSR_UNDEFINED);
|
||||
|
||||
// get/set moderator HV
|
||||
runData.SetTransport(PMUSR_UNDEFINED);
|
||||
|
||||
// get/set RA HV's (LEM specific)
|
||||
for (UInt_t i=0; i<4; i++)
|
||||
runData.SetRingAnode(i, PMUSR_UNDEFINED);
|
||||
|
||||
// get/set setup
|
||||
sstr = "n/a";
|
||||
runData.SetSetup(str);
|
||||
|
||||
// get/set sample
|
||||
sstr = "n/a";
|
||||
if (nxs_file->HasDataset("/raw_data_1/sample/name"))
|
||||
sstr = nxs_file->template GetDataset<std::string>("/raw_data_1/sample/name").GetData()[0];
|
||||
runData.SetSample(sstr);
|
||||
|
||||
// get/set orientation
|
||||
runData.SetOrientation("n/a");
|
||||
|
||||
// get/set time resolution (ns)
|
||||
dval = PMUSR_UNDEFINED;
|
||||
sstr = "n/a";
|
||||
factor = 1.0;
|
||||
if (nxs_file->HasDataset("/raw_data_1/instrument/detector_1/resolution")) {
|
||||
auto res_ds = nxs_file->template GetDataset<int>("/raw_data_1/instrument/detector_1/resolution");
|
||||
dval = res_ds.GetData()[0];
|
||||
if (res_ds.HasAttribute("units"))
|
||||
sstr = std::any_cast<std::string>(res_ds.GetAttribute("units"));
|
||||
if ((sstr == "picoseconds") || (sstr == "pico.seconds"))
|
||||
factor = 1.0e-3; // ps -> ns
|
||||
}
|
||||
runData.SetTimeResolution(dval*factor);
|
||||
|
||||
// get/set start/stop time
|
||||
sstr = "n/a";
|
||||
TString date{"n/a"}, time{"n/a"};
|
||||
if (nxs_file->HasDataset("/raw_data_1/start_time"))
|
||||
sstr = nxs_file->template GetDataset<std::string>("/raw_data_1/start_time").GetData()[0];
|
||||
str = sstr;
|
||||
SplitTimeDate(str, time, date, ok);
|
||||
if (ok) {
|
||||
runData.SetStartTime(time);
|
||||
runData.SetStartDate(date);
|
||||
}
|
||||
|
||||
sstr = "n/a";
|
||||
date = "n/a";
|
||||
time = "n/a";
|
||||
if (nxs_file->HasDataset("/raw_data_1/end_time"))
|
||||
sstr = nxs_file->template GetDataset<std::string>("/raw_data_1/end_time").GetData()[0];
|
||||
str = sstr;
|
||||
SplitTimeDate(str, time, date, ok);
|
||||
if (ok) {
|
||||
runData.SetStopTime(time);
|
||||
runData.SetStopDate(date);
|
||||
}
|
||||
|
||||
// get/set deadtime relevant parameters
|
||||
if (nxs_file->HasDataset("/raw_data_1/instrument/detector_1/dead_time")) {
|
||||
std::vector<float> dt;
|
||||
dt = nxs_file->template GetDataset<float>("/raw_data_1/instrument/detector_1/dead_time").GetData();
|
||||
runData.SetDeadTimeParam(dt);
|
||||
}
|
||||
if (nxs_file->HasDataset("/raw_data_1/good_frames")) {
|
||||
ival = nxs_file->template GetDataset<int>("/raw_data_1/good_frames").GetData()[0];
|
||||
runData.SetNumberOfGoodFrames(ival);
|
||||
}
|
||||
|
||||
// data with its metadata
|
||||
if (nxs_file->HasDataset("/raw_data_1/instrument/detector_1/counts")) {
|
||||
int t0_bin{-1}, fgb{-1}, lgb{-1}, noOfHistos{-1}, histoLength{-1};
|
||||
auto count_ds = nxs_file->template GetDataset<int>("/raw_data_1/instrument/detector_1/counts");
|
||||
auto count = count_ds.GetData();
|
||||
auto dims = count_ds.GetDimensions();
|
||||
if (dims.size() < 3) {
|
||||
std::cerr << std::endl << "**ERROR** PNeXus data dimension error! dims.size()=" << dims.size() << ", expecting == 3." << std::endl;
|
||||
return false;
|
||||
}
|
||||
noOfHistos = dims[1];
|
||||
histoLength = dims[2];
|
||||
// get all necessary attributes
|
||||
if (count_ds.HasAttribute("t0_bin"))
|
||||
t0_bin = std::any_cast<int>(count_ds.GetAttribute("t0_bin"));
|
||||
if (count_ds.HasAttribute("first_good_bin"))
|
||||
fgb = std::any_cast<int>(count_ds.GetAttribute("first_good_bin"));
|
||||
if (count_ds.HasAttribute("last_good_bin"))
|
||||
lgb = std::any_cast<int>(count_ds.GetAttribute("last_good_bin"));
|
||||
if (static_cast<int>(count.size()) != noOfHistos*histoLength) {
|
||||
std::cerr << std::endl << "**ERROR** PNeXus data size error! count.size()=" << count.size() << ", #histos=" << noOfHistos << ", length=" << histoLength << "." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// fill dataSet
|
||||
PDoubleVector data;
|
||||
for (int i=0; i<noOfHistos; i++) {
|
||||
dataSet.Clear();
|
||||
dataSet.SetHistoNo(i+1); // i.e. histo numbers start with 1
|
||||
dataSet.SetTimeZeroBin(t0_bin);
|
||||
dataSet.SetFirstGoodBin(fgb);
|
||||
dataSet.SetLastGoodBin(lgb);
|
||||
for (int j=0; j<histoLength; j++)
|
||||
data.push_back(count[i*histoLength+j]);
|
||||
dataSet.SetData(data);
|
||||
runData.SetDataSet(dataSet);
|
||||
data.clear();
|
||||
}
|
||||
|
||||
// keep run name from the msr-file
|
||||
runData.SetRunName(fRunName);
|
||||
|
||||
// keep the information
|
||||
fData.push_back(runData);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // _PRUNDATAHANDLER_H_
|
||||
|
||||
Reference in New Issue
Block a user