HDF5 to root

Hello all,
After several days struggling with the HDF5 to ROOT conversion, I have created a program based on the original one posted by Giuseppe Vacanti:hdf2root.tar.gz (3.74 KB)
It converts the whole HDF5 structure into TTrees:
For every Group in the HDF5 file, hdf2root creates a TTree (named as the orginal Group) which stores the info contained in the original DataSets. Moreover, the Attributes of the Group are stored in another TTree (named as the original group plus “_att”), together with the Attributes of every DataSet in the Group.
The program is thought to work in any kind of HDF5 file and make a “general” conversion.
It works in all the data files I have tested, which amounts to 4 or 5 different types (only!).
A clear limitation would be how to handle more complex DataTypes. Up to know, only simple types are supported, but this could be enough for many users (it is actually enough for the files I have to handle!).
The usage is quite simple:

Usage: hdf2root [--seq] <inFile.h5> <outFile.root(default=inFile.root)>
 
            --seq  Enables sequential mode.

hdf2root just needs the original HDF5 file as input to create a root file with the same name. If you want a different output name, put it in as a second argument. If the –seq is set, hdf2root create the TTrees for the DataSets in sequential mode. This means that the first dimension of the data set is used like an “event index” (if you know what I mean…).

I aim you (interested people) to take a look and send some feedback.
One could start with the example file I posted in a previous post in this thread (gamma.h5).

Warning: I am only experiencing problems with the conversion of hdf5_strings mostly present in Attributes.
The size of these objects is not 1 to 1 with their length and, as a result, larger strings of characters are stored in root unnecessarily. This could be a problem of the particular hdf5 files I am using, instead of the converter itself.

I hope it helps to the community.

Cheers,
Alberto

Hi all,

This also looks promising: amas.web.psi.ch/tools/H5root/index.html

I have not tried it yet, but there is an interactive tool as well as a library that you can use to open/read/plot hdf5 files from the root prompt…

Hi delaossa,

I tried to compile the program you attached but I get the msg below. I am guessing that I am missing mpif77. I tried to install that through yum searching for openmpi but none of the packages I found help. Do you know if mpif77 is compatible with SLC6?

======================================
[wht34@icarus hdf2root]$ make
make: mpif77: Command not found
Linking hdf2root
hdf2root.o: In function main': /home/wht34/MyCodes/hdf2root/hdf2root.cpp:394: undefined reference toH5check_version’
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/…/…/…/…/lib64/libhdf5_cpp.so: undefined reference to H5Tunregister' /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/libhdf5_cpp.so: undefined reference toH5set_free_list_limits’

Hello,

Try this new version:hdf2root.tar.gz (4.86 KB)
You will need a root installation and the HDF5 libraries for C++.
There are a configuration script where you can define the paths to the needed libraries.
Let me know wether you succeed to compile and or not.

Cheers,
Alberto

Hi Alberto,

I modified the env.sh file to point to my root installation directory. I am not sure if I pointed the hdf5 interface correctly but they’re the only hdf5 libraries I found on my computer. Make is still complaining about
undefined reference to `H5check_version’ and so on with all these H5 commands being undefined.

Thanks,

Wing

======================
#!/bin/bash

Setting up Root environment…

#export ROOTSYS=/usr/local/root
export ROOTSYS=/usr/share/root
export DYLD_LIBRARY_PATH=$ROOTSYS/lib:$DYLD_LIBRARY_PATH
export PATH=$ROOTSYS/bin:$PATH

HDF5: C++ interface

#export HDF5CPP=/usr/share/hdf5-c++
export HDF5CPP=/usr/bin/h5c++
#export DYLD_LIBRARY_PATH=$HDF5CPP/lib:$DYLD_LIBRARY_PATH
export DYLD_LIBRARY_PATH=/usr/lib64/:$DYLD_LIBRARY_PATH

============================
[wht34@icarus hdf2root]$ make
Linking hdf2root.e
g++ -fPIC -pthread -m64 -I/usr/share/root/include -I/include -I. hdf2root.cc -o hdf2root.e -L. -L/usr/share/root/lib -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -pthread -lm -ldl -rdynamic -L/lib -lhdf5_cpp
/tmp/wht34/ccAALUJ7.o: In function main': hdf2root.cc:(.text+0x2834): undefined reference toH5check_version’
/usr/lib/…/lib64/libhdf5_cpp.so: undefined reference to `H5Tunregister’

Hello,

The compiler also has to know where the headers for HDF5 are.
If in the configuration script you define the environment variable HDF5CPP, the Makefile would define the path to the HDF5 headers in this way: $HDF5CPP/include.

Make sure that the file H5Cpp.h is located there.

Cheers,
Alberto

IMPORTANT:

I somehow messed up the code in the version that I uploaded yesterday.
It was working, but it was full of unnecessary repeated function definitions.

Download please the following (fix) version:
hdf2root.tar.gz (4.39 KB)

Cheers,
Alberto

Hi Alberto,

The code compiles now but I run into this runtime error now. I have libhdf5_cpp.so.6 but not 8 in my /usr/lib64.

[wht34@icarus hdf2root]$ ./hdf2root --ver lux10_20130611T0605_f000001_eb00014.hdf5 lux10_20130611T0605_f000001_eb00014.hdf5.root
./hdf2root: error while loading shared libraries: libhdf5_cpp.so.8: cannot open shared object file: No such file or directory
[wht34@icarus hdf2root]$ ldd hdf2root.e | grep libhdf5_cpp.so.8
libhdf5_cpp.so.8 => not found

Okay, I found these libraries in

/usr/local/hdf5/lib/ … but the program is looking for it in /usr/lib64…

If i make symblic links for the two missing libraries. The program runs but doesn’t give any output.

sudo ln -s /usr/local/hdf5/lib/libhdf5.so.8 /usr/lib64/libhdf5.so.8
sudo ln -s /usr/local/hdf5/lib/libhdf5_cpp.so.8 /usr/lib64/libhdf5_cpp.so.8
[wht34@icarus hdf2root]$ ./hdf2root lux10_20130611T0605_f000001_eb00014.hdf5 lux10_20130611T0605_f000001_eb00014.hdf5.root
Converting …
[wht34@icarus hdf2root]$ ll
total 12M
-rw-r–r--. 1 wht34 caselux 275 Mar 25 12:06 env.csh
-rwxr-xr-x. 1 wht34 caselux 373 Mar 26 15:04 env.sh
lrwxrwxrwx. 1 wht34 caselux 10 Mar 26 15:53 hdf2root -> hdf2root.e
-rw-r–r--. 1 wht34 caselux 14K Mar 26 14:44 hdf2root.cc
-rwxr-xr-x. 1 wht34 caselux 157K Mar 26 15:53 hdf2root.e
-rw-r–r--. 1 wht34 caselux 462 Mar 26 14:44 hdf2root.hh
-rw-r–r--. 1 wht34 caselux 12M Mar 26 14:55 lux10_20130611T0605_f000001_eb00014.hdf5
-rw-r–r--. 1 wht34 caselux 615 Mar 26 15:06 Makefile

Hello,

If the hdf5 libraries are located at /usr/local/hdf5/lib, the include files should be at /usr/local/hdf5/include.
In the configuration script you should define:
export HDF5CPP= /usr/local/hdf5
export LD_LIBRARY_PATH=$HDF5CPP/lib:$LD_LIBRARY_PATH

By the way, in which system are you trying to build the program?
DYLD_LIBRARY_PATH is used for macos, for linux systems it is LD_LIBRARY_PATH the variable which holds the path to the needed libraries.

Cheers,
Alberti

Hi Alberto,

I am on SLC6, so I changed the DYLD_LIBRARY_PATH to LD_LIBRARY_PATH as you showed. The code compiles but nothing happen when I ran the executable.

[wht34@icarus hdf2root]$ echo $HDF5CPP
/usr/local/hdf5
[wht34@icarus hdf2root]$ echo $LD_LIBRARY_PATH
/usr/local/hdf5/lib:/usr/share/root//lib:/usr/share/clhep/install/lib:/usr/share/geant4/install/lib/geant4/Linux-g++:/usr/share/clhep/install/lib:/usr/share/root//lib

[wht34@icarus hdf2root]$ make
Linking hdf2root.e
g++ -fPIC -pthread -m64 -I/usr/share/root/include -I/usr/local/hdf5/include -I. hdf2root.cc -o hdf2root.e -L. -L/usr/share/root/lib -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -pthread -lm -ldl -rdynamic -L/usr/local/hdf5/lib -lhdf5_cpp

[wht34@icarus hdf2root]$ ./hdf2root.e test.hdf5
Converting …
[wht34@icarus hdf2root]$ ll
total 24M
-rw-r–r--. 1 wht34 caselux 275 Mar 25 12:06 env.csh
-rwxr-xr-x. 1 wht34 caselux 365 Apr 2 14:48 env.sh
lrwxrwxrwx. 1 wht34 caselux 10 Apr 2 14:52 hdf2root -> hdf2root.e
-rw-r–r--. 1 wht34 caselux 14K Mar 26 14:44 hdf2root.cc
-rwxr-xr-x. 1 wht34 caselux 157K Apr 2 14:52 hdf2root.e
-rw-r–r--. 1 wht34 caselux 462 Mar 26 14:44 hdf2root.hh
-rw-r–r--. 1 wht34 caselux 615 Mar 26 15:06 Makefile
-rw-r–r--. 1 wht34 caselux 12M Mar 26 16:11 test.hdf5

Hello,
Thanks to your interest I have updated the code into a more professional fashion.
I have tried it and it works in both linux and mac os platforms.
Give it a try: github.com/delaossa/hdf2root

In the config folder there are various examples of configuration files.
Pick up the most similar to your system and modify it accordingly.
Good luck!

Hi Alberto,

The git version of your code compiles fine but the executable still doesn’t do anything to the hdf5 test file.
It’ll just say converting … , but no root output comes out with hdf2root test.hdf5 test.root.
Here’s the log for the compilation and my env.sh file.

#!/bin/bash

MAC flag

#export PLATFORM=linux
export ROOTSYS=/usr/share/root/
export LD_LIBRARY_PATH=$ROOTSYS/lib:$LD_LIBRARY_PATH
export PATH=$ROOTSYS/bin:$PATH
export HDF5CPP=/usr/local/hdf5
export LD_LIBRARY_PATH=$HDF5CPP/lib:$LD_LIBRARY_PATH
export HDF2ROOT=/home/wht34/SVN/Scratch/wht34/hdf2root-master
export LD_LIBRARY_PATH=$HDF2ROOT/lib:$LD_LIBRARY_PATH
export PATH=$HDF2ROOT/bin:$PATH

wht34@icarus hdf2root-master]$ source config/env.sh
[wht34@icarus hdf2root-master]$ make
make[1]: Entering directory /home/wht34/SVN/Scratch/wht34/hdf2root-master/src' Compiling hdf2root_methods.cc g++ -c -O2 -Wall -fPIC -pthread -m64 -I/usr/share/root/include -I/usr/local/hdf5/include -I/home/wht34/SVN/Scratch/wht34/hdf2root-master/inc -I. hdf2root_methods.cc Building shared library /home/wht34/SVN/Scratch/wht34/hdf2root-master/lib/libhdf2root.so ... g++ -shared hdf2root_methods.o -o /home/wht34/SVN/Scratch/wht34/hdf2root-master/lib/libhdf2root.so -L/usr/share/root/lib -lCore -lRIO -lTree -L/usr/local/hdf5/lib -lhdf5 -lhdf5_cpp Done Compiling hdf2root.cc g++ -c -O2 -Wall -fPIC -pthread -m64 -I/usr/share/root/include -I/usr/local/hdf5/include -I/home/wht34/SVN/Scratch/wht34/hdf2root-master/inc -I. hdf2root.cc Linking hdf2root.o g++ -O2 -m64 -o hdf2root.e hdf2root.o -L/usr/share/root/lib -lCore -lRIO -lTree -L/usr/local/hdf5/lib -lhdf5 -lhdf5_cpp -L/home/wht34/SVN/Scratch/wht34/hdf2root-master/lib -lhdf2root ln -sf /home/wht34/SVN/Scratch/wht34/hdf2root-master/src/hdf2root.e /home/wht34/SVN/Scratch/wht34/hdf2root-master/bin/hdf2root rm hdf2root.o make[1]: Leaving directory/home/wht34/SVN/Scratch/wht34/hdf2root-master/src’

Strange… What happens if you just execute the hdf2root program without any input parameters?
This is what i get:

[code][Behemoth] ~/plasma/software/hdf2root $> hdf2root

Usage: hdf2root [–seq] <inFile.h5> <outFile.root(=inFile.root)>

        --seq  Enables sequential mode. 
        --ver  Enables print out. 

[/code]

I get the same thing. Do you have a hdf5 file that I can test this program on? Maybe the file I have may not work with your program.

[wht34@icarus hdf2root-master]$ hdf2root

Usage: hdf2root [–seq] <inFile.h5> <outFile.root(=inFile.root)>

        --seq  Enables sequential mode. 
        --ver  Enables print out.

Actually by renaming the extension of my hdf5 to h5 the program does convert the h5 to root. The output created a bunch of broken trees however. Do you know if there’s any specially formatting of the hdf5 file in order to make this conversion to .root?

[wht34@icarus hdf2root-master]$ hdf2root test.h5 test.root
Converting test.h5 …
Error in TBranch::TLeaf: Illegal data type for nb_seqs/nb_seqs/c
Error in TBranch::TLeaf: Illegal data type for nb_chs/nb_chs/c
Error in TBranch::TLeaf: Illegal data type for trig_ch/trig_ch/c
Error in TBranch::TLeaf: Illegal data type for pulse_detect_pretrigger/pulse_detect_pretrigger/c
Error in TBranch::TLeaf: Illegal data type for pulse_end_posttrigger/pulse_end_posttrigger/c
Error in TBranch::TLeaf: Illegal data type for baseline_average_samples/baseline_average_samples/c
Error in TBranch::TLeaf: Illegal data type for sampling_freq_MHz/sampling_freq_MHz/c
Error in TBranch::TLeaf: Illegal data type for delay_buffer/delay_buffer/c
Error in TBranch::TLeaf: Illegal data type for vptg/vptg/c
Error in TBranch::TLeaf: Illegal data type for save_pair/save_pair/c
Error in TBranch::TLeaf: Illegal data type for baseline_freeze_enable/baseline_freeze_enable/c
Error in TBranch::TLeaf: Illegal data type for timestamp_clear/timestamp_clear/c
Error in TBranch::TLeaf: Illegal data type for end_address_threshold/end_address_threshold/c
Error in TBranch::TLeaf: Illegal data type for read_xlm/read_xlm/c
Error in TBranch::TLeaf: Illegal data type for water_thresh/water_thresh/c
Error in TBranch::TLeaf: Illegal data type for max_pulse_length/max_pulse_length/c
Error in TBranch::TLeaf: Illegal data type for write_log_files/write_log_files/c
Error in TBranch::TLeaf: Illegal data type for max_file_time_secs/max_file_time_secs/c

Hello,
Good. That means that the program works to such an extend…
It is true that the program filters the input files to have the .h5 extension. I have just fixed that and now it also accepts .hdf5 extensions. Update it from the git repository to get that version if you want.

Take into account that I made the program for my personal purpose and decided to shared it with others.
Normally, I only have to convert relatively simple hdf5 files and the program does its job.
But it is very likely that your files are more complex and/or they contain some elements that cannot be currently handled by hdf2root.

Would you send me one of your files so I can take a deeper look to it?
Another solution, if you are familiar with C++, is that you implement the missing features that you need and contribute to the hdf2root utility. The Git repository is also meant for that and you can “fork” the project, develop what you want, and eventually merge with the original one if success.
Are you up for this?

Cheers,
Alberto

Dear delaossa,
thanks to your code I has been able to convert hdf file to root file (I just modified the extension from hdf5 to hdf).
I tried to visualize my root file with TreeViewer but I have some problem. And I would like understand if is just my fault or the output root file have some limit to fix. Probably not.
My hdf file has X value, Y value, Z value (equal to X value), a dataset called DATA that is a matrix 360X1024 and another dadaset with the errors of DATA so another matrix 360X1024.
Using TreeViewer when I put in in x_empty the Y value, in y_empty the X value (for my case the axis are inverse) and in z_empty the DATA. I try to plot I get out just a 2 dimensional graph in 3D plot and I and he is not able to associated the columns whit X-axes and the row with Y-axes, so I don’t have a surfacer as I would like have. It depends because the z_empty want a vector and not a matrix? I put in some information about my root file end I put in also the root file to better understand. What I would like see is a 3D plot with all my data…

[code]echo "root [3] TFile f2(“120195_120199.root”);
root [4] gDirectory->pwd()
120195_120199.root:/
root [5] .ls
TFile** 120195_120199.root Dump of HDF file
TFile* 120195_120199.root Dump of HDF file
KEY: TTree root;1 DataSets in root group
KEY: TTree entry1;1 DataSets in entry1 group
KEY: TTree data1;1 DataSets in data1 group
KEY: TTree root_att;1 Attributes of root group
KEY: TTree entry1_att;1 Attributes of entry1 group
KEY: TTree data1_att;1 Attributes of data1 group

data1->Print()


*Tree :data1 : DataSets in data1 group *
*Entries : 1 : Total = 2978283 bytes File Size = 2976213 *

  •    :          : Tree compression factor =   1.00                       *
    

*Br 0 :DATA : DATA[362][1024]/F *
*Entries : 1 : Total Size= 1483316 bytes File Size = 1482824 *
*Baskets : 1 : Basket Size= 32000 bytes Compression= 1.00 *

*Br 1 :X : X[1024]/F *
*Entries : 1 : Total Size= 4635 bytes File Size = 4165 *
*Baskets : 1 : Basket Size= 32000 bytes Compression= 1.00 *

*Br 2 :Y : Y[362]/F *
*Entries : 1 : Total Size= 1985 bytes File Size = 1517 *
*Baskets : 1 : Basket Size= 32000 bytes Compression= 1.00 *

*Br 3 :Z : Z[1024]/F *
*Entries : 1 : Total Size= 4635 bytes File Size = 4165 *
*Baskets : 1 : Basket Size= 32000 bytes Compression= 1.00 *

*Br 4 :errors : errors[362][1024]/F *
*Entries : 1 : Total Size= 1483326 bytes File Size = 1482826 *
*Baskets : 1 : Basket Size= 32000 bytes Compression= 1.00 *
";[/code]

Hi Alberto,
your code works fine, but looks like it skips datetime objects (such as 18-char-long YYYYMMDDHHMMSS.mmm), since non-supported.
Could this feature be added?
Alex

FYI (just ignore me), but here is some code (in C++) to do the reverse: