diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | INSTALL.md | 20 | ||||
-rw-r--r-- | config.h.cmake.in | 1 | ||||
-rw-r--r-- | config.h.in | 1 | ||||
-rw-r--r-- | libcrystfel/libcrystfel-config.h.cmake.in | 1 | ||||
-rw-r--r-- | libcrystfel/libcrystfel-config.h.meson.in | 1 | ||||
-rw-r--r-- | libcrystfel/src/image-hdf5.c | 66 | ||||
-rw-r--r-- | libcrystfel/src/image.c | 35 | ||||
-rw-r--r-- | meson.build | 42 | ||||
-rw-r--r-- | meson_options.txt | 1 | ||||
-rw-r--r-- | src/ambigator.c | 6 | ||||
-rw-r--r-- | tests/meson.build | 82 |
12 files changed, 166 insertions, 91 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 75783bf8..f9073ca6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,6 +112,7 @@ set(HAVE_OPENCL ${OpenCL_FOUND}) set(HAVE_GDKPIXBUF ${GDKPIXBUF_FOUND}) set(HAVE_GDK ${GDK_FOUND}) set(HAVE_ZMQ ${ZMQ_FOUND}) +set(HAVE_HDF5 1) set(PACKAGE_VERSION ${PROJECT_VERSION}) @@ -26,24 +26,24 @@ supported facility installations. Dependencies ------------ -Here are the mandatory dependencies - you cannot install CrystFEL without these: +There are very few mandatory dependencies for CrystFEL. They are: * [Meson](https://mesonbuild.com/) 0.55.0 or later -* [HDF5](https://www.hdfgroup.org/downloads/hdf5/) 1.8.0 or later (1.10.0 or later is required for many recent data formats which use the 'virtual data set' feature) * [GNU Scientific Library (GSL)](https://www.gnu.org/software/gsl/) * [Bison](https://www.gnu.org/software/bison/) 2.6 or later * [Flex](https://www.gnu.org/software/flex/) [CMake](https://cmake.org/) 3.12 or later can be used in place of Meson, -but Meson is strongly preferred. The CMake build system is considered -deprecated, already lacks several useful features and will be removed at some -point in the future. +but Meson is strongly preferred. CrystFEL's CMake-based build system is +considered deprecated and will be removed at some point in the future. It +already lacks several features compared to the Meson-based system. The following dependencies are "optional", in the sense that you can install CrystFEL without them. However, a CrystFEL installation without these will lack important features such as the graphical user interface. The following list is roughly in order of importance: +* [HDF5](https://www.hdfgroup.org/downloads/hdf5/) 1.8.0 or later (required for HDF5 file read/write. Version 1.10.0 or later is required for many recent data formats which use the 'virtual data set' feature) * [GTK](https://gtk.org/) version between 3.12 and 3.24 inclusive (required for GUI) * [Cairo](https://www.cairographics.org/) 1.2 or later (required for GUI) * [Pango](https://pango.gnome.org/) 1.0 or later, including [PangoCairo](https://docs.gtk.org/PangoCairo/) (required for GUI) @@ -58,6 +58,16 @@ roughly in order of importance: * [msgpack-c](https://github.com/msgpack/msgpack-c) (for online data streaming) * [SLURM](https://slurm.schedmd.com/) (development files required for submitting jobs via GUI) +When building with Meson, it's possible to compile without HDF5. This is +useful if you only need to use other file formats, e.g. CBF. You may have +noticed that most compilation problems (see *Notes about strange problems* +below) are related to HDF5. To build without HDF5, set up your build directory +as follows, replacing the `meson build` step: +``` +meson build -Dhdf5=disabled +``` +When building with CMake, HDF5 is a mandatory dependency. + Most of the dependencies mentioned above should be available from your Linux distribution's package manager, or from [Homebrew](https://brew.sh/) on Mac OS. We emphatically recommend against trying to install GTK, Cairo, Pango or diff --git a/config.h.cmake.in b/config.h.cmake.in index 81944a12..2c781b3c 100644 --- a/config.h.cmake.in +++ b/config.h.cmake.in @@ -9,3 +9,4 @@ #cmakedefine HAVE_CLOCK_GETTIME #cmakedefine HAVE_ZMQ #cmakedefine HAVE_SLURM +#cmakedefine HAVE_HDF5 diff --git a/config.h.in b/config.h.in index 858e1d7d..058e5cea 100644 --- a/config.h.in +++ b/config.h.in @@ -9,3 +9,4 @@ #mesondefine HAVE_CLOCK_GETTIME #mesondefine HAVE_ZMQ #mesondefine HAVE_SLURM +#mesondefine HAVE_HDF5 diff --git a/libcrystfel/libcrystfel-config.h.cmake.in b/libcrystfel/libcrystfel-config.h.cmake.in index 31f28ee1..830055cb 100644 --- a/libcrystfel/libcrystfel-config.h.cmake.in +++ b/libcrystfel/libcrystfel-config.h.cmake.in @@ -11,6 +11,7 @@ #cmakedefine HAVE_LIBCCP4 #cmakedefine HAVE_MSGPACK #cmakedefine HAVE_CLOCK_GETTIME +#cmakedefine HAVE_HDF5 #cmakedefine HAVE_FORKPTY_PTY_H #cmakedefine HAVE_FORKPTY_UTIL_H diff --git a/libcrystfel/libcrystfel-config.h.meson.in b/libcrystfel/libcrystfel-config.h.meson.in index 6796857e..7d43147d 100644 --- a/libcrystfel/libcrystfel-config.h.meson.in +++ b/libcrystfel/libcrystfel-config.h.meson.in @@ -9,6 +9,7 @@ #mesondefine HAVE_LIBCCP4 #mesondefine HAVE_MSGPACK #mesondefine HAVE_CLOCK_GETTIME +#mesondefine HAVE_HDF5 #mesondefine HAVE_FORKPTY_PTY_H #mesondefine HAVE_FORKPTY_UTIL_H diff --git a/libcrystfel/src/image-hdf5.c b/libcrystfel/src/image-hdf5.c index 702c1392..7023e811 100644 --- a/libcrystfel/src/image-hdf5.c +++ b/libcrystfel/src/image-hdf5.c @@ -33,9 +33,11 @@ #include <assert.h> #include <math.h> #include <stdio.h> +#include <unistd.h> +#ifdef HAVE_HDF5 #include <hdf5.h> #include <hdf5_hl.h> -#include <unistd.h> +#endif #include "image.h" #include "utils.h" @@ -45,34 +47,6 @@ #include "datatemplate_priv.h" -static void close_hdf5(hid_t fh) -{ - int n_ids, i; - hid_t ids[2048]; - - n_ids = H5Fget_obj_ids(fh, H5F_OBJ_ALL, 2048, ids); - - for ( i=0; i<n_ids; i++ ) { - - hid_t id; - H5I_type_t type; - - id = ids[i]; - - type = H5Iget_type(id); - - if ( type == H5I_GROUP ) H5Gclose(id); - if ( type == H5I_DATASET ) H5Dclose(id); - if ( type == H5I_DATATYPE ) H5Tclose(id); - if ( type == H5I_DATASPACE ) H5Sclose(id); - if ( type == H5I_ATTR ) H5Aclose(id); - - } - - H5Fclose(fh); -} - - /* Get the path parts of the event ID * e.g. ev_orig = abc/def/ghi//5/2/7 * -> [abc, def, ghi], with *pn_plvals=3. @@ -320,6 +294,8 @@ char *substitute_path(const char *ev, const char *pattern, int skip_ok) } +#ifdef HAVE_HDF5 + static void make_placeholder_skip(signed int *dt_dims, signed int *panel_dims) { @@ -355,6 +331,36 @@ static int total_dimensions(const struct panel_template *p) } +static void close_hdf5(hid_t fh) +{ + int n_ids, i; + hid_t ids[2048]; + + n_ids = H5Fget_obj_ids(fh, H5F_OBJ_ALL, 2048, ids); + + for ( i=0; i<n_ids; i++ ) { + + hid_t id; + H5I_type_t type; + + id = ids[i]; + + type = H5Iget_type(id); + + if ( type == H5I_GROUP ) H5Gclose(id); + if ( type == H5I_DATASET ) H5Dclose(id); + if ( type == H5I_DATATYPE ) H5Tclose(id); + if ( type == H5I_DATASPACE ) H5Sclose(id); + if ( type == H5I_ATTR ) H5Aclose(id); + + } + + H5Fclose(fh); +} + + + + static int load_hdf5_hyperslab(struct panel_template *p, hid_t fh, const char *event, @@ -2316,3 +2322,5 @@ int image_hdf5_write(const struct image *image, free(locations); return 0; } + +#endif /* HAVE_HDF5 */ diff --git a/libcrystfel/src/image.c b/libcrystfel/src/image.c index 3a8fb482..e428b606 100644 --- a/libcrystfel/src/image.c +++ b/libcrystfel/src/image.c @@ -49,6 +49,13 @@ /** \file image.h */ +#ifndef HAVE_HDF5 +int is_hdf5_file(const char *filename) +{ + return 0; +} +#endif + struct _imagefeaturelist { struct imagefeature *features; @@ -378,7 +385,11 @@ static int read_header_to_cache(struct image *image, const char *from) return 1; case DATA_SOURCE_TYPE_HDF5: + #ifdef HAVE_HDF5 return image_hdf5_read_header_to_cache(image, from); + #else + return 1; + #endif case DATA_SOURCE_TYPE_CBF: case DATA_SOURCE_TYPE_CBFGZ: @@ -776,7 +787,11 @@ static int image_read_image_data(struct image *image, return 1; case DATA_SOURCE_TYPE_HDF5: + #ifdef HAVE_HDF5 return image_hdf5_read(image, dtempl); + #else + return 1; + #endif case DATA_SOURCE_TYPE_CBF: return image_cbf_read(image, dtempl, 0); @@ -1008,8 +1023,10 @@ static int load_mask(struct panel_template *p, unsigned int mask_bad) { if ( is_hdf5_file(mask_fn) ) { + #ifdef HAVE_HDF5 image_hdf5_read_mask(p, mask_fn, ev, bad, mask_location, mask_good, mask_bad); + #endif } else if ( is_cbf_file(mask_fn) ) { image_cbf_read_mask(p, mask_fn, ev, 0, bad, @@ -1189,9 +1206,11 @@ static int create_satmap(struct image *image, } if ( is_hdf5_file(map_fn) ) { + #ifdef HAVE_HDF5 image->sat[i] = image_hdf5_read_satmap(p, map_fn, image->ev, p->satmap); + #endif } else { ERROR("Saturation map must be in HDF5 format\n"); @@ -1476,6 +1495,7 @@ ImageFeatureList *image_read_peaks(const DataTemplate *dtempl, { if ( is_hdf5_file(filename) ) { + #ifdef HAVE_HDF5 enum peak_layout layout; if ( dtempl->peak_list_type == PEAK_LIST_AUTO ) { @@ -1516,6 +1536,10 @@ ImageFeatureList *image_read_peaks(const DataTemplate *dtempl, return NULL; } + #else + ERROR("Can't read peak list - compiled without HDF5\n"); + return NULL; + #endif } else { ERROR("Peak lists can only be read from HDF5 files\n"); @@ -1528,8 +1552,14 @@ char **image_expand_frames(const DataTemplate *dtempl, const char *filename, int *n_frames) { if ( is_hdf5_file(filename) ) { + #ifdef HAVE_HDF5 return image_hdf5_expand_frames(dtempl, filename, n_frames); + #else + ERROR("Can't expand frames - compiled without HDF5\n"); + return NULL; + #endif + } else { char **list; list = malloc(sizeof(char *)); @@ -1580,7 +1610,12 @@ int image_write(const struct image *image, const char *filename) { if ( is_hdf5_file(filename) ) { + #ifdef HAVE_HDF5 return image_hdf5_write(image, dtempl, filename); + #else + ERROR("Can't write image - compiled without HDF5\n"); + return 1; + #endif } ERROR("Can only write to HDF5 files.\n"); diff --git a/meson.build b/meson.build index 9e9a6985..a9848901 100644 --- a/meson.build +++ b/meson.build @@ -34,13 +34,14 @@ if slurmdep.found() endif # Find HDF5 using inbuilt Meson methods. Requires Meson >= 0.50.0 -hdf5dep = dependency('hdf5', language: 'c', required: true) - -# Request HDF5 1.10-style API -add_project_arguments('-DH5_USE_110_API', language: 'c') -add_project_arguments('-DH5O_GET_INFO_BY_IDX1', language: 'c') +hdf5dep = dependency('hdf5', language: 'c', required: get_option('hdf5')) +if hdf5dep.found() + conf_data.set10('HAVE_HDF5', 1) + # Request HDF5 1.10-style API + add_project_arguments('-DH5_USE_110_API', language: 'c') + add_project_arguments('-DH5O_GET_INFO_BY_IDX1', language: 'c') +endif -# "Optional" dependencies fftwdep = dependency('fftw3', required: false) if fftwdep.found() conf_data.set10('HAVE_FFTW', 1) @@ -184,11 +185,13 @@ indexamajig = executable('indexamajig', indexamajig_sources, install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib') # make_pixelmap -executable('make_pixelmap', - ['src/make_pixelmap.c', versionc], - dependencies: [mdep, libcrystfeldep, hdf5dep], - install: true, - install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib') +if hdf5dep.found() + executable('make_pixelmap', + ['src/make_pixelmap.c', versionc], + dependencies: [mdep, libcrystfeldep, hdf5dep], + install: true, + install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib') +endif # geoptimiser # FIXME: restore @@ -248,20 +251,21 @@ if gtkdep.found() endif # pattern_sim -pattern_sim_sources = ['src/pattern_sim.c', 'src/diffraction.c', versionc] -if opencldep.found() - pattern_sim_sources += ['src/diffraction-gpu.c', 'src/cl-utils.c'] +if hdf5dep.found() + pattern_sim_sources = ['src/pattern_sim.c', 'src/diffraction.c', versionc] + if opencldep.found() + pattern_sim_sources += ['src/diffraction-gpu.c', 'src/cl-utils.c'] + endif + executable('pattern_sim', pattern_sim_sources, + dependencies: [mdep, libcrystfeldep, gsldep, hdf5dep, opencldep], + install: true, + install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib') endif -executable('pattern_sim', pattern_sim_sources, - dependencies: [mdep, libcrystfeldep, gsldep, hdf5dep, opencldep], - install: true, - install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib') # For testing (see tests/meson.build) simulation_bits = files(['src/diffraction.c', 'src/diffraction-gpu.c', 'src/cl-utils.c']) - # ************************ Misc resources ************************ install_data(['data/crystfel.svg'], diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 00000000..16439ae3 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1 @@ +option('hdf5', type: 'feature', value: 'enabled') diff --git a/src/ambigator.c b/src/ambigator.c index fe4d5fa1..3777cf0a 100644 --- a/src/ambigator.c +++ b/src/ambigator.c @@ -43,7 +43,9 @@ #include <gsl/gsl_rng.h> #include <gsl/gsl_permutation.h> #include <gsl/gsl_randist.h> +#ifdef HAVE_HDF5 #include <hdf5.h> +#endif #include <image.h> #include <utils.h> @@ -909,6 +911,7 @@ static void write_reindexed_stream(const char *infile, const char *outfile, static void save_corr(const char *filename, struct cc_list *ccs, int n_crystals, int *assignments) { +#ifdef HAVE_HDF5 hid_t fh, fsh, msh, cdh, rdh; herr_t r; hsize_t size[2]; @@ -1035,6 +1038,9 @@ static void save_corr(const char *filename, struct cc_list *ccs, int n_crystals, H5Fclose(fh); STATUS("Wrote correlation matrix in HDF5 format to %s\n", filename); +#else + ERROR("Can't save correlation matrix - not compiled with HDF5\n"); +#endif } diff --git a/tests/meson.build b/tests/meson.build index 0109ec9d..b3b3cc79 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -24,11 +24,13 @@ endforeach # Test of waiting for files -test('file-wait', - find_program('file-wait'), - args : [indexamajig.full_path(), - files('wavelength_geom.h5'), - files('wavelength_geom1.geom')]) +if hdf5dep.found() + test('file-wait', + find_program('file-wait'), + args : [indexamajig.full_path(), + files('wavelength_geom.h5'), + files('wavelength_geom1.geom')]) +endif test('indexamajig-missing-file', @@ -105,40 +107,44 @@ if opencldep.found() endif # Event enumeration tests -ev_enum_tests = ['ev_enum1', - 'ev_enum2', - 'ev_enum3'] +if hdf5dep.found() + ev_enum_tests = ['ev_enum1', + 'ev_enum2', + 'ev_enum3'] + + foreach name : ev_enum_tests + exe = executable(name, ''.join([name, '.c']), + dependencies : [libcrystfeldep, hdf5dep]) + h5 = files(''.join([name, '.h5'])) + geom = files(''.join([name, '.geom'])) + test(name, exe, args : [h5, geom]) + endforeach +endif -foreach name : ev_enum_tests - exe = executable(name, ''.join([name, '.c']), + +# Wavelength tests +if hdf5dep.found() + wavelength_tests = [['wavelength_geom1', '1e-10'], + ['wavelength_geom2', '1.3776e-10'], + ['wavelength_geom3', '1.3776e-10'], + ['wavelength_geom4', '1.9687e-12'], + ['wavelength_geom5', '1.9687e-12'], + ['wavelength_geom6', '1.3776e-10'], + ['wavelength_geom7', '1.3776e-10'], + ['wavelength_geom8', '1.9687e-12'], + ['wavelength_geom9', '1.3776e-10'], + ['wavelength_geom10', '1.3776e-10'], + ['wavelength_geom11', '1.125e-10'], + ['wavelength_geom12', '1.125e-10']] + + exe = executable('wavelength_geom', 'wavelength_geom.c', dependencies : [libcrystfeldep, hdf5dep]) - h5 = files(''.join([name, '.h5'])) - geom = files(''.join([name, '.geom'])) - test(name, exe, args : [h5, geom]) -endforeach + h5 = files('wavelength_geom.h5') -# Wavelength tests -wavelength_tests = [['wavelength_geom1', '1e-10'], - ['wavelength_geom2', '1.3776e-10'], - ['wavelength_geom3', '1.3776e-10'], - ['wavelength_geom4', '1.9687e-12'], - ['wavelength_geom5', '1.9687e-12'], - ['wavelength_geom6', '1.3776e-10'], - ['wavelength_geom7', '1.3776e-10'], - ['wavelength_geom8', '1.9687e-12'], - ['wavelength_geom9', '1.3776e-10'], - ['wavelength_geom10', '1.3776e-10'], - ['wavelength_geom11', '1.125e-10'], - ['wavelength_geom12', '1.125e-10']] - -exe = executable('wavelength_geom', 'wavelength_geom.c', - dependencies : [libcrystfeldep, hdf5dep]) - -h5 = files('wavelength_geom.h5') - -foreach p : wavelength_tests - geom = files(''.join([p[0], '.geom'])) - expected_wl = p[1] - test(p[0], exe, args : [h5, geom, expected_wl]) -endforeach + foreach p : wavelength_tests + geom = files(''.join([p[0], '.geom'])) + expected_wl = p[1] + test(p[0], exe, args : [h5, geom, expected_wl]) + endforeach +endif |