aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml19
-rw-r--r--AUTHORS20
-rw-r--r--CMake/FindFDIP.cmake25
-rw-r--r--CMake/FindNBP.cmake24
-rw-r--r--CMake/FindPINKINDEXER.cmake24
-rw-r--r--CMake/FindXGANDALF.cmake24
-rw-r--r--CMakeLists.txt215
-rw-r--r--README208
-rw-r--r--README.md134
-rw-r--r--config.h.cmake.in13
-rw-r--r--config.h.in13
-rw-r--r--data/crystfel.svg459
-rw-r--r--doc/man/compare_hkl.17
-rw-r--r--doc/man/crystfel_geometry.5139
-rw-r--r--doc/man/hdfsee.1128
-rw-r--r--doc/man/indexamajig.142
-rw-r--r--doc/man/partialator.18
-rw-r--r--doc/stream-format.txt15
-rw-r--r--libcrystfel/CMakeLists.txt84
-rw-r--r--libcrystfel/config.h.cmake.in2
-rw-r--r--libcrystfel/config.h.in13
-rw-r--r--libcrystfel/doc/Doxyfile.in2536
-rw-r--r--libcrystfel/doc/index.md1
-rw-r--r--libcrystfel/meson.build185
-rw-r--r--libcrystfel/src/cell-utils.c127
-rw-r--r--libcrystfel/src/cell-utils.h11
-rw-r--r--libcrystfel/src/cell.c363
-rw-r--r--libcrystfel/src/cell.h28
-rw-r--r--libcrystfel/src/colscale.c (renamed from libcrystfel/src/render.c)21
-rw-r--r--libcrystfel/src/colscale.h (renamed from libcrystfel/src/render.h)26
-rw-r--r--libcrystfel/src/crystal.c45
-rw-r--r--libcrystfel/src/crystal.h10
-rw-r--r--libcrystfel/src/datatemplate.c1683
-rw-r--r--libcrystfel/src/datatemplate.h99
-rw-r--r--libcrystfel/src/datatemplate_priv.h239
-rw-r--r--libcrystfel/src/detector.c2401
-rw-r--r--libcrystfel/src/detector.h333
-rw-r--r--libcrystfel/src/detgeom.c141
-rw-r--r--libcrystfel/src/detgeom.h112
-rw-r--r--libcrystfel/src/events.c636
-rw-r--r--libcrystfel/src/events.h110
-rw-r--r--libcrystfel/src/filters.c14
-rw-r--r--libcrystfel/src/filters.h10
-rw-r--r--libcrystfel/src/fom.c1465
-rw-r--r--libcrystfel/src/fom.h141
-rw-r--r--libcrystfel/src/geometry.c71
-rw-r--r--libcrystfel/src/geometry.h14
-rw-r--r--libcrystfel/src/hdf5-file.c2785
-rw-r--r--libcrystfel/src/hdf5-file.h117
-rw-r--r--libcrystfel/src/image-cbf.c634
-rw-r--r--libcrystfel/src/image-cbf.h56
-rw-r--r--libcrystfel/src/image-hdf5.c2007
-rw-r--r--libcrystfel/src/image-hdf5.h72
-rw-r--r--libcrystfel/src/image-msgpack.c315
-rw-r--r--libcrystfel/src/image-msgpack.h64
-rw-r--r--libcrystfel/src/image.c1413
-rw-r--r--libcrystfel/src/image.h127
-rw-r--r--libcrystfel/src/index.c207
-rw-r--r--libcrystfel/src/index.h43
-rw-r--r--libcrystfel/src/indexers/asdf.c (renamed from libcrystfel/src/asdf.c)67
-rw-r--r--libcrystfel/src/indexers/asdf.h (renamed from libcrystfel/src/asdf.h)41
-rw-r--r--libcrystfel/src/indexers/dirax.c (renamed from libcrystfel/src/dirax.c)11
-rw-r--r--libcrystfel/src/indexers/dirax.h (renamed from libcrystfel/src/dirax.h)8
-rw-r--r--libcrystfel/src/indexers/felix.c (renamed from libcrystfel/src/felix.c)71
-rw-r--r--libcrystfel/src/indexers/felix.h (renamed from libcrystfel/src/felix.h)13
-rw-r--r--libcrystfel/src/indexers/mosflm.c (renamed from libcrystfel/src/mosflm.c)30
-rw-r--r--libcrystfel/src/indexers/mosflm.h (renamed from libcrystfel/src/mosflm.h)10
-rw-r--r--libcrystfel/src/indexers/pinkindexer.c (renamed from libcrystfel/src/pinkindexer.c)433
-rw-r--r--libcrystfel/src/indexers/pinkindexer.h (renamed from libcrystfel/src/pinkindexer.h)37
-rw-r--r--libcrystfel/src/indexers/taketwo.c (renamed from libcrystfel/src/taketwo.c)111
-rw-r--r--libcrystfel/src/indexers/taketwo.h (renamed from libcrystfel/src/taketwo.h)6
-rw-r--r--libcrystfel/src/indexers/xds.c (renamed from libcrystfel/src/xds.c)26
-rw-r--r--libcrystfel/src/indexers/xds.h (renamed from libcrystfel/src/xds.h)10
-rw-r--r--libcrystfel/src/indexers/xgandalf.c (renamed from libcrystfel/src/xgandalf.c)67
-rw-r--r--libcrystfel/src/indexers/xgandalf.h (renamed from libcrystfel/src/xgandalf.h)11
-rw-r--r--libcrystfel/src/integer_matrix.c19
-rw-r--r--libcrystfel/src/integer_matrix.h8
-rw-r--r--libcrystfel/src/integration.c334
-rw-r--r--libcrystfel/src/integration.h22
-rw-r--r--libcrystfel/src/libcrystfel-version.c.cmake.in4
-rw-r--r--libcrystfel/src/libcrystfel-version.c.in6
-rw-r--r--libcrystfel/src/libcrystfel-version.h5
-rw-r--r--libcrystfel/src/peakfinder8.c59
-rw-r--r--libcrystfel/src/peakfinder8.h9
-rw-r--r--libcrystfel/src/peaks.c253
-rw-r--r--libcrystfel/src/peaks.h32
-rw-r--r--libcrystfel/src/predict-refine.c128
-rw-r--r--libcrystfel/src/predict-refine.h9
-rw-r--r--libcrystfel/src/rational.c18
-rw-r--r--libcrystfel/src/rational.h6
-rw-r--r--libcrystfel/src/reflist-utils.c12
-rw-r--r--libcrystfel/src/reflist-utils.h8
-rw-r--r--libcrystfel/src/reflist.c39
-rw-r--r--libcrystfel/src/reflist.h12
-rw-r--r--libcrystfel/src/spectrum.c2
-rw-r--r--libcrystfel/src/spectrum.h6
-rw-r--r--libcrystfel/src/stream.c1256
-rw-r--r--libcrystfel/src/stream.h139
-rw-r--r--libcrystfel/src/symmetry.c19
-rw-r--r--libcrystfel/src/symmetry.h7
-rw-r--r--libcrystfel/src/thread-pool.c5
-rw-r--r--libcrystfel/src/thread-pool.h10
-rw-r--r--libcrystfel/src/utils.c170
-rw-r--r--libcrystfel/src/utils.h73
-rw-r--r--meson.build309
-rwxr-xr-xscripts/check-near-bragg107
-rwxr-xr-xscripts/check-peak-detection153
-rwxr-xr-xscripts/display-hdf519
-rwxr-xr-xscripts/make-csplit58
-rwxr-xr-xscripts/random-image14
-rwxr-xr-xscripts/sequence-image8
-rw-r--r--src/ambigator.c49
-rw-r--r--src/cell_explorer.c204
-rw-r--r--src/cell_tool.c23
-rw-r--r--src/check_hkl.c406
-rw-r--r--src/cl-utils.c5
-rw-r--r--src/cl-utils.h6
-rw-r--r--src/compare_hkl.c1196
-rw-r--r--src/crystfel_gui.c1260
-rw-r--r--src/crystfel_gui.h75
-rw-r--r--src/crystfelimageview.c1061
-rw-r--r--src/crystfelimageview.h132
-rw-r--r--src/crystfelindexingopts.c1139
-rw-r--r--src/crystfelindexingopts.h166
-rw-r--r--src/crystfelmergeopts.c613
-rw-r--r--src/crystfelmergeopts.h133
-rw-r--r--src/crystfelsymmetryselector.c90
-rw-r--r--src/crystfelsymmetryselector.h75
-rw-r--r--src/diffraction-gpu.c21
-rw-r--r--src/diffraction-gpu.h4
-rw-r--r--src/diffraction.c17
-rw-r--r--src/diffraction.h4
-rw-r--r--src/dw-hdfsee.c3168
-rw-r--r--src/dw-hdfsee.h167
-rw-r--r--src/geoptimiser.c388
-rw-r--r--src/get_hkl.c22
-rw-r--r--src/gtk-util-routines.c128
-rw-r--r--src/gtk-util-routines.h44
-rw-r--r--src/gui_ambi.c568
-rw-r--r--src/gui_ambi.h47
-rw-r--r--src/gui_backend_local.c704
-rw-r--r--src/gui_backend_local.h36
-rw-r--r--src/gui_backend_slurm.c1077
-rw-r--r--src/gui_backend_slurm.h36
-rw-r--r--src/gui_export.c742
-rw-r--r--src/gui_export.h39
-rw-r--r--src/gui_fom.c677
-rw-r--r--src/gui_fom.h (renamed from src/hdfsee.h)24
-rw-r--r--src/gui_import.c608
-rw-r--r--src/gui_import.h38
-rw-r--r--src/gui_index.c876
-rw-r--r--src/gui_index.h56
-rw-r--r--src/gui_merge.c528
-rw-r--r--src/gui_merge.h49
-rw-r--r--src/gui_peaksearch.c527
-rw-r--r--src/gui_peaksearch.h41
-rw-r--r--src/gui_project.c1349
-rw-r--r--src/gui_project.h373
-rw-r--r--src/hdfsee-render.c419
-rw-r--r--src/hdfsee-render.h53
-rw-r--r--src/hdfsee.c344
-rw-r--r--src/im-sandbox.c217
-rw-r--r--src/im-sandbox.h2
-rw-r--r--src/im-zmq.c373
-rw-r--r--src/im-zmq.h16
-rw-r--r--src/indexamajig.c261
-rw-r--r--src/list_events.c65
-rw-r--r--src/list_tmp.h4
-rw-r--r--src/make_pixelmap.c148
-rw-r--r--src/merge.c4
-rw-r--r--src/merge.h4
-rw-r--r--src/multihistogram.c4
-rw-r--r--src/multihistogram.h4
-rw-r--r--src/partial_sim.c237
-rw-r--r--src/partialator.c256
-rw-r--r--src/pattern_sim.c371
-rw-r--r--src/pattern_sim.h6
-rw-r--r--src/post-refinement.c28
-rw-r--r--src/post-refinement.h4
-rw-r--r--src/process_hkl.c241
-rw-r--r--src/process_image.c306
-rw-r--r--src/process_image.h33
-rw-r--r--src/rejection.c2
-rw-r--r--src/rejection.h2
-rw-r--r--src/render_hkl.c50
-rw-r--r--src/render_hkl.h4
-rw-r--r--src/scaling.c12
-rw-r--r--src/scaling.h2
-rw-r--r--src/time-accounts.c2
-rw-r--r--src/time-accounts.h2
-rw-r--r--src/version.c.cmake.in13
-rw-r--r--src/version.c.in17
-rw-r--r--src/version.h5
-rw-r--r--src/whirligig.c46
-rw-r--r--tests/CMakeLists.txt119
-rw-r--r--tests/ambi_check.c5
-rw-r--r--tests/cell_check.c5
-rw-r--r--tests/cellcompare_check.c275
-rw-r--r--tests/centering_check.c5
-rw-r--r--tests/ev_enum1.c89
-rw-r--r--tests/ev_enum1.geom12
-rw-r--r--tests/ev_enum1.h5bin0 -> 46504 bytes
-rw-r--r--tests/ev_enum2.c73
-rw-r--r--tests/ev_enum2.geom14
-rw-r--r--tests/ev_enum2.h5bin0 -> 9064 bytes
-rw-r--r--tests/ev_enum3.c68
-rw-r--r--tests/ev_enum3.geom12
-rw-r--r--tests/ev_enum3.h5bin0 -> 4752 bytes
-rw-r--r--tests/evparse1.c69
-rw-r--r--tests/evparse2.c61
-rw-r--r--tests/evparse3.c53
-rw-r--r--tests/evparse4.c63
-rw-r--r--tests/evparse5.c59
-rw-r--r--tests/evparse6.c54
-rw-r--r--tests/evparse7.c53
-rw-r--r--tests/gen-ev-test.py48
-rw-r--r--tests/gpu_sim_check.c120
-rw-r--r--tests/gpu_sim_check.geom28
-rw-r--r--tests/histogram.c4
-rw-r--r--tests/histogram.h4
-rw-r--r--tests/integration_check.c78
-rw-r--r--tests/list_check.c5
-rw-r--r--tests/meson.build123
-rwxr-xr-xtests/partialator_merge_check_117
-rwxr-xr-xtests/partialator_merge_check_217
-rwxr-xr-xtests/partialator_merge_check_317
-rw-r--r--tests/polarisation_check.c198
-rw-r--r--tests/prediction_gradient_check.c100
-rwxr-xr-xtests/process_hkl_check_113
-rwxr-xr-xtests/process_hkl_check_213
-rwxr-xr-xtests/process_hkl_check_313
-rwxr-xr-xtests/process_hkl_check_413
-rw-r--r--tests/prof2d_check.c65
-rw-r--r--tests/rational_check.c5
-rw-r--r--tests/ring_check.c92
-rw-r--r--tests/scaling_check.c5
-rw-r--r--tests/spectrum_check.c5
-rw-r--r--tests/stream_read.c62
-rw-r--r--tests/symmetry_check.c5
-rw-r--r--tests/test.stream12642
-rw-r--r--tests/transformation_check.c5
-rw-r--r--tests/wavelength_geom.c67
-rw-r--r--tests/wavelength_geom.h5bin0 -> 7048 bytes
-rw-r--r--tests/wavelength_geom1.geom11
-rw-r--r--tests/wavelength_geom10.geom11
-rw-r--r--tests/wavelength_geom11.geom11
-rw-r--r--tests/wavelength_geom12.geom11
-rw-r--r--tests/wavelength_geom2.geom11
-rw-r--r--tests/wavelength_geom3.geom11
-rw-r--r--tests/wavelength_geom4.geom11
-rw-r--r--tests/wavelength_geom5.geom11
-rw-r--r--tests/wavelength_geom6.geom11
-rw-r--r--tests/wavelength_geom7.geom11
-rw-r--r--tests/wavelength_geom8.geom11
-rw-r--r--tests/wavelength_geom9.geom11
255 files changed, 43496 insertions, 18605 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 00000000..29a556ae
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,19 @@
+build-cmake:
+ image: fedora:32
+ script:
+ - dnf group install -y 'Development Tools'
+ - dnf install -y hdf5-devel gsl-devel flex bison
+ - dnf install -y gtk3-devel cairo-devel pango-devel gdk-pixbuf2-devel fftw-devel ncurses-devel libpng-devel diffutils
+ - dnf install -y cmake
+ - mkdir build && cd build && cmake .. && make
+ - make test
+
+build-meson:
+ image: fedora:32
+ script:
+ - dnf group install -y 'Development Tools'
+ - dnf install -y hdf5-devel gsl-devel flex bison
+ - dnf install -y gtk3-devel cairo-devel pango-devel gdk-pixbuf2-devel fftw-devel ncurses-devel libpng-devel diffutils
+ - dnf install -y meson
+ - meson build && ninja -C build
+ - ninja -C build test
diff --git a/AUTHORS b/AUTHORS
index b00a2a08..8b49d146 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,23 +1,3 @@
-Funding acknowledgements
-------------------------
-
-Development of CrystFEL is primarily funded by the Helmholtz Association via
-programme-oriented funds.
-
-Additional funding for CrystFEL is provided by "X-Probe", a project of the
-European Union's 2020 Research and Innovation Program Under the Marie
-Skłodowska-Curie grant agreement 637295 (2015-2018).
-
-Additional funding for CrystFEL is provided by the BMBF German-Russian
-Cooperation "SyncFELMed", grant 05K14CHA (2014-2017).
-
-Past funding for CrystFEL has been received from BioStruct-X, a project funded
-by the Seventh Framework Programme (FP7) of the European Commission.
-
-
-Contributors
-------------
-
* Thomas White <taw@physics.org>
Lead author, architecture, "vision" and so on.
diff --git a/CMake/FindFDIP.cmake b/CMake/FindFDIP.cmake
deleted file mode 100644
index 3306b483..00000000
--- a/CMake/FindFDIP.cmake
+++ /dev/null
@@ -1,25 +0,0 @@
-# - Find FDIP
-# Find the native FDIP includes and library
-#
-# FDIP_INCLUDES - where to find streakFinder.h
-# FDIP_LIBRARIES - List of libraries when using FDIP.
-# FDIP_FOUND - True if FDIP found.
-
-if (FDIP_INCLUDES)
- # Already in cache, be silent
- set (FDIP_FIND_QUIETLY TRUE)
-endif (FDIP_INCLUDES)
-
-find_path (FDIP_INCLUDES fastDiffractionImageProcessing/streakFinder.h
- PATHS
- ${CMAKE_INSTALL_PREFIX}/include)
-
-find_library (FDIP_LIBRARIES fastDiffractionImageProcessing
- PATHS
- ${CMAKE_INSTALL_PREFIX}/lib)
-
-# handle the QUIETLY and REQUIRED arguments and set FDIP_FOUND to TRUE if
-# all listed variables are TRUE
-include (FindPackageHandleStandardArgs)
-set(FDIP_INCLUDES ${FDIP_INCLUDES};${FDIP_INCLUDES}/fastDiffractionImageProcessing)
-find_package_handle_standard_args (FDIP DEFAULT_MSG FDIP_LIBRARIES FDIP_INCLUDES)
diff --git a/CMake/FindNBP.cmake b/CMake/FindNBP.cmake
deleted file mode 100644
index 052f16df..00000000
--- a/CMake/FindNBP.cmake
+++ /dev/null
@@ -1,24 +0,0 @@
-# - Find NBP - numericalBraggPrediction
-# Find the native NBP includes and library
-#
-# NBP_INCLUDES - where to find IndexerBase.h
-# NBP_LIBRARIES - List of libraries when using NBP.
-# NBP_FOUND - True if NBP found.
-
-if (NBP_INCLUDES)
- # Already in cache, be silent
- set (NBP_FIND_QUIETLY TRUE)
-endif (NBP_INCLUDES)
-
-find_path (NBP_INCLUDES numericalBraggPrediction/ProjectionCalculation.h
- PATHS
- ${CMAKE_INSTALL_PREFIX}/include)
-
-find_library (NBP_LIBRARIES numericalBraggPrediction
- PATHS
- ${CMAKE_INSTALL_PREFIX}/lib)
-
-# handle the QUIETLY and REQUIRED arguments and set NBP_FOUND to TRUE if
-# all listed variables are TRUE
-include (FindPackageHandleStandardArgs)
-find_package_handle_standard_args (NBP DEFAULT_MSG NBP_LIBRARIES NBP_INCLUDES)
diff --git a/CMake/FindPINKINDEXER.cmake b/CMake/FindPINKINDEXER.cmake
deleted file mode 100644
index 3c217ff9..00000000
--- a/CMake/FindPINKINDEXER.cmake
+++ /dev/null
@@ -1,24 +0,0 @@
-# - Find PINKINDEXER
-# Find the native PINKINDEXER includes and library
-#
-# PINKINDEXER_INCLUDES - where to find IndexerBase.h
-# PINKINDEXER_LIBRARIES - List of libraries when using PINKINDEXER.
-# PINKINDEXER_FOUND - True if PINKINDEXER found.
-
-if (PINKINDEXER_INCLUDES)
- # Already in cache, be silent
- set (PINKINDEXER_FIND_QUIETLY TRUE)
-endif (PINKINDEXER_INCLUDES)
-
-find_path (PINKINDEXER_INCLUDES pinkIndexer/PinkIndexer.h
- PATHS
- ${CMAKE_INSTALL_PREFIX}/include)
-
-find_library (PINKINDEXER_LIBRARIES pinkIndexer
- PATHS
- ${CMAKE_INSTALL_PREFIX}/lib)
-
-# handle the QUIETLY and REQUIRED arguments and set PINKINDEXER_FOUND to TRUE if
-# all listed variables are TRUE
-include (FindPackageHandleStandardArgs)
-find_package_handle_standard_args (PINKINDEXER DEFAULT_MSG PINKINDEXER_LIBRARIES PINKINDEXER_INCLUDES)
diff --git a/CMake/FindXGANDALF.cmake b/CMake/FindXGANDALF.cmake
deleted file mode 100644
index 8138da77..00000000
--- a/CMake/FindXGANDALF.cmake
+++ /dev/null
@@ -1,24 +0,0 @@
-# - Find XGANDALF
-# Find the native XGANDALF includes and library
-#
-# XGANDALF_INCLUDES - where to find IndexerBase.h
-# XGANDALF_LIBRARIES - List of libraries when using XGANDALF.
-# XGANDALF_FOUND - True if XGANDALF found.
-
-if (XGANDALF_INCLUDES)
- # Already in cache, be silent
- set (XGANDALF_FIND_QUIETLY TRUE)
-endif (XGANDALF_INCLUDES)
-
-find_path (XGANDALF_INCLUDES xgandalf/IndexerBase.h
- PATHS
- ${CMAKE_INSTALL_PREFIX}/include)
-
-find_library (XGANDALF_LIBRARIES xgandalf
- PATHS
- ${CMAKE_INSTALL_PREFIX}/lib)
-
-# handle the QUIETLY and REQUIRED arguments and set XGANDALF_FOUND to TRUE if
-# all listed variables are TRUE
-include (FindPackageHandleStandardArgs)
-find_package_handle_standard_args (XGANDALF DEFAULT_MSG XGANDALF_LIBRARIES XGANDALF_INCLUDES)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d51d5dc6..7f6d8a72 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,10 +14,14 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake")
find_package(HDF5 REQUIRED COMPONENTS C)
find_package(Threads REQUIRED)
find_package(GSL REQUIRED)
-find_package(TIFF)
find_package(OpenCL)
find_package(PkgConfig)
+# Find SLURM
+set(CMAKE_REQUIRED_LIBRARIES "-lslurm")
+check_symbol_exists(slurm_api_version "slurm/slurm.h" HAVE_SLURM)
+unset(CMAKE_REQUIRED_LIBRARIES)
+
# Request HDF5 1.10-style API (can't use 1.12-style yet)
add_definitions(-DH5_USE_110_API)
@@ -41,42 +45,38 @@ else ()
message(STATUS "ZMQ not found.")
endif ()
-pkg_search_module(GTK gtk+-3.0)
-if (NOT GTK_FOUND)
-
- # No GTK3. Try GTK2?
- pkg_search_module(GTK gtk+-2.0)
- if (GTK_FOUND)
- message(STATUS "Using GTK 2")
- pkg_search_module(GDK gdk-2.0)
- endif ()
-
-else ()
+# Find out where forkpty() is declared
+set(CMAKE_REQUIRED_LIBRARIES "-lutil")
+check_symbol_exists(forkpty "pty.h" HAVE_FORKPTY_PTY_H)
+check_symbol_exists(forkpty "util.h" HAVE_FORKPTY_UTIL_H)
+unset(CMAKE_REQUIRED_LIBRARIES)
+if(HAVE_FORKPTY_PTY_H)
+ message(STATUS "Found forkpty() in pty.h")
+elseif(HAVE_FORKPTY_UTIL_H)
+ message(STATUS "Found forkpty() in util.h")
+else()
+ message(SEND_ERROR "Couldn't find forkpty()")
+endif()
- message(STATUS "Using GTK 3")
+pkg_search_module(GTK gtk+-3.0)
+if (GTK_FOUND)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
- pkg_search_module(GDK gdk-3.0)
-
+ link_directories(${GTK_LIBRARY_DIRS})
endif ()
# If no version of GTK was found, try for GDK
if (NOT GTK_FOUND)
- message(STATUS "GTK not found. hdfsee and cell_explorer will not be compiled")
+ message(STATUS "GTK3 not found. GUI parts will not be compiled")
message(STATUS "Looking separately for GDK")
pkg_search_module(GDK gdk-3.0)
if (NOT GDK_FOUND)
- pkg_search_module(GDK gdk-2.0)
- if (GDK_FOUND)
- message(STATUS "Using GDK 2")
- endif()
- else ()
- message(STATUS "Using GDK 3")
+ message(STATUS "GDK not found.")
endif()
endif()
-link_directories(${GTK_LIBRARY_DIRS})
pkg_search_module(CAIRO cairo)
pkg_search_module(GDKPIXBUF gdk-pixbuf-2.0)
+pkg_search_module(LIBCCP4 libccp4c)
include(CheckCCompilerFlag)
check_c_compiler_flag("-fdiagnostics-color=always" HAVE_DIAG_COLOR)
@@ -107,20 +107,20 @@ else ()
else ()
message(STATUS "This is a packaged release version")
endif ()
-
endif ()
+configure_file(src/version.c.cmake.in version.c)
include(CheckIncludeFile)
include(CheckLibraryExists)
set(HAVE_CAIRO ${CAIRO_FOUND})
-set(HAVE_TIFF ${TIFF_FOUND})
set(HAVE_GTK ${GTK_FOUND})
set(HAVE_OPENCL ${OpenCL_FOUND})
set(HAVE_GDKPIXBUF ${GDKPIXBUF_FOUND})
set(HAVE_GDK ${GDK_FOUND})
set(HAVE_MSGPACK ${MSGPACK_FOUND})
set(HAVE_ZMQ ${ZMQ_FOUND})
+set(HAVE_LIBCCP4 ${LIBCCP4_FOUND})
set(PACKAGE_VERSION ${PROJECT_VERSION})
@@ -145,10 +145,10 @@ check_symbol_exists(clock_gettime "time.h" HAVE_CLOCK_GETTIME)
# Check for argp
check_symbol_exists(argp_parse "argp.h" HAVE_ARGP)
-if (!HAVE_ARGP)
- message(ERROR "argp not found. If you're building on Mac OS using libraries"
- "from Homebrew, install argp-standalone.")
-endif (!HAVE_ARGP)
+if (NOT HAVE_ARGP)
+ message(ERROR " argp not found. If you're building on Mac OS using libraries"
+ " from Homebrew, install argp-standalone.")
+endif (NOT HAVE_ARGP)
# Add the libcrystfel target
add_subdirectory(libcrystfel)
@@ -164,11 +164,16 @@ add_subdirectory(tests)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/scripts
DESTINATION ${CMAKE_INSTALL_DOCDIR})
+# Misc resources
+install(FILES ${CMAKE_SOURCE_DIR}/data/crystfel.svg
+ DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps)
+
# ----------------------------------------------------------------------
# partial_sim
set(PARTIAL_SIM_SOURCES src/partial_sim.c)
-add_executable(partial_sim ${PARTIAL_SIM_SOURCES})
+add_executable(partial_sim ${PARTIAL_SIM_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/version.c)
target_include_directories(partial_sim PRIVATE ${COMMON_INCLUDES})
target_link_libraries(partial_sim ${COMMON_LIBRARIES})
list(APPEND CRYSTFEL_EXECUTABLES partial_sim)
@@ -182,7 +187,8 @@ if(HAVE_OPENCL)
set(PATTERN_SIM_OPENCL_SOURCES src/cl-utils.c src/diffraction-gpu.c)
endif(HAVE_OPENCL)
-add_executable(pattern_sim ${PATTERN_SIM_SOURCES} ${PATTERN_SIM_OPENCL_SOURCES})
+add_executable(pattern_sim ${PATTERN_SIM_SOURCES} ${PATTERN_SIM_OPENCL_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/version.c)
target_include_directories(pattern_sim PRIVATE ${COMMON_INCLUDES})
target_link_libraries(pattern_sim ${COMMON_LIBRARIES} ${HDF5_C_LIBRARIES})
@@ -194,33 +200,14 @@ endif(HAVE_OPENCL)
list(APPEND CRYSTFEL_EXECUTABLES pattern_sim)
# ----------------------------------------------------------------------
-# hdfsee
-
-if (GTK_FOUND)
-
- set(HDFSEE_SOURCES src/hdfsee.c src/dw-hdfsee.c src/hdfsee-render.c)
- add_executable(hdfsee ${HDFSEE_SOURCES})
-
- target_include_directories(hdfsee PRIVATE ${COMMON_INCLUDES} ${GTK_INCLUDE_DIRS})
- target_link_libraries(hdfsee ${COMMON_LIBRARIES} ${GTK_LIBRARIES})
-
- if (TIFF_FOUND)
- target_include_directories(hdfsee PRIVATE ${TIFF_INCLUDE_DIRS})
- target_link_libraries(hdfsee ${TIFF_LIBRARIES})
- endif (TIFF_FOUND)
-
- list(APPEND CRYSTFEL_EXECUTABLES hdfsee)
-
-endif (GTK_FOUND)
-
-# ----------------------------------------------------------------------
# cell_explorer
if (GTK_FOUND)
set(CELL_EXPLORER_SOURCES src/cell_explorer.c src/multihistogram.c)
- add_executable(cell_explorer ${CELL_EXPLORER_SOURCES})
+ add_executable(cell_explorer ${CELL_EXPLORER_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/version.c)
target_include_directories(cell_explorer PRIVATE ${COMMON_INCLUDES} ${GTK_INCLUDE_DIRS})
target_link_libraries(cell_explorer ${COMMON_LIBRARIES} ${GTK_LIBRARIES})
@@ -234,7 +221,8 @@ endif (GTK_FOUND)
if (CAIRO_FOUND)
set(RENDER_HKL_SOURCES src/render_hkl.c)
- add_executable(render_hkl ${RENDER_HKL_SOURCES})
+ add_executable(render_hkl ${RENDER_HKL_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/version.c)
target_include_directories(render_hkl PRIVATE ${COMMON_INCLUDES} ${CAIRO_INCLUDE_DIRS})
target_link_libraries(render_hkl ${COMMON_LIBRARIES} ${CAIRO_LIBRARIES})
@@ -247,7 +235,8 @@ endif (CAIRO_FOUND)
# process_hkl
set(PROCESS_HKL_SOURCES src/process_hkl.c)
-add_executable(process_hkl ${PROCESS_HKL_SOURCES})
+add_executable(process_hkl ${PROCESS_HKL_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/version.c)
target_include_directories(process_hkl PRIVATE ${COMMON_INCLUDES})
target_link_libraries(process_hkl ${COMMON_LIBRARIES})
list(APPEND CRYSTFEL_EXECUTABLES process_hkl)
@@ -256,7 +245,8 @@ list(APPEND CRYSTFEL_EXECUTABLES process_hkl)
# list_events
set(LIST_EVENTS_SOURCES src/list_events.c)
-add_executable(list_events ${LIST_EVENTS_SOURCES})
+add_executable(list_events ${LIST_EVENTS_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/version.c)
target_include_directories(list_events PRIVATE ${COMMON_INCLUDES})
target_link_libraries(list_events ${COMMON_LIBRARIES})
list(APPEND CRYSTFEL_EXECUTABLES list_events)
@@ -271,7 +261,8 @@ if ( ZMQ_FOUND AND MSGPACK_FOUND )
list(APPEND INDEXAMAJIG_SOURCES src/im-zmq.c)
endif ()
-add_executable(indexamajig ${INDEXAMAJIG_SOURCES})
+add_executable(indexamajig ${INDEXAMAJIG_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/version.c)
target_include_directories(indexamajig PRIVATE ${COMMON_INCLUDES})
target_link_libraries(indexamajig ${COMMON_LIBRARIES})
list(APPEND CRYSTFEL_EXECUTABLES indexamajig)
@@ -286,7 +277,8 @@ endif ()
# get_hkl
set(GET_HKL_SOURCES src/get_hkl.c)
-add_executable(get_hkl ${GET_HKL_SOURCES})
+add_executable(get_hkl ${GET_HKL_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/version.c)
target_include_directories(get_hkl PRIVATE ${COMMON_INCLUDES})
target_link_libraries(get_hkl ${COMMON_LIBRARIES})
list(APPEND CRYSTFEL_EXECUTABLES get_hkl)
@@ -295,7 +287,8 @@ list(APPEND CRYSTFEL_EXECUTABLES get_hkl)
# compare_hkl
set(COMPARE_HKL_SOURCES src/compare_hkl.c)
-add_executable(compare_hkl ${COMPARE_HKL_SOURCES})
+add_executable(compare_hkl ${COMPARE_HKL_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/version.c)
target_include_directories(compare_hkl PRIVATE ${COMMON_INCLUDES})
target_link_libraries(compare_hkl ${COMMON_LIBRARIES})
list(APPEND CRYSTFEL_EXECUTABLES compare_hkl)
@@ -304,7 +297,8 @@ list(APPEND CRYSTFEL_EXECUTABLES compare_hkl)
# check_hkl
set(CHECK_HKL_SOURCES src/check_hkl.c)
-add_executable(check_hkl ${CHECK_HKL_SOURCES})
+add_executable(check_hkl ${CHECK_HKL_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/version.c)
target_include_directories(check_hkl PRIVATE ${COMMON_INCLUDES})
target_link_libraries(check_hkl ${COMMON_LIBRARIES})
list(APPEND CRYSTFEL_EXECUTABLES check_hkl)
@@ -314,7 +308,8 @@ list(APPEND CRYSTFEL_EXECUTABLES check_hkl)
set(PARTIALATOR_SOURCES src/partialator.c src/post-refinement.c src/merge.c
src/rejection.c src/scaling.c)
-add_executable(partialator ${PARTIALATOR_SOURCES})
+add_executable(partialator ${PARTIALATOR_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/version.c)
target_include_directories(partialator PRIVATE ${COMMON_INCLUDES})
target_link_libraries(partialator ${COMMON_LIBRARIES})
list(APPEND CRYSTFEL_EXECUTABLES partialator)
@@ -323,7 +318,8 @@ list(APPEND CRYSTFEL_EXECUTABLES partialator)
# ambigator
set(AMBIGATOR_SOURCES src/ambigator.c)
-add_executable(ambigator ${AMBIGATOR_SOURCES})
+add_executable(ambigator ${AMBIGATOR_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/version.c)
target_include_directories(ambigator PRIVATE ${COMMON_INCLUDES})
target_link_libraries(ambigator ${COMMON_LIBRARIES} ${HDF5_C_LIBRARIES})
list(APPEND CRYSTFEL_EXECUTABLES ambigator)
@@ -331,39 +327,43 @@ list(APPEND CRYSTFEL_EXECUTABLES ambigator)
# ----------------------------------------------------------------------
# geoptimiser
-set(GEOPTIMISER_SOURCES src/geoptimiser.c src/hdfsee-render.c)
-add_executable(geoptimiser ${GEOPTIMISER_SOURCES})
-target_include_directories(geoptimiser PRIVATE ${COMMON_INCLUDES})
-target_link_libraries(geoptimiser ${COMMON_LIBRARIES})
-list(APPEND CRYSTFEL_EXECUTABLES geoptimiser)
-
-# Add features one by one so that #ifdef HAVE_XX//#include XX.h always works
-# If Cairo, gdk-pixbuf and GDK are all found, geoptimiser will add PNG support
-if (CAIRO_FOUND)
- target_include_directories(geoptimiser PRIVATE ${CAIRO_INCLUDE_DIRS})
- target_link_libraries(geoptimiser ${CAIRO_LIBRARIES})
-endif (CAIRO_FOUND)
-
-if (GDKPIXBUF_FOUND)
- target_include_directories(geoptimiser PRIVATE ${GDKPIXBUF_INCLUDE_DIRS})
- target_link_libraries(geoptimiser ${GDKPIXBUF_LIBRARIES})
-endif (GDKPIXBUF_FOUND)
-
-if (GDK_FOUND)
- target_include_directories(geoptimiser PRIVATE ${GDK_INCLUDE_DIRS})
- target_link_libraries(geoptimiser ${GDK_LIBRARIES})
-endif (GDK_FOUND)
-
-if (TIFF_FOUND)
- target_include_directories(geoptimiser PRIVATE ${TIFF_INCLUDE_DIRS})
- target_link_libraries(geoptimiser ${TIFF_LIBRARIES})
-endif (TIFF_FOUND)
+ # FIXME!
+#if (GDKPIXBUF_FOUND)
+# target_include_directories(${PROJECT_NAME} PRIVATE ${GDKPIXBUF_INCLUDE_DIRS})
+# target_link_libraries(${PROJECT_NAME} PRIVATE ${GDKPIXBUF_LIBRARIES})
+#endif (GDKPIXBUF_FOUND)
+
+# FIXME: Restore!
+#set(GEOPTIMISER_SOURCES src/geoptimiser.c)
+#add_executable(geoptimiser ${GEOPTIMISER_SOURCES}
+# ${CMAKE_CURRENT_BINARY_DIR}/version.c)
+#target_include_directories(geoptimiser PRIVATE ${COMMON_INCLUDES})
+#target_link_libraries(geoptimiser ${COMMON_LIBRARIES})
+#list(APPEND CRYSTFEL_EXECUTABLES geoptimiser)
+#
+## Add features one by one so that #ifdef HAVE_XX//#include XX.h always works
+## If Cairo, gdk-pixbuf and GDK are all found, geoptimiser will add PNG support
+#if (CAIRO_FOUND)
+# target_include_directories(geoptimiser PRIVATE ${CAIRO_INCLUDE_DIRS})
+# target_link_libraries(geoptimiser ${CAIRO_LIBRARIES})
+#endif (CAIRO_FOUND)
+#
+#if (GDKPIXBUF_FOUND)
+# target_include_directories(geoptimiser PRIVATE ${GDKPIXBUF_INCLUDE_DIRS})
+# target_link_libraries(geoptimiser ${GDKPIXBUF_LIBRARIES})
+#endif (GDKPIXBUF_FOUND)
+#
+#if (GDK_FOUND)
+# target_include_directories(geoptimiser PRIVATE ${GDK_INCLUDE_DIRS})
+# target_link_libraries(geoptimiser ${GDK_LIBRARIES})
+#endif (GDK_FOUND)
# ----------------------------------------------------------------------
# whirligig
set(WHIRLIGIG_SOURCES src/whirligig.c)
-add_executable(whirligig ${WHIRLIGIG_SOURCES})
+add_executable(whirligig ${WHIRLIGIG_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/version.c)
target_include_directories(whirligig PRIVATE ${COMMON_INCLUDES})
target_link_libraries(whirligig ${COMMON_LIBRARIES})
list(APPEND CRYSTFEL_EXECUTABLES whirligig)
@@ -372,7 +372,8 @@ list(APPEND CRYSTFEL_EXECUTABLES whirligig)
# make_pixelmap
set(MAKE_PIXELMAP_SOURCES src/make_pixelmap.c)
-add_executable(make_pixelmap ${MAKE_PIXELMAP_SOURCES})
+add_executable(make_pixelmap ${MAKE_PIXELMAP_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/version.c)
target_include_directories(make_pixelmap PRIVATE ${COMMON_INCLUDES})
target_link_libraries(make_pixelmap ${COMMON_LIBRARIES} ${HDF5_C_LIBRARIES})
list(APPEND CRYSTFEL_EXECUTABLES make_pixelmap)
@@ -381,12 +382,43 @@ list(APPEND CRYSTFEL_EXECUTABLES make_pixelmap)
# cell_tool
set(CELL_TOOL_SOURCES src/cell_tool.c)
-add_executable(cell_tool ${CELL_TOOL_SOURCES})
+add_executable(cell_tool ${CELL_TOOL_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/version.c)
target_include_directories(cell_tool PRIVATE ${COMMON_INCLUDES})
target_link_libraries(cell_tool ${COMMON_LIBRARIES})
list(APPEND CRYSTFEL_EXECUTABLES cell_tool)
# ----------------------------------------------------------------------
+# crystfel (main graphical user interface)
+
+if (GTK_FOUND)
+
+ set(CRYSTFEL_GUI_SOURCES src/crystfel_gui.c src/crystfelimageview.c
+ src/gui_peaksearch.c src/gui_index.c src/gui_merge.c src/gui_backend_local.c
+ src/gui_project.c src/crystfelindexingopts.c src/crystfelmergeopts.c
+ src/crystfelsymmetryselector.c src/gtk-util-routines.c src/gui_fom.c
+ src/gui_export.c src/gui_ambi.c src/gui_import.c)
+
+ if (HAVE_SLURM)
+ set(CRYSTFEL_GUI_SOURCES ${CRYSTFEL_GUI_SOURCES} src/gui_backend_slurm.c)
+ endif (HAVE_SLURM)
+
+ add_executable(crystfel ${CRYSTFEL_GUI_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/version.c)
+ target_include_directories(crystfel PRIVATE ${COMMON_INCLUDES} ${GTK_INCLUDE_DIRS}
+ ${LIBCCP4_INCLUDES})
+ target_link_libraries (crystfel ${COMMON_LIBRARIES} util ${GTK_LIBRARIES}
+ ${LIBCCP4_LIBRARIES})
+
+ if (HAVE_SLURM)
+ target_link_libraries(crystfel slurm)
+ endif (HAVE_SLURM)
+
+ list(APPEND CRYSTFEL_EXECUTABLES crystfel)
+
+endif (GTK_FOUND)
+
+# ----------------------------------------------------------------------
# Install targets
set_target_properties(${CRYSTFEL_EXECUTABLES}
@@ -408,7 +440,6 @@ install(FILES
doc/man/compare_hkl.1
doc/man/geoptimiser.1
doc/man/get_hkl.1
- doc/man/hdfsee.1
doc/man/indexamajig.1
doc/man/list_events.1
doc/man/partialator.1
diff --git a/README b/README
deleted file mode 100644
index d74ea8c6..00000000
--- a/README
+++ /dev/null
@@ -1,208 +0,0 @@
-CrystFEL - Data processing for serial crystallography
------------------------------------------------------
-
-Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
- a research centre of the Helmholtz Association.
-
-Authors:
- Thomas White <taw@physics.org>
- Richard Kirian <rkirian@asu.edu>
- Kenneth Beyerlein <kenneth.beyerlein@desy.de>
- Andrew Aquila <andrew.aquila@cfel.de>
- Andrew Martin <andrew.martin@desy.de>
- Lorenzo Galli <lorenzo.galli@desy.de>
- Chun Hong Yoon <chun.hong.yoon@desy.de>
- Kenneth Beyerlein <kenneth.beyerlein@desy.de>
- Karol Nass <karol.nass@desy.de>
- Nadia Zatsepin <nadia.zatsepin@asu.edu>
- Anton Barty <anton.barty@desy.de>
- Cornelius Gati <cornelius.gati@desy.de>
- Fedor Chervinskii <fedor.chervinskii@gmail.com>
- Alexandra Tolstikova <alexandra.tolstikova@desy.de>
- Wolfgang Brehm <wolfgang.brehm@gmail.com>
- Valerio Mariani <valerio.mariani@desy.de>
- Parker de Waal <Parker.deWaal@vai.org>
- Takanori Nakane <nakane.t@gmail.com>
- Keitaro Yamashita <k.yamashita@spring8.or.jp>
- Mamoru Suzuki <mamoru.suzuki@protein.osaka-u.ac.jp>
- Thomas Grant <tgrant@hwi.buffalo.edu>
- Steve Aplin <steve.aplin@desy.de>
- Oleksandr Yefanov <oleksandr.yefanov@desy.de>
- Helen Ginn <helen@strubi.ox.ac.uk>
- Nicolas Riebesel <nicolas.riebesel@tuhh.de>
- Yaroslav Gevorkov <yaroslav.gevorkov@desy.de>
- Omri Mor <omor1@asu.edu>
-
---------------------------------------------------------------------------------
-
-CrystFEL is free software: you can redistribute it and/or modify it under the
-terms of the GNU General Public License as published by the Free Software
-Foundation, either version 3 of the License, or (at your option) any later
-version.
-
-CrystFEL is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-CrystFEL. If not, see <http://www.gnu.org/licenses/>.
-
---------------------------------------------------------------------------------
-
-CrystFEL is a suite of programs for processing (and simulating) Bragg
-diffraction data from "serial crystallography" experiments, often (but not
-always) performed using an X-ray Free-Electron Laser. Some of the particular
-characteristics of such data which call for a specialised software suite are:
-
-- The sliced, rather than integrated, measurement of intensity data. Many, if
- not all reflections are partially integrated.
-
-- Many patterns (thousands) are required - high throughput is needed.
-
-- The crystal orientations in each pattern are random and uncorrelated, meaning
- that:
-
-- Merging into lower symmetry point groups may require the resolution of
- indexing ambiguities.
-
-
-CrystFEL includes programs for simulating and processing patterns subject to the
-above characteristics. The main data processing pipeline is defined by four
-programs:
-
- - indexamajig, for bulk indexing and integration of diffraction patterns
-
- - process_hkl, for quickly merging per-pattern lists of intensities into
- a single reflection list
-
- - partialator, for merging patterns more accurately (and much more
- slowly) using scaling, partiality modelling and
- post refinement
-
- - ambigator, for resolving indexing ambiguities
-
-There are two tools for calculating figures of merit for reflection data:
-
- - compare_hkl, for figures of merit that involve comparing two sets of
- data, like CC* and R_split
-
- - check_hkl, for figures of merit based on only one set of data, like
- completeness, redundancy and twinning tests
-
-Three tools are provided for visualising data:
-
- - cell_explorer, for examining distributions of lattice parameters
-
- - hdfsee, an image viewer
-
- - render_hkl, for turning reflection lists into pretty graphics
-
-CrystFEL can also simulate data, e.g. for methods development:
-
- - pattern_sim, which performs a Fourier image calculation
-
- - partial_sim, which calculates reflection intensities based on a
- partiality calculation and optionally plots the peaks
- in an image
-
-There are also five utility programs:
-
- - get_hkl, for doing various simple operations on reflection lists such
- as expanding by symmetry or adding noise
-
- - cell_tool, for doing operations on unit cells such as applying
- transformations or looking for indexing ambiguities
-
- - geoptimiser, for refining detector geometry.
-
- - list_events, for creating event lists from multi-event files.
-
- - make_pixelmap, for creating HDF5 pixel map files for other programs
- like Cheetah and OnDA
-
- - whirligig, for finding multiple shots from single crystals.
-
-
-There is also a folder full of scripts for achieving many related tasks, such as
-file format conversion.
-
-Standard "man" pages are provided for documentation, or you can invoke any
-program with the argument "--help" to get a summary of options. There are some
-example geometry and beam description files in doc/examples, and API
-documentation created using Doxygen.
-
-
-Installation
-------------
-
-The terse installation instructions below should be enough if you're experienced
-with installing software from source. More detailed installation information is
-available on the website:
-https://www.desy.de/~twhite/crystfel/install.html
-
-Mandatory dependencies:
- - CMake 3.12 or later
- - HDF5 1.8.0 or later (1.10.0 or later preferred)
- - GNU Scientific Library (GSL)
- - Bison 2.6 or later
- - Flex
- - Zlib (1.2.3.5 or later preferred)
-
-"Optional" dependencies:
- - GTK2 or later (GTK3 preferred)
- - Cairo
- - Pango
- - gdk-pixbuf
- - NCurses
- - libPNG
- - libTIFF
- - FFTW3
- - XGandalf (https://stash.desy.de/users/gevorkov/repos/xgandalf)
-
-"Optional" run-time dependencies:
- - Mosflm (https://www.mrc-lmb.cam.ac.uk/mosflm/mosflm/)
- - DirAx (http://www.crystal.chem.uu.nl/distr/dirax/)
- - XDS (http://xds.mpimf-heidelberg.mpg.de/)
-
-Note that "optional" means that you *can* install CrystFEL without them, however
-your installation will lack important components such as the visualisation
-tools and certain indexing algorithms.
-
-For processing electron diffraction or wide-bandwidth X-ray data, you should
-also install PinkIndexer from:
-https://stash.desy.de/users/gevorkov/repos/pinkindexer
-
-Installation follows the normal CMake procedure:
-
-$ mkdir build
-$ cd build
-$ cmake ..
-$ make
-$ sudo make install
-
-If external libraries have been installed in non-standard locations, you can set
-the path like this, for example for Xgandalf:
- cmake -DXGANDALF_INCLUDES=/path/to/xgandalf/include \
- -DXGANDALF_LIBRARIES=/path/to/xgandalf/lib/libxgandalf.so
-
-The path to HDF5 can be set similarly:
- cmake -DHDF5_ROOT=/path/to/hdf5 (... /include, /lib etc)
-
-To install CrystFEL in a custom location, use:
- cmake -DCMAKE_INSTALL_PREFIX=/path/for/crystfel/installation
-
-
-Funding acknowledgements
-------------------------
-
-Development of CrystFEL is primarily funded by the Helmholtz Association.
-
-Partial funding for CrystFEL has previously been provided by:
-
-- "X-Probe", a project of the European Union's 2020 Research and Innovation
- Program Under the Marie Skłodowska-Curie grant agreement 637295 (2015-2018).
-
-- The BMBF German-Russian Cooperation "SyncFELMed", grant 05K14CHA (2014-2017).
-
-- BioStruct-X, a project funded by the Seventh Framework Programme (FP7) of the
- European Commission (2011-2016).
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..8306c030
--- /dev/null
+++ b/README.md
@@ -0,0 +1,134 @@
+CrystFEL - Data processing for serial crystallography
+=====================================================
+
+Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
+ a research centre of the Helmholtz Association.
+
+See AUTHORS for full details of contributors.
+
+Introduction
+------------
+
+CrystFEL is a suite of programs for processing (and simulating) Bragg
+diffraction data from "serial crystallography" experiments, often (but not
+always) performed using an X-ray Free-Electron Laser. Compared to rotation data,
+some of the particular characteristics of such data which call for a
+specialised software suite are:
+
+* The sliced, rather than integrated, measurement of intensity data. Many, if
+ not all reflections are partially integrated.
+
+* Many patterns (thousands) are required - high throughput is needed.
+
+* The crystal orientations in each pattern are random and uncorrelated.
+
+* Merging into lower symmetry point groups may require the resolution of
+ indexing ambiguities.
+
+
+Getting started
+---------------
+
+The best way to get started, after installation, is to run command ```crystfel```
+to start the graphical user interface.
+
+
+Installation
+------------
+
+CrystFEL installation is supported on GNU/Linux and Mac OS X. The terse
+installation instructions below should be enough if you're experienced with
+installing software from source. More detailed installation information is
+available [on the website](https://www.desy.de/~twhite/crystfel/install.html).
+
+Here are the mandatory dependencies - you cannot install CrystFEL without these:
+
+* Either [CMake](https://cmake.org/) 3.12 or later or [Meson](https://mesonbuild.com/) (Meson is preferred)
+* [HDF5](https://www.hdfgroup.org/downloads/hdf5/) 1.8.0 or later (1.10.0 or later is required for many recent data formats)
+* [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/)
+* [Zlib](https://www.zlib.net/) (1.2.3.5 or later preferred for better decompression speed)
+
+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:
+
+* GTK3 or later
+* Cairo
+* Pango
+* gdk-pixbuf
+* NCurses
+* libPNG
+* [libccp4](ftp://ftp.ccp4.ac.uk/opensource/)
+
+Note that all of the dependencies mentioned above (including libccp4) should be
+available from your Linux distribution's package manager, or from
+[Homebrew](https://brew.sh/) on Mac OS. You should not need to download and
+install any of them separately from source, and we emphatically recommend
+against trying to do so!
+
+Note that using the libraries from the full CCP4 suite is not recommended. CCP4
+includes so many other libraries that it becomes very difficult to link using
+the correct versions of everything.
+
+Processing data relies on indexing algorithms. The more of the following are
+installed, the better your experience will be:
+
+* [FFTW3](http://fftw.org/)
+* [XGandalf](https://stash.desy.de/users/gevorkov/repos/xgandalf)
+* [PinkIndexer](https://stash.desy.de/users/gevorkov/repos/pinkindexer)
+* [Mosflm](https://www.mrc-lmb.cam.ac.uk/mosflm/mosflm/)
+* [DirAx](http://www.crystal.chem.uu.nl/distr/dirax/)
+* [XDS](http://xds.mpimf-heidelberg.mpg.de/)
+
+Installation follows the normal CMake procedure:
+
+```
+$ mkdir build
+$ cd build
+$ cmake ..
+$ make
+$ sudo make install
+```
+
+Or, with Meson:
+
+```
+$ meson . build
+$ ninja -C build
+$ sudo ninja -C build install
+```
+
+
+Licence
+-------
+
+CrystFEL is free software: you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+CrystFEL is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+
+
+Funding acknowledgements
+------------------------
+
+Development of CrystFEL is primarily funded by the Helmholtz Association.
+
+Partial funding for CrystFEL has previously been provided by:
+
+- "X-Probe", a project of the European Union's 2020 Research and Innovation
+ Program Under the Marie Skłodowska-Curie grant agreement 637295 (2015-2018).
+
+- The BMBF German-Russian Cooperation "SyncFELMed", grant 05K14CHA (2014-2017).
+
+- BioStruct-X, a project funded by the Seventh Framework Programme (FP7) of the
+ European Commission (2011-2016).
+
diff --git a/config.h.cmake.in b/config.h.cmake.in
index 6d630f9e..a206adda 100644
--- a/config.h.cmake.in
+++ b/config.h.cmake.in
@@ -3,20 +3,11 @@
#cmakedefine HAVE_GTK
#cmakedefine HAVE_GDKPIXBUF
#cmakedefine HAVE_GDK
-#cmakedefine HAVE_TIFF
#cmakedefine HAVE_CAIRO
#cmakedefine HAVE_OPENCL
#cmakedefine HAVE_CL_CL_H
#cmakedefine HAVE_CLOCK_GETTIME
#cmakedefine HAVE_MSGPACK
#cmakedefine HAVE_ZMQ
-
-#define PACKAGE_VERSION "${CRYSTFEL_VERSION}"
-
-#define CRYSTFEL_VERSIONSTRING "${CRYSTFEL_VERSION}"
-
-#define CRYSTFEL_BOILERPLATE "License GPLv3+: GNU GPL version 3 or later"\
- " <http://gnu.org/licenses/gpl.html>.\n"\
- "This is free software: you are free to change and redistribute it.\n"\
- "There is NO WARRANTY, to the extent permitted by law.\n\n"\
- "Written by Thomas White and others."
+#cmakedefine HAVE_SLURM
+#cmakedefine HAVE_LIBCCP4
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 00000000..ba3f42a3
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,13 @@
+/* config.h for CrystFEL main programs */
+
+#mesondefine HAVE_GTK
+#mesondefine HAVE_GDKPIXBUF
+#mesondefine HAVE_GDK
+#mesondefine HAVE_CAIRO
+#mesondefine HAVE_OPENCL
+#mesondefine HAVE_CL_CL_H
+#mesondefine HAVE_CLOCK_GETTIME
+#mesondefine HAVE_MSGPACK
+#mesondefine HAVE_ZMQ
+#mesondefine HAVE_SLURM
+#mesondefine HAVE_LIBCCP4
diff --git a/data/crystfel.svg b/data/crystfel.svg
new file mode 100644
index 00000000..7c4bb70f
--- /dev/null
+++ b/data/crystfel.svg
@@ -0,0 +1,459 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="128.59746"
+ height="128.59746"
+ id="svg2"
+ version="1.1"
+ inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+ sodipodi:docname="crystfel.svg"
+ inkscape:export-filename="/home/taw/Documents/crystfel.png"
+ inkscape:export-xdpi="680.25"
+ inkscape:export-ydpi="680.25">
+ <defs
+ id="defs4">
+ <filter
+ id="filter3388"
+ inkscape:label="Drop shadow"
+ width="1.5"
+ height="1.5"
+ x="-0.25"
+ y="-0.25"
+ style="color-interpolation-filters:sRGB">
+ <feGaussianBlur
+ id="feGaussianBlur3390"
+ in="SourceAlpha"
+ stdDeviation="3"
+ result="blur" />
+ <feColorMatrix
+ id="feColorMatrix3392"
+ result="bluralpha"
+ type="matrix"
+ values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.5 0 " />
+ <feOffset
+ id="feOffset3394"
+ in="bluralpha"
+ dx="3"
+ dy="3"
+ result="offsetBlur" />
+ <feMerge
+ id="feMerge3396">
+ <feMergeNode
+ id="feMergeNode3398"
+ in="offsetBlur" />
+ <feMergeNode
+ id="feMergeNode3400"
+ in="SourceGraphic" />
+ </feMerge>
+ </filter>
+ <filter
+ id="filter3402"
+ inkscape:label="Drop shadow"
+ width="1.5"
+ height="1.5"
+ x="-0.25"
+ y="-0.25"
+ style="color-interpolation-filters:sRGB">
+ <feGaussianBlur
+ id="feGaussianBlur3404"
+ in="SourceAlpha"
+ stdDeviation="3"
+ result="blur" />
+ <feColorMatrix
+ id="feColorMatrix3406"
+ result="bluralpha"
+ type="matrix"
+ values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.5 0 " />
+ <feOffset
+ id="feOffset3408"
+ in="bluralpha"
+ dx="3"
+ dy="3"
+ result="offsetBlur" />
+ <feMerge
+ id="feMerge3410">
+ <feMergeNode
+ id="feMergeNode3412"
+ in="offsetBlur" />
+ <feMergeNode
+ id="feMergeNode3414"
+ in="SourceGraphic" />
+ </feMerge>
+ </filter>
+ <filter
+ id="filter3096"
+ inkscape:label="Drop shadow"
+ width="1.5"
+ height="1.5"
+ x="-0.25"
+ y="-0.25">
+ <feGaussianBlur
+ id="feGaussianBlur3098"
+ in="SourceAlpha"
+ stdDeviation="3"
+ result="blur" />
+ <feColorMatrix
+ id="feColorMatrix3100"
+ result="bluralpha"
+ type="matrix"
+ values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.5 0 " />
+ <feOffset
+ id="feOffset3102"
+ in="bluralpha"
+ dx="2"
+ dy="2"
+ result="offsetBlur" />
+ <feMerge
+ id="feMerge3104">
+ <feMergeNode
+ id="feMergeNode3106"
+ in="offsetBlur" />
+ <feMergeNode
+ id="feMergeNode3108"
+ in="SourceGraphic" />
+ </feMerge>
+ </filter>
+ <filter
+ id="filter3110"
+ inkscape:label="Drop shadow"
+ width="1.5"
+ height="1.5"
+ x="-0.25"
+ y="-0.25">
+ <feGaussianBlur
+ id="feGaussianBlur3112"
+ in="SourceAlpha"
+ stdDeviation="3"
+ result="blur" />
+ <feColorMatrix
+ id="feColorMatrix3114"
+ result="bluralpha"
+ type="matrix"
+ values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.5 0 " />
+ <feOffset
+ id="feOffset3116"
+ in="bluralpha"
+ dx="2"
+ dy="2"
+ result="offsetBlur" />
+ <feMerge
+ id="feMerge3118">
+ <feMergeNode
+ id="feMergeNode3120"
+ in="offsetBlur" />
+ <feMergeNode
+ id="feMergeNode3122"
+ in="SourceGraphic" />
+ </feMerge>
+ </filter>
+ <filter
+ id="filter3124"
+ inkscape:label="Drop shadow"
+ width="1.5"
+ height="1.5"
+ x="-0.25"
+ y="-0.25">
+ <feGaussianBlur
+ id="feGaussianBlur3126"
+ in="SourceAlpha"
+ stdDeviation="3"
+ result="blur" />
+ <feColorMatrix
+ id="feColorMatrix3128"
+ result="bluralpha"
+ type="matrix"
+ values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.5 0 " />
+ <feOffset
+ id="feOffset3130"
+ in="bluralpha"
+ dx="2"
+ dy="2"
+ result="offsetBlur" />
+ <feMerge
+ id="feMerge3132">
+ <feMergeNode
+ id="feMergeNode3134"
+ in="offsetBlur" />
+ <feMergeNode
+ id="feMergeNode3136"
+ in="SourceGraphic" />
+ </feMerge>
+ </filter>
+ <filter
+ style="color-interpolation-filters:sRGB"
+ inkscape:label="Drop Shadow"
+ id="filter994">
+ <feFlood
+ flood-opacity="0.498039"
+ flood-color="rgb(0,0,0)"
+ result="flood"
+ id="feFlood984" />
+ <feComposite
+ in="flood"
+ in2="SourceGraphic"
+ operator="in"
+ result="composite1"
+ id="feComposite986" />
+ <feGaussianBlur
+ in="composite1"
+ stdDeviation="3"
+ result="blur"
+ id="feGaussianBlur988" />
+ <feOffset
+ dx="3"
+ dy="3"
+ result="offset"
+ id="feOffset990" />
+ <feComposite
+ in="SourceGraphic"
+ in2="offset"
+ operator="over"
+ result="composite2"
+ id="feComposite992" />
+ </filter>
+ <filter
+ style="color-interpolation-filters:sRGB"
+ inkscape:label="Drop Shadow"
+ id="filter1366"
+ width="2"
+ height="1.34"
+ x="-0.28999999"
+ y="-0.15000001">
+ <feFlood
+ flood-opacity="0.498039"
+ flood-color="rgb(0,0,0)"
+ result="flood"
+ id="feFlood1356" />
+ <feComposite
+ in="flood"
+ in2="SourceGraphic"
+ operator="in"
+ result="composite1"
+ id="feComposite1358" />
+ <feGaussianBlur
+ in="composite1"
+ stdDeviation="3"
+ result="blur"
+ id="feGaussianBlur1360" />
+ <feOffset
+ dx="2.8999999999999999"
+ dy="2.8999999999999999"
+ result="offset"
+ id="feOffset1362" />
+ <feComposite
+ in="SourceGraphic"
+ in2="offset"
+ operator="over"
+ result="composite2"
+ id="feComposite1364" />
+ </filter>
+ <filter
+ style="color-interpolation-filters:sRGB"
+ inkscape:label="Drop Shadow"
+ id="filter1378"
+ width="1.8234743"
+ height="1.24018"
+ x="-0.41173714"
+ y="-0.12009">
+ <feFlood
+ flood-opacity="0.498039"
+ flood-color="rgb(0,0,0)"
+ result="flood"
+ id="feFlood1368" />
+ <feComposite
+ in="flood"
+ in2="SourceGraphic"
+ operator="in"
+ result="composite1"
+ id="feComposite1370" />
+ <feGaussianBlur
+ in="composite1"
+ stdDeviation="3.00225"
+ result="blur"
+ id="feGaussianBlur1372" />
+ <feOffset
+ dx="2.8999999999999999"
+ dy="2.8999999999999999"
+ result="offset"
+ id="feOffset1374" />
+ <feComposite
+ in="SourceGraphic"
+ in2="offset"
+ operator="over"
+ result="composite2"
+ id="feComposite1376" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="93.60503"
+ inkscape:cy="66.795339"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1920"
+ inkscape:window-height="1019"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ fit-margin-top="10"
+ fit-margin-left="10"
+ fit-margin-right="10"
+ fit-margin-bottom="10"
+ inkscape:document-rotation="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid2985"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ spacingx="0.5"
+ spacingy="0.5"
+ originx="-5.701246"
+ originy="1.076735" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-248.67537,-500.40195)">
+ <g
+ id="g3795"
+ style="fill:#d10018;fill-opacity:1"
+ inkscape:export-filename="/home/taw/crystfel-website/g3833.png"
+ inkscape:export-xdpi="64.290001"
+ inkscape:export-ydpi="64.290001"
+ transform="translate(-29.838415,35.13816)">
+ <rect
+ transform="rotate(-45)"
+ ry="10.349516"
+ rx="10.349516"
+ y="600.24524"
+ x="-148.66928"
+ height="33.234211"
+ width="33.234211"
+ id="rect2987"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d10018;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.8;marker:none;enable-background:accumulate" />
+ <rect
+ transform="rotate(-45)"
+ ry="6.646842"
+ rx="6.646842"
+ y="580.30469"
+ x="-142.02243"
+ height="13.293684"
+ width="19.940527"
+ id="rect3757"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d10018;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.8;marker:none;enable-background:accumulate" />
+ <rect
+ transform="rotate(-45)"
+ ry="6.646842"
+ rx="6.646842"
+ y="640.12628"
+ x="-142.02243"
+ height="13.293684"
+ width="19.940527"
+ id="rect3759"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d10018;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.8;marker:none;enable-background:accumulate" />
+ <rect
+ transform="rotate(-45)"
+ ry="6.646842"
+ rx="6.646842"
+ y="606.89209"
+ x="-168.6098"
+ height="19.940527"
+ width="13.293684"
+ id="rect3761"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d10018;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.8;marker:none;enable-background:accumulate" />
+ <rect
+ transform="rotate(-45)"
+ ry="6.646842"
+ rx="6.646842"
+ y="606.89209"
+ x="-108.78822"
+ height="19.940527"
+ width="13.293684"
+ id="rect3763"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d10018;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.8;marker:none;enable-background:accumulate" />
+ <rect
+ transform="rotate(-45)"
+ ry="6.646842"
+ rx="6.646842"
+ y="613.53888"
+ x="-88.847694"
+ height="6.646842"
+ width="6.646842"
+ id="rect3765"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d10018;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.8;marker:none;enable-background:accumulate" />
+ <rect
+ transform="rotate(-45)"
+ ry="6.646842"
+ rx="6.646842"
+ y="567.01099"
+ x="-135.3756"
+ height="6.646842"
+ width="6.646842"
+ id="rect3767"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d10018;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.8;marker:none;enable-background:accumulate" />
+ <rect
+ transform="rotate(-45)"
+ ry="6.646842"
+ rx="6.646842"
+ y="613.53888"
+ x="-181.90349"
+ height="6.646842"
+ width="6.646842"
+ id="rect3769"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d10018;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.8;marker:none;enable-background:accumulate" />
+ <rect
+ transform="rotate(-45)"
+ ry="6.646842"
+ rx="6.646842"
+ y="660.06677"
+ x="-135.3756"
+ height="6.646842"
+ width="6.646842"
+ id="rect3771"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#d10018;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.8;marker:none;enable-background:accumulate" />
+ </g>
+ <path
+ style="fill:none;stroke:#007acc;stroke-width:5.02812;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 330.3125,499.5625 h -17.5 v 60 h 17.5"
+ id="path3773"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ transform="matrix(1.6700076,0,0,1.6700076,-259.52538,-319.67272)" />
+ <path
+ style="fill:none;stroke:#007acc;stroke-width:5.02812;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 355.3125,499.5625 h 17.5 v 60 h -17.5"
+ id="path3775"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc"
+ transform="matrix(1.6700076,0,0,1.6700076,-259.52538,-319.67272)"
+ clip-path="none" />
+ </g>
+</svg>
diff --git a/doc/man/compare_hkl.1 b/doc/man/compare_hkl.1
index 8c54b4c9..22de7df7 100644
--- a/doc/man/compare_hkl.1
+++ b/doc/man/compare_hkl.1
@@ -125,13 +125,6 @@ High resolution cutoff, as 1/d in m<sup>-1</sup>. Use this or \fB--highres\fR,
.IP \fB--highres=\fR\fId\fR
High resolution cutoff in Angstroms. Use this or \fB--rmax\fR, but not both.
-.PD 0
-.IP \fB--intensity-shells\fR
-.PD
-Use intensity shells instead of resolution shells. The range of shells will start at the intensity of the least intense reflection, and extend from there by 1/5000th of the intensity of the difference between the strongest and weakest reflection in the first reflection list. The pairs of reflections will also be assigned their bins according to the intensity of the reflection in the first list.
-.sp
-Because of the hardcoded factor of 1/5000, needed to avoid a very uneven distribution of the number of reflection pairs in each bin, you are advised not to draw strong conclusions from the results of using this option.
-
.SH AUTHOR
This page was written by Thomas White.
diff --git a/doc/man/crystfel_geometry.5 b/doc/man/crystfel_geometry.5
index 871af139..02551a73 100644
--- a/doc/man/crystfel_geometry.5
+++ b/doc/man/crystfel_geometry.5
@@ -46,11 +46,6 @@ Naively speaking, this means that CrystFEL looks at the images from the "into th
beam" perspective, but please avoid thinking of things in this way. It's much
better to consider the precise way in which the coordinates are mapped.
-Some file formats store data for multiple patterns ("events") within a single file.
-Information about the layout of the file data can be included in the geometry file.
-This allows CrystFEL to unambigously identify data blocks which contain
-data for a specific event, and to determine the number of events that each file contains.
-
The geometry file should contain lines of the following form:
.IP
@@ -69,10 +64,50 @@ clen = 0.560
In this case, the value will be used for all \fBsubsequent\fR panels appearing in the file which do not have their own specific values for the property, or until you specify another default value further down the file. Panel-specific values always have priority over default values, and changing the default value has no effect for panels which had already be mentioned at the point in the file where the default value was specified.
.PP
-Lines which should be ignored start with a semicolon.
+Comments start with a semicolon. They will be ignored.
-.PP
-The properties which can be set are:
+.SH TOP-LEVEL ONLY PARAMETERS
+
+The parameters in this section can only appear without a panel name.
+
+.PD 0
+.IP "\fBwavelength \fInnn\fR \fB[m|A]"
+.IP "\fBphoton_energy \fInnn\fR \fB[eV|keV]"
+.IP "\fBelectron_voltage \fInnn\fR \fB[V|kV]"
+.PD
+These statements specify the incident radiation wavelength. You must include one (not more) of these statements. \fBwavelength\fR specifies the wavelength directly, \fBphoton_energy\fR specifies the energy per photon for electromagnetic radiation (e.g. X-rays), and \fBelectron_voltage\fR specifies the accelerating voltage for an electron beam.
+.IP
+\fInnn\fR can be a literal number, or it can be a header location in the image data file. In the latter case, the program will do what you expect in the case of multi-frame data files, e.g. a scalar value in the metadata will be applied to all frames, or an array of values can be used to provide a separate wavelength for each frame.
+.IP
+Units should be specified after the value (or location). These can be \fBm\fR or \fBA\fR for \fBwavelength\fR, \fBeV\fR or \fBkeV\fR for \fBphoton_energy\fR, and \fBV\fR or \fBkV\fR for \fBelectron_voltage\fR. For \fBphoton_energy\fR, if no units are given then the value will be taken to be in eV.
+
+.PD 0
+.IP "\fBdetector_shift_x = \fInnn \fB[m|mm]"
+.IP "\fBdetector_shift_y = \fInnn \fB[m|mm]"
+.PD
+These specify that the entire detector should be shifted by this amount in the x and y directions. The units should be specified as \fBm\fR or \fBmm\fR. If units are not specified, the value will be taken as metres. \fInnn\fR can be a file metadata location (e.g. an HDF5 path).
+
+.PD 0
+.IP "\fBpeak_list = \fIloc"
+.PD
+This gives the location of the peak list in the data files, for peak detection methods \fBhdf5\fR and \fBcxi\fR (see \fBman indexamajig\fR).
+
+.PD 0
+.IP "\fBpeak_list_type = \fIlayout"
+.PD
+Specify the layout of the peak list. Allowed values are \fBcxi\fR, \fBlist3\fR and \fBauto\fR.
+.IP
+\fBlist3\fR expects the peak list to be a two dimensional array whose size in the first dimension equals the number of peaks and whose size in the second dimension is exactly three. The first two columns contain the fast scan and slow scan coordinates, the third contains the intensities. This is the correct option for "single-frame" HDF5 files as written by older versions of Cheetah.
+.IP
+\fBcxi\fR expects the peak list to be a group containing four separate HDF5 datasets: \fBnPeaks\fR, \fBpeakXPosRaw\fR, \fBpeakYPosRaw\fR and \fBpeakTotalIntensity\fR. See the specification for the CXI file format at http://www.cxidb.org/ for more details. This is the correct option for "multi-event" HDF5 files as output by recent versions of Cheetah.
+.IP
+\fBauto\fR tells CrystFEL to decide between the above options based on the file extension.
+.IP
+Note that CrystFEL considers all peak locations to be distances from the corner of the detector panel, in pixel units, consistent with its description of detector geometry (see 'man crystfel_geometry'). The software which generates the HDF5 or CXI files, including Cheetah, may instead consider the peak locations to be pixel indices in the data array. To compensate for this discrepancy, CrystFEL will, by default, add 0.5 to all peak coordinates. Use \fB--no-half-pixel-shift\fR if this isn't what you want.
+
+.SH PER-PANEL VALUES
+
+The following parameters can be set for each panel individually. Don't forget that they can also be used at the "top level" to set default values.
.PD 0
.IP \fBdata\fR
@@ -133,13 +168,9 @@ The range of pixels in the data block specified by the 'data' property that corr
.PD 0
.IP \fBadu_per_eV\fR
-.PD
-The number of detector intensity units (ADU) which will arise from one electron-Volt of photon energy. This is used to estimate Poisson errors. Note that setting different values for this parameter for different panels does \fBnot\fR result in the intensities being scaled accordingly when integrating data, but it does affect the intensities calculated by \fBpattern_sim\fR. You should only specify one out of \fBadu_per_eV\fR and \fBadu_per_photon\fR, but if you use both then \fBadu_per_photon\fR will have priority.
-
-.PD 0
.IP \fBadu_per_photon\fR
.PD
-The number of detector intensity units (ADU) which will arise from one photon. This is used to estimate Poisson errors. Note that setting different values for this parameter for different panels does \fBnot\fR result in the intensities being scaled accordingly when integrating data, but it does affect the intensities calculated by \fBpattern_sim\fR. You should only specify one out of \fBadu_per_eV\fR and \fBadu_per_photon\fR, but if you use both then \fBadu_per_photon\fR will have priority.
+The number of detector intensity units (ADU) which will arise from either one electron-Volt of photon energy, or one photon. This is used to estimate Poisson errors. Note that setting different values for this parameter for different panels does \fBnot\fR result in the intensities being scaled accordingly when integrating data, but it does affect the intensities calculated by \fBpattern_sim\fR. You should only specify one out of \fBadu_per_eV\fR and \fBadu_per_photon\fR.
.PD 0
.IP \fBbadrow_direction\fR
@@ -178,15 +209,52 @@ The corner of this panel, defined as the first point in the panel to appear in t
.PD 0
.IP \fBmax_adu\fR
-The maximum value, in ADU, before the pixel will be considered as bad. That is, the saturation value for the panel.
+The saturation value for the panel. You can use this to exclude saturated peaks from the peak search or to avoid integrating saturated reflections. However, usually it's best to include saturated peaks, and exclude saturated reflections with the --max-adu option of process_hkl and partialator. Therefore you should avoid setting this parameter - a warning will be displayed if you do.
.PD 0
-.IP \fBmask\fR
-If you have a bad pixel mask, you can include it in the HDF5 file as data blocks with the same structure and size as the panel data. You need to specify the location of each panel's mask data block using this property, and two bitmasks (see below). The number of placeholders ('%') in the \fBmask\fR must be the same for all panels. They will be substituted with the same values as used for the placeholders in the \fBdata\fR fields, although there may be fewer of them for \fBmask\fR than for \fBdata\fR.
+.IP \fBflag_lessthan
+.IP \fBflag_morethan
+.IP \fBflag_equal
+Mark pixels as "bad" if their values are respectively less than, more than or equal to the given value. Note carefully that the inequalities are strict, not inclusive: "less than", not "less than or equal to".
.PD 0
-.IP \fBmask_file\fR
-Use this option to specify that the bad pixel mask should be read from a different file to the image data. The \fBmask\fR field, if it contains placeholders, will be expanded in exactly the same way as normal, it's just that the data will be read from the file you specify instead of the image data file. The \fBmask_file\fR may be specified as an absolute filename, or relative to the working directory.
+.IP \fBmaskN_data\fR
+.IP \fBmaskN_file\fR
+.IP \fBmaskN_goodbits\fR
+.IP \fBmaskN_badbits\fR
+.PD
+These specify the parameters for bad pixel mask number \fIN\fR. You can have up to 8 bad pixel masks, numbered from 0 to 7 inclusive. Placeholders ('%') in the location (\fBmaskN_data\fR) will be substituted with the same values as used for the placeholders in the image data, although there may be fewer of them for the masks than from the image data.
+.IP
+You can optionally give a filename for each mask with \fBmaskN_file\fR. The filename may be specified as an absolute filename, or relative to the working directory. If you don't specify a filename, the mask will be read from the same file as the image data.
+.IP
+A pixel will be considered bad unless \fIall\fR of the bits which are set in \fBgoodbits\fR are set. A pixel will also be considered bad if \fIany\fR of the bits which are set in \fBbadbits\fR are set. Note that pixels can additionally be marked as bad via other mechanisms as well (e.g. \fBno_index\fR or \fBbad\fR).
+.IP
+Example:
+.RS
+.PD 0
+.IP
+mask2_data = /data/bad_pixel_map
+.IP
+mask2_file = /home/myself/mybadpixels.h5
+.IP
+mask2_goodbits = 0x00
+.IP
+mask2_badbits = 0xff
+.RE
+.PD
+.IP
+There are some older mask directives which are still understood by this version of CrystFEL. They are synonyms of the new directives as follows:
+.RS
+.PD 0
+.IP
+mask -----> mask0_data
+.IP
+mask_file -----> mask0_file
+.IP
+mask_good -----> mask0_goodbits
+.IP
+mask_bad -----> mask0_badbits
+.RE
.PD 0
.IP \fBsaturation_map\fR
@@ -197,18 +265,6 @@ This specifies the location of the per-pixel saturation map in the HDF5 file. T
Specifies that the saturation map should come from the HDF5 file named here, instead of the HDF5 file being processed. It can be an absolute filename or relative to the working directory.
.PD 0
-.IP \fBmask_good\fR
-.IP \fBmask_bad\fR
-.PD
-Bitmasks for bad pixel masks. The pixel is considered good if all of the bits which are set in \fBmask_good\fR are set, \fIand\fR if none of the bits which are set in \fBmask_bad\fR are set. Example:
-.IP
-mask = /processing/hitfinder/masks
-.br
-mask_good = 0x27
-.br
-mask_bad = 0x00
-
-.PD 0
.IP \fBno_index\fR
Set this to 1 or "true" to ignore this panel completely.
@@ -220,7 +276,7 @@ Specify the direction in which the panel should move when the camera length is i
.SH BAD REGIONS
-You can also specify bad regions. Bad regions will be completely ignored by CrystFEL. Bad regions are specified in pixel units, either in the lab coordinate system (see above) or in fast scan/slow scan coordinates (mixtures are not allowed). In the latter case, the range of pixels is specified \fIinclusively\fR. Bad regions are distinguished from normal panels by the fact that they begin with the three letters "bad".
+Bad regions will be completely ignored by CrystFEL. You can specify the pixels to exclude in pixel units, either in the lab coordinate system (see above) or in fast scan/slow scan coordinates (mixtures are not allowed). In the latter case, the range of pixels is specified \fIinclusively\fR. Bad regions are distinguished from normal panels by the fact that they begin with the three letters "bad".
.PP
You can specify a panel name for the bad region, in which case the pixels will only be considered bad if they are within the range you specify \fIand\fR in the panel you specify. This might be necessary if your HDF5 file layout has overlapping ranges of fs/ss coordinates for different panels (e.g. if the data blocks for the panels are in different HDF5 datasets).
@@ -268,27 +324,6 @@ Definitions of rigid groups and rigid group collections can appear at any place
.PP
See the "examples" folder for some examples (look at the ones ending in .geom).
-.SH BEAM CHARACTERISTICS
-
-The geometry file can include information about beam characteristics, using general properties, that can appear anywhere in the geometry file and do not follow the usual panel/property syntax. The following beam properties are supported:
-
-.PD 0
-.IP \fBphoton_energy\fR
-.PD
-The beam photon energy in eV. You can also specify the HDF5 path to a floating point data block value containing the photon energy in eV. For example: "photon_energy = /LCLS/photon_energy_eV". If the HDF5 file contains more than one event, and the data block is scalar, the photon energy value
-it contains will be used for all events. If, however, the data block is multidimensional and the second dimension is bigger than one, the CrystFEL programs will try to match the content of the data block with the events in the file, assigning the first value in the data block to the first event in the file,
-the second value in the data block to the second event in the file, etc. See also \fBphoton_energy_scale\fR.
-
-.PD 0
-.IP \fBphoton_energy_scale\fR
-.PD
-Sometimes the photon energy value recorded in an HDF5 file differs from the true photon energy value by a multiplication factor. This property defines a correction factor that is applied by the CrystFEL programs. The photon energy value read from a file is multiplied by the value of this property if the property is defined in the geometry file.
-
-
-.SH PEAK INFO LOCATION
-
-Finally, the geometry file can include information about where to look in the HDF5 or CXI files for the table of peak positions. CrystFEL can use these peak locations for indexing. Simply include \fBpeak_info_location\fR = \fIlocation\fR, where \fIlocation\fR could be something like /processing/hitfinder/peakinfo. A peak location given on the indexamajig command line, e.g. \fB--hdf5-peaks=/some/location\fR, has priority over the location in the geometry file. If neither the geometry file nor the command line specify a location, the default is \fB/processing/hitfinder/peakinfo\fR when \fB--peaks=hdf5\fR is used, and \fB/entry_1/result_1\fR when \fB--peaks=cxi\fR is used.
-
.SH AUTHOR
This page was written by Thomas White and Valerio Mariani.
diff --git a/doc/man/hdfsee.1 b/doc/man/hdfsee.1
deleted file mode 100644
index 7eb93f09..00000000
--- a/doc/man/hdfsee.1
+++ /dev/null
@@ -1,128 +0,0 @@
-.\"
-.\" hdfsee man page
-.\"
-.\" Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
-.\" a research centre of the Helmholtz Association.
-.\"
-.\" Part of CrystFEL - crystallography with a FEL
-.\"
-
-.TH HDFSEE 1
-.SH NAME
-hdfsee \- HDF5 image viewer
-.SH SYNOPSIS
-.PP
-.B hdfsee \fIimage.h5\fR [\fIoptions\fR] \fB...\fR
-.PP
-\fBhdfsee --help\fR
-
-.SH DESCRIPTION
-hdfsee is a simple image viewer for images stored in HDF5 files.
-.PP
-Most of the options that can be set on the command line can be changed via the user interface once the program is running. The command line options are to help when running hdfsee from a script.
-
-.SH OPTIONS
-.PD 0
-.IP "\fB-p\fR \fIfilename\fR"
-.IP \fB--peak-overlay=\fR\fIfilename\fR
-.PD
-Peak locations will be read from \fIfilename\fR and displayed on the image. The peak location file can use the format used in CrystFEL stream files for lists of integrated reflections, i.e. including the Miller indices. If a line cannot be read using this format, it will be assumed to be a simple two-column list of fast scan and slow scan coordinates. Any text beyond the second column will be ignored. If the line cannot be read in either format, it will be ignored.
-
-.PD 0
-.IP \fB--ring-size=\fR\fIradius\fR
-.PD
-Set the radius of the rings used for displaying peak locations. The radius is given in pixels on the screen, i.e. the circles are drawn \fIafter\fR binning the image data.
-
-.PD 0
-.IP "\fB-b\fR \fIb\fR"
-.IP \fB--binning=\fR\fIb\fR
-.PD
-Show the image after binning down by a factor of \fIb\fR.
-
-.PD 0
-.IP "\fB-e\fR \fIpath\fR"
-.IP \fB--image=\fR\fIpath\fR
-.PD
-Get the image data to display from \fIpath\fR inside the HDF5 file. Example: \fI/data/rawdata\fR.
-.IP
-If no geometry file is provided (see \fB-g\fR) and this option is not used, hdfsee will display the first two-dimensional dataset it finds in the file with both dimensions greater than 64. If a geometry file is provided, the data layout description from the file determines which image is displayed (see \fB man crystfel_geometry\fR).
-.IP
-If \fB-e\fR is used in combination with \fB-g\fR, hdfsee will attempt to show the specified dataset with the geometry applied. The data layout description from the geometry file will be ignored, the data block to be used as data source for all panels will be set to \fIpath\fR and it will be assumed to be 2-dimensional.
-
-.PD 0
-.IP \fB--event=\fIID\fR
-.PD
-Show the event identified by \fIID\fR. Use this when you have a multi-event HDF5 file and the corresponding geometry file.
-
-.PD 0
-.IP "\fB-g\fR \fIfilename\fR"
-.IP \fB--geometry=\fR\fIfilename\fR
-.PD
-Display the image data according to the geometry description in \fIfilename\fR. Out of plane components of the geometry will be ignored. This is required to display resolution rings.
-
-.PD 0
-.IP "\fB-i\fR \fIn\fR"
-.IP \fB--int-boost=\fR\fIn\fR
-.PD
-Multiply the intensity in the image by \fIn\fR before displaying. With n=1, the top of the colour scale will represent the maximum pixel intensity found in the image.
-
-.PD 0
-.IP \fB--show-rings\fR
-.PD
-Show resolution rings on the image at 1 Angstrom intervals. You must provide both a geometry and a beam file to use this option.
-
-.PD 0
-.IP \fB--simple-rings=\fR\fIradii\fR
-.PD
-Show rings on the image with the radii specified. \fIradii\fR can be a comma-deliminated list of several values, for example \fI100,200\fR. The radii have units of pixels on the detector before bininng. You must provide a geometry file to use this option.
-
-.PD 0
-.IP "\fB-c\fR \fIscale\fR"
-.IP \fB--colscale=\fR\fIscale\fR
-.PD
-Use \fIscale\fR as the colour scale. Possible scales are: \fBmono\fR, \fBinvmono\fR and \fBcolour\fR.
-
-.PD 0
-.IP \fB--median-filter=\fR\fIn\fR
-.PD
-Apply a median filter with box "radius" \fIn\fR to the image. Each pixel will be set to the median of the values from a \fI(n+1)\fRx\fI(n+1)\fR square centered on the pixel. If you also use \fB--noise-filter\fR, the median filter will be applied first.
-
-.PD 0
-.IP \fB--filter-noise\fR
-.PD
-Apply a noise filter to the image with checks 3x3 squares of pixels and sets all of them to zero if any of the nine pixels have a negative value. If you also use \fB--median-filter\fR, the median filter will be applied first.
-
-.PD 0
-.IP "\fB-o \fIcoll\fR"
-.IP \fB--rigid-groups=\fIcoll\fR
-.PD
-Use \fIcoll\fR as the rigid group collection for calibration mode.
-
-.SH CALIBRATION MODE
-Calibration mode allows you to visually adjust the locations of panels. To enter calibration mode, select Tools->Calibration Mode from the menu. The currently selected panel will be bordered in white. Press + or - to move to the next or previous panel (as listed in the geometry file). Use the arrow keys to move the current panel. Press 'f' to hide or restore the white border. Press 's' to save the geometry file with your modifications. Press 'g' to toggle between moving individual panels, rigid groups (if any are defined in the geometry file) and moving all panels together.
-Most of these actions can also be accessed from the Calibration menu, which becomes aptive when calibration mode is toggled once
-
-.SH EVENT NAVIGATION
-When multi-event files are opened, the Events menu in the menubar becomes active, and some event navigation tools become available. The title bar shows, in addition to the file name, the name of the event currently displayed (See \fBman crystfel_geometry\fR and \fBman indexamajig\fR for a description of event naming). Press 'n' to move to the next event in the file, and 'p' to move to the previous one'. Press 'e' to jump to a specific event, by providing an event name (Use the \fBlist_events\fR program to get a list of the events included in a file). Press 'r' to jump to a random event. These actions are also accessible from the Events menu in the menubar.
-
-.SH AUTHOR
-This page was written by Thomas White and Valerio Mariani.
-
-.SH REPORTING BUGS
-Report bugs to <taw@physics.org>, or visit <http://www.desy.de/~twhite/crystfel>.
-
-.SH COPYRIGHT AND DISCLAIMER
-Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY, a research centre of the Helmholtz Association.
-.P
-hdfsee, and this manual, are part of CrystFEL.
-.P
-CrystFEL is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
-.P
-CrystFEL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-.P
-You should have received a copy of the GNU General Public License along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
-
-.SH SEE ALSO
-.BR crystfel (7),
-.BR pattern_sim (1),
-.BR crystfel_geometry (5).
diff --git a/doc/man/indexamajig.1 b/doc/man/indexamajig.1
index e400c211..6dffdffd 100644
--- a/doc/man/indexamajig.1
+++ b/doc/man/indexamajig.1
@@ -41,11 +41,7 @@ Indexamajig requires an input file with a list of diffraction patterns ("events"
.SH PEAK DETECTION
-You can control the peak detection on the command line. Firstly, you can choose the peak detection method using \fB--peaks=\fR\fImethod\fR. There are three possibilities for "method" here. \fB--peaks=hdf5\fR will take the peak locations from the HDF5 file. It expects a two dimensional array, by default at /processing/hitfinder/peakinfo, whose size in the first dimension equals the number of peaks and whose size in the second dimension is three. The first two columns contain the fast scan and slow scan coordinates, the third contains the intensity. However, the intensity will be ignored since the pattern will always be re-integrated using the unit cell provided by the indexer on the basis of the peaks. You can tell indexamajig where to find this table inside each HDF5 file using \fB--hdf5-peaks=\fR\fIpath\fR.
-
-\fB--peaks=cxi\fR works similarly to this, but expects four separate HDF5 datasets beneath \fIpath\fR, \fBnPeaks\fR, \fBpeakXPosRaw\fR, \fBpeakYPosRaw\fR and \fBpeakTotalIntensity\fR. See the specification for the CXI file format at http://www.cxidb.org/ for more details.
-
-CrystFEL considers all peak locations to be distances from the corner of the detector panel, in pixel units, consistent with its description of detector geometry (see 'man crystfel_geometry'). The software which generates the HDF5 or CXI files, including Cheetah, may instead consider the peak locations to be pixel indices in the data array. Therefore, the peak coordinates from \fB--peaks=cxi\fR or \fB--peaks=hdf5\fR will by default have 0.5 added to them. Use \fB--no-half-pixel-shift\fR if this isn't what you want.
+You can control the peak detection on the command line. Firstly, you can choose the peak detection method using \fB--peaks=\fR\fImethod\fR. \fB--peaks=hdf5\fR or \fB--peaks=cxi\fR will take the peak locations from the input file. See the documentation for \fBpeak_list\fR and \fBpeak_list_type\fR in crystfel_geometry(5) for details.
If you use \fB--peaks=zaef\fR, indexamajig will use a simple gradient search after Zaefferer (2000). You can control the overall threshold and minimum squared gradient for finding a peak using \fB--threshold\fR and \fB--min-squared-gradient\fR. The threshold has arbitrary units matching the pixel values in the data, and the minimum gradient has the equivalent squared units. Peaks will be rejected if the 'foot point' is further away from the 'summit' of the peak by more than the inner integration radius (see below). They will also be rejected if the peak is closer than twice the inner integration radius from another peak.
@@ -147,7 +143,7 @@ Center the peak boxes iteratively on the actual peak locations. The opposite is
.IP \fB-sat\fR
.PD
-Normally, reflections which contain one or more pixels above max_adu (defined in the detector geometry file) will not be integrated and written to the stream. Using this option skips this check, and allows saturated reflections to be passed to the later merging stages. This is not usually a good idea, but might be your only choice if there are many saturated reflections. The opposite is \fB-nosat\fR, which is the default for all integration methods.
+Normally, reflections which contain one or more pixels above max_adu (defined in the detector geometry file) will not be integrated and written to the stream. Using this option skips this check, and allows saturated reflections to be passed to the later merging stages. The opposite is \fB-nosat\fR, which is the default for all integration methods. However, note that the saturation check will only be done if max_adu is set in the geometry file. Usually, it's better to exclude saturated reflections at the merging stage. The the documentation for max_adu in crystfel_geometry(5).
.IP \fB-grad\fR
.PD
@@ -194,7 +190,7 @@ Prefix the filenames from the input file with \fIprefix\fR. If \fB--basename\fR
.PD 0
.IP "\fB-j\fR \fIn\fR"
.PD
-Run \fIn\fR analyses in parallel. Default: 1.
+Run \fIn\fR analyses in parallel. Default: 1. See also \fB--max-indexer-threads\fR.
.PD 0
.IP \fB--no-check-prefix\fR
@@ -389,6 +385,16 @@ Skip the prediction refinement step. Usually this will decrease the quality of
Check that most of the peaks can be accounted for by the indexing solution. This usually increases the quality of the indexing solutions, but prevents "subtract and retry" multi-lattice indexing from working well.
.PD 0
+.IP \fB--wavelength-estimate=\fIm\fR
+.PD
+Some indexing algorithms need to know the wavelength of the incident radiation in advance, e.g. to prepare an internal look-up table. However, if the wavelength is taken from image headers, then the wavelength is not available at start-up. In this case, you will be prompted to add this option to give an approximate wavelength, in metres. A warning will be generated if the actual wavelength differs from this value by more than 10%.
+
+.PD 0
+.IP \fB--max-indexer-threads=\fIn\fR
+.PD
+Some indexing algorithms (e.g. pinkIndexer) can use multiple threads for faster calculations. This is in addition to the frame-based parallelism already available in indexamajig (see \fB-j\fR). This option sets the maximum number of threads that each indexing engine is allowed to use. Default: 1.
+
+.PD 0
.IP \fB--taketwo-member-threshold=\fIn\fR
.IP \fB--taketwo-len-tolerance=\fIn\fR
.IP \fB--taketwo-angle-tolerance=\fIn\fR
@@ -445,13 +451,7 @@ These set low-level parameters for the XGANDALF indexing algorithm.
.IP \fB--pinkIndexer-tolerance=\fIn\fR
.IP \fB--pinkIndexer-reflection-radius=\fIn\fR
.IP \fB--pinkIndexer-max-resolution-for-indexing=\fIn\fR
-.IP \fB--pinkIndexer-multi\fR
-.IP \fB--pinkIndexer-thread-count=\fIn\fR
-.IP \fB--pinkIndexer-no-check-indexed\fR
.IP \fB--pinkIndexer-max-refinement-disbalance=\fIn\fR
-.IP \fB--pinkIndexer-override-bandwidth=\fIn\fR
-.IP \fB--pinkIndexer-override-photon-energy=\fIn\fR
-.IP \fB--pinkIndexer-override-visible-energy-range=\fImin-max\fR
.PD
These set low-level parameters for the PinkIndexer indexing algorithm.
@@ -466,21 +466,9 @@ These set low-level parameters for the PinkIndexer indexing algorithm.
.IP
\fB--pinkIndexer-reflection-radius\fR sets radius of the reflections in reciprocal space in 1/A. Default is 2%% of a* (which works quiet well for X-rays). Should be chosen much bigger for electrons (~0.002).
.IP
-\fB--pinkIndexer-max-resolution-for-indexing\fR sets the maximum resolition in 1/A used for indexing. Peaks at high resolution don't add much information, but they add a lot of computation time. Default is infinity. Does not influence the refinement.
-.IP
-\fB--pinkIndexer-multi\fR Use pinkIndexers own multi indexing. Should be combined with the --no-multi flag.
-.IP
-\fB--pinkIndexer-thread-count\fR sets the thread count for internal parallelization. Default is 1. Very useful for small datasets (e.g. for screening). Internal parallelization does not significantly increase the amount of RAM needed, whereas CrystFEL's parallelization does. For HPCs typically a mixture of both parallelizations leads to best results.
-.IP
-\fB--pinkIndexer-no-check-indexed\fR Leave the check whether a pattern is indexed completely to CrystFEL. Useful for monochromatic (since CrystFEL's prediction model is smarter than the one of pinkIndexer) or in combnation with --no-check-peaks for geometry optimization. This flag is meant to eventually disappear, when the full pink pipeline is implemented.
-.IP
-\fB--pinkIndexer-max-refinement-disbalance Indexing solutions are dismissed if the refinement refined very well to one side of the detector and very badly to the other side. Allowed values range from 0 (no disbalance) to 2 (extreme disbalance), default 0.4. Disbalance after refinement usually appears for bad geometries or bad prior unit cell parameters.
-.IP
-\fB--pinkIndexer-override-bandwidth=\fIn\fR Overrides the bandwidth in (delta energy)/(mean energy) to use for indexing (which usually is defined in the geometry file). Should be used together with \fB--pinkIndexer-override-photon-energy=\fIn\fR. Note: this option sets the borders for the spectrum, whereas the option in the geometry file sets the standard deviation for a Gaussian that fits the spectrum. Internally, the standard deviation is multiplied by 5 to compute the hard borders of the spectrum. I.e., photon_energy_bandwith = 0.005 in the geometry file equals --pinkIndexer-override-bandwidth=0.025. For monochromatic experiments usually --pinkIndexer-override-bandwidth=0.02 is sufficiently large. If in doubt, use --pinkIndexer-override-visible-energy-range.
-.IP
-\fB--pinkIndexer-override-photon-energy=\fIn\fR Overrides the mean energy in eV to use for indexing (which usually is defined in the geometry file). Should be used together with \fB--pinkIndexer-override-bandwidth=\fIn\fR
+\fB--pinkIndexer-max-resolution-for-indexing\fR sets the maximum resolution in 1/A used for indexing. Peaks at high resolution don't add much information, but they add a lot of computation time. Default is infinity. Does not influence the refinement.
.IP
-\fB--pinkIndexer-override-visible-energy-range=\fImin-max\fR Overrides photon energy and bandwidth according to a range of energies that have high enough intensity to produce visible Bragg spots on the detector. min and max range borders are separated by a minus sign (no whitespace).
+\fB--pinkIndexer-max-refinement-disbalance\fR Indexing solutions are dismissed if the refinement refined very well to one side of the detector and very badly to the other side. Allowed values range from 0 (no disbalance) to 2 (extreme disbalance), default 0.4. Disbalance after refinement usually appears for bad geometries or bad prior unit cell parameters.
.SH INTEGRATION OPTIONS
.PD 0
diff --git a/doc/man/partialator.1 b/doc/man/partialator.1
index 515f66d7..601a2c44 100644
--- a/doc/man/partialator.1
+++ b/doc/man/partialator.1
@@ -196,6 +196,14 @@ This model is the same as that described in Acta Cryst. D71 (2015) p1400.
.PD
Fix all partialities at 1.
+.IP \fBoffset\fR
+.PD
+Treat the radiation as perfectly monochromatic, and calculate the partiality as exp(-t^2/R^2), where t is the excitation error and R is the reflection radius (taking mosaicity into account). This model is similar to that used by XDS.
+
+.IP \fBggpm\fR
+.PD
+An analytical overlap integral modelling the reflection profiles as Gaussian functions, and the radiation spectrum as a sum of Gaussians.
+
.SH USAGE CASES
.IP "Merging without scaling, partialities or post-refinement:"
diff --git a/doc/stream-format.txt b/doc/stream-format.txt
deleted file mode 100644
index b74d50c1..00000000
--- a/doc/stream-format.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-CrystFEL stream format
-----------------------
-
-num_peaks: The number of peaks accepted for indexing. If you used
- "--use-saturated", this includes the saturated peaks which are also counted by
- num_saturated_peaks. If you didn't, then it doesn't.
-
-num_saturated_peaks: The number of saturated peaks, regardless of whether or not
- they were used for indexing (see --use-saturated).
-
-num_saturated_reflections: The number of saturated reflections, regardless of
- whether or not they were included in the reflection list
- (see --integrate-saturated). Reflections which could not be integrated for
- some other reason, e.g. because they were close to a panel edge or hit a bad
- region, are NOT included in this count.
diff --git a/libcrystfel/CMakeLists.txt b/libcrystfel/CMakeLists.txt
index b0f29543..f92e8be2 100644
--- a/libcrystfel/CMakeLists.txt
+++ b/libcrystfel/CMakeLists.txt
@@ -1,15 +1,17 @@
project(libcrystfel VERSION ${CRYSTFEL_SHORT_VERSION} LANGUAGES C)
find_package(Curses)
-find_package(XGANDALF)
-find_package(PINKINDEXER)
-find_package(FDIP)
+pkg_check_modules (XGANDALF xgandalf)
+pkg_check_modules (PINKINDEXER pinkIndexer)
+pkg_check_modules (FDIP fdip)
find_package(ZLIB REQUIRED)
find_package(FLEX REQUIRED)
find_package(BISON REQUIRED)
find_package(Doxygen)
pkg_search_module(FFTW fftw3)
+configure_file(src/libcrystfel-version.c.cmake.in libcrystfel-version.c)
+
set(HAVE_CURSES ${CURSES_FOUND})
set(HAVE_FFTW ${FFTW_FOUND})
set(HAVE_XGANDALF ${XGANDALF_FOUND})
@@ -21,19 +23,6 @@ set(CMAKE_REQUIRED_LIBRARIES "-lz")
check_symbol_exists(gzbuffer "zlib.h" HAVE_GZBUFFER)
unset(CMAKE_REQUIRED_LIBRARIES)
-# Find out where forkpty() is declared
-set(CMAKE_REQUIRED_LIBRARIES "-lutil")
-check_symbol_exists(forkpty "pty.h" HAVE_FORKPTY_PTY_H)
-check_symbol_exists(forkpty "util.h" HAVE_FORKPTY_UTIL_H)
-unset(CMAKE_REQUIRED_LIBRARIES)
-if(HAVE_FORKPTY_PTY_H)
- message(STATUS "Found forkpty() in pty.h")
-elseif(HAVE_FORKPTY_UTIL_H)
- message(STATUS "Found forkpty() in util.h")
-else()
- message(SEND_ERROR "Couldn't find forkpty()")
-endif()
-
configure_file(config.h.cmake.in config.h)
bison_target(symopp src/symop.y ${CMAKE_CURRENT_BINARY_DIR}/symop-parse.c COMPILE_FLAGS --report=all)
@@ -46,10 +35,8 @@ set(LIBCRYSTFEL_SOURCES
src/reflist.c
src/utils.c
src/cell.c
- src/detector.c
src/thread-pool.c
src/image.c
- src/hdf5-file.c
src/geometry.c
src/peakfinder8.c
src/symmetry.c
@@ -57,70 +44,68 @@ set(LIBCRYSTFEL_SOURCES
src/peaks.c
src/reflist-utils.c
src/filters.c
- src/render.c
src/index.c
- src/dirax.c
- src/mosflm.c
src/cell-utils.c
src/integer_matrix.c
src/crystal.c
- src/xds.c
src/integration.c
src/predict-refine.c
- src/events.c
- src/felix.c
src/peakfinder8.c
- src/taketwo.c
- src/xgandalf.c
- src/pinkindexer.c
src/rational.c
src/spectrum.c
+ src/datatemplate.c
+ src/colscale.c
+ src/detgeom.c
+ src/image-cbf.c
+ src/image-hdf5.c
+ src/fom.c
src/fromfile.c
${BISON_symopp_OUTPUTS}
${FLEX_symopl_OUTPUTS}
+ src/indexers/dirax.c
+ src/indexers/mosflm.c
+ src/indexers/xds.c
+ src/indexers/felix.c
+ src/indexers/taketwo.c
+ src/indexers/asdf.c
+ src/indexers/xgandalf.c
+ src/indexers/pinkindexer.c
)
-if (HAVE_FFTW)
- set(LIBCRYSTFEL_FFTW_SOURCES src/asdf.c)
-endif (HAVE_FFTW)
-
set(LIBCRYSTFEL_HEADERS
- src/hdf5-file.h
src/reflist.h
src/symmetry.h
src/cell.h
src/reflist-utils.h
src/thread-pool.h
src/utils.h
- src/detector.h
src/geometry.h
src/peakfinder8.h
src/peaks.h
src/stream.h
- src/render.h
src/index.h
src/image.h
src/filters.h
- src/dirax.h
- src/mosflm.h
src/cell-utils.h
src/integer_matrix.h
src/crystal.h
- src/xds.h
src/predict-refine.h
src/integration.h
- src/events.h
- src/asdf.h
- src/felix.h
src/peakfinder8.h
- src/taketwo.h
- src/xgandalf.h
- src/pinkindexer.h
src/rational.h
src/spectrum.h
+ src/datatemplate.h
+ src/colscale.h
+ src/detgeom.h
+ src/image-msgpack.h
+ src/fom.h
src/fromfile.h
)
+if (MSGPACK_FOUND)
+ set(LIBCRYSTFEL_SOURCES ${LIBCRYSTFEL_SOURCES} src/image-msgpack.c)
+endif (MSGPACK_FOUND)
+
if (DOXYGEN_FOUND)
configure_file(${PROJECT_SOURCE_DIR}/doc/index.md index.md)
set(DOXYGEN_SHOW_INCLUDE_FILES NO)
@@ -133,6 +118,7 @@ endif (DOXYGEN_FOUND)
add_library(${PROJECT_NAME} SHARED
${LIBCRYSTFEL_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/libcrystfel-version.c
${LIBCRYSTFEL_FFTW_SOURCES}
${LIBCRYSTFEL_HEADERS})
@@ -153,18 +139,18 @@ target_link_libraries(${PROJECT_NAME} PRIVATE util ${HDF5_C_LIBRARIES} ${ZLIB_LI
Threads::Threads GSL::gsl m)
if (XGANDALF_FOUND)
- target_include_directories(${PROJECT_NAME} PRIVATE ${XGANDALF_INCLUDES})
- target_link_libraries(${PROJECT_NAME} PRIVATE ${XGANDALF_LIBRARIES})
+ target_include_directories(${PROJECT_NAME} PRIVATE ${XGANDALF_INCLUDE_DIRS})
+ target_link_libraries(${PROJECT_NAME} PRIVATE ${XGANDALF_LDFLAGS})
endif (XGANDALF_FOUND)
if (FDIP_FOUND)
- target_include_directories(${PROJECT_NAME} PRIVATE ${FDIP_INCLUDES})
- target_link_libraries(${PROJECT_NAME} PRIVATE ${FDIP_LIBRARIES})
+ target_include_directories(${PROJECT_NAME} PRIVATE ${FDIP_INCLUDE_DIRS})
+ target_link_libraries(${PROJECT_NAME} PRIVATE ${FDIP_LDFLAGS})
endif (FDIP_FOUND)
if (PINKINDEXER_FOUND)
- target_include_directories(${PROJECT_NAME} PRIVATE ${PINKINDEXER_INCLUDES})
- target_link_libraries(${PROJECT_NAME} PRIVATE ${PINKINDEXER_LIBRARIES})
+ target_include_directories(${PROJECT_NAME} PRIVATE ${PINKINDEXER_INCLUDE_DIRS})
+ target_link_libraries(${PROJECT_NAME} PRIVATE ${PINKINDEXER_LDFLAGS})
endif (PINKINDEXER_FOUND)
if (FFTW_FOUND)
diff --git a/libcrystfel/config.h.cmake.in b/libcrystfel/config.h.cmake.in
index 731e6fe0..7f0dcd94 100644
--- a/libcrystfel/config.h.cmake.in
+++ b/libcrystfel/config.h.cmake.in
@@ -3,11 +3,11 @@
#cmakedefine HAVE_CLOCK_GETTIME
#cmakedefine HAVE_FFTW
#cmakedefine HAVE_XGANDALF
-#cmakedefine HAVE_NBP
#cmakedefine HAVE_PINKINDEXER
#cmakedefine HAVE_FDIP
#cmakedefine HAVE_CURSES
#cmakedefine HAVE_GZBUFFER
+#cmakedefine HAVE_GDKPIXBUF
#cmakedefine HAVE_FORKPTY_PTY_H
#cmakedefine HAVE_FORKPTY_UTIL_H
diff --git a/libcrystfel/config.h.in b/libcrystfel/config.h.in
new file mode 100644
index 00000000..1fdd2e13
--- /dev/null
+++ b/libcrystfel/config.h.in
@@ -0,0 +1,13 @@
+/* config.h for libcrystfel */
+
+#mesondefine HAVE_FFTW
+#mesondefine HAVE_XGANDALF
+#mesondefine HAVE_PINKINDEXER
+#mesondefine HAVE_FDIP
+#mesondefine HAVE_CURSES
+#mesondefine HAVE_GZBUFFER
+
+#mesondefine HAVE_FORKPTY_PTY_H
+#mesondefine HAVE_FORKPTY_UTIL_H
+
+#define CRYSTFEL_VERSIONSTRING "${CRYSTFEL_VERSION}"
diff --git a/libcrystfel/doc/Doxyfile.in b/libcrystfel/doc/Doxyfile.in
new file mode 100644
index 00000000..b3d42b18
--- /dev/null
+++ b/libcrystfel/doc/Doxyfile.in
@@ -0,0 +1,2536 @@
+# Doxyfile 1.8.15
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "libcrystfel"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER = @VERSION@
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = "@OUTPUT_DIR@"
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all generated output in the proper direction.
+# Possible values are: None, LTR, RTL and Context.
+# The default value is: None.
+
+OUTPUT_TEXT_DIRECTION = None
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines (in the resulting output). You can put ^^ in the value part of an
+# alias to insert a newline as if a physical newline was in the original file.
+# When you need a literal { or } or , in the value part of an alias you have to
+# escape them by means of a backslash (\), this can lead to conflicts with the
+# commands \{ and \} for these it is advised to use the version @{ and @} or use
+# a double escape (\\{ and \\})
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
+# .inc files as Fortran files (default is PHP), and .f files as C (default is
+# Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 0.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 0
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = NO
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = NO
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation. If
+# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = @DOX_TOP@ @INDEX_MD@ @CODING_MD@
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
+# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
+
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.idl \
+ *.ddl \
+ *.odl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.cs \
+ *.d \
+ *.php \
+ *.php4 \
+ *.php5 \
+ *.phtml \
+ *.inc \
+ *.m \
+ *.markdown \
+ *.md \
+ *.mm \
+ *.dox \
+ *.py \
+ *.pyw \
+ *.f90 \
+ *.f95 \
+ *.f03 \
+ *.f08 \
+ *.f \
+ *.for \
+ *.tcl \
+ *.vhd \
+ *.vhdl \
+ *.ucf \
+ *.qsf \
+ *.ice
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE = @INDEX_MD@
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# entity all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see https://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via Javascript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have Javascript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: https://developer.apple.com/xcode/), introduced with OSX
+# 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# https://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from https://www.mathjax.org before deployment.
+# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: https://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: https://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME =
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: \makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD = \makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED = HAVE_FFTW
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/libcrystfel/doc/index.md b/libcrystfel/doc/index.md
index a14e62db..f1c72ed4 100644
--- a/libcrystfel/doc/index.md
+++ b/libcrystfel/doc/index.md
@@ -49,6 +49,7 @@ API documentation
* \ref felix.h "Felix indexer interface"
* \ref predict-refine.h "Prediction refinement"
* \ref integration.h "Integration of reflections"
+* \ref datatemplate.h "Contents of geometry files"
* \ref detector.h "Detector geometry descriptions"
* \ref spectrum.h "Radiation spectrum object"
* \ref hdf5-file.h "HDF5 file interface"
diff --git a/libcrystfel/meson.build b/libcrystfel/meson.build
new file mode 100644
index 00000000..8b8eb77d
--- /dev/null
+++ b/libcrystfel/meson.build
@@ -0,0 +1,185 @@
+# libcrystfel
+
+zlibdep = dependency('zlib', required : true)
+if cc.has_function('gzbuffer',
+ prefix: '#include <zlib.h>',
+ dependencies: zlibdep)
+ conf_data.set10('HAVE_GZBUFFER', 1)
+endif
+
+fftwdep = dependency('fftw3', required : false)
+if fftwdep.found()
+ conf_data.set10('HAVE_FFTW', 1)
+endif
+
+ncursesdep = dependency('ncurses', required: false)
+if ncursesdep.found()
+ conf_data.set10('HAVE_CURSES', 1)
+endif
+
+xgandalfdep = dependency('xgandalf', required: false)
+if xgandalfdep.found()
+ conf_data.set10('HAVE_XGANDALF', 1)
+endif
+
+pinkindexerdep = dependency('pinkIndexer', required: false)
+if pinkindexerdep.found()
+ conf_data.set10('HAVE_PINKINDEXER', 1)
+endif
+
+fdipdep = dependency('fdip', required: false)
+if fdipdep.found()
+ conf_data.set10('HAVE_FDIP', 1)
+endif
+
+libcrystfel_versionc = vcs_tag(input: 'src/libcrystfel-version.c.in',
+ output: 'libcrystfel-version.c')
+
+
+libcrystfel_includes = include_directories('src')
+
+# Find forkpty()
+utildep = cc.find_library('util', required : true)
+if cc.has_function('forkpty', dependencies : utildep, prefix : '#include <pty.h>')
+ conf_data.set10('HAVE_FORKPTY_PTY_H', 1)
+elif cc.has_function('forkpty', dependencies : utildep, prefix : '#include <util.h>')
+ conf_data.set10('HAVE_FORKPTY_UTIL_H', 1)
+else
+ error('Couldn\'t find forkpty()')
+endif
+
+
+# Symmetry operation parser Flex/Bison stuff
+flex = find_program('flex')
+bison = find_program('bison')
+
+flex_gen = generator(flex,
+ output : ['@BASENAME@-lex.c', '@BASENAME@-lex.h'],
+ arguments : ['--outfile=@OUTPUT0@',
+ '--header-file=@OUTPUT1@',
+ '@INPUT@'])
+
+bison_gen = generator(bison,
+ output : ['@BASENAME@-parse.c', '@BASENAME@-parse.h'],
+ arguments : ['--output=@OUTPUT0@',
+ '--defines=@OUTPUT1@',
+ '--report=all',
+ '@INPUT@'])
+
+symop_parse_ch = bison_gen.process('src/symop.y')
+symop_lex_ch = flex_gen.process('src/symop.l')
+
+
+libcrystfel_sources = ['src/image.c',
+ 'src/cell.c',
+ 'src/index.c',
+ 'src/spectrum.c',
+ 'src/cell-utils.c',
+ 'src/integer_matrix.c',
+ 'src/stream.c',
+ 'src/crystal.c',
+ 'src/integration.c',
+ 'src/symmetry.c',
+ 'src/peakfinder8.c',
+ 'src/thread-pool.c',
+ 'src/peaks.c',
+ 'src/utils.c',
+ 'src/predict-refine.c',
+ 'src/filters.c',
+ 'src/rational.c',
+ 'src/geometry.c',
+ 'src/reflist.c',
+ 'src/reflist-utils.c',
+ 'src/datatemplate.c',
+ 'src/colscale.c',
+ 'src/detgeom.c',
+ 'src/fom.c',
+ 'src/image-cbf.c',
+ 'src/image-hdf5.c',
+ 'src/indexers/dirax.c',
+ 'src/indexers/felix.c',
+ 'src/indexers/mosflm.c',
+ 'src/indexers/taketwo.c',
+ 'src/indexers/xds.c',
+ 'src/indexers/asdf.c',
+ 'src/indexers/xgandalf.c',
+ 'src/indexers/pinkindexer.c',
+ symop_lex_ch,
+ symop_parse_ch,
+ ]
+
+if msgpackdep.found()
+ libcrystfel_sources += 'src/image-msgpack.c'
+endif
+
+configure_file(input : 'config.h.in',
+ output : 'config.h',
+ configuration : conf_data)
+
+libcrystfel_conf_inc = include_directories('.')
+
+libcrystfel = library('crystfel', [libcrystfel_sources, libcrystfel_versionc],
+ include_directories : [libcrystfel_includes, libcrystfel_conf_inc],
+ dependencies : [mdep, utildep, fftwdep, gsldep, zlibdep,
+ hdf5dep, pthreaddep, ncursesdep,
+ xgandalfdep, pinkindexerdep, fdipdep],
+ install : true)
+
+libcrystfeldep = declare_dependency(include_directories : libcrystfel_includes,
+ link_with : libcrystfel,
+ dependencies: gsldep)
+
+
+install_headers(['src/reflist.h',
+ 'src/symmetry.h',
+ 'src/cell.h',
+ 'src/reflist-utils.h',
+ 'src/thread-pool.h',
+ 'src/utils.h',
+ 'src/geometry.h',
+ 'src/peakfinder8.h',
+ 'src/peaks.h',
+ 'src/stream.h',
+ 'src/index.h',
+ 'src/image.h',
+ 'src/filters.h',
+ 'src/cell-utils.h',
+ 'src/integer_matrix.h',
+ 'src/crystal.h',
+ 'src/predict-refine.h',
+ 'src/integration.h',
+ 'src/peakfinder8.h',
+ 'src/rational.h',
+ 'src/spectrum.h',
+ 'src/datatemplate.h',
+ 'src/colscale.h',
+ 'src/detgeom.h',
+ 'src/image-msgpack.h',
+ 'src/fom.h'],
+ subdir: 'crystfel')
+
+# API documentation (Doxygen)
+doxygen = find_program('doxygen')
+
+index_md = files('doc/index.md')
+coding_md = files('doc/coding.md')
+
+doc_data = configuration_data()
+doc_data.set('DOX_TOP', join_paths(meson.current_source_dir(), 'src'))
+doc_data.set('INDEX_MD', join_paths(meson.current_source_dir(), 'doc/index.md'))
+doc_data.set('CODING_MD', join_paths(meson.current_source_dir(), 'doc/coding.md'))
+doc_data.set('OUTPUT_DIR', join_paths(meson.current_build_dir(), 'docs'))
+doc_data.set('VERSION', meson.project_version())
+
+doxyfile = configure_file(input: 'doc/Doxyfile.in',
+ output: 'Doxyfile',
+ configuration: doc_data,
+ install: false)
+
+api_docs = run_target('api-docs', command : [doxygen, doxyfile])
+
+
+# pkg-config file
+pkg = import('pkgconfig')
+pkg.generate(libcrystfel,
+ description: 'Data processing for serial crystallography (shared library)')
diff --git a/libcrystfel/src/cell-utils.c b/libcrystfel/src/cell-utils.c
index d269e703..bb654bc5 100644
--- a/libcrystfel/src/cell-utils.c
+++ b/libcrystfel/src/cell-utils.c
@@ -3,12 +3,12 @@
*
* Unit Cell utility functions
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2012 Lorenzo Galli
*
* Authors:
- * 2009-2019 Thomas White <taw@physics.org>
+ * 2009-2021 Thomas White <taw@physics.org>
* 2012 Lorenzo Galli
*
* This file is part of CrystFEL.
@@ -256,6 +256,48 @@ void cell_print(UnitCell *cell)
}
+void cell_print_oneline(UnitCell *cell)
+{
+ LatticeType lt;
+ char cen;
+
+ if ( cell == NULL ) {
+ STATUS("(NULL cell)\n");
+ return;
+ }
+
+ lt = cell_get_lattice_type(cell);
+ cen = cell_get_centering(cell);
+
+ STATUS("%s %c", str_lattice(lt), cen);
+
+ if ( (lt==L_MONOCLINIC) || (lt==L_TETRAGONAL) || ( lt==L_HEXAGONAL)
+ || ( (lt==L_ORTHORHOMBIC) && (cen=='A') )
+ || ( (lt==L_ORTHORHOMBIC) && (cen=='B') )
+ || ( (lt==L_ORTHORHOMBIC) && (cen=='C') ) )
+ {
+ STATUS(", unique axis %c", cell_get_unique_axis(cell));
+ }
+
+ if ( cell_has_parameters(cell) ) {
+
+ double a, b, c, alpha, beta, gamma;
+
+ if ( !right_handed(cell) ) {
+ STATUS(" (left handed)");
+ }
+
+ cell_get_parameters(cell, &a, &b, &c, &alpha, &beta, &gamma);
+
+ STATUS(" %.2f %.2f %.2f A, %.2f %.2f %.2f deg\n",
+ a*1e10, b*1e10, c*1e10,
+ rad2deg(alpha), rad2deg(beta), rad2deg(gamma));
+ } else {
+ STATUS(", no cell parameters.\n");
+ }
+}
+
+
void cell_print_full(UnitCell *cell)
{
cell_print(cell);
@@ -291,8 +333,6 @@ void cell_print_full(UnitCell *cell)
rad2deg(angle_between(asx, asy, asz, csx, csy, csz)),
rad2deg(angle_between(asx, asy, asz, bsx, bsy, bsz)));
- STATUS("Cell representation is %s.\n", cell_rep(cell));
-
}
}
@@ -577,28 +617,18 @@ UnitCell *uncenter_cell(UnitCell *in, IntegerMatrix **pC, RationalMatrix **pCi)
/* Return sin(theta)/lambda = 1/2d. Multiply by two if you want 1/d */
double resolution(UnitCell *cell, signed int h, signed int k, signed int l)
{
- double a, b, c, alpha, beta, gamma;
-
- cell_get_parameters(cell, &a, &b, &c, &alpha, &beta, &gamma);
-
- const double Vsq = a*a*b*b*c*c*(1 - cos(alpha)*cos(alpha)
- - cos(beta)*cos(beta)
- - cos(gamma)*cos(gamma)
- + 2*cos(alpha)*cos(beta)*cos(gamma) );
-
- const double S11 = b*b*c*c*sin(alpha)*sin(alpha);
- const double S22 = a*a*c*c*sin(beta)*sin(beta);
- const double S33 = a*a*b*b*sin(gamma)*sin(gamma);
- const double S12 = a*b*c*c*(cos(alpha)*cos(beta) - cos(gamma));
- const double S23 = a*a*b*c*(cos(beta)*cos(gamma) - cos(alpha));
- const double S13 = a*b*b*c*(cos(gamma)*cos(alpha) - cos(beta));
+ double asx, asy, asz;
+ double bsx, bsy, bsz;
+ double csx, csy, csz;
- const double brackets = S11*h*h + S22*k*k + S33*l*l
- + 2*S12*h*k + 2*S23*k*l + 2*S13*h*l;
- const double oneoverdsq = brackets / Vsq;
- const double oneoverd = sqrt(oneoverdsq);
+ cell_get_reciprocal(cell,
+ &asx, &asy, &asz,
+ &bsx, &bsy, &bsz,
+ &csx, &csy, &csz);
- return oneoverd / 2;
+ return modulus(h*asx + k*bsx + l*csx,
+ h*asy + k*bsy + l*csy,
+ h*asz + k*bsz + l*csz) / 2.0;
}
@@ -1271,6 +1301,49 @@ double cell_get_volume(UnitCell *cell)
/**
+ * \param cell: A %UnitCell
+ *
+ * \returns the value of 1/d for the lowest order reflection
+ * that is not systematically absent according to the centering.
+ *
+ */
+double lowest_reflection(UnitCell *cell)
+{
+ signed int h, k, l;
+ double lowres = INFINITY;
+
+ /* FIXME: Inelegant and nasty. Anyone want to work out
+ * all the possible cases? */
+ for ( h=0; h<4; h++ ) {
+ for ( k=0; k<4; k++ ) {
+ for ( l=0; l<4; l++ ) {
+ if ( (h==0) && (k==0) && (l==0) ) continue;
+ if ( !forbidden_reflection(cell, h, k, l) ) {
+ double r = resolution(cell, h, k, l);
+ if ( r < lowres ) {
+ lowres = r;
+ }
+ }
+ }
+ }
+ }
+ return lowres;
+}
+
+
+/* Return true if the two centering symbols are identical,
+ * or if they are a pair of R/P, which should be considered the
+ * same for the purposes of cell comparison */
+static int centering_equivalent(char cen1, char cen2)
+{
+ if ( cen1 == cen2 ) return 1;
+ if ( (cen1=='P') && (cen2=='R') ) return 1;
+ if ( (cen1=='R') && (cen2=='P') ) return 1;
+ return 0;
+}
+
+
+/**
* \param cell: A UnitCell
* \param reference: Another UnitCell
* \param tols: Pointer to tolerances for a,b,c (fractional), al,be,ga (radians)
@@ -1294,11 +1367,13 @@ int compare_cell_parameters(UnitCell *cell, UnitCell *reference,
/* Centering must match: we don't arbitrate primitive vs centered,
* different cell choices etc */
- if ( cell_get_centering(cell) != cell_get_centering(reference) ) return 0;
+ if ( !centering_equivalent(cell_get_centering(cell),
+ cell_get_centering(reference)) ) return 0;
cell_get_parameters(cell, &a1, &b1, &c1, &al1, &be1, &ga1);
cell_get_parameters(reference, &a2, &b2, &c2, &al2, &be2, &ga2);
+ /* within_tolerance() takes a percentage */
if ( !within_tolerance(a1, a2, tols[0]*100.0) ) return 0;
if ( !within_tolerance(b1, b2, tols[1]*100.0) ) return 0;
if ( !within_tolerance(c1, c2, tols[2]*100.0) ) return 0;
@@ -1344,6 +1419,7 @@ static double moduli_check(double ax, double ay, double az,
* \returns non-zero if the cells match.
*
*/
+/* 'tols' is in frac (not %) and radians */
int compare_cell_parameters_and_orientation(UnitCell *cell, UnitCell *reference,
const double *tols)
{
@@ -1399,6 +1475,7 @@ int compare_cell_parameters_and_orientation(UnitCell *cell, UnitCell *reference,
* \returns non-zero if the cells match.
*
*/
+/* 'tols' is in frac (not %) and radians */
int compare_permuted_cell_parameters_and_orientation(UnitCell *cell,
UnitCell *reference,
const double *tols,
diff --git a/libcrystfel/src/cell-utils.h b/libcrystfel/src/cell-utils.h
index 1c356588..8eefe800 100644
--- a/libcrystfel/src/cell-utils.h
+++ b/libcrystfel/src/cell-utils.h
@@ -3,12 +3,12 @@
*
* Unit Cell utility functions
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2012 Lorenzo Galli
*
* Authors:
- * 2009-2018 Thomas White <taw@physics.org>
+ * 2009-2020 Thomas White <taw@physics.org>
* 2012 Lorenzo Galli
*
* This file is part of CrystFEL.
@@ -31,10 +31,6 @@
#ifndef CELL_UTILS_H
#define CELL_UTILS_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include <gsl/gsl_matrix.h>
#include "cell.h"
@@ -57,6 +53,7 @@ extern UnitCell *rotate_cell(UnitCell *in, double omega, double phi,
double rot);
extern void cell_print(UnitCell *cell);
+extern void cell_print_oneline(UnitCell *cell);
extern void cell_print_full(UnitCell *cell);
extern UnitCell *load_cell_from_pdb(const char *filename);
@@ -82,6 +79,8 @@ extern int forbidden_reflection(UnitCell *cell,
extern double cell_get_volume(UnitCell *cell);
+extern double lowest_reflection(UnitCell *cell);
+
extern int compare_cell_parameters(UnitCell *cell, UnitCell *reference,
const double *tols);
diff --git a/libcrystfel/src/cell.c b/libcrystfel/src/cell.c
index f6ed412d..2e944ddb 100644
--- a/libcrystfel/src/cell.c
+++ b/libcrystfel/src/cell.c
@@ -3,15 +3,15 @@
*
* A class representing a unit cell
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2012 Richard Kirian
* Copyright © 2012 Lorenzo Galli
*
* Authors:
- * 2009-2012,2014,2017 Thomas White <taw@physics.org>
- * 2010 Richard Kirian
- * 2012 Lorenzo Galli
+ * 2009-2021 Thomas White <taw@physics.org>
+ * 2010 Richard Kirian
+ * 2012 Lorenzo Galli
*
* This file is part of CrystFEL.
*
@@ -35,6 +35,7 @@
#endif
#include <math.h>
+#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -54,19 +55,14 @@
*/
-typedef enum {
- CELL_REP_CRYST,
- CELL_REP_CART,
- CELL_REP_RECIP
-} CellRepresentation;
-
struct _unitcell {
- CellRepresentation rep;
-
- int have_parameters;
+ LatticeType lattice_type;
+ char centering;
+ char unique_axis;
/* Crystallographic representation */
+ int have_cryst;
double a; /* m */
double b; /* m */
double c; /* m */
@@ -75,18 +71,16 @@ struct _unitcell {
double gamma; /* Radians */
/* Cartesian representation */
+ int have_cart;
double ax; double bx; double cx;
double ay; double by; double cy;
double az; double bz; double cz;
/* Cartesian representation of reciprocal axes */
+ int have_recip;
double axs; double bxs; double cxs;
double ays; double bys; double cys;
double azs; double bzs; double czs;
-
- LatticeType lattice_type;
- char centering;
- char unique_axis;
};
typedef enum {
@@ -127,12 +121,13 @@ UnitCell *cell_new()
cell->beta = 0.0;
cell->gamma = 0.0;
- cell->rep = CELL_REP_CRYST;
+ cell->have_cryst = 0;
+ cell->have_cart = 0;
+ cell->have_recip = 0;
cell->lattice_type = L_TRICLINIC;
cell->centering = 'P';
cell->unique_axis = '?';
- cell->have_parameters = 0;
return cell;
}
@@ -157,10 +152,12 @@ void cell_free(UnitCell *cell)
* \returns True if cell has its parameters specified.
*
*/
-int cell_has_parameters(UnitCell *cell)
+int cell_has_parameters(const UnitCell *cell)
{
if ( cell == NULL ) return 0;
- return cell->have_parameters;
+ return (cell->have_cryst > 0)
+ || (cell->have_cart > 0 )
+ || (cell->have_recip > 0);
}
@@ -176,8 +173,9 @@ void cell_set_parameters(UnitCell *cell, double a, double b, double c,
cell->beta = beta;
cell->gamma = gamma;
- cell->rep = CELL_REP_CRYST;
- cell->have_parameters = 1;
+ cell->have_cryst = 1;
+ cell->have_cart = 0;
+ cell->have_recip = 0;
}
@@ -192,8 +190,9 @@ void cell_set_cartesian(UnitCell *cell,
cell->bx = bx; cell->by = by; cell->bz = bz;
cell->cx = cx; cell->cy = cy; cell->cz = cz;
- cell->rep = CELL_REP_CART;
- cell->have_parameters = 1;
+ cell->have_cryst = 0;
+ cell->have_cart = 1;
+ cell->have_recip = 0;
}
@@ -223,8 +222,9 @@ UnitCell *cell_new_from_reciprocal_axes(struct rvec as, struct rvec bs,
cell->bxs = bs.u; cell->bys = bs.v; cell->bzs = bs.w;
cell->cxs = cs.u; cell->cys = cs.v; cell->czs = cs.w;
- cell->rep = CELL_REP_RECIP;
- cell->have_parameters = 1;
+ cell->have_cryst = 0;
+ cell->have_cart = 0;
+ cell->have_recip = 1;
return cell;
}
@@ -241,8 +241,9 @@ UnitCell *cell_new_from_direct_axes(struct rvec a, struct rvec b, struct rvec c)
cell->bx = b.u; cell->by = b.v; cell->bz = b.w;
cell->cx = c.u; cell->cy = c.v; cell->cz = c.w;
- cell->rep = CELL_REP_CART;
- cell->have_parameters = 1;
+ cell->have_cryst = 0;
+ cell->have_cart = 1;
+ cell->have_recip = 0;
return cell;
}
@@ -268,8 +269,9 @@ void cell_set_reciprocal(UnitCell *cell,
cell->bxs = bsx; cell->bys = bsy; cell->bzs = bsz;
cell->cxs = csx; cell->cys = csy; cell->czs = csz;
- cell->rep = CELL_REP_RECIP;
- cell->have_parameters = 1;
+ cell->have_cryst = 0;
+ cell->have_cart = 0;
+ cell->have_recip = 1;
}
@@ -291,31 +293,25 @@ void cell_set_unique_axis(UnitCell *cell, char unique_axis)
}
-/************************* Getter helper functions ****************************/
+/************************* Conversion functions ****************************/
-static int cell_crystallographic_to_cartesian(const UnitCell *cell,
- double *ax, double *ay, double *az,
- double *bx, double *by, double *bz,
- double *cx, double *cy, double *cz)
+static void crystallographic_to_cartesian(UnitCell *cell)
{
double tmp, V, cosalphastar, cstar;
- if ( !cell->have_parameters ) {
- ERROR("Unit cell has unspecified parameters.\n");
- return 1;
- }
+ assert(cell->have_cryst == 1);
/* Firstly: Get a in terms of x, y and z
* +a (cryst) is defined to lie along +x (cart) */
- *ax = cell->a;
- *ay = 0.0;
- *az = 0.0;
+ cell->ax = cell->a;
+ cell->ay = 0.0;
+ cell->az = 0.0;
/* b in terms of x, y and z
* b (cryst) is defined to lie in the xy (cart) plane */
- *bx = cell->b*cos(cell->gamma);
- *by = cell->b*sin(cell->gamma);
- *bz = 0.0;
+ cell->bx = cell->b*cos(cell->gamma);
+ cell->by = cell->b*sin(cell->gamma);
+ cell->bz = 0.0;
tmp = cos(cell->alpha)*cos(cell->alpha)
+ cos(cell->beta)*cos(cell->beta)
@@ -329,21 +325,41 @@ static int cell_crystallographic_to_cartesian(const UnitCell *cell,
cstar = (cell->a * cell->b * sin(cell->gamma))/V;
/* c in terms of x, y and z */
- *cx = cell->c*cos(cell->beta);
- *cy = -cell->c*sin(cell->beta)*cosalphastar;
- *cz = 1.0/cstar;
+ cell->cx = cell->c*cos(cell->beta);
+ cell->cy = -cell->c*sin(cell->beta)*cosalphastar;
+ cell->cz = 1.0/cstar;
- return 0;
+ cell->have_cart = 1;
+}
+
+
+static void cartesian_to_crystallographic(UnitCell *cell)
+{
+ assert(cell->have_cart);
+
+ /* Convert cartesian -> crystallographic */
+ cell->a = modulus(cell->ax, cell->ay, cell->az);
+ cell->b = modulus(cell->bx, cell->by, cell->bz);
+ cell->c = modulus(cell->cx, cell->cy, cell->cz);
+
+ cell->alpha = angle_between(cell->bx, cell->by, cell->bz,
+ cell->cx, cell->cy, cell->cz);
+ cell->beta = angle_between(cell->ax, cell->ay, cell->az,
+ cell->cx, cell->cy, cell->cz);
+ cell->gamma = angle_between(cell->ax, cell->ay, cell->az,
+ cell->bx, cell->by, cell->bz);
+
+ cell->have_cryst = 1;
}
/* Why yes, I do enjoy long argument lists...! */
-static int cell_invert(double ax, double ay, double az,
- double bx, double by, double bz,
- double cx, double cy, double cz,
- double *asx, double *asy, double *asz,
- double *bsx, double *bsy, double *bsz,
- double *csx, double *csy, double *csz)
+static int invert(double ax, double ay, double az,
+ double bx, double by, double bz,
+ double cx, double cy, double cz,
+ double *asx, double *asy, double *asz,
+ double *bsx, double *bsy, double *bsz,
+ double *csx, double *csy, double *csz)
{
int s;
gsl_matrix *m;
@@ -413,167 +429,153 @@ static int cell_invert(double ax, double ay, double az,
}
+static int reciprocal_to_cartesian(UnitCell *cell)
+{
+ assert(cell->have_recip);
+
+ if ( invert(cell->axs, cell->ays, cell->azs,
+ cell->bxs, cell->bys, cell->bzs,
+ cell->cxs, cell->cys, cell->czs,
+ &cell->ax, &cell->ay, &cell->az,
+ &cell->bx, &cell->by, &cell->bz,
+ &cell->cx, &cell->cy, &cell->cz) ) return 1;
+
+ cell->have_cart = 1;
+ return 0;
+}
+
+
+static int cartesian_to_reciprocal(UnitCell *cell)
+{
+ assert(cell->have_cart);
+
+ if ( invert(cell->ax, cell->ay, cell->az,
+ cell->bx, cell->by, cell->bz,
+ cell->cx, cell->cy, cell->cz,
+ &cell->axs, &cell->ays, &cell->azs,
+ &cell->bxs, &cell->bys, &cell->bzs,
+ &cell->cxs, &cell->cys, &cell->czs) ) return 1;
+
+ cell->have_recip = 1;
+ return 0;
+}
+
+
/********************************** Getters ***********************************/
-int cell_get_parameters(const UnitCell *cell, double *a, double *b, double *c,
+int cell_get_parameters(UnitCell *cell,
+ double *a, double *b, double *c,
double *alpha, double *beta, double *gamma)
{
- double ax, ay, az, bx, by, bz, cx, cy, cz;
-
if ( cell == NULL ) return 1;
- if ( !cell->have_parameters ) {
+ if ( cell->have_cryst ) {
+
+ /* Nothing to do */
+
+ } else if ( cell->have_cart ) {
+
+ cartesian_to_crystallographic(cell);
+
+ } else if ( cell->have_recip ) {
+
+ if ( reciprocal_to_cartesian(cell) ) return 1;
+ cartesian_to_crystallographic(cell);
+
+ } else {
+
ERROR("Unit cell has unspecified parameters.\n");
return 1;
- }
- switch ( cell->rep ) {
-
- case CELL_REP_CRYST:
- /* Direct response */
- *a = cell->a;
- *b = cell->b;
- *c = cell->c;
- *alpha = cell->alpha;
- *beta = cell->beta;
- *gamma = cell->gamma;
- return 0;
-
- case CELL_REP_CART:
- /* Convert cartesian -> crystallographic */
- *a = modulus(cell->ax, cell->ay, cell->az);
- *b = modulus(cell->bx, cell->by, cell->bz);
- *c = modulus(cell->cx, cell->cy, cell->cz);
-
- *alpha = angle_between(cell->bx, cell->by, cell->bz,
- cell->cx, cell->cy, cell->cz);
- *beta = angle_between(cell->ax, cell->ay, cell->az,
- cell->cx, cell->cy, cell->cz);
- *gamma = angle_between(cell->ax, cell->ay, cell->az,
- cell->bx, cell->by, cell->bz);
- return 0;
-
- case CELL_REP_RECIP:
- /* Convert reciprocal -> crystallographic.
- * Start by converting reciprocal -> cartesian */
- if ( cell_invert(cell->axs, cell->ays, cell->azs,
- cell->bxs, cell->bys, cell->bzs,
- cell->cxs, cell->cys, cell->czs,
- &ax, &ay, &az,
- &bx, &by, &bz,
- &cx, &cy, &cz) ) return 1;
-
- /* Now convert cartesian -> crystallographic */
- *a = modulus(ax, ay, az);
- *b = modulus(bx, by, bz);
- *c = modulus(cx, cy, cz);
-
- *alpha = angle_between(bx, by, bz, cx, cy, cz);
- *beta = angle_between(ax, ay, az, cx, cy, cz);
- *gamma = angle_between(ax, ay, az, bx, by, bz);
- return 0;
}
- return 1;
+ *a = cell->a;
+ *b = cell->b;
+ *c = cell->c;
+ *alpha = cell->alpha;
+ *beta = cell->beta;
+ *gamma = cell->gamma;
+ return 0;
}
-int cell_get_cartesian(const UnitCell *cell,
+int cell_get_cartesian(UnitCell *cell,
double *ax, double *ay, double *az,
double *bx, double *by, double *bz,
double *cx, double *cy, double *cz)
{
if ( cell == NULL ) return 1;
- if ( !cell->have_parameters ) {
+ if ( cell->have_cart ) {
+
+ /* Nothing to do */
+
+ } else if ( cell->have_recip ) {
+
+ /* NB recip->cart has priority over
+ * cryst->cart, to preserve orientation */
+ reciprocal_to_cartesian(cell);
+
+ } else if ( cell->have_cryst ) {
+
+ crystallographic_to_cartesian(cell);
+
+ } else {
+
ERROR("Unit cell has unspecified parameters.\n");
return 1;
- }
-
- switch ( cell->rep ) {
-
- case CELL_REP_CRYST:
- /* Convert crystallographic -> cartesian. */
- return cell_crystallographic_to_cartesian(cell,
- ax, ay, az,
- bx, by, bz,
- cx, cy, cz);
-
- case CELL_REP_CART:
- /* Direct response */
- *ax = cell->ax; *ay = cell->ay; *az = cell->az;
- *bx = cell->bx; *by = cell->by; *bz = cell->bz;
- *cx = cell->cx; *cy = cell->cy; *cz = cell->cz;
- return 0;
-
- case CELL_REP_RECIP:
- /* Convert reciprocal -> cartesian */
- return cell_invert(cell->axs, cell->ays, cell->azs,
- cell->bxs, cell->bys, cell->bzs,
- cell->cxs, cell->cys, cell->czs,
- ax, ay, az, bx, by, bz, cx, cy, cz);
}
- return 1;
+ *ax = cell->ax; *ay = cell->ay; *az = cell->az;
+ *bx = cell->bx; *by = cell->by; *bz = cell->bz;
+ *cx = cell->cx; *cy = cell->cy; *cz = cell->cz;
+ return 0;
}
-int cell_get_reciprocal(const UnitCell *cell,
+int cell_get_reciprocal(UnitCell *cell,
double *asx, double *asy, double *asz,
double *bsx, double *bsy, double *bsz,
double *csx, double *csy, double *csz)
{
- int r;
- double ax, ay, az, bx, by, bz, cx, cy, cz;
-
if ( cell == NULL ) return 1;
- if ( !cell->have_parameters ) {
+ if ( cell->have_recip ) {
+
+ /* Nothing to do */
+
+ } else if ( cell->have_cart ) {
+
+ /* NB cart->recip has priority over cryst->recip */
+ cartesian_to_reciprocal(cell);
+
+ } else if ( cell->have_cryst ) {
+
+ crystallographic_to_cartesian(cell);
+ cartesian_to_reciprocal(cell);
+
+ } else {
+
ERROR("Unit cell has unspecified parameters.\n");
return 1;
- }
-
- switch ( cell->rep ) {
-
- case CELL_REP_CRYST:
- /* Convert crystallographic -> reciprocal */
- r = cell_crystallographic_to_cartesian(cell,
- &ax, &ay, &az,
- &bx, &by, &bz,
- &cx, &cy, &cz);
- if ( r ) return r;
- return cell_invert(ax, ay, az,bx, by, bz, cx, cy, cz,
- asx, asy, asz, bsx, bsy, bsz, csx, csy, csz);
-
- case CELL_REP_CART:
- /* Convert cartesian -> reciprocal */
- cell_invert(cell->ax, cell->ay, cell->az,
- cell->bx, cell->by, cell->bz,
- cell->cx, cell->cy, cell->cz,
- asx, asy, asz, bsx, bsy, bsz, csx, csy, csz);
- return 0;
-
- case CELL_REP_RECIP:
- /* Direct response */
- *asx = cell->axs; *asy = cell->ays; *asz = cell->azs;
- *bsx = cell->bxs; *bsy = cell->bys; *bsz = cell->bzs;
- *csx = cell->cxs; *csy = cell->cys; *csz = cell->czs;
- return 0;
}
- return 1;
+ *asx = cell->axs; *asy = cell->ays; *asz = cell->azs;
+ *bsx = cell->bxs; *bsy = cell->bys; *bsz = cell->bzs;
+ *csx = cell->cxs; *csy = cell->cys; *csz = cell->czs;
+ return 0;
}
-char cell_get_centering(UnitCell *cell)
+char cell_get_centering(const UnitCell *cell)
{
return cell->centering;
}
-LatticeType cell_get_lattice_type(UnitCell *cell)
+LatticeType cell_get_lattice_type(const UnitCell *cell)
{
return cell->lattice_type;
}
@@ -594,31 +596,12 @@ struct g6 cell_get_G6(UnitCell *cell)
}
-char cell_get_unique_axis(UnitCell *cell)
+char cell_get_unique_axis(const UnitCell *cell)
{
return cell->unique_axis;
}
-const char *cell_rep(UnitCell *cell)
-{
- switch ( cell->rep ) {
-
- case CELL_REP_CRYST:
- return "crystallographic, direct space";
-
- case CELL_REP_CART:
- return "cartesian, direct space";
-
- case CELL_REP_RECIP:
- return "cartesian, reciprocal space";
-
- }
-
- return "unknown";
-}
-
-
UnitCell *cell_transform_gsl_direct(UnitCell *in, gsl_matrix *m)
{
gsl_matrix *c;
diff --git a/libcrystfel/src/cell.h b/libcrystfel/src/cell.h
index 3deb92ff..ed82fff7 100644
--- a/libcrystfel/src/cell.h
+++ b/libcrystfel/src/cell.h
@@ -3,15 +3,15 @@
*
* A class representing a unit cell
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2012 Richard Kirian
* Copyright © 2012 Lorenzo Galli
*
* Authors:
- * 2009-2012,2014,2017 Thomas White <taw@physics.org>
- * 2010,2012 Richard Kirian
- * 2012 Lorenzo Galli
+ * 2009-2021 Thomas White <taw@physics.org>
+ * 2010-2012 Richard Kirian
+ * 2012 Lorenzo Galli
*
* This file is part of CrystFEL.
*
@@ -33,10 +33,6 @@
#ifndef CELL_H
#define CELL_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include "utils.h"
#include "integer_matrix.h"
@@ -101,7 +97,7 @@ extern UnitCell *cell_new_from_reciprocal_axes(struct rvec as, struct rvec bs,
extern UnitCell *cell_new_from_direct_axes(struct rvec as, struct rvec bs,
struct rvec cs);
-extern int cell_has_parameters(UnitCell *cell);
+extern int cell_has_parameters(const UnitCell *cell);
extern void cell_set_cartesian(UnitCell *cell,
double ax, double ay, double az,
@@ -111,15 +107,15 @@ extern void cell_set_cartesian(UnitCell *cell,
extern void cell_set_parameters(UnitCell *cell, double a, double b, double c,
double alpha, double beta, double gamma);
-extern int cell_get_parameters(const UnitCell *cell, double *a, double *b, double *c,
+extern int cell_get_parameters(UnitCell *cell, double *a, double *b, double *c,
double *alpha, double *beta, double *gamma);
-extern int cell_get_cartesian(const UnitCell *cell,
+extern int cell_get_cartesian(UnitCell *cell,
double *ax, double *ay, double *az,
double *bx, double *by, double *bz,
double *cx, double *cy, double *cz);
-extern int cell_get_reciprocal(const UnitCell *cell,
+extern int cell_get_reciprocal(UnitCell *cell,
double *asx, double *asy, double *asz,
double *bsx, double *bsy, double *bsz,
double *csx, double *csy, double *csz);
@@ -129,7 +125,7 @@ extern void cell_set_reciprocal(UnitCell *cell,
double bsx, double bsy, double bsz,
double csx, double csy, double csz);
-extern LatticeType cell_get_lattice_type(UnitCell *cell);
+extern LatticeType cell_get_lattice_type(const UnitCell *cell);
extern void cell_set_lattice_type(UnitCell *cell, LatticeType lattice_type);
struct g6
@@ -144,14 +140,12 @@ struct g6
extern struct g6 cell_get_G6(UnitCell *cell);
-extern char cell_get_centering(UnitCell *cell);
+extern char cell_get_centering(const UnitCell *cell);
extern void cell_set_centering(UnitCell *cell, char centering);
-extern char cell_get_unique_axis(UnitCell *cell);
+extern char cell_get_unique_axis(const UnitCell *cell);
extern void cell_set_unique_axis(UnitCell *cell, char unique_axis);
-extern const char *cell_rep(UnitCell *cell);
-
extern UnitCell *cell_transform_gsl_direct(UnitCell *in, gsl_matrix *m);
extern UnitCell *cell_transform_rational(UnitCell *cell, RationalMatrix *m);
diff --git a/libcrystfel/src/render.c b/libcrystfel/src/colscale.c
index 284f4c46..4a39de8d 100644
--- a/libcrystfel/src/render.c
+++ b/libcrystfel/src/colscale.c
@@ -1,13 +1,13 @@
/*
- * render.c
+ * colscale.c
*
- * Render a high dynamic range buffer in some sensible way
+ * Colour scales
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2009-2012,2014 Thomas White <taw@physics.org>
+ * 2009-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -35,14 +35,9 @@
#include <math.h>
#include <stdint.h>
+#include "colscale.h"
-#include "hdf5-file.h"
-#include "render.h"
-#include "peaks.h"
-#include "filters.h"
-#include "utils.h"
-
-/** \file render.h */
+/** \file colscale.h */
static void render_rgb(double val, double max,
double *rp, double *gp, double *bp)
@@ -223,8 +218,8 @@ static void render_invmono(double val, double max,
}
-void render_scale(double val, double max, int scale,
- double *rp, double *gp, double *bp)
+void colscale_lookup(double val, double max, int scale,
+ double *rp, double *gp, double *bp)
{
switch ( scale ) {
diff --git a/libcrystfel/src/render.h b/libcrystfel/src/colscale.h
index a3292515..972b659b 100644
--- a/libcrystfel/src/render.h
+++ b/libcrystfel/src/colscale.h
@@ -1,13 +1,13 @@
/*
- * render.h
+ * colscale.h
*
- * Render a high dynamic range buffer in some sensible way
+ * Colour scales
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2009-2012 Thomas White <taw@physics.org>
+ * 2009-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -26,16 +26,12 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifndef RENDER_H
-#define RENDER_H
+#ifndef COLSCALE_H
+#define COLSCALE_H
/**
- * \file render.h
- * Colour scale for rendering
+ * \file colscale.h
+ * Colour scales for rendering
*/
enum {
@@ -51,12 +47,12 @@ extern "C" {
#endif
/* Colour scale lookup */
-extern void render_scale(double val, double max, int scale,
- double *rp, double *gp, double *bp);
+extern void colscale_lookup(double val, double max, int scale,
+ double *rp, double *gp, double *bp);
#ifdef __cplusplus
}
#endif
-#endif /* RENDER_H */
+#endif /* COLSCALE_H */
diff --git a/libcrystfel/src/crystal.c b/libcrystfel/src/crystal.c
index 9202c668..c9f59bb7 100644
--- a/libcrystfel/src/crystal.c
+++ b/libcrystfel/src/crystal.c
@@ -3,11 +3,11 @@
*
* A class representing a single crystal
*
- * Copyright © 2013-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2013-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2013-2016 Thomas White <taw@physics.org>
+ * 2013-2020 Thomas White <taw@physics.org>
* 2016 Valerio Mariani
*
* This file is part of CrystFEL.
@@ -33,6 +33,7 @@
#include "crystal.h"
#include "utils.h"
+#include "reflist-utils.h"
/**
@@ -66,7 +67,7 @@ struct _crystal
/* Text notes, which go in the stream */
char *notes;
- /* Detector shift */
+ /* Detector shift in metres */
double det_shift_x;
double det_shift_y;
};
@@ -127,6 +128,44 @@ Crystal *crystal_copy(const Crystal *cryst)
/**
+ * \param cryst: A \ref Crystal to copy.
+ *
+ * Creates a new \ref Crystal which is a copy of \p cryst. The copy is a "deep
+ * copy", which means that copies ARE made of the data structures which
+ * \p cryst contains references to, for example its \ref RefList.
+ *
+ * \returns A (deep) copy of \p cryst, or NULL on failure.
+ *
+ */
+Crystal *crystal_copy_deep(const Crystal *cryst)
+{
+ Crystal *c;
+
+ c = crystal_new();
+ if ( c == NULL ) return NULL;
+
+ memcpy(c, cryst, sizeof(Crystal));
+ if ( c->notes != NULL ) c->notes = strdup(c->notes);
+
+ if ( cryst->cell != NULL ) {
+ UnitCell *cell;
+ cell = cell_new_from_cell(cryst->cell);
+ if ( cell == NULL ) return NULL;
+ c->cell = cell;
+ }
+
+ if ( cryst->reflections != NULL ) {
+ RefList *refls;
+ refls = copy_reflist(cryst->reflections);
+ if ( refls == NULL ) return NULL;
+ c->reflections = refls;
+ }
+
+ return c;
+}
+
+
+/**
* \param cryst: A \ref Crystal to free.
*
* Frees a \ref Crystal, and all internal resources concerning that crystal.
diff --git a/libcrystfel/src/crystal.h b/libcrystfel/src/crystal.h
index 669c173f..5a4ca3f6 100644
--- a/libcrystfel/src/crystal.h
+++ b/libcrystfel/src/crystal.h
@@ -3,11 +3,11 @@
*
* A class representing a single crystal
*
- * Copyright © 2013-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2013-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2013-2016 Thomas White <taw@physics.org>
+ * 2013-2020 Thomas White <taw@physics.org>
* 2016 Valerio Mariani
*
* This file is part of CrystFEL.
@@ -30,11 +30,6 @@
#ifndef CRYSTAL_H
#define CRYSTAL_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include "cell.h"
/**
@@ -56,6 +51,7 @@ extern "C" {
extern Crystal *crystal_new(void);
extern Crystal *crystal_copy(const Crystal *cryst);
+extern Crystal *crystal_copy_deep(const Crystal *cryst);
extern void crystal_free(Crystal *cryst);
extern UnitCell *crystal_get_cell(Crystal *cryst);
diff --git a/libcrystfel/src/datatemplate.c b/libcrystfel/src/datatemplate.c
new file mode 100644
index 00000000..290b9227
--- /dev/null
+++ b/libcrystfel/src/datatemplate.c
@@ -0,0 +1,1683 @@
+/*
+ * datatemplate.c
+ *
+ * Data template structure
+ *
+ * Copyright © 2019-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2019-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "utils.h"
+#include "datatemplate.h"
+
+#include "datatemplate_priv.h"
+
+
+/**
+ * \file datatemplate.h
+ */
+
+struct rg_definition {
+ char *name;
+ char *pns;
+};
+
+
+struct rgc_definition {
+ char *name;
+ char *rgs;
+};
+
+
+static struct panel_template *new_panel(DataTemplate *det,
+ const char *name,
+ struct panel_template *defaults)
+{
+ struct panel_template *new;
+ int i;
+
+ det->n_panels++;
+ det->panels = realloc(det->panels,
+ det->n_panels*sizeof(struct panel_template));
+
+ new = &det->panels[det->n_panels-1];
+ memcpy(new, defaults, sizeof(struct panel_template));
+
+ /* Set name */
+ new->name = strdup(name);
+
+ /* Copy strings */
+ new->cnz_from = safe_strdup(defaults->cnz_from);
+ new->data = safe_strdup(defaults->data);
+ new->satmap = safe_strdup(defaults->satmap);
+ new->satmap_file = safe_strdup(defaults->satmap_file);
+ for ( i=0; i<MAX_MASKS; i++ ) {
+ new->masks[i].data_location = safe_strdup(defaults->masks[i].data_location);
+ new->masks[i].filename = safe_strdup(defaults->masks[i].filename);
+ }
+
+ return new;
+}
+
+
+static struct dt_badregion *new_bad_region(DataTemplate *det, const char *name)
+{
+ struct dt_badregion *new;
+
+ det->n_bad++;
+ det->bad = realloc(det->bad, det->n_bad*sizeof(struct dt_badregion));
+
+ new = &det->bad[det->n_bad-1];
+ new->min_x = NAN;
+ new->max_x = NAN;
+ new->min_y = NAN;
+ new->max_y = NAN;
+ new->min_fs = 0;
+ new->max_fs = 0;
+ new->min_ss = 0;
+ new->max_ss = 0;
+ new->is_fsss = 99; /* Slightly nasty: means "unassigned" */
+ new->panel_name = NULL;
+ new->panel_number = 0; /* Needs to be set after loading */
+ strcpy(new->name, name);
+
+ return new;
+}
+
+
+static struct panel_template *find_panel_by_name(DataTemplate *det,
+ const char *name)
+{
+ int i;
+
+ for ( i=0; i<det->n_panels; i++ ) {
+ if ( strcmp(det->panels[i].name, name) == 0 ) {
+ return &det->panels[i];
+ }
+ }
+
+ return NULL;
+}
+
+
+static struct dt_badregion *find_bad_region_by_name(DataTemplate *det,
+ const char *name)
+{
+ int i;
+
+ for ( i=0; i<det->n_bad; i++ ) {
+ if ( strcmp(det->bad[i].name, name) == 0 ) {
+ return &det->bad[i];
+ }
+ }
+
+ return NULL;
+}
+
+
+static struct rigid_group *find_or_add_rg(DataTemplate *det,
+ const char *name)
+{
+ int i;
+ struct rigid_group **new;
+ struct rigid_group *rg;
+
+ for ( i=0; i<det->n_rigid_groups; i++ ) {
+
+ if ( strcmp(det->rigid_groups[i]->name, name) == 0 ) {
+ return det->rigid_groups[i];
+ }
+
+ }
+
+ new = realloc(det->rigid_groups,
+ (1+det->n_rigid_groups)*sizeof(struct rigid_group *));
+ if ( new == NULL ) return NULL;
+
+ det->rigid_groups = new;
+
+ rg = malloc(sizeof(struct rigid_group));
+ if ( rg == NULL ) return NULL;
+
+ det->rigid_groups[det->n_rigid_groups++] = rg;
+
+ rg->name = strdup(name);
+ rg->panel_numbers = NULL;
+ rg->n_panels = 0;
+
+ return rg;
+}
+
+
+static struct rg_collection *find_or_add_rg_coll(DataTemplate *det,
+ const char *name)
+{
+ int i;
+ struct rg_collection **new;
+ struct rg_collection *rgc;
+
+ for ( i=0; i<det->n_rg_collections; i++ ) {
+ if ( strcmp(det->rigid_group_collections[i]->name, name) == 0 )
+ {
+ return det->rigid_group_collections[i];
+ }
+ }
+
+ new = realloc(det->rigid_group_collections,
+ (1+det->n_rg_collections)*sizeof(struct rg_collection *));
+ if ( new == NULL ) return NULL;
+
+ det->rigid_group_collections = new;
+
+ rgc = malloc(sizeof(struct rg_collection));
+ if ( rgc == NULL ) return NULL;
+
+ det->rigid_group_collections[det->n_rg_collections++] = rgc;
+
+ rgc->name = strdup(name);
+ rgc->rigid_groups = NULL;
+ rgc->n_rigid_groups = 0;
+
+ return rgc;
+}
+
+
+static void add_to_rigid_group(struct rigid_group *rg, int panel_number)
+{
+ int *pn;
+
+ pn = realloc(rg->panel_numbers, (1+rg->n_panels)*sizeof(int));
+ if ( pn == NULL ) {
+ ERROR("Couldn't add panel to rigid group.\n");
+ return;
+ }
+
+ rg->panel_numbers = pn;
+ rg->panel_numbers[rg->n_panels++] = panel_number;
+}
+
+
+static void add_to_rigid_group_coll(struct rg_collection *rgc,
+ struct rigid_group *rg)
+{
+ struct rigid_group **r;
+
+ r = realloc(rgc->rigid_groups, (1+rgc->n_rigid_groups)*
+ sizeof(struct rigid_group *));
+ if ( r == NULL ) {
+ ERROR("Couldn't add rigid group to collection.\n");
+ return;
+ }
+
+ rgc->rigid_groups = r;
+ rgc->rigid_groups[rgc->n_rigid_groups++] = rg;
+}
+
+
+/* Free all rigid groups in detector */
+static void free_all_rigid_groups(DataTemplate *det)
+{
+ int i;
+
+ if ( det->rigid_groups == NULL ) return;
+ for ( i=0; i<det->n_rigid_groups; i++ ) {
+ free(det->rigid_groups[i]->name);
+ free(det->rigid_groups[i]->panel_numbers);
+ free(det->rigid_groups[i]);
+ }
+ free(det->rigid_groups);
+}
+
+
+/* Free all rigid groups in detector */
+static void free_all_rigid_group_collections(DataTemplate *det)
+{
+ int i;
+
+ if ( det->rigid_group_collections == NULL ) return;
+ for ( i=0; i<det->n_rg_collections; i++ ) {
+ free(det->rigid_group_collections[i]->name);
+ free(det->rigid_group_collections[i]->rigid_groups);
+ free(det->rigid_group_collections[i]);
+ }
+ free(det->rigid_group_collections);
+}
+
+
+static struct rigid_group *find_rigid_group_by_name(DataTemplate *det,
+ char *name)
+{
+ int i;
+
+ for ( i=0; i<det->n_rigid_groups; i++ ) {
+ if ( strcmp(det->rigid_groups[i]->name, name) == 0 ) {
+ return det->rigid_groups[i];
+ }
+ }
+
+ return NULL;
+}
+
+
+static int atob(const char *a)
+{
+ if ( strcasecmp(a, "true") == 0 ) return 1;
+ if ( strcasecmp(a, "false") == 0 ) return 0;
+ return atoi(a);
+}
+
+
+static int assplode_algebraic(const char *a_orig, char ***pbits)
+{
+ int len, i;
+ int nexp;
+ char **bits;
+ char *a;
+ int idx, istr;
+
+ len = strlen(a_orig);
+
+ /* Add plus at start if no sign there already */
+ if ( (a_orig[0] != '+') && (a_orig[0] != '-') ) {
+ len += 1;
+ a = malloc(len+1);
+ snprintf(a, len+1, "+%s", a_orig);
+ a[len] = '\0';
+
+ } else {
+ a = strdup(a_orig);
+ }
+
+ /* Count the expressions */
+ nexp = 0;
+ for ( i=0; i<len; i++ ) {
+ if ( (a[i] == '+') || (a[i] == '-') ) nexp++;
+ }
+
+ bits = calloc(nexp, sizeof(char *));
+
+ /* Break the string up */
+ idx = -1;
+ istr = 0;
+ assert((a[0] == '+') || (a[0] == '-'));
+ for ( i=0; i<len; i++ ) {
+
+ char ch;
+
+ ch = a[i];
+
+ if ( ch == ' ' ) continue;
+
+ if ( (ch == '+') || (ch == '-') ) {
+ if ( idx >= 0 ) bits[idx][istr] = '\0';
+ idx++;
+ bits[idx] = malloc(len+1);
+ istr = 0;
+ }
+
+ if ( !isdigit(ch) && (ch != '.') && (ch != '+') && (ch != '-')
+ && (ch != 'x') && (ch != 'y') && (ch != 'z') )
+ {
+ ERROR("Invalid character '%c' found.\n", ch);
+ return 0;
+ }
+
+ assert(idx >= 0);
+ bits[idx][istr++] = ch;
+
+ }
+ if ( idx >= 0 ) bits[idx][istr] = '\0';
+
+ *pbits = bits;
+ free(a);
+
+ return nexp;
+}
+
+
+/* Parses the scan directions (accounting for possible rotation)
+ * Assumes all white spaces have been already removed */
+static int dir_conv(const char *a, double *sx, double *sy, double *sz)
+{
+ int n;
+ char **bits;
+ int i;
+
+ *sx = 0.0; *sy = 0.0; *sz = 0.0;
+
+ n = assplode_algebraic(a, &bits);
+
+ if ( n == 0 ) {
+ ERROR("Invalid direction '%s'\n", a);
+ return 1;
+ }
+
+ for ( i=0; i<n; i++ ) {
+
+ int len;
+ double val;
+ char axis;
+ int j;
+
+ len = strlen(bits[i]);
+ assert(len != 0);
+ axis = bits[i][len-1];
+ if ( (axis != 'x') && (axis != 'y') && (axis != 'z') ) {
+ ERROR("Invalid symbol '%c' - must be x, y or z.\n",
+ axis);
+ return 1;
+ }
+
+ /* Chop off the symbol now it's dealt with */
+ bits[i][len-1] = '\0';
+
+ /* Check for anything that isn't part of a number */
+ for ( j=0; j<strlen(bits[i]); j++ ) {
+ if ( isdigit(bits[i][j]) ) continue;
+ if ( bits[i][j] == '+' ) continue;
+ if ( bits[i][j] == '-' ) continue;
+ if ( bits[i][j] == '.' ) continue;
+ ERROR("Invalid coefficient '%s'\n", bits[i]);
+ }
+
+ if ( strlen(bits[i]) == 0 ) {
+ val = 1.0;
+ } else {
+ val = atof(bits[i]);
+ }
+ if ( strlen(bits[i]) == 1 ) {
+ if ( bits[i][0] == '+' ) val = 1.0;
+ if ( bits[i][0] == '-' ) val = -1.0;
+ }
+ switch ( axis ) {
+
+ case 'x' :
+ *sx += val;
+ break;
+
+ case 'y' :
+ *sy += val;
+ break;
+
+ case 'z' :
+ *sz += val;
+ break;
+ }
+
+ free(bits[i]);
+
+ }
+ free(bits);
+
+ return 0;
+}
+
+
+int set_dim(struct panel_template *panel, int dimension,
+ const char *val)
+{
+ if ( dimension >= MAX_DIMS ) {
+ ERROR("Too many dimensions!\n");
+ return 1;
+ }
+
+ if ( strcmp(val, "fs") == 0 ) {
+ panel->dims[dimension] = DIM_FS;
+ } else if ( strcmp(val, "ss") == 0 ) {
+ panel->dims[dimension] = DIM_SS;
+ } else if ( strcmp(val, "%") == 0 ) {
+ panel->dims[dimension] = DIM_PLACEHOLDER;
+ } else {
+ char *endptr;
+ unsigned long int fix_val = strtoul(val, &endptr, 10);
+ if ( endptr[0] != '\0' ) {
+ ERROR("Invalid dimension value '%s'\n", val);
+ return 1;
+ } else {
+ panel->dims[dimension] = fix_val;
+ }
+ }
+ return 0;
+}
+
+
+static int add_flag_value(struct panel_template *p,
+ float val,
+ enum flag_value_type type)
+{
+ int i;
+
+ for ( i=0; i<MAX_FLAG_VALUES; i++ ) {
+ if ( p->flag_types[i] == FLAG_NOTHING ) {
+ p->flag_types[i] = type;
+ p->flag_values[i] = val;
+ return 0;
+ }
+ }
+
+ ERROR("Too many flag values.\n");
+ return 1;
+}
+
+
+static int parse_mask(struct panel_template *panel,
+ const char *key_orig,
+ const char *val)
+{
+ int n;
+ char *key;
+
+ if ( sscanf(key_orig, "mask%d_", &n) != 1 ) {
+ ERROR("Invalid mask directive '%s'\n", key_orig);
+ return 1;
+ }
+
+ key = strdup(key_orig);
+ if ( key == NULL ) return 1;
+
+ key[4] = '_';
+
+ if ( strcmp(key, "mask__file") == 0 ) {
+
+ panel->masks[n].filename = strdup(val);
+
+ } else if ( strcmp(key, "mask__data") == 0 ) {
+
+ if ( strncmp(val, "/", 1) != 0 ) {
+ ERROR("Invalid mask location '%s'\n", val);
+ free(key);
+ return 1;
+ }
+ panel->masks[n].data_location = strdup(val);
+
+ } else if ( strcmp(key, "mask__goodbits") == 0 ) {
+
+ char *end;
+ double v = strtod(val, &end);
+
+ if ( end != val ) {
+ panel->masks[n].good_bits = v;
+ } else {
+ free(key);
+ return 1;
+ }
+
+ } else if ( strcmp(key, "mask__badbits") == 0 ) {
+
+ char *end;
+ double v = strtod(val, &end);
+
+ if ( end != val ) {
+ panel->masks[n].bad_bits = v;
+ } else {
+ free(key);
+ return 1;
+ }
+
+ }
+
+ free(key);
+ return 0;
+}
+
+
+static int parse_field_for_panel(struct panel_template *panel, const char *key,
+ const char *val, DataTemplate *det)
+{
+ int reject = 0;
+
+ if ( strcmp(key, "min_fs") == 0 ) {
+ panel->orig_min_fs = atof(val);
+ } else if ( strcmp(key, "max_fs") == 0 ) {
+ panel->orig_max_fs = atof(val);
+ } else if ( strcmp(key, "min_ss") == 0 ) {
+ panel->orig_min_ss = atof(val);
+ } else if ( strcmp(key, "max_ss") == 0 ) {
+ panel->orig_max_ss = atof(val);
+ } else if ( strcmp(key, "corner_x") == 0 ) {
+ panel->cnx = atof(val);
+ } else if ( strcmp(key, "corner_y") == 0 ) {
+ panel->cny = atof(val);
+ } else if ( strcmp(key, "rail_direction") == 0 ) {
+ if ( dir_conv(val, &panel->rail_x,
+ &panel->rail_y,
+ &panel->rail_z) )
+ {
+ ERROR("Invalid rail direction '%s'\n", val);
+ reject = 1;
+ }
+ } else if ( strcmp(key, "clen_for_centering") == 0 ) {
+ panel->clen_for_centering = atof(val);
+ } else if ( strcmp(key, "adu_per_eV") == 0 ) {
+ panel->adu_scale = atof(val);
+ panel->adu_scale_unit = ADU_PER_EV;
+ } else if ( strcmp(key, "adu_per_photon") == 0 ) {
+ panel->adu_scale = atof(val);
+ panel->adu_scale_unit = ADU_PER_PHOTON;
+ } else if ( strcmp(key, "clen") == 0 ) {
+ /* Gets expanded when image is loaded */
+ panel->cnz_from = strdup(val);
+
+ } else if ( strcmp(key, "data") == 0 ) {
+ if ( strncmp(val,"/",1) != 0 ) {
+ ERROR("Invalid data location '%s'\n", val);
+ reject = -1;
+ }
+ free(panel->data);
+ panel->data = strdup(val);
+
+ } else if ( strcmp(key, "mask_bad") == 0 ) {
+ parse_field_for_panel(panel, "mask0_badbits", val, det);
+ } else if ( strcmp(key, "mask_good") == 0 ) {
+ parse_field_for_panel(panel, "mask0_goodbits", val, det);
+ } else if ( strcmp(key, "mask") == 0 ) {
+ parse_field_for_panel(panel, "mask0_data", val, det);
+ } else if ( strcmp(key, "mask_file") == 0 ) {
+ parse_field_for_panel(panel, "mask0_file", val, det);
+
+ } else if ( strncmp(key, "mask", 4) == 0 ) {
+ reject = parse_mask(panel, key, val);
+
+ } else if ( strcmp(key, "saturation_map") == 0 ) {
+ panel->satmap = strdup(val);
+ } else if ( strcmp(key, "saturation_map_file") == 0 ) {
+ panel->satmap_file = strdup(val);
+
+ } else if ( strcmp(key, "coffset") == 0) {
+ panel->cnz_offset = atof(val);
+ } else if ( strcmp(key, "res") == 0 ) {
+ panel->pixel_pitch = 1.0/atof(val);
+ } else if ( strcmp(key, "max_adu") == 0 ) {
+ panel->max_adu = atof(val);
+ ERROR("WARNING: It's usually better not to set max_adu "
+ "in the geometry file. Use --max-adu during "
+ "merging instead.\n");
+
+ } else if ( strcmp(key, "flag_equal") == 0 ) {
+ if ( add_flag_value(panel, atof(val), FLAG_EQUAL) ) {
+ reject = -1;
+ }
+ } else if ( strcmp(key, "flag_lessthan") == 0 ) {
+ if ( add_flag_value(panel, atof(val), FLAG_LESSTHAN) ) {
+ reject = -1;
+ }
+ } else if ( strcmp(key, "flag_morethan") == 0 ) {
+ if ( add_flag_value(panel, atof(val), FLAG_MORETHAN) ) {
+ reject = -1;
+ }
+
+ } else if ( strcmp(key, "badrow_direction") == 0 ) {
+ ERROR("WARNING 'badrow_direction' is ignored in this version.\n");
+ } else if ( strcmp(key, "no_index") == 0 ) {
+ panel->bad = atob(val);
+ } else if ( strcmp(key, "fs") == 0 ) {
+ if ( dir_conv(val, &panel->fsx, &panel->fsy, &panel->fsz) != 0 )
+ {
+ ERROR("Invalid fast scan direction '%s'\n", val);
+ reject = 1;
+ }
+ } else if ( strcmp(key, "ss") == 0 ) {
+ if ( dir_conv(val, &panel->ssx, &panel->ssy, &panel->ssz) != 0 )
+ {
+ ERROR("Invalid slow scan direction '%s'\n", val);
+ reject = 1;
+ }
+ } else if ( strncmp(key, "dim", 3) == 0) {
+ int dim_entry;
+ char *endptr;
+ if ( key[3] != '\0' ) {
+ dim_entry = strtoul(key+3, &endptr, 10);
+ if ( endptr[0] != '\0' ) {
+ ERROR("Invalid dimension number %s\n",
+ key+3);
+ } else {
+ if ( set_dim(panel, dim_entry, val) ) {
+ ERROR("Failed to set dim structure entry\n");
+ }
+ }
+ } else {
+ ERROR("'dim' must be followed by a number, e.g. 'dim0'\n");
+ }
+ } else {
+ ERROR("Unrecognised field '%s'\n", key);
+ }
+
+ return reject;
+}
+
+
+static int check_badr_fsss(struct dt_badregion *badr, int is_fsss)
+{
+ /* First assignment? */
+ if ( badr->is_fsss == 99 ) {
+ badr->is_fsss = is_fsss;
+ return 0;
+ }
+
+ if ( is_fsss != badr->is_fsss ) {
+ ERROR("You can't mix x/y and fs/ss in a bad region.\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int parse_field_bad(struct dt_badregion *badr, const char *key,
+ const char *val)
+{
+ int reject = 0;
+
+ if ( strcmp(key, "min_x") == 0 ) {
+ badr->min_x = atof(val);
+ reject = check_badr_fsss(badr, 0);
+ } else if ( strcmp(key, "max_x") == 0 ) {
+ badr->max_x = atof(val);
+ reject = check_badr_fsss(badr, 0);
+ } else if ( strcmp(key, "min_y") == 0 ) {
+ badr->min_y = atof(val);
+ reject = check_badr_fsss(badr, 0);
+ } else if ( strcmp(key, "max_y") == 0 ) {
+ badr->max_y = atof(val);
+ reject = check_badr_fsss(badr, 0);
+ } else if ( strcmp(key, "min_fs") == 0 ) {
+ badr->min_fs = atof(val);
+ reject = check_badr_fsss(badr, 1);
+ } else if ( strcmp(key, "max_fs") == 0 ) {
+ badr->max_fs = atof(val);
+ reject = check_badr_fsss(badr, 1);
+ } else if ( strcmp(key, "min_ss") == 0 ) {
+ badr->min_ss = atof(val);
+ reject = check_badr_fsss(badr, 1);
+ } else if ( strcmp(key, "max_ss") == 0 ) {
+ badr->max_ss = atof(val);
+ reject = check_badr_fsss(badr, 1);
+ } else if ( strcmp(key, "panel") == 0 ) {
+ badr->panel_name = strdup(val);
+ } else {
+ ERROR("Unrecognised field '%s'\n", key);
+ }
+
+ return reject;
+}
+
+
+static int parse_electron_voltage(const char *val,
+ char **p_from,
+ enum wavelength_unit *punit)
+{
+ char *valcpy;
+ char *sp;
+
+ valcpy = strdup(val);
+ if ( valcpy == NULL ) return 1;
+
+ /* "electron_voltage" directive must have explicit units */
+ sp = strchr(valcpy, ' ');
+ if ( sp == NULL ) {
+ free(valcpy);
+ return 1;
+ }
+
+ if ( strcmp(sp+1, "V") == 0 ) {
+ *punit = WAVELENGTH_ELECTRON_V;
+ } else if ( strcmp(sp+1, "kV") == 0 ) {
+ *punit = WAVELENGTH_ELECTRON_KV;
+ } else {
+ free(valcpy);
+ return 1;
+ }
+
+ sp[0] = '\0';
+ *p_from = valcpy;
+ return 0;
+}
+
+
+static int parse_wavelength(const char *val,
+ char **p_from,
+ enum wavelength_unit *punit)
+{
+ char *valcpy;
+ char *sp;
+
+ valcpy = strdup(val);
+ if ( valcpy == NULL ) return 1;
+
+ /* "wavelength" directive must have explicit units */
+ sp = strchr(valcpy, ' ');
+ if ( sp == NULL ) {
+ free(valcpy);
+ return 1;
+ }
+
+ if ( strcmp(sp+1, "m") == 0 ) {
+ *punit = WAVELENGTH_M;
+ } else if ( strcmp(sp+1, "A") == 0 ) {
+ *punit = WAVELENGTH_A;
+ } else {
+ free(valcpy);
+ return 1;
+ }
+
+ sp[0] = '\0';
+ *p_from = valcpy;
+ return 0;
+}
+
+
+static int parse_photon_energy(const char *val,
+ char **p_from,
+ enum wavelength_unit *punit)
+{
+ char *valcpy;
+ char *sp;
+
+ valcpy = strdup(val);
+ if ( valcpy == NULL ) return 1;
+
+ /* "photon_energy" is the only one of the wavelength
+ * directives which is allowed to not have units */
+ sp = strchr(valcpy, ' ');
+ if ( sp == NULL ) {
+ *punit = WAVELENGTH_PHOTON_EV;
+ } else if ( strcmp(sp+1, "eV") == 0 ) {
+ *punit = WAVELENGTH_PHOTON_EV;
+ sp[0] = '\0';
+ } else if ( strcmp(sp+1, "keV") == 0 ) {
+ *punit = WAVELENGTH_PHOTON_KEV;
+ sp[0] = '\0';
+ } else {
+ /* Unit specified, but unrecognised */
+ free(valcpy);
+ return 1;
+ }
+
+ *p_from = valcpy;
+ return 0;
+}
+
+
+static int parse_peak_layout(const char *val,
+ enum peak_layout *layout)
+{
+ if ( strcmp(val, "auto") == 0 ) {
+ *layout = PEAK_LIST_AUTO;
+ return 0;
+ }
+
+ if ( strcmp(val, "cxi") == 0 ) {
+ *layout = PEAK_LIST_CXI;
+ return 0;
+ }
+
+ if ( (strcmp(val, "list3") == 0) ) {
+ *layout = PEAK_LIST_LIST3;
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static int parse_toplevel(DataTemplate *dt,
+ const char *key,
+ const char *val,
+ struct rg_definition ***rg_defl,
+ struct rgc_definition ***rgc_defl,
+ int *n_rg_defs,
+ int *n_rgc_defs,
+ struct panel_template *defaults)
+{
+ if ( strcmp(key, "detector_shift_x") == 0 ) {
+ dt->shift_x_from = strdup(val);
+
+ } else if ( strcmp(key, "detector_shift_y") == 0 ) {
+ dt->shift_y_from = strdup(val);
+
+ } else if ( strcmp(key, "photon_energy") == 0 ) {
+ return parse_photon_energy(val,
+ &dt->wavelength_from,
+ &dt->wavelength_unit);
+
+ } else if ( strcmp(key, "electron_voltage") == 0 ) {
+ return parse_electron_voltage(val,
+ &dt->wavelength_from,
+ &dt->wavelength_unit);
+
+ } else if ( strcmp(key, "wavelength") == 0 ) {
+ return parse_wavelength(val,
+ &dt->wavelength_from,
+ &dt->wavelength_unit);
+
+ } else if ( strcmp(key, "peak_list") == 0 ) {
+ dt->peak_list = strdup(val);
+
+ } else if ( strcmp(key, "peak_list_type") == 0 ) {
+ return parse_peak_layout(val, &dt->peak_list_type);
+
+ } else if ( strcmp(key, "bandwidth") == 0 ) {
+ double v;
+ char *end;
+ v = strtod(val, &end);
+ if ( (val[0] != '\0') && (end[0] == '\0') ) {
+ dt->bandwidth = v;
+ } else {
+ ERROR("Invalid value for bandwidth\n");
+ }
+
+ } else if (strncmp(key, "rigid_group", 11) == 0
+ && strncmp(key, "rigid_group_collection", 22) != 0 ) {
+
+ struct rg_definition **new;
+
+ new = realloc(*rg_defl,
+ ((*n_rg_defs)+1)*sizeof(struct rg_definition*));
+ *rg_defl = new;
+
+ (*rg_defl)[*n_rg_defs] = malloc(sizeof(struct rg_definition));
+ (*rg_defl)[*n_rg_defs]->name = strdup(key+12);
+ (*rg_defl)[*n_rg_defs]->pns = strdup(val);
+ *n_rg_defs = *n_rg_defs+1;
+
+ } else if ( strncmp(key, "rigid_group_collection", 22) == 0 ) {
+
+ struct rgc_definition **new;
+
+ new = realloc(*rgc_defl, ((*n_rgc_defs)+1)*
+ sizeof(struct rgc_definition*));
+ *rgc_defl = new;
+
+ (*rgc_defl)[*n_rgc_defs] =
+ malloc(sizeof(struct rgc_definition));
+ (*rgc_defl)[*n_rgc_defs]->name = strdup(key+23);
+ (*rgc_defl)[*n_rgc_defs]->rgs = strdup(val);
+ *n_rgc_defs = *n_rgc_defs+1;
+
+ } else if ( parse_field_for_panel(defaults, key, val, dt) ) {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int dt_num_path_placeholders(const char *str)
+{
+ size_t i, len;
+ int n_pl = 0;
+
+ if ( str == NULL ) return 0;
+
+ len = strlen(str);
+ for ( i=0; i<len; i++ ) {
+ if ( str[i] == '%' ) n_pl++;
+ }
+
+ return n_pl;
+}
+
+
+signed int find_dim(signed int *dims, int which)
+{
+ int i;
+
+ for ( i=0; i<MAX_DIMS; i++ ) {
+ if ( dims[i] == DIM_UNDEFINED ) break;
+ if ( dims[i] == which ) return i;
+ }
+
+ return -1;
+}
+
+
+static int lookup_panel(const char *panel_name,
+ const DataTemplate *dt,
+ int *res)
+{
+ int i;
+
+ /* If there is exactly one panel, you can get away without
+ * specifying the panel name */
+ if ( (panel_name == NULL) && (dt->n_panels == 1) ) {
+ *res = 0;
+ return 0;
+ }
+
+ for ( i=0; i<dt->n_panels; i++ ) {
+ if ( strcmp(dt->panels[i].name, panel_name) == 0 ) {
+ *res = i;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+
+static int check_mask_and_satmap_placeholders(const DataTemplate *dt)
+{
+ int i;
+
+ for ( i=0; i<dt->n_panels; i++ ) {
+
+ int num_data_pl;
+ int num_satmap_pl;
+ int j;
+
+ num_data_pl = dt_num_path_placeholders(dt->panels[i].data);
+ num_satmap_pl = dt_num_path_placeholders(dt->panels[i].satmap);
+
+ if ( num_satmap_pl > num_data_pl ) return 1;
+
+ for ( j=0; j<MAX_MASKS; j++ ) {
+
+ int num_mask_pl;
+
+ /* Unused slot? */
+ if ( dt->panels[i].masks[j].data_location == NULL ) continue;
+
+ num_mask_pl = dt_num_path_placeholders(dt->panels[i].masks[j].data_location);
+ if ( num_mask_pl > num_data_pl ) return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+DataTemplate *data_template_new_from_string(const char *string_in)
+{
+ DataTemplate *dt;
+ char **bits;
+ int done = 0;
+ int i;
+ int rgi, rgci;
+ int reject = 0;
+ struct rg_definition **rg_defl = NULL;
+ struct rgc_definition **rgc_defl = NULL;
+ int n_rg_definitions = 0;
+ int n_rgc_definitions = 0;
+ char *string;
+ char *string_orig;
+ size_t len;
+ struct panel_template defaults;
+
+ dt = calloc(1, sizeof(DataTemplate));
+ if ( dt == NULL ) return NULL;
+
+ dt->n_panels = 0;
+ dt->panels = NULL;
+ dt->n_bad = 0;
+ dt->bad = NULL;
+ dt->n_rigid_groups = 0;
+ dt->rigid_groups = NULL;
+ dt->n_rg_collections = 0;
+ dt->rigid_group_collections = NULL;
+ dt->bandwidth = 0.00000001;
+ dt->peak_list = NULL;
+ dt->shift_x_from = NULL;
+ dt->shift_y_from = NULL;
+
+ /* The default defaults... */
+ defaults.orig_min_fs = -1;
+ defaults.orig_min_ss = -1;
+ defaults.orig_max_fs = -1;
+ defaults.orig_max_ss = -1;
+ defaults.cnx = NAN;
+ defaults.cny = NAN;
+ defaults.cnz_from = NULL;
+ defaults.cnz_offset = 0.0;
+ defaults.pixel_pitch = -1.0;
+ defaults.bad = 0;
+ defaults.fsx = 1.0;
+ defaults.fsy = 0.0;
+ defaults.fsz = 0.0;
+ defaults.ssx = 0.0;
+ defaults.ssy = 1.0;
+ defaults.ssz = 0.0;
+ defaults.rail_x = NAN; /* The actual default rail direction */
+ defaults.rail_y = NAN; /* is below */
+ defaults.rail_z = NAN;
+ defaults.clen_for_centering = NAN;
+ defaults.adu_scale = NAN;
+ defaults.adu_scale_unit = ADU_PER_PHOTON;
+ for ( i=0; i<MAX_FLAG_VALUES; i++ ) defaults.flag_values[i] = 0;
+ for ( i=0; i<MAX_FLAG_VALUES; i++ ) defaults.flag_types[i] = FLAG_NOTHING;
+ for ( i=0; i<MAX_MASKS; i++ ) {
+ defaults.masks[i].data_location = NULL;
+ defaults.masks[i].filename = NULL;
+ defaults.masks[i].good_bits = 0;
+ defaults.masks[i].bad_bits = 0;
+ }
+ defaults.max_adu = +INFINITY;
+ defaults.satmap = NULL;
+ defaults.satmap_file = NULL;
+ defaults.data = strdup("/data/data");
+ defaults.name = NULL;
+ defaults.dims[0] = DIM_SS;
+ defaults.dims[1] = DIM_FS;
+ for ( i=2; i<MAX_DIMS; i++ ) defaults.dims[i] = DIM_UNDEFINED;
+
+ string = strdup(string_in);
+ if ( string == NULL ) return NULL;
+ len = strlen(string);
+ for ( i=0; i<len; i++ ) {
+ if ( string_in[i] == '\r' ) string[i] = '\n';
+ }
+
+ /* Becaue 'string' will get modified */
+ string_orig = string;
+
+ do {
+
+ char *line;
+ struct dt_badregion *badregion = NULL;
+ struct panel_template *panel = NULL;
+
+ /* Copy the next line from the big string */
+ const char *nl = strchr(string, '\n');
+ if ( nl != NULL ) {
+ size_t len = nl - string;
+ line = strndup(string, nl-string);
+ line[len] = '\0';
+ string += len+1;
+ } else {
+ line = strdup(string);
+ done = 1;
+ }
+
+ /* Trim leading spaces */
+ i = 0;
+ char *line_orig = line;
+ while ( (line_orig[i] == ' ')
+ || (line_orig[i] == '\t') ) i++;
+ line = strdup(line+i);
+ free(line_orig);
+
+ /* Stop at comment symbol */
+ char *comm = strchr(line, ';');
+ if ( comm != NULL ) comm[0] = '\0';
+
+ /* Nothing left? Entire line was commented out,
+ * and can be silently ignored */
+ if ( line[0] == '\0' ) {
+ free(line);
+ continue;
+ }
+
+ /* Find the equals sign */
+ char *eq = strchr(line, '=');
+ if ( eq == NULL ) {
+ ERROR("Bad line in geometry file: '%s'\n", line);
+ free(line);
+ reject = 1;
+ continue;
+ }
+
+ /* Split into two strings */
+ eq[0] = '\0';
+ char *val = eq+1;
+
+ /* Trim leading and trailing spaces in value */
+ while ( (val[0] == ' ') || (val[0] == '\t') ) val++;
+ notrail(val);
+
+ /* Trim trailing spaces in key
+ * (leading spaces already done above) */
+ notrail(line);
+
+ /* Find slash after panel name */
+ char *slash = strchr(line, '/');
+ if ( slash == NULL ) {
+
+ /* Top-level option */
+ if ( parse_toplevel(dt, line, val,
+ &rg_defl,
+ &rgc_defl,
+ &n_rg_definitions,
+ &n_rgc_definitions,
+ &defaults) )
+ {
+ ERROR("Invalid top-level line '%s'\n",
+ line);
+ reject = 1;
+ }
+ free(line);
+ continue;
+ }
+
+ slash[0] = '\0';
+ char *key = slash+1;
+ /* No space trimming this time - must be "panel/key" */
+
+ /* Find either panel or bad region */
+ if ( strncmp(line, "bad", 3) == 0 ) {
+ badregion = find_bad_region_by_name(dt, line);
+ if ( badregion == NULL ) {
+ badregion = new_bad_region(dt, line);
+ }
+ } else {
+ panel = find_panel_by_name(dt, line);
+ if ( panel == NULL ) {
+ panel = new_panel(dt, line, &defaults);
+ }
+ }
+
+ if ( panel != NULL ) {
+ if ( parse_field_for_panel(panel, key, val,
+ dt) ) reject = 1;
+ } else {
+ if ( parse_field_bad(badregion, key,
+ val) ) reject = 1;
+ }
+
+ free(line);
+
+ } while ( !done );
+
+ if ( dt->n_panels == 0 ) {
+ ERROR("No panel descriptions in geometry file.\n");
+ free(dt);
+ return NULL;
+ }
+
+ if ( check_mask_and_satmap_placeholders(dt) ) {
+ ERROR("Mask and saturation map paths must have fewer "
+ "placeholders than image data path.\n");
+ reject = 1;
+ }
+
+ for ( i=0; i<dt->n_panels; i++ ) {
+
+ int j;
+ struct panel_template *p = &dt->panels[i];
+ signed int dim_fs = find_dim(p->dims, DIM_FS);
+ signed int dim_ss = find_dim(p->dims, DIM_SS);
+
+ if ( (dim_fs<0) || (dim_ss<0) ) {
+ ERROR("Panel %s does not have dimensions "
+ "assigned to both fs and ss.\n",
+ p->name);
+ reject = 1;
+ }
+
+ if ( dim_ss > dim_fs ) {
+ ERROR("Fast scan dimension must be lower than "
+ "slow scan (panel %s)\n", p->name);
+ reject = 1;
+ }
+
+ if ( p->orig_min_fs < 0 ) {
+ ERROR("Please specify the minimum FS coordinate for"
+ " panel %s\n", dt->panels[i].name);
+ reject = 1;
+ }
+ if ( p->orig_max_fs < 0 ) {
+ ERROR("Please specify the maximum FS coordinate for"
+ " panel %s\n", dt->panels[i].name);
+ reject = 1;
+ }
+ if ( p->orig_min_ss < 0 ) {
+ ERROR("Please specify the minimum SS coordinate for"
+ " panel %s\n", dt->panels[i].name);
+ reject = 1;
+ }
+ if ( p->orig_max_ss < 0 ) {
+ ERROR("Please specify the maximum SS coordinate for"
+ " panel %s\n", dt->panels[i].name);
+ reject = 1;
+ }
+ if ( isnan(p->cnx) ) {
+ ERROR("Please specify the corner X coordinate for"
+ " panel %s\n", dt->panels[i].name);
+ reject = 1;
+ }
+ if ( isnan(p->cny) ) {
+ ERROR("Please specify the corner Y coordinate for"
+ " panel %s\n", dt->panels[i].name);
+ reject = 1;
+ }
+ if ( p->cnz_from == NULL ) {
+ ERROR("Please specify the camera length for panel %s\n",
+ dt->panels[i].name);
+ reject = 1;
+ }
+ if ( p->pixel_pitch < 0 ) {
+ ERROR("Please specify the pixel size for"
+ " panel %s\n", dt->panels[i].name);
+ reject = 1;
+ }
+ if ( p->data == NULL ) {
+ ERROR("Please specify the data location for panel %s\n",
+ p->name);
+ reject = 1;
+ }
+ if ( isnan(p->adu_scale) ) {
+ ERROR("Please specify either adu_per_eV or "
+ "adu_per_photon for panel %s\n",
+ dt->panels[i].name);
+ reject = 1;
+ }
+
+ if ( isnan(p->clen_for_centering) && !isnan(p->rail_x) )
+ {
+ ERROR("You must specify clen_for_centering if you "
+ "specify the rail direction (panel %s)\n",
+ p->name);
+ reject = 1;
+ }
+
+ for ( j=0; j<MAX_MASKS; j++ ) {
+ if ( (p->masks[j].filename != NULL)
+ && (p->masks[j].data_location == NULL) )
+ {
+ ERROR("You have specified filename but not data"
+ " location for mask %i of panel %s\n",
+ j, p->name);
+ reject = 1;
+ }
+ }
+
+ /* The default rail direction */
+ if ( isnan(p->rail_x) ) {
+ p->rail_x = 0.0;
+ p->rail_y = 0.0;
+ p->rail_z = 1.0;
+ }
+ if ( isnan(p->clen_for_centering) ) p->clen_for_centering = 0.0;
+
+ }
+
+ for ( i=0; i<dt->n_bad; i++ ) {
+
+ if ( dt->bad[i].is_fsss == 99 ) {
+ ERROR("Please specify the coordinate ranges for"
+ " bad region %s\n", dt->bad[i].name);
+ reject = 1;
+ }
+
+ if ( dt->bad[i].is_fsss ) {
+ if ( dt->bad[i].panel_name == NULL ) {
+
+ ERROR("Panel not specified for bad region '%s'\n",
+ dt->bad[i].name);
+ reject = 1;
+
+ } else if ( lookup_panel(dt->bad[i].panel_name, dt,
+ &dt->bad[i].panel_number) )
+ {
+ ERROR("No such panel '%s' for bad region %s\n",
+ dt->bad[i].panel_name, dt->bad[i].name);
+ reject = 1;
+
+ } else {
+ struct panel_template *p;
+ struct dt_badregion *bad;
+ int r = 0;
+ p = &dt->panels[dt->bad[i].panel_number];
+ bad = &dt->bad[i];
+ if ( bad->min_fs < p->orig_min_fs ) r = 1;
+ if ( bad->min_ss < p->orig_min_ss ) r = 1;
+ if ( bad->max_fs > p->orig_max_fs ) r = 1;
+ if ( bad->max_ss > p->orig_max_ss ) r = 1;
+ if ( r ) {
+ ERROR("Bad region '%s' is outside the "
+ "panel bounds (%s) as presented "
+ "in data (%i %i, %i %i inclusive): "
+ "Bad region %i,%i to %i, %i "
+ "inclusive\n",
+ bad->name, p->name,
+ p->orig_min_fs, p->orig_min_ss,
+ p->orig_max_fs, p->orig_max_ss,
+ bad->min_fs, bad->min_ss,
+ bad->max_fs, bad->max_ss);
+ reject = 1;
+ }
+ bad->min_fs -= p->orig_min_fs;
+ bad->max_fs -= p->orig_min_fs;
+ bad->min_ss -= p->orig_min_ss;
+ bad->max_ss -= p->orig_min_ss;
+ }
+ }
+ }
+
+ free(defaults.cnz_from);
+ free(defaults.data);
+ for ( i=0; i<MAX_MASKS; i++ ) {
+ free(defaults.masks[i].data_location);
+ free(defaults.masks[i].filename);
+ }
+
+ for ( rgi=0; rgi<n_rg_definitions; rgi++) {
+
+ int pi, n1;
+ struct rigid_group *rigidgroup = NULL;
+
+ rigidgroup = find_or_add_rg(dt, rg_defl[rgi]->name);
+
+ n1 = assplode(rg_defl[rgi]->pns, ",", &bits, ASSPLODE_NONE);
+
+ for ( pi=0; pi<n1; pi++ ) {
+
+ int panel_number;
+ if ( data_template_panel_name_to_number(dt,
+ bits[pi],
+ &panel_number) )
+ {
+ ERROR("Cannot add panel to rigid group\n");
+ ERROR("Panel not found: %s\n", bits[pi]);
+ return NULL;
+ }
+ add_to_rigid_group(rigidgroup, panel_number);
+ free(bits[pi]);
+
+ }
+ free(bits);
+ free(rg_defl[rgi]->name);
+ free(rg_defl[rgi]->pns);
+ free(rg_defl[rgi]);
+ }
+ free(rg_defl);
+
+ for ( rgci=0; rgci<n_rgc_definitions; rgci++ ) {
+
+ int rgi, n2;
+ struct rg_collection *rgcollection = NULL;
+
+ rgcollection = find_or_add_rg_coll(dt, rgc_defl[rgci]->name);
+
+ n2 = assplode(rgc_defl[rgci]->rgs, ",", &bits, ASSPLODE_NONE);
+
+ for ( rgi=0; rgi<n2; rgi++ ) {
+
+ struct rigid_group *r;
+
+ r = find_rigid_group_by_name(dt, bits[rgi]);
+ if ( r == NULL ) {
+ ERROR("Cannot add rigid group to collection\n");
+ ERROR("Rigid group not found: %s\n", bits[rgi]);
+ return NULL;
+ }
+ add_to_rigid_group_coll(rgcollection, r);
+ free(bits[rgi]);
+ }
+ free(bits);
+ free(rgc_defl[rgci]->name);
+ free(rgc_defl[rgci]->rgs);
+ free(rgc_defl[rgci]);
+
+ }
+ free(rgc_defl);
+
+ free(string_orig);
+
+ if ( reject ) return NULL;
+
+ return dt;
+}
+
+
+DataTemplate *data_template_new_from_file(const char *filename)
+{
+ char *contents;
+ DataTemplate *dt;
+
+ contents = load_entire_file(filename);
+ if ( contents == NULL ) {
+ ERROR("Failed to load geometry file '%s'\n", filename);
+ return NULL;
+ }
+
+ dt = data_template_new_from_string(contents);
+ free(contents);
+ return dt;
+}
+
+
+void data_template_free(DataTemplate *dt)
+{
+ int i;
+
+ if ( dt == NULL ) return;
+
+ free_all_rigid_groups(dt);
+ free_all_rigid_group_collections(dt);
+
+ for ( i=0; i<dt->n_panels; i++ ) {
+
+ int j;
+
+ free(dt->panels[i].name);
+ free(dt->panels[i].data);
+ free(dt->panels[i].satmap);
+ free(dt->panels[i].satmap_file);
+ free(dt->panels[i].cnz_from);
+
+ for ( j=0; j<MAX_MASKS; j++ ) {
+ free(dt->panels[i].masks[j].filename);
+ free(dt->panels[i].masks[j].data_location);
+ }
+ }
+
+ free(dt->wavelength_from);
+ free(dt->peak_list);
+
+ free(dt->panels);
+ free(dt->bad);
+ free(dt);
+}
+
+
+static int data_template_find_panel(const DataTemplate *dt,
+ int fs, int ss, int *ppn)
+{
+ int p;
+
+ for ( p=0; p<dt->n_panels; p++ ) {
+ if ( (fs >= dt->panels[p].orig_min_fs)
+ && (fs < dt->panels[p].orig_max_fs+1)
+ && (ss >= dt->panels[p].orig_min_ss)
+ && (ss < dt->panels[p].orig_max_ss+1) ) {
+ *ppn = p;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+
+int data_template_file_to_panel_coords(const DataTemplate *dt,
+ float *pfs, float *pss,
+ int *ppn)
+{
+ int pn;
+
+ if ( data_template_find_panel(dt, *pfs, *pss, &pn) ) {
+ return 1;
+ }
+
+ *ppn = pn;
+ *pfs = *pfs - dt->panels[pn].orig_min_fs;
+ *pss = *pss - dt->panels[pn].orig_min_ss;
+ return 0;
+}
+
+
+int data_template_panel_to_file_coords(const DataTemplate *dt,
+ int pn, float *pfs, float *pss)
+{
+ if ( pn >= dt->n_panels ) return 1;
+ *pfs = *pfs + dt->panels[pn].orig_min_fs;
+ *pss = *pss + dt->panels[pn].orig_min_ss;
+ return 0;
+}
+
+
+const char *data_template_panel_number_to_name(const DataTemplate *dt,
+ int pn)
+{
+ if ( pn >= dt->n_panels ) return NULL;
+ return dt->panels[pn].name;
+}
+
+
+int data_template_panel_name_to_number(const DataTemplate *dt,
+ const char *panel_name,
+ int *pn)
+{
+ int i;
+
+ if ( panel_name == NULL ) return 1;
+
+ for ( i=0; i<dt->n_panels; i++ ) {
+ if ( strcmp(panel_name, dt->panels[i].name) == 0 ) {
+ *pn = i;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+
+void data_template_add_copy_header(DataTemplate *dt,
+ const char *header)
+{
+ /* FIXME: Add "header" to list of things to copy */
+ STATUS("Adding %s\n", header);
+}
+
+
+static int dt_num_placeholders(const struct panel_template *p)
+{
+ int i;
+ int n_pl = 0;
+ for ( i=0; i<MAX_DIMS; i++ ) {
+ if ( p->dims[i] == DIM_PLACEHOLDER ) n_pl++;
+ }
+ return n_pl;
+}
+
+
+int data_template_get_slab_extents(const DataTemplate *dt,
+ int *pw, int *ph)
+{
+ int w, h;
+ char *data_from;
+ int i;
+
+ data_from = dt->panels[0].data;
+
+ w = 0; h = 0;
+ for ( i=0; i<dt->n_panels; i++ ) {
+
+ struct panel_template *p = &dt->panels[i];
+
+ if ( strcmp(data_from, p->data) != 0 ) {
+ /* Not slabby */
+ return 1;
+ }
+
+ if ( dt_num_placeholders(p) > 0 ) {
+ /* Not slabby */
+ return 1;
+ }
+
+ if ( p->orig_max_fs > w ) {
+ w = p->orig_max_fs;
+ }
+ if ( p->orig_max_ss > h ) {
+ h = p->orig_max_ss;
+ }
+
+ }
+
+ /* Inclusive -> exclusive */
+ *pw = w + 1;
+ *ph = h + 1;
+ return 0;
+}
+
+
+double convert_to_m(double val, int units)
+{
+ switch ( units ) {
+
+ case WAVELENGTH_M :
+ return val;
+
+ case WAVELENGTH_A :
+ return val * 1e-10;
+
+ case WAVELENGTH_PHOTON_EV :
+ return ph_eV_to_lambda(val);
+
+ case WAVELENGTH_PHOTON_KEV :
+ return ph_eV_to_lambda(val*1e3);
+
+ case WAVELENGTH_ELECTRON_V :
+ return el_V_to_lambda(val);
+
+ case WAVELENGTH_ELECTRON_KV :
+ return el_V_to_lambda(val*1e3);
+
+ }
+
+ return NAN;
+}
+
+
+/**
+ * Get the wavelength from a DataTemplate, if possible.
+ *
+ * WARNING: This is probably not the routine you are looking for!
+ * See the disclaimer for image_create_for_simulation(), which applies
+ * equally to this routine.
+ *
+ * \returns the wavelength, in metres, or NAN if impossible.
+ */
+double data_template_get_wavelength_if_possible(const DataTemplate *dt)
+{
+ float val;
+ char *rval;
+
+ if ( dt->wavelength_from == NULL ) return NAN;
+
+ val = strtod(dt->wavelength_from, &rval);
+ if ( (*rval == '\0') && (rval != dt->wavelength_from) ) {
+ return convert_to_m(val, dt->wavelength_unit);
+ } else {
+ return NAN;
+ }
+}
diff --git a/libcrystfel/src/datatemplate.h b/libcrystfel/src/datatemplate.h
new file mode 100644
index 00000000..3d457f80
--- /dev/null
+++ b/libcrystfel/src/datatemplate.h
@@ -0,0 +1,99 @@
+/*
+ * datatemplate.h
+ *
+ * Template for loading data
+ *
+ * Copyright © 2019-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2019-2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DATATEMPLATE_H
+#define DATATEMPLATE_H
+
+#include "detgeom.h"
+
+/**
+ * \file datatemplate.h
+ * Template for loading data.
+ */
+
+/**
+ * This data structure is opaque. You must use the available accessor functions
+ * to read and write its contents.
+ **/
+typedef struct _datatemplate DataTemplate;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct rigid_group
+{
+ char *name;
+ int *panel_numbers;
+ int n_panels;
+};
+
+
+struct rg_collection
+{
+ char *name;
+ struct rigid_group **rigid_groups;
+ int n_rigid_groups;
+};
+
+
+extern DataTemplate *data_template_new_from_file(const char *filename);
+extern DataTemplate *data_template_new_from_string(const char *string_in);
+extern void data_template_free(DataTemplate *dt);
+
+extern const char *data_template_panel_number_to_name(const DataTemplate *dt,
+ int pn);
+
+extern int data_template_panel_name_to_number(const DataTemplate *dt,
+ const char *panel_name,
+ int *pn);
+
+extern int data_template_file_to_panel_coords(const DataTemplate *dt,
+ float *pfs, float *pss,
+ int *pn);
+
+extern int data_template_panel_to_file_coords(const DataTemplate *dt,
+ int pn,
+ float *pfs, float *pss);
+
+extern void data_template_add_copy_header(DataTemplate *dt,
+ const char *header);
+
+extern int data_template_get_slab_extents(const DataTemplate *dt, int *pw, int *ph);
+
+extern struct rg_collection *data_template_get_rigid_groups(const DataTemplate *dtempl,
+ const char *collection_name);
+
+extern double data_template_get_wavelength_if_possible(const DataTemplate *dt);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DATATEMPLATE_H */
diff --git a/libcrystfel/src/datatemplate_priv.h b/libcrystfel/src/datatemplate_priv.h
new file mode 100644
index 00000000..71569273
--- /dev/null
+++ b/libcrystfel/src/datatemplate_priv.h
@@ -0,0 +1,239 @@
+/*
+ * datatemplate_priv.h
+ *
+ * Data template structure (private parts)
+ *
+ * Copyright © 2019-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2019-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/* NB This file is NOT part of the public API, and should NOT
+ * be installed, but rather stays in the libcrystfel source folder. */
+
+#ifndef DATATEMPLATE_PRIV_H
+#define DATATEMPLATE_PRIV_H
+
+/* Maximum number of dimensions expected in data files */
+#define MAX_DIMS (16)
+
+/* Maximum number of placeholders expected in path structure */
+#define MAX_PATH_PARTS (16)
+
+enum adu_per_unit
+{
+ ADU_PER_PHOTON,
+ ADU_PER_EV
+};
+
+
+enum wavelength_unit
+{
+ WAVELENGTH_M,
+ WAVELENGTH_A,
+ WAVELENGTH_ELECTRON_KV,
+ WAVELENGTH_ELECTRON_V,
+ WAVELENGTH_PHOTON_KEV,
+ WAVELENGTH_PHOTON_EV
+};
+
+#define MAX_FLAG_VALUES (16)
+
+enum flag_value_type
+{
+ FLAG_NOTHING,
+ FLAG_EQUAL,
+ FLAG_MORETHAN,
+ FLAG_LESSTHAN
+};
+
+enum peak_layout
+{
+ PEAK_LIST_AUTO,
+ PEAK_LIST_CXI,
+ PEAK_LIST_LIST3
+};
+
+/* Special values for dimension IDs */
+#define DIM_FS (-1)
+#define DIM_SS (-2)
+#define DIM_UNDEFINED (-3)
+#define DIM_PLACEHOLDER (-4)
+
+
+/* Maximum number of masks per panel */
+#define MAX_MASKS (8)
+
+struct mask_template
+{
+ /** Location of mask data */
+ char *data_location;
+
+ /** Filename for mask data */
+ char *filename;
+
+ /** Bit mask for bad pixels
+ * (pixel is bad if any of these are set) */
+ unsigned int bad_bits;
+
+ /** Bit mask for good pixels
+ * (pixel cannot be good unless all of these are set) */
+ unsigned int good_bits;
+};
+
+
+/**
+ * Represents one panel of a detector
+ */
+struct panel_template
+{
+ /** Text name for panel */
+ char *name;
+
+ /** \name Location of corner in units of the pixel size of this panel */
+ /**@{*/
+ double cnx;
+ double cny;
+ /**@}*/
+
+ /** Location to get \ref cnz from, e.g. from HDF5 file */
+ char *cnz_from;
+
+ /** The offset to be applied from \ref clen */
+ double cnz_offset;
+
+ /** Mask definitions */
+ struct mask_template masks[MAX_MASKS];
+
+ /** Location of per-pixel saturation map */
+ char *satmap;
+
+ /** Filename for saturation map */
+ char *satmap_file;
+
+ /** Mark entire panel as bad if set */
+ int bad;
+
+ /** Resolution in pixels per metre */
+ double pixel_pitch;
+
+ /** Number of detector intensity units per photon, or eV */
+ double adu_scale;
+ enum adu_per_unit adu_scale_unit;
+
+ /** Treat pixel as unreliable if higher than this */
+ double max_adu;
+
+ /** Pixels with exactly this value will be marked as bad */
+ enum flag_value_type flag_types[MAX_FLAG_VALUES];
+ signed int flag_values[MAX_FLAG_VALUES];
+
+ /** Location of data in file (possibly with placeholders) */
+ char *data;
+
+ /** Dimensions (see definitions for DIM_FS etc above) */
+ signed int dims[MAX_DIMS];
+
+ /** \name Transformation matrix from pixel coordinates to lab frame */
+ /*@{*/
+ double fsx;
+ double fsy;
+ double fsz;
+ double ssx;
+ double ssy;
+ double ssz;
+ /*@}*/
+
+ /** \name Rail direction */
+ /*@{*/
+ double rail_x;
+ double rail_y;
+ double rail_z;
+ /*@}*/
+
+ /* Value of clen (without coffset) at which beam is centered */
+ double clen_for_centering;
+
+ /** \name Position of the panel in the data block in the file. */
+ /*@{*/
+ int orig_min_fs;
+ int orig_max_fs;
+ int orig_min_ss;
+ int orig_max_ss;
+ /*@}*/
+};
+
+
+#define PANEL_WIDTH(p) ((p)->orig_max_fs - (p)->orig_min_fs + 1)
+#define PANEL_HEIGHT(p) ((p)->orig_max_ss - (p)->orig_min_ss + 1)
+
+
+struct dt_badregion
+{
+ char name[1024];
+ int is_fsss;
+
+ double min_x;
+ double max_x;
+ double min_y;
+ double max_y;
+
+ /* Coordinates are specified INCLUSIVELY */
+ int panel_number;
+ char *panel_name;
+ int min_fs;
+ int max_fs;
+ int min_ss;
+ int max_ss;
+
+};
+
+
+struct _datatemplate
+{
+ struct panel_template *panels;
+ int n_panels;
+
+ struct dt_badregion *bad;
+ int n_bad;
+
+ char *wavelength_from;
+ enum wavelength_unit wavelength_unit;
+
+ double bandwidth;
+
+ struct rigid_group **rigid_groups;
+ int n_rigid_groups;
+
+ struct rg_collection **rigid_group_collections;
+ int n_rg_collections;
+
+ char *peak_list;
+ enum peak_layout peak_list_type;
+
+ /* Shift of whole detector, in m */
+ char *shift_x_from;
+ char *shift_y_from;
+};
+
+extern double convert_to_m(double val, int units);
+
+#endif /* DATATEMPLATE_PRIV_H */
diff --git a/libcrystfel/src/detector.c b/libcrystfel/src/detector.c
deleted file mode 100644
index 629e13f0..00000000
--- a/libcrystfel/src/detector.c
+++ /dev/null
@@ -1,2401 +0,0 @@
-/*
- * detector.c
- *
- * Detector properties
- *
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
- * a research centre of the Helmholtz Association.
- * Copyright © 2012 Richard Kirian
- *
- * Authors:
- * 2009-2019 Thomas White <taw@physics.org>
- * 2014 Valerio Mariani
- * 2014 Kenneth Beyerlein <kenneth.beyerlein@desy.de>
- * 2011 Andrew Aquila
- * 2011 Richard Kirian <rkirian@asu.edu>
- *
- * This file is part of CrystFEL.
- *
- * CrystFEL is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * CrystFEL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <stdlib.h>
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <ctype.h>
-#include <sys/stat.h>
-
-#include "image.h"
-#include "utils.h"
-#include "detector.h"
-#include "hdf5-file.h"
-
-
-/**
- * \file detector.h
- */
-
-
-struct rg_definition {
- char *name;
- char *pns;
-};
-
-
-struct rgc_definition {
- char *name;
- char *rgs;
-};
-
-
-static int atob(const char *a)
-{
- if ( strcasecmp(a, "true") == 0 ) return 1;
- if ( strcasecmp(a, "false") == 0 ) return 0;
- return atoi(a);
-}
-
-
-static int assplode_algebraic(const char *a_orig, char ***pbits)
-{
- int len, i;
- int nexp;
- char **bits;
- char *a;
- int idx, istr;
-
- len = strlen(a_orig);
-
- /* Add plus at start if no sign there already */
- if ( (a_orig[0] != '+') && (a_orig[0] != '-') ) {
- len += 1;
- a = malloc(len+1);
- snprintf(a, len+1, "+%s", a_orig);
- a[len] = '\0';
-
- } else {
- a = strdup(a_orig);
- }
-
- /* Count the expressions */
- nexp = 0;
- for ( i=0; i<len; i++ ) {
- if ( (a[i] == '+') || (a[i] == '-') ) nexp++;
- }
-
- bits = calloc(nexp, sizeof(char *));
-
- /* Break the string up */
- idx = -1;
- istr = 0;
- assert((a[0] == '+') || (a[0] == '-'));
- for ( i=0; i<len; i++ ) {
-
- char ch;
-
- ch = a[i];
-
- if ( (ch == '+') || (ch == '-') ) {
- if ( idx >= 0 ) bits[idx][istr] = '\0';
- idx++;
- bits[idx] = malloc(len+1);
- istr = 0;
- }
-
- if ( !isdigit(ch) && (ch != '.') && (ch != '+') && (ch != '-')
- && (ch != 'x') && (ch != 'y') && (ch != 'z') )
- {
- ERROR("Invalid character '%c' found.\n", ch);
- return 0;
- }
-
- assert(idx >= 0);
- bits[idx][istr++] = ch;
-
- }
- if ( idx >= 0 ) bits[idx][istr] = '\0';
-
- *pbits = bits;
- free(a);
-
- return nexp;
-}
-
-
-/* Parses the scan directions (accounting for possible rotation)
- * Assumes all white spaces have been already removed */
-static int dir_conv(const char *a, double *sx, double *sy, double *sz)
-{
- int n;
- char **bits;
- int i;
-
- *sx = 0.0; *sy = 0.0; *sz = 0.0;
-
- n = assplode_algebraic(a, &bits);
-
- if ( n == 0 ) {
- ERROR("Invalid direction '%s'\n", a);
- return 1;
- }
-
- for ( i=0; i<n; i++ ) {
-
- int len;
- double val;
- char axis;
- int j;
-
- len = strlen(bits[i]);
- assert(len != 0);
- axis = bits[i][len-1];
- if ( (axis != 'x') && (axis != 'y') && (axis != 'z') ) {
- ERROR("Invalid symbol '%c' - must be x, y or z.\n",
- axis);
- return 1;
- }
-
- /* Chop off the symbol now it's dealt with */
- bits[i][len-1] = '\0';
-
- /* Check for anything that isn't part of a number */
- for ( j=0; j<strlen(bits[i]); j++ ) {
- if ( isdigit(bits[i][j]) ) continue;
- if ( bits[i][j] == '+' ) continue;
- if ( bits[i][j] == '-' ) continue;
- if ( bits[i][j] == '.' ) continue;
- ERROR("Invalid coefficient '%s'\n", bits[i]);
- }
-
- if ( strlen(bits[i]) == 0 ) {
- val = 1.0;
- } else {
- val = atof(bits[i]);
- }
- if ( strlen(bits[i]) == 1 ) {
- if ( bits[i][0] == '+' ) val = 1.0;
- if ( bits[i][0] == '-' ) val = -1.0;
- }
- switch ( axis ) {
-
- case 'x' :
- *sx += val;
- break;
-
- case 'y' :
- *sy += val;
- break;
-
- case 'z' :
- *sz += val;
- break;
- }
-
- free(bits[i]);
-
- }
- free(bits);
-
- return 0;
-}
-
-
-static int count_trailing_spaces(const char *string) {
-
- int i;
-
- for ( i=0; i<strlen(string); i++ ) {
- if ( !isspace(string[i]) ) {
- return i;
- }
- }
-
- return -1;
-}
-
-
-static void build_output_line(const char *line, char *new_line,
- const char *string_to_write)
-{
- int nsp, i, w, ww;
- int trailsp;
- int n_bits;
- char **bits;
-
- n_bits = assplode(line, "=", &bits, ASSPLODE_NONE);
- trailsp = count_trailing_spaces(bits[1]);
-
- strcat(new_line, bits[0]);
- strcat(new_line, "=");
-
- for ( nsp=0; nsp < trailsp; nsp++ ) {
- strcat(new_line, " ");
- }
- strcat(new_line, string_to_write);
-
- for ( w=0; w<strlen(line); w++ ) {
- if ( strncmp(&line[w],";",1) == 0 ) {
- for ( ww=w-1; ww>=0; ww-- ) {
- if ( !isspace(line[ww])) {
- strcat(new_line, &line[ww]);
- break;
- }
- }
- break;
- }
- }
- for ( i=0; i<n_bits; i++) free(bits[i]);
- free(bits);
-}
-
-
-struct rvec get_q_for_panel(struct panel *p, double fs, double ss,
- double *ttp, double k)
-{
- struct rvec q;
- double ctt, twotheta;
- double xs, ys, zs;
- double az;
-
- /* Calculate 3D position of given position, in m */
- xs = (p->cnx + fs*p->fsx + ss*p->ssx) / p->res;
- ys = (p->cny + fs*p->fsy + ss*p->ssy) / p->res;
- zs = p->clen + (fs*p->fsz + ss*p->ssz) / p->res;
-
- ctt = zs/sqrt(xs*xs + ys*ys + zs*zs);
- twotheta = acos(ctt);
- az = atan2(ys, xs);
- if ( ttp != NULL ) *ttp = twotheta;
-
- q.u = k * sin(twotheta)*cos(az);
- q.v = k * sin(twotheta)*sin(az);
- q.w = k * (ctt - 1.0);
-
- return q;
-}
-
-
-int in_bad_region(struct detector *det, struct panel *p, double fs, double ss)
-{
- double rx, ry;
- double xs, ys;
- int i;
-
- /* No panel found -> definitely bad! */
- if ( p == NULL ) return 1;
-
- /* Convert xs and ys, which are in fast scan/slow scan coordinates,
- * to x and y */
- xs = fs*p->fsx + ss*p->ssx;
- ys = fs*p->fsy + ss*p->ssy;
-
- rx = xs + p->cnx;
- ry = ys + p->cny;
-
- for ( i=0; i<det->n_bad; i++ ) {
-
- struct badregion *b = &det->bad[i];
-
- if ( (b->panel != NULL)
- && (strcmp(b->panel, p->name) != 0) ) continue;
-
- if ( b->is_fsss ) {
-
- int nfs, nss;
-
- /* fs/ss bad regions are specified according to the
- * original coordinates */
- nfs = fs + p->orig_min_fs;
- nss = ss + p->orig_min_ss;
-
- if ( nfs < b->min_fs ) continue;
- if ( nfs > b->max_fs ) continue;
- if ( nss < b->min_ss ) continue;
- if ( nss > b->max_ss ) continue;
-
- } else {
-
- if ( rx < b->min_x ) continue;
- if ( rx > b->max_x ) continue;
- if ( ry < b->min_y ) continue;
- if ( ry > b->max_y ) continue;
-
- }
-
- return 1;
- }
-
- return 0;
-}
-
-
-int detector_has_clen_references(struct detector *det)
-{
- int i;
-
- for ( i=0; i<det->n_panels; i++ ) {
- if ( det->panels[i].clen_from != NULL ) return 1;
- }
-
- return 0;
-}
-
-
-static void record_panel(struct panel *p, float *dp, int do_poisson,
- gsl_rng *rng, double ph_per_e, double background,
- double lambda,
- int *n_neg1, int *n_inf1, int *n_nan1,
- int *n_neg2, int *n_inf2, int *n_nan2,
- double *max_tt)
-{
- int fs, ss;
-
- for ( ss=0; ss<p->h; ss++ ) {
- for ( fs=0; fs<p->w; fs++ ) {
-
- double counts;
- double cf;
- double intensity, sa;
- double pix_area, Lsq;
- double xs, ys, rx, ry;
- double dsq, proj_area;
- float dval;
- double twotheta;
-
- intensity = (double)dp[fs + p->w*ss];
- if ( isinf(intensity) ) (*n_inf1)++;
- if ( intensity < 0.0 ) (*n_neg1)++;
- if ( isnan(intensity) ) (*n_nan1)++;
-
- /* Area of one pixel */
- pix_area = pow(1.0/p->res, 2.0);
- Lsq = pow(p->clen, 2.0);
-
- /* Calculate distance from crystal to pixel */
- xs = fs*p->fsx + ss*p->ssx;
- ys = ss*p->fsy + ss*p->ssy;
- rx = (xs + p->cnx) / p->res;
- ry = (ys + p->cny) / p->res;
- dsq = pow(rx, 2.0) + pow(ry, 2.0);
- twotheta = atan2(sqrt(dsq), p->clen);
-
- /* Area of pixel as seen from crystal (approximate) */
- proj_area = pix_area * cos(twotheta);
-
- /* Projected area of pixel divided by distance squared */
- sa = proj_area / (dsq + Lsq);
-
- if ( do_poisson ) {
- counts = poisson_noise(rng, intensity * ph_per_e * sa);
- } else {
- cf = intensity * ph_per_e * sa;
- counts = cf;
- }
-
- /* Number of photons in pixel */
- dval = counts + poisson_noise(rng, background);
-
- /* Convert to ADU */
- dval *= p->adu_per_photon;
-
- /* Saturation */
- if ( dval > p->max_adu ) dval = p->max_adu;
-
- dp[fs + p->w*ss] = dval;
-
- /* Sanity checks */
- if ( isinf(dp[fs + p->w*ss]) ) n_inf2++;
- if ( isnan(dp[fs + p->w*ss]) ) n_nan2++;
- if ( dp[fs + p->w*ss] < 0.0 ) n_neg2++;
-
- if ( twotheta > *max_tt ) *max_tt = twotheta;
-
- }
- }
-}
-
-
-void record_image(struct image *image, int do_poisson, double background,
- gsl_rng *rng, double beam_radius, double nphotons)
-{
- double total_energy, energy_density;
- double ph_per_e;
- double area;
- double max_tt = 0.0;
- int n_inf1 = 0;
- int n_neg1 = 0;
- int n_nan1 = 0;
- int n_inf2 = 0;
- int n_neg2 = 0;
- int n_nan2 = 0;
- int pn;
-
- /* How many photons are scattered per electron? */
- area = M_PI*pow(beam_radius, 2.0);
- total_energy = nphotons * ph_lambda_to_en(image->lambda);
- energy_density = total_energy / area;
- ph_per_e = (nphotons /area) * pow(THOMSON_LENGTH, 2.0);
- STATUS("Fluence = %8.2e photons, "
- "Energy density = %5.3f kJ/cm^2, "
- "Total energy = %5.3f microJ\n",
- nphotons, energy_density/1e7, total_energy*1e6);
-
- fill_in_adu(image);
-
- for ( pn=0; pn<image->det->n_panels; pn++ ) {
-
- record_panel(&image->det->panels[pn], image->dp[pn],
- do_poisson, rng, ph_per_e, background,
- image->lambda,
- &n_neg1, &n_inf1, &n_nan1,
- &n_neg2, &n_inf2, &n_nan2, &max_tt);
- }
-
- STATUS("Max 2theta = %.2f deg, min d = %.2f nm\n",
- rad2deg(max_tt), (image->lambda/(2.0*sin(max_tt/2.0)))/1e-9);
-
- STATUS("Halve the d values to get the voxel size for a synthesis.\n");
-
- if ( n_neg1 + n_inf1 + n_nan1 + n_neg2 + n_inf2 + n_nan2 ) {
- ERROR("WARNING: The raw calculation produced %i negative"
- " values, %i infinities and %i NaNs.\n",
- n_neg1, n_inf1, n_nan1);
- ERROR("WARNING: After processing, there were %i negative"
- " values, %i infinities and %i NaNs.\n",
- n_neg2, n_inf2, n_nan2);
- }
-}
-
-
-signed int find_orig_panel_number(struct detector *det, double fs, double ss)
-{
- int p;
-
- for ( p=0; p<det->n_panels; p++ ) {
- if ( (fs >= det->panels[p].orig_min_fs)
- && (fs < det->panels[p].orig_max_fs+1)
- && (ss >= det->panels[p].orig_min_ss)
- && (ss < det->panels[p].orig_max_ss+1) ) return p;
- }
-
- return -1;
-}
-
-
-/* Like find_panel(), but uses the original panel bounds, i.e. referring to
- * what's in the HDF5 file */
-struct panel *find_orig_panel(struct detector *det, double fs, double ss)
-{
- signed int pn = find_orig_panel_number(det, fs, ss);
- if ( pn == -1 ) return NULL;
- return &det->panels[pn];
-}
-
-
-int panel_number(const struct detector *det, const struct panel *p)
-{
- int pn;
-
- for ( pn=0; pn<det->n_panels; pn++ ) {
- if ( &det->panels[pn] == p ) return pn;
- }
-
- return det->n_panels;
-}
-
-
-void adjust_centering_for_rail(struct panel *p)
-{
- double offs;
-
- /* Offset in +z direction from calibrated clen to actual */
- offs = p->clen - p->clen_for_centering;
- p->cnx += p->rail_x * offs;
- p->cny += p->rail_y * offs;
- p->clen = p->clen_for_centering + p->coffset + p->rail_z * offs;
-}
-
-
-void fill_in_adu(struct image *image)
-{
- int i;
-
- if ( image->det == NULL ) return;
-
- for ( i=0; i<image->det->n_panels; i++ ) {
-
- struct panel *p = &image->det->panels[i];
-
- /* Already have ADU per photon? */
- if ( !isnan(p->adu_per_photon) ) continue;
-
- if ( isnan(p->adu_per_eV) ) {
- ERROR("Neither adu_per_eV nor adu_per_photon set for "
- "panel %s\n", p->name);
- continue;
- }
-
- /* Convert ADU per eV to ADU per photon */
- p->adu_per_photon = ph_lambda_to_eV(image->lambda)
- * p->adu_per_eV;
- }
-}
-
-
-int panel_is_in_rigid_group(const struct rigid_group *rg, struct panel *p)
-{
- int i;
-
- for ( i=0; i<rg->n_panels; i++ ) {
- if ( rg->panels[i] == p ) {
- return 1;
- }
- }
-
- return 0;
-}
-
-
-int rigid_group_is_in_collection(struct rg_collection *c,
- struct rigid_group *rg)
-{
- int i;
-
- for ( i=0; i<c->n_rigid_groups; i++ ) {
- if ( c->rigid_groups[i] == rg ) {
- return 1;
- }
- }
-
- return 0;
-}
-
-
-struct rg_collection *find_rigid_group_collection_by_name(struct detector *det,
- const char *name)
-{
- int i;
-
- for ( i=0; i<det->n_rg_collections; i++ ) {
- if ( strcmp(det->rigid_group_collections[i]->name,
- name) == 0 ) {
- return det->rigid_group_collections[i];
- }
- }
-
- return NULL;
-}
-
-
-static struct panel *new_panel(struct detector *det, const char *name)
-{
- struct panel *new;
-
- det->n_panels++;
- det->panels = realloc(det->panels, det->n_panels*sizeof(struct panel));
-
- new = &det->panels[det->n_panels-1];
- memcpy(new, &det->defaults, sizeof(struct panel));
-
- strcpy(new->name, name);
-
- /* Create a new copy of the camera length location if needed */
- if ( new->clen_from != NULL ) {
- new->clen_from = strdup(new->clen_from);
- }
-
- /* Create a new copy of the data location if needed */
- if ( new->data != NULL ) {
- new->data = strdup(new->data);
- }
-
- /* Create a new copy of the dim_structure if needed */
- if ( new->dim_structure != NULL ) {
-
- struct dim_structure *dim_copy;
- int di;
-
- dim_copy = initialize_dim_structure();
- dim_copy->num_dims = new->dim_structure->num_dims;
- dim_copy->dims = malloc(dim_copy->num_dims*sizeof(int));
- for ( di=0; di<dim_copy->num_dims; di++ ) {
- dim_copy->dims[di] = new->dim_structure->dims[di];
- }
-
- new->dim_structure = dim_copy;
- }
-
- /* Create a new copy of the bad pixel mask location */
- if ( new->mask != NULL ) {
- new->mask = strdup(new->mask);
- }
-
- return new;
-}
-
-
-static struct badregion *new_bad_region(struct detector *det, const char *name)
-{
- struct badregion *new;
-
- det->n_bad++;
- det->bad = realloc(det->bad, det->n_bad*sizeof(struct badregion));
-
- new = &det->bad[det->n_bad-1];
- new->min_x = NAN;
- new->max_x = NAN;
- new->min_y = NAN;
- new->max_y = NAN;
- new->min_fs = 0;
- new->max_fs = 0;
- new->min_ss = 0;
- new->max_ss = 0;
- new->is_fsss = 99; /* Slightly nasty: means "unassigned" */
- new->panel = NULL;
- strcpy(new->name, name);
-
- return new;
-}
-
-
-struct panel *find_panel_by_name(struct detector *det, const char *name)
-{
- int i;
-
- for ( i=0; i<det->n_panels; i++ ) {
- if ( strcmp(det->panels[i].name, name) == 0 ) {
- return &det->panels[i];
- }
- }
-
- return NULL;
-}
-
-
-static struct badregion *find_bad_region_by_name(struct detector *det,
- const char *name)
-{
- int i;
-
- for ( i=0; i<det->n_bad; i++ ) {
- if ( strcmp(det->bad[i].name, name) == 0 ) {
- return &det->bad[i];
- }
- }
-
- return NULL;
-}
-
-
-static struct rigid_group *find_or_add_rg(struct detector *det,
- const char *name)
-{
- int i;
- struct rigid_group **new;
- struct rigid_group *rg;
-
- for ( i=0; i<det->n_rigid_groups; i++ ) {
-
- if ( strcmp(det->rigid_groups[i]->name, name) == 0 ) {
- return det->rigid_groups[i];
- }
-
- }
-
- new = realloc(det->rigid_groups,
- (1+det->n_rigid_groups)*sizeof(struct rigid_group *));
- if ( new == NULL ) return NULL;
-
- det->rigid_groups = new;
-
- rg = malloc(sizeof(struct rigid_group));
- if ( rg == NULL ) return NULL;
-
- det->rigid_groups[det->n_rigid_groups++] = rg;
-
- rg->name = strdup(name);
- rg->panels = NULL;
- rg->n_panels = 0;
-
- return rg;
-}
-
-
-static struct rg_collection *find_or_add_rg_coll(struct detector *det,
- const char *name)
-{
- int i;
- struct rg_collection **new;
- struct rg_collection *rgc;
-
- for ( i=0; i<det->n_rg_collections; i++ ) {
- if ( strcmp(det->rigid_group_collections[i]->name, name) == 0 )
- {
- return det->rigid_group_collections[i];
- }
- }
-
- new = realloc(det->rigid_group_collections,
- (1+det->n_rg_collections)*sizeof(struct rg_collection *));
- if ( new == NULL ) return NULL;
-
- det->rigid_group_collections = new;
-
- rgc = malloc(sizeof(struct rg_collection));
- if ( rgc == NULL ) return NULL;
-
- det->rigid_group_collections[det->n_rg_collections++] = rgc;
-
- rgc->name = strdup(name);
- rgc->rigid_groups = NULL;
- rgc->n_rigid_groups = 0;
-
- return rgc;
-}
-
-
-static void add_to_rigid_group(struct rigid_group *rg, struct panel *p)
-{
- struct panel **pn;
-
- pn = realloc(rg->panels, (1+rg->n_panels)*sizeof(struct panel *));
- if ( pn == NULL ) {
- ERROR("Couldn't add panel to rigid group.\n");
- return;
- }
-
- rg->panels = pn;
- rg->panels[rg->n_panels++] = p;
-}
-
-
-static void add_to_rigid_group_coll(struct rg_collection *rgc,
- struct rigid_group *rg)
-{
- struct rigid_group **r;
-
- r = realloc(rgc->rigid_groups, (1+rgc->n_rigid_groups)*
- sizeof(struct rigid_group *));
- if ( r == NULL ) {
- ERROR("Couldn't add rigid group to collection.\n");
- return;
- }
-
- rgc->rigid_groups = r;
- rgc->rigid_groups[rgc->n_rigid_groups++] = rg;
-}
-
-
-/* Free all rigid groups in detector */
-static void free_all_rigid_groups(struct detector *det)
-{
- int i;
-
- if ( det->rigid_groups == NULL ) return;
- for ( i=0; i<det->n_rigid_groups; i++ ) {
- free(det->rigid_groups[i]->name);
- free(det->rigid_groups[i]->panels);
- free(det->rigid_groups[i]);
- }
- free(det->rigid_groups);
-}
-
-
-/* Free all rigid groups in detector */
-static void free_all_rigid_group_collections(struct detector *det)
-{
- int i;
-
- if ( det->rigid_group_collections == NULL ) return;
- for ( i=0; i<det->n_rg_collections; i++ ) {
- free(det->rigid_group_collections[i]->name);
- free(det->rigid_group_collections[i]->rigid_groups);
- free(det->rigid_group_collections[i]);
- }
- free(det->rigid_group_collections);
-}
-
-
-static struct rigid_group *find_rigid_group_by_name(struct detector *det,
- char *name)
-{
- int i;
-
- for ( i=0; i<det->n_rigid_groups; i++ ) {
- if ( strcmp(det->rigid_groups[i]->name, name) == 0 ) {
- return det->rigid_groups[i];
- }
- }
-
- return NULL;
-}
-
-
-static int parse_field_for_panel(struct panel *panel, const char *key,
- const char *val, struct detector *det)
-{
- int reject = 0;
-
- if ( strcmp(key, "min_fs") == 0 ) {
- panel->orig_min_fs = atof(val);
- } else if ( strcmp(key, "max_fs") == 0 ) {
- panel->orig_max_fs = atof(val);
- } else if ( strcmp(key, "min_ss") == 0 ) {
- panel->orig_min_ss = atof(val);
- } else if ( strcmp(key, "max_ss") == 0 ) {
- panel->orig_max_ss = atof(val);
- } else if ( strcmp(key, "corner_x") == 0 ) {
- panel->cnx = atof(val);
- } else if ( strcmp(key, "corner_y") == 0 ) {
- panel->cny = atof(val);
- } else if ( strcmp(key, "rail_direction") == 0 ) {
- if ( dir_conv(val, &panel->rail_x,
- &panel->rail_y,
- &panel->rail_z) )
- {
- ERROR("Invalid rail direction '%s'\n", val);
- reject = 1;
- }
- } else if ( strcmp(key, "clen_for_centering") == 0 ) {
- panel->clen_for_centering = atof(val);
- } else if ( strcmp(key, "adu_per_eV") == 0 ) {
- panel->adu_per_eV = atof(val);
- } else if ( strcmp(key, "adu_per_photon") == 0 ) {
- panel->adu_per_photon = atof(val);
- } else if ( strcmp(key, "rigid_group") == 0 ) {
- add_to_rigid_group(find_or_add_rg(det, val), panel);
- } else if ( strcmp(key, "clen") == 0 ) {
-
- char *end;
- double v = strtod(val, &end);
- if ( end == val ) {
- /* This means "fill in later" */
- panel->clen = -1.0;
- panel->clen_from = strdup(val);
- } else {
- panel->clen = v;
- panel->clen_from = NULL;
- }
-
- } else if ( strcmp(key, "data") == 0 ) {
- if ( strncmp(val,"/",1) != 0 ) {
- ERROR("Invalid data location '%s'\n", val);
- reject = -1;
- }
- panel->data = strdup(val);
-
- } else if ( strcmp(key, "mask") == 0 ) {
- if ( strncmp(val,"/",1) != 0 ) {
- ERROR("Invalid mask location '%s'\n", val);
- reject = -1;
- }
- panel->mask = strdup(val);
-
- } else if ( strcmp(key, "mask_file") == 0 ) {
- panel->mask_file = strdup(val);
-
- } else if ( strcmp(key, "saturation_map") == 0 ) {
- panel->satmap = strdup(val);
- } else if ( strcmp(key, "saturation_map_file") == 0 ) {
- panel->satmap_file = strdup(val);
-
- } else if ( strcmp(key, "coffset") == 0) {
- panel->coffset = atof(val);
- } else if ( strcmp(key, "res") == 0 ) {
- panel->res = atof(val);
- } else if ( strcmp(key, "max_adu") == 0 ) {
- panel->max_adu = atof(val);
- } else if ( strcmp(key, "badrow_direction") == 0 ) {
- panel->badrow = val[0]; /* First character only */
- if ( (panel->badrow != 'x') && (panel->badrow != 'y')
- && (panel->badrow != 'f') && (panel->badrow != 's')
- && (panel->badrow != '-') ) {
- ERROR("badrow_direction must be x, y, f, s or '-'\n");
- ERROR("Assuming '-'\n.");
- panel->badrow = '-';
- }
- if ( panel->badrow == 'x' ) panel->badrow = 'f';
- if ( panel->badrow == 'y' ) panel->badrow = 's';
- } else if ( strcmp(key, "no_index") == 0 ) {
- panel->no_index = atob(val);
- } else if ( strcmp(key, "fs") == 0 ) {
- if ( dir_conv(val, &panel->fsx, &panel->fsy, &panel->fsz) != 0 )
- {
- ERROR("Invalid fast scan direction '%s'\n", val);
- reject = 1;
- }
- } else if ( strcmp(key, "ss") == 0 ) {
- if ( dir_conv(val, &panel->ssx, &panel->ssy, &panel->ssz) != 0 )
- {
- ERROR("Invalid slow scan direction '%s'\n", val);
- reject = 1;
- }
- } else if ( strncmp(key, "dim", 3) == 0) {
- int dim_entry;
- char *endptr;
- if ( key[3] != '\0' ) {
- if ( panel->dim_structure == NULL ) {
- panel->dim_structure = initialize_dim_structure();
- }
- dim_entry = strtoul(key+3, &endptr, 10);
- if ( endptr[0] != '\0' ) {
- ERROR("Invalid dimension number %s\n", key+3);
- } else {
- if ( set_dim_structure_entry(panel->dim_structure,
- dim_entry, val) )
- {
- ERROR("Failed to set dim structure entry\n");
- }
- }
- } else {
- ERROR("'dim' must be followed by a number, e.g. 'dim0'\n");
- }
- } else {
- ERROR("Unrecognised field '%s'\n", key);
- }
-
- return reject;
-}
-
-
-static int check_badr_fsss(struct badregion *badr, int is_fsss)
-{
- /* First assignment? */
- if ( badr->is_fsss == 99 ) {
- badr->is_fsss = is_fsss;
- return 0;
- }
-
- if ( is_fsss != badr->is_fsss ) {
- ERROR("You can't mix x/y and fs/ss in a bad region.\n");
- return 1;
- }
-
- return 0;
-}
-
-
-static int parse_field_bad(struct badregion *badr, const char *key,
- const char *val)
-{
- int reject = 0;
-
- if ( strcmp(key, "min_x") == 0 ) {
- badr->min_x = atof(val);
- reject = check_badr_fsss(badr, 0);
- } else if ( strcmp(key, "max_x") == 0 ) {
- badr->max_x = atof(val);
- reject = check_badr_fsss(badr, 0);
- } else if ( strcmp(key, "min_y") == 0 ) {
- badr->min_y = atof(val);
- reject = check_badr_fsss(badr, 0);
- } else if ( strcmp(key, "max_y") == 0 ) {
- badr->max_y = atof(val);
- reject = check_badr_fsss(badr, 0);
- } else if ( strcmp(key, "min_fs") == 0 ) {
- badr->min_fs = atof(val);
- reject = check_badr_fsss(badr, 1);
- } else if ( strcmp(key, "max_fs") == 0 ) {
- badr->max_fs = atof(val);
- reject = check_badr_fsss(badr, 1);
- } else if ( strcmp(key, "min_ss") == 0 ) {
- badr->min_ss = atof(val);
- reject = check_badr_fsss(badr, 1);
- } else if ( strcmp(key, "max_ss") == 0 ) {
- badr->max_ss = atof(val);
- reject = check_badr_fsss(badr, 1);
- } else if ( strcmp(key, "panel") == 0 ) {
- badr->panel = strdup(val);
- } else {
- ERROR("Unrecognised field '%s'\n", key);
- }
-
- return reject;
-}
-
-
-static void parse_toplevel(struct detector *det, struct beam_params *beam,
- const char *key, const char *val,
- struct rg_definition ***rg_defl,
- struct rgc_definition ***rgc_defl, int *n_rg_defs,
- int *n_rgc_defs, char **hdf5_peak_path)
-{
-
- if ( strcmp(key, "mask_bad") == 0 ) {
-
- char *end;
- double v = strtod(val, &end);
-
- if ( end != val ) {
- det->mask_bad = v;
- }
-
- } else if ( strcmp(key, "mask_good") == 0 ) {
-
- char *end;
- double v = strtod(val, &end);
-
- if ( end != val ) {
- det->mask_good = v;
- }
-
- } else if ( strcmp(key, "coffset") == 0 ) {
- det->defaults.coffset = atof(val);
-
- } else if ( strcmp(key, "photon_energy") == 0 ) {
- if ( beam != NULL ) {
- double v;
- char *end;
- v = strtod(val, &end);
- if ( (val[0] != '\0') && (end[0] == '\0') ) {
- beam->photon_energy = v;
- beam->photon_energy_from = NULL;
- } else {
- beam->photon_energy = 0.0;
- beam->photon_energy_from = strdup(val);
- }
- }
-
- } else if ( strcmp(key, "photon_energy_bandwidth") == 0 ) {
- if ( beam != NULL ) {
- double v;
- char *end;
- v = strtod(val, &end);
- if ( (val[0] != '\0') && (end[0] == '\0') ) {
- beam->bandwidth = v;
- } else {
- ERROR("Invalid value for "
- "photon_energy_bandwidth\n");
- }
- }
-
- } else if ( strcmp(key, "photon_energy_scale") == 0 ) {
- if ( beam != NULL ) {
- beam->photon_energy_scale = atof(val);
- }
-
- } else if ( strcmp(key, "peak_info_location") == 0 ) {
- if ( hdf5_peak_path != NULL ) {
- *hdf5_peak_path = strdup(val);
- }
-
- } else if (strncmp(key, "rigid_group", 11) == 0
- && strncmp(key, "rigid_group_collection", 22) != 0 ) {
-
- struct rg_definition **new;
-
- new = realloc(*rg_defl,
- ((*n_rg_defs)+1)*sizeof(struct rg_definition*));
- *rg_defl = new;
-
- (*rg_defl)[*n_rg_defs] = malloc(sizeof(struct rg_definition));
- (*rg_defl)[*n_rg_defs]->name = strdup(key+12);
- (*rg_defl)[*n_rg_defs]->pns = strdup(val);
- *n_rg_defs = *n_rg_defs+1;
-
- } else if ( strncmp(key, "rigid_group_collection", 22) == 0 ) {
-
- struct rgc_definition **new;
-
- new = realloc(*rgc_defl, ((*n_rgc_defs)+1)*
- sizeof(struct rgc_definition*));
- *rgc_defl = new;
-
- (*rgc_defl)[*n_rgc_defs] =
- malloc(sizeof(struct rgc_definition));
- (*rgc_defl)[*n_rgc_defs]->name = strdup(key+23);
- (*rgc_defl)[*n_rgc_defs]->rgs = strdup(val);
- *n_rgc_defs = *n_rgc_defs+1;
-
- } else if ( parse_field_for_panel(&det->defaults, key, val, det) ) {
- ERROR("Unrecognised top level field '%s'\n", key);
- }
-}
-
-
-/* Test if fs,ss in panel "p" is further {out,in} than {*p_max_d,*p_min_d}, and
- * if so update det->furthest_{out,in}_{panel,fs,ss}. */
-static void check_point(struct panel *p, double fs, double ss,
- double *p_min_d, double *p_max_d, struct detector *det)
-{
- double xs, ys, rx, ry, d;
-
- xs = fs*p->fsx + ss*p->ssx;
- ys = fs*p->fsy + ss*p->ssy;
-
- rx = (xs + p->cnx) / p->res;
- ry = (ys + p->cny) / p->res;
-
- d = sqrt(pow(rx, 2.0) + pow(ry, 2.0));
-
- if ( d > *p_max_d ) {
-
- det->furthest_out_panel = p;
- det->furthest_out_fs = fs;
- det->furthest_out_ss = ss;
- *p_max_d = d;
-
- } else if ( d < *p_min_d ) {
-
- det->furthest_in_panel = p;
- det->furthest_in_fs = fs;
- det->furthest_in_ss = ss;
- *p_min_d = d;
-
- }
-}
-
-
-static void find_min_max_d(struct detector *det)
-{
- double max_d, min_d;
- int i;
-
- min_d = +INFINITY;
- max_d = 0.0;
- for ( i=0; i<det->n_panels; i++ ) {
-
- struct panel *p;
-
- p = &det->panels[i];
-
- check_point(p, 0, 0, &min_d, &max_d, det);
- check_point(p, p->w, 0, &min_d, &max_d, det);
- check_point(p, 0, p->h, &min_d, &max_d, det);
- check_point(p, p->w, p->h, &min_d, &max_d, det);
-
- }
-}
-
-
-struct detector *get_detector_geometry(const char *filename,
- struct beam_params *beam)
-{
- return get_detector_geometry_2(filename, beam, NULL);
-}
-
-
-struct detector *get_detector_geometry_from_string(const char *string_in,
- struct beam_params *beam,
- char **hdf5_peak_path)
-{
- struct detector *det;
- char **bits;
- int done = 0;
- int i;
- int rgi, rgci;
- int reject = 0;
- int path_dim, mask_path_dim;
- int dim_dim;
- int dim_reject = 0;
- int dim_dim_reject = 0;
- struct rg_definition **rg_defl = NULL;
- struct rgc_definition **rgc_defl = NULL;
- int n_rg_definitions = 0;
- int n_rgc_definitions = 0;
- char *string;
- char *string_orig;
- size_t len;
-
- det = calloc(1, sizeof(struct detector));
- if ( det == NULL ) return NULL;
-
- if ( beam != NULL ) {
- beam->photon_energy = 0.0;
- beam->photon_energy_from = NULL;
- beam->photon_energy_scale = 1.0;
- beam->bandwidth = 0.00000001;
- }
-
- det->n_panels = 0;
- det->panels = NULL;
- det->n_bad = 0;
- det->bad = NULL;
- det->mask_good = 0;
- det->mask_bad = 0;
- det->n_rigid_groups = 0;
- det->rigid_groups = NULL;
- det->path_dim = 0;
- det->dim_dim = 0;
- det->n_rg_collections = 0;
- det->rigid_group_collections = NULL;
-
- /* The default defaults... */
- det->defaults.orig_min_fs = -1;
- det->defaults.orig_min_ss = -1;
- det->defaults.orig_max_fs = -1;
- det->defaults.orig_max_ss = -1;
- det->defaults.cnx = NAN;
- det->defaults.cny = NAN;
- det->defaults.clen = NAN;
- det->defaults.coffset = 0.0;
- det->defaults.res = -1.0;
- det->defaults.badrow = '-';
- det->defaults.no_index = 0;
- det->defaults.fsx = 1.0;
- det->defaults.fsy = 0.0;
- det->defaults.fsz = 0.0;
- det->defaults.ssx = 0.0;
- det->defaults.ssy = 1.0;
- det->defaults.ssz = 0.0;
- det->defaults.rail_x = NAN; /* The actual default rail direction */
- det->defaults.rail_y = NAN; /* is below */
- det->defaults.rail_z = NAN;
- det->defaults.clen_for_centering = NAN;
- det->defaults.adu_per_eV = NAN;
- det->defaults.adu_per_photon = NAN;
- det->defaults.max_adu = +INFINITY;
- det->defaults.mask = NULL;
- det->defaults.mask_file = NULL;
- det->defaults.satmap = NULL;
- det->defaults.satmap_file = NULL;
- det->defaults.data = NULL;
- det->defaults.dim_structure = NULL;
- strncpy(det->defaults.name, "", 1023);
-
- string = strdup(string_in);
- if ( string == NULL ) return NULL;
- len = strlen(string);
- for ( i=0; i<len; i++ ) {
- if ( string_in[i] == '\r' ) string[i] = '\n';
- }
-
- /* Because 'string' will get modified */
- string_orig = string;
-
- do {
-
- int n1, n2;
- char **path;
- char *line;
- struct badregion *badregion = NULL;
- struct panel *panel = NULL;
- char wholeval[1024];
-
- const char *nl = strchr(string, '\n');
- if ( nl != NULL ) {
- size_t len = nl - string;
- line = strndup(string, nl-string);
- line[len] = '\0';
- string += len+1;
- } else {
- line = strdup(string);
- done = 1;
- }
-
- if ( line[0] == ';' ) {
- free(line);
- continue;
- }
-
- n1 = assplode(line, " \t", &bits, ASSPLODE_NONE);
- if ( n1 < 3 ) {
- for ( i=0; i<n1; i++ ) free(bits[i]);
- free(bits);
- free(line);
- continue;
- }
-
- /* Stitch the pieces of the "value" back together */
- wholeval[0] = '\0'; /* Empty string */
- for ( i=2; i<n1; i++ ) {
- if ( bits[i][0] == ';' ) break; /* Stop on comment */
- strncat(wholeval, bits[i], 1023);
- }
-
- if ( bits[1][0] != '=' ) {
- for ( i=0; i<n1; i++ ) free(bits[i]);
- free(bits);
- free(line);
- continue;
- }
-
- n2 = assplode(bits[0], "/\\.", &path, ASSPLODE_NONE);
- if ( n2 < 2 ) {
-
- /* This was a top-level option, not handled above. */
- parse_toplevel(det, beam, bits[0], wholeval, &rg_defl,
- &rgc_defl, &n_rg_definitions,
- &n_rgc_definitions, hdf5_peak_path);
- for ( i=0; i<n1; i++ ) free(bits[i]);
- free(bits);
- for ( i=0; i<n2; i++ ) free(path[i]);
- free(path);
- free(line);
- continue;
- }
-
- if ( strncmp(path[0], "bad", 3) == 0 ) {
- badregion = find_bad_region_by_name(det, path[0]);
- if ( badregion == NULL ) {
- badregion = new_bad_region(det, path[0]);
- }
- } else {
- panel = find_panel_by_name(det, path[0]);
- if ( panel == NULL ) {
- panel = new_panel(det, path[0]);
- }
- }
-
- if ( panel != NULL ) {
- if ( parse_field_for_panel(panel, path[1],
- wholeval, det) )
- {
- reject = 1;
- }
- } else {
- if ( parse_field_bad(badregion, path[1], wholeval) ) {
- reject = 1;
- }
- }
-
- for ( i=0; i<n1; i++ ) free(bits[i]);
- for ( i=0; i<n2; i++ ) free(path[i]);
- free(bits);
- free(path);
- free(line);
-
- } while ( !done );
-
- if ( det->n_panels == -1 ) {
- ERROR("No panel descriptions in geometry file.\n");
- free(det);
- return NULL;
- }
-
- path_dim = -1;
- dim_reject = 0;
-
- for ( i=0; i<det->n_panels; i++ ) {
-
- int panel_dim = 0;
- char *next_instance;
-
- next_instance = det->panels[i].data;
-
- while ( next_instance ) {
- next_instance = strstr(next_instance, "%");
- if ( next_instance != NULL ) {
- next_instance += 1*sizeof(char);
- panel_dim += 1;
- }
- }
-
- if ( path_dim == -1 ) {
- path_dim = panel_dim;
- } else {
- if ( panel_dim != path_dim ) {
- dim_reject = 1;
- }
- }
-
- }
-
- mask_path_dim = -1;
- for ( i=0; i<det->n_panels; i++ ) {
-
- int panel_mask_dim = 0;
- char *next_instance;
-
- if ( det->panels[i].mask != NULL ) {
-
- next_instance = det->panels[i].mask;
-
- while ( next_instance ) {
- next_instance = strstr(next_instance, "%");
- if ( next_instance != NULL ) {
- next_instance += 1*sizeof(char);
- panel_mask_dim += 1;
- }
- }
-
- if ( mask_path_dim == -1 ) {
- mask_path_dim = panel_mask_dim;
- } else {
- if ( panel_mask_dim != mask_path_dim ) {
- dim_reject = 1;
- }
- }
-
- }
- }
-
- if ( dim_reject == 1 ) {
- ERROR("All panels' data and mask entries must have the same "
- "number of placeholders\n");
- reject = 1;
- }
-
- if ( mask_path_dim > path_dim ) {
- ERROR("Number of placeholders in mask cannot be larger than "
- "for data\n");
- reject = 1;
- }
-
- det->path_dim = path_dim;
-
- dim_dim_reject = 0;
- dim_dim = -1;
-
- for ( i=0; i<det->n_panels; i++ ) {
-
- int di;
- int found_ss = 0;
- int found_fs = 0;
- int panel_dim_dim = 0;
-
- if ( det->panels[i].dim_structure == NULL ) {
- det->panels[i].dim_structure = default_dim_structure();
- }
-
- for ( di=0; di<det->panels[i].dim_structure->num_dims; di++ ) {
-
- if ( det->panels[i].dim_structure->dims[di] ==
- HYSL_UNDEFINED ) {
- dim_dim_reject = 1;
- ERROR("Dimension %i for panel %s is undefined.\n",
- di, det->panels[i].name);
- }
- if ( det->panels[i].dim_structure->dims[di] ==
- HYSL_PLACEHOLDER ) {
- panel_dim_dim += 1;
- }
- if ( det->panels[i].dim_structure->dims[di] ==
- HYSL_SS ) {
- found_ss += 1;
- }
- if ( det->panels[i].dim_structure->dims[di] ==
- HYSL_FS ) {
- found_fs += 1;
- }
-
- }
-
- if ( found_ss != 1 ) {
- ERROR("Exactly one slow scan dim coordinate is needed "
- "(found %i for panel %s)\n", found_ss,
- det->panels[i].name);
- dim_dim_reject = 1;
- }
-
- if ( found_fs != 1 ) {
- ERROR("Exactly one fast scan dim coordinate is needed "
- "(found %i for panel %s)\n", found_fs,
- det->panels[i].name);
- dim_dim_reject = 1;
- }
-
- if ( panel_dim_dim > 1 ) {
- ERROR("Maximum one placeholder dim coordinate is "
- "allowed (found %i for panel %s)\n",
- panel_dim_dim, det->panels[i].name);
- dim_dim_reject = 1;
- }
-
- if ( dim_dim == -1 ) {
- dim_dim = panel_dim_dim;
- } else {
- if ( panel_dim_dim != dim_dim ) {
- dim_dim_reject = 1;
- }
- }
-
- }
-
- if ( dim_dim_reject == 1) {
- reject = 1;
- }
-
- det->dim_dim = dim_dim;
-
- for ( i=0; i<det->n_panels; i++ ) {
-
- struct panel *p = &det->panels[i];
-
- if ( p->orig_min_fs < 0 ) {
- ERROR("Please specify the minimum FS coordinate for"
- " panel %s\n", det->panels[i].name);
- reject = 1;
- }
- if ( p->orig_max_fs < 0 ) {
- ERROR("Please specify the maximum FS coordinate for"
- " panel %s\n", det->panels[i].name);
- reject = 1;
- }
- if ( p->orig_min_ss < 0 ) {
- ERROR("Please specify the minimum SS coordinate for"
- " panel %s\n", det->panels[i].name);
- reject = 1;
- }
- if ( p->orig_max_ss < 0 ) {
- ERROR("Please specify the maximum SS coordinate for"
- " panel %s\n", det->panels[i].name);
- reject = 1;
- }
- if ( isnan(p->cnx) ) {
- ERROR("Please specify the corner X coordinate for"
- " panel %s\n", det->panels[i].name);
- reject = 1;
- }
- if ( isnan(p->cny) ) {
- ERROR("Please specify the corner Y coordinate for"
- " panel %s\n", det->panels[i].name);
- reject = 1;
- }
- if ( isnan(p->clen) && (p->clen_from == NULL) ) {
- ERROR("Please specify the camera length for"
- " panel %s\n", det->panels[i].name);
- reject = 1;
- }
- if ( p->res < 0 ) {
- ERROR("Please specify the resolution for"
- " panel %s\n", det->panels[i].name);
- reject = 1;
- }
- if ( isnan(p->adu_per_eV) && isnan(p->adu_per_photon) ) {
- ERROR("Please specify either adu_per_eV or "
- "adu_per_photon for panel %s\n",
- det->panels[i].name);
- reject = 1;
- }
-
- if ( isnan(p->clen_for_centering) && !isnan(p->rail_x) )
- {
- ERROR("You must specify clen_for_centering if you "
- "specify the rail direction (panel %s)\n",
- p->name);
- reject = 1;
- }
-
- if ( (p->mask_file != NULL) && (p->mask == NULL) ) {
- ERROR("You have specified 'mask_file' but not 'mask'. "
- "'mask_file' will therefore have no effect. "
- "(panel %s)\n", p->name);
- reject = 1;
- }
-
- /* The default rail direction */
- if ( isnan(p->rail_x) ) {
- p->rail_x = 0.0;
- p->rail_y = 0.0;
- p->rail_z = 1.0;
- }
- if ( isnan(p->clen_for_centering) ) p->clen_for_centering = 0.0;
-
- /* It's OK if the badrow direction is '0' */
- /* It's not a problem if "no_index" is still zero */
- /* The default transformation matrix is at least valid */
-
- det->panels[i].w = det->panels[i].orig_max_fs
- - det->panels[i].orig_min_fs+1;
- det->panels[i].h = det->panels[i].orig_max_ss
- - det->panels[i].orig_min_ss+1;
-
- }
-
- for ( i=0; i<det->n_bad; i++ ) {
- if ( det->bad[i].is_fsss == 99 ) {
- ERROR("Please specify the coordinate ranges for"
- " bad region %s\n", det->bad[i].name);
- reject = 1;
- }
- }
-
- free(det->defaults.clen_from);
- free(det->defaults.data);
- free(det->defaults.mask);
-
- for ( rgi=0; rgi<n_rg_definitions; rgi++) {
-
- int pi, n1;
- struct rigid_group *rigidgroup = NULL;
-
- rigidgroup = find_or_add_rg(det, rg_defl[rgi]->name);
-
- n1 = assplode(rg_defl[rgi]->pns, ",", &bits, ASSPLODE_NONE);
-
- for ( pi=0; pi<n1; pi++ ) {
-
- struct panel *p;
-
- p = find_panel_by_name(det, bits[pi]);
- if ( p == NULL ) {
- ERROR("Cannot add panel to rigid group\n");
- ERROR("Panel not found: %s\n", bits[pi]);
- return NULL;
- }
- add_to_rigid_group(rigidgroup, p);
- free(bits[pi]);
- }
- free(bits);
- free(rg_defl[rgi]->name);
- free(rg_defl[rgi]->pns);
- free(rg_defl[rgi]);
- }
- free(rg_defl);
-
- for ( rgci=0; rgci<n_rgc_definitions; rgci++ ) {
-
- int rgi, n2;
- struct rg_collection *rgcollection = NULL;
-
- rgcollection = find_or_add_rg_coll(det, rgc_defl[rgci]->name);
-
- n2 = assplode(rgc_defl[rgci]->rgs, ",", &bits, ASSPLODE_NONE);
-
- for ( rgi=0; rgi<n2; rgi++ ) {
-
- struct rigid_group *r;
-
- r = find_rigid_group_by_name(det, bits[rgi]);
- if ( r == NULL ) {
- ERROR("Cannot add rigid group to collection\n");
- ERROR("Rigid group not found: %s\n", bits[rgi]);
- return NULL;
- }
- add_to_rigid_group_coll(rgcollection, r);
- free(bits[rgi]);
- }
- free(bits);
- free(rgc_defl[rgci]->name);
- free(rgc_defl[rgci]->rgs);
- free(rgc_defl[rgci]);
-
- }
- free(rgc_defl);
-
- if ( n_rg_definitions == 0 ) {
-
- int pi;
-
- for ( pi=0; pi<det->n_panels; pi++ ) {
-
- struct rigid_group *rigidgroup = NULL;
-
- rigidgroup = find_or_add_rg(det, det->panels[pi].name);
- add_to_rigid_group(rigidgroup, &det->panels[pi]);
-
- }
- }
-
- if ( n_rgc_definitions == 0 ) {
-
- int rgi;
- struct rg_collection *rgcollection = NULL;
-
- rgcollection = find_or_add_rg_coll(det, "default");
-
- for ( rgi=0; rgi<det->n_rigid_groups; rgi++ ) {
-
- add_to_rigid_group_coll(rgcollection,
- det->rigid_groups[rgi]);
-
- }
- }
-
- /* Calculate matrix inverses and other stuff */
- for ( i=0; i<det->n_panels; i++ ) {
-
- struct panel *p;
- double d;
-
- p = &det->panels[i];
-
- if ( p->fsx*p->ssy == p->ssx*p->fsy ) {
- ERROR("Panel %i transformation singular.\n", i);
- }
-
- d = (double)p->fsx*p->ssy - p->ssx*p->fsy;
- p->xfs = p->ssy / d;
- p->yfs = -p->ssx / d;
- p->xss = -p->fsy / d;
- p->yss = p->fsx / d;
-
- p->w = p->orig_max_fs - p->orig_min_fs + 1;
- p->h = p->orig_max_ss - p->orig_min_ss + 1;
-
- }
-
- find_min_max_d(det);
- free(string_orig);
-
- if ( reject ) return NULL;
-
- return det;
-}
-
-
-char *load_entire_file(const char *filename)
-{
- struct stat statbuf;
- int r;
- char *contents;
- FILE *fh;
-
- r = stat(filename, &statbuf);
- if ( r != 0 ) {
- ERROR("File '%s' not found\n", filename);
- return NULL;
- }
-
- contents = malloc(statbuf.st_size+1);
- if ( contents == NULL ) {
- ERROR("Failed to allocate memory for file\n");
- return NULL;
- }
-
- fh = fopen(filename, "r");
- if ( fh == NULL ) {
- ERROR("Failed to open file '%s'\n", filename);
- free(contents);
- return NULL;
- }
-
- if ( fread(contents, 1, statbuf.st_size, fh) != statbuf.st_size ) {
- ERROR("Failed to read file '%s'\n", filename);
- free(contents);
- return NULL;
- }
- contents[statbuf.st_size] = '\0';
-
- fclose(fh);
-
- return contents;
-}
-
-
-struct detector *get_detector_geometry_2(const char *filename,
- struct beam_params *beam,
- char **hdf5_peak_path)
-{
- char *contents;
- struct detector *det;
-
- contents = load_entire_file(filename);
- if ( contents == NULL ) {
- ERROR("Failed to load geometry file '%s'\n", filename);
- return NULL;
- }
-
- det = get_detector_geometry_from_string(contents, beam, hdf5_peak_path);
- free(contents);
- return det;
-}
-
-
-void free_detector_geometry(struct detector *det)
-{
- int i;
-
- free_all_rigid_groups(det);
- free_all_rigid_group_collections(det);
-
- for ( i=0; i<det->n_panels; i++ ) {
- free(det->panels[i].clen_from);
- free_dim_structure(det->panels[i].dim_structure);
- }
-
- free(det->panels);
- free(det->bad);
- free(det);
-}
-
-
-static int rg_number(const struct detector *det, const struct rigid_group *rg)
-{
- int i;
- for ( i=0; i<det->n_rigid_groups; i++ ) {
- if ( det->rigid_groups[i] == rg ) return i;
- }
- return det->n_rigid_groups;
-}
-
-
-struct detector *copy_geom(const struct detector *in)
-{
- struct detector *out;
- int i;
-
- if ( in == NULL ) return NULL;
-
- out = malloc(sizeof(struct detector));
- if ( out == NULL ) return NULL;
-
- /* Copy everything */
- memcpy(out, in, sizeof(struct detector));
-
- out->panels = malloc(out->n_panels * sizeof(struct panel));
- memcpy(out->panels, in->panels, out->n_panels * sizeof(struct panel));
-
- out->bad = malloc(out->n_bad * sizeof(struct badregion));
- memcpy(out->bad, in->bad, out->n_bad * sizeof(struct badregion));
-
- /* Copy the panels */
- for ( i=0; i<out->n_panels; i++ ) {
-
- struct panel *p;
-
- /* Copy all fields */
- p = &out->panels[i];
-
- /* Now fix up everything involving pointers... */
-
- if ( p->clen_from != NULL ) {
- /* Make a copy of the clen_from fields unique to this
- * copy of the structure. */
- p->clen_from = strdup(p->clen_from);
- }
-
- if ( p->data != NULL ) {
- /* Make a copy of the data fields unique to this
- * copy of the structure. */
- p->data = strdup(p->data);
- }
-
- if ( p->dim_structure != NULL ) {
- /* Make a copy of the dim_structure fields unique to this
- * copy of the structure. */
-
- struct dim_structure *dim_new;
- int di;
-
- dim_new = initialize_dim_structure();
- dim_new->num_dims = p->dim_structure->num_dims;
- dim_new->dims = malloc(dim_new->num_dims*sizeof(int));
- for ( di=0; di<dim_new->num_dims; di++ ) {
- dim_new->dims[di] = p->dim_structure->dims[di];
- }
-
- p->dim_structure = dim_new;
-
- }
-
- if ( &in->panels[i] == in->furthest_out_panel ) {
- out->furthest_out_panel = &out->panels[i];
- }
- if ( &in->panels[i] == in->furthest_in_panel ) {
- out->furthest_in_panel = &out->panels[i];
- }
-
- }
-
- /* Copy all the rigid groups */
- out->rigid_groups = malloc(out->n_rigid_groups*sizeof(struct rigid_group));
- if ( out->rigid_groups == NULL ) return NULL;
- for ( i=0; i<out->n_rigid_groups; i++ ) {
-
- struct rigid_group *inrg;
- struct rigid_group *rg;
- int j;
-
- rg = malloc(sizeof(struct rigid_group));
- if ( rg == NULL ) return NULL;
-
- out->rigid_groups[i] = rg;
-
- inrg = in->rigid_groups[i];
-
- rg->name = strdup(inrg->name);
- if ( rg->name == NULL ) return NULL;
-
- rg->n_panels = inrg->n_panels;
- rg->panels = malloc(inrg->n_panels*sizeof(struct panel *));
- if ( rg->panels == NULL ) return NULL;
-
- for ( j=0; j<rg->n_panels; j++ ) {
- int k = panel_number(in, inrg->panels[j]);
- rg->panels[j] = &out->panels[k];
- }
-
- }
-
- /* Copy all the rigid group collections */
- out->rigid_group_collections = malloc(out->n_rg_collections*sizeof(struct rg_collection));
- if ( out->rigid_group_collections == NULL ) return NULL;
- for ( i=0; i<out->n_rg_collections; i++ ) {
-
- struct rg_collection *inrgc;
- struct rg_collection *rgc;
- int j;
-
- rgc = malloc(sizeof(struct rg_collection));
- if ( rgc == NULL ) return NULL;
-
- out->rigid_group_collections[i] = rgc;
-
- inrgc = in->rigid_group_collections[i];
-
- rgc->name = strdup(inrgc->name);
- if ( rgc->name == NULL ) return NULL;
-
- rgc->n_rigid_groups = inrgc->n_rigid_groups;
- rgc->rigid_groups = malloc(rgc->n_rigid_groups*sizeof(struct rg_collection));
- if ( rgc->rigid_groups == NULL ) return NULL;
-
- for ( j=0; j<rgc->n_rigid_groups; j++ ) {
- int k = rg_number(in, inrgc->rigid_groups[j]);
- if ( k == in->n_rigid_groups ) return NULL;
- rgc->rigid_groups[j] = out->rigid_groups[k];
- }
-
- }
-
- return out;
-}
-
-
-struct detector *simple_geometry(const struct image *image, int w, int h)
-{
- struct detector *geom;
-
- geom = calloc(1, sizeof(struct detector));
-
- geom->n_panels = 1;
- geom->panels = calloc(1, sizeof(struct panel));
-
- geom->panels[0].orig_min_fs = 0;
- geom->panels[0].orig_max_fs = w-1;
- geom->panels[0].orig_min_ss = 0;
- geom->panels[0].orig_max_ss = h-1;
- geom->panels[0].cnx = -w / 2.0;
- geom->panels[0].cny = -h / 2.0;
- geom->panels[0].max_adu = INFINITY;
- geom->panels[0].orig_min_fs = -1;
- geom->panels[0].orig_max_fs = -1;
- geom->panels[0].orig_min_ss = -1;
- geom->panels[0].orig_max_ss = -1;
-
- geom->panels[0].fsx = 1;
- geom->panels[0].fsy = 0;
- geom->panels[0].fsz = 0;
- geom->panels[0].ssx = 0;
- geom->panels[0].ssy = 1;
- geom->panels[0].ssz = 0;
-
- geom->panels[0].xfs = 1;
- geom->panels[0].xss = 0;
- geom->panels[0].yfs = 0;
- geom->panels[0].yss = 1;
-
- geom->panels[0].w = w;
- geom->panels[0].h = h;
-
- geom->panels[0].mask = NULL;
- geom->panels[0].data = NULL;
-
- find_min_max_d(geom);
-
- return geom;
-}
-
-
-int reverse_2d_mapping(double x, double y, struct detector *det,
- struct panel **pp, double *pfs, double *pss)
-{
- int i;
-
- for ( i=0; i<det->n_panels; i++ ) {
-
- struct panel *p = &det->panels[i];
- double cx, cy, fs, ss;
-
- /* Get position relative to corner */
- cx = x - p->cnx;
- cy = y - p->cny;
-
- /* Reverse the transformation matrix */
- fs = cx*p->xfs + cy*p->yfs;
- ss = cx*p->xss + cy*p->yss;
-
- /* In range? */
- if ( fs < 0 ) continue;
- if ( ss < 0 ) continue;
- if ( fs > p->w ) continue;
- if ( ss > p->h ) continue;
-
- *pfs = fs;
- *pss = ss;
- *pp = p;
- return 0;
-
- }
-
- return 1;
-}
-
-
-static void check_extents(struct panel p, double *min_x, double *min_y,
- double *max_x, double *max_y, double fs, double ss)
-{
- double xs, ys, rx, ry;
-
- xs = fs*p.fsx + ss*p.ssx;
- ys = fs*p.fsy + ss*p.ssy;
-
- rx = xs + p.cnx;
- ry = ys + p.cny;
-
- if ( rx > *max_x ) *max_x = rx;
- if ( ry > *max_y ) *max_y = ry;
- if ( rx < *min_x ) *min_x = rx;
- if ( ry < *min_y ) *min_y = ry;
-}
-
-
-static void rewrite_panel_fields(const struct panel *p, char *line,
- FILE *fh, char **bits,
- int write_panel_coffset)
-{
- char new_line[1024];
- char string_to_write[512];
-
- strcpy(new_line,"\0");
- strcpy(string_to_write,"\0");
-
- if(strstr(bits[1], "fs") != NULL &&
- strstr(bits[1], "min_fs") == NULL &&
- strstr(bits[1], "max_fs") == NULL &&
- strstr(bits[1], "offset") == NULL ) {
-
- sprintf(string_to_write, "%+fx %+fy",
- p->fsx, p->fsy);
- build_output_line(line, new_line,
- string_to_write);
- fputs(new_line, fh);
- fputs("\n", fh);
- return;
-
- } else if ( strstr(bits[1], "ss") != NULL &&
- strstr(bits[1], "min_ss") == NULL &&
- strstr(bits[1], "max_ss") == NULL) {
-
- sprintf(string_to_write, "%+fx %+fy",
- p->ssx, p->ssy);
- build_output_line(line, new_line,
- string_to_write);
- fputs(new_line, fh);
- fputs("\n", fh);
- return;
-
- } else if ( strstr(bits[1], "corner_x") != NULL) {
-
- sprintf(string_to_write, "%g",
- p->cnx);
- build_output_line(line, new_line,
- string_to_write);
- fputs(new_line, fh);
- fputs("\n", fh);
- return;
-
- } else if ( strstr(bits[1], "corner_y") != NULL) {
-
- sprintf(string_to_write, "%g",
- p->cny);
- build_output_line(line, new_line,
- string_to_write);
- fputs(new_line, fh);
- fputs("\n", fh);
- return;
-
- } else if ( strstr(bits[1], "coffset") != NULL) {
-
- if ( write_panel_coffset ) {
- return;
- } else {
- fputs(line, fh);
- fputs("\n", fh);
- return;
- }
-
- } else {
- fputs(line, fh);
- fputs("\n", fh);
- }
-}
-
-
-double largest_q(struct image *image)
-{
- struct rvec q;
- double tt;
-
- if ( image->det == NULL ) {
- ERROR("No detector geometry. assuming detector is infinite!\n");
- return INFINITY;
- }
-
- q = get_q_for_panel(image->det->furthest_out_panel,
- image->det->furthest_out_fs,
- image->det->furthest_out_ss,
- &tt, 1.0/image->lambda);
-
- return modulus(q.u, q.v, q.w);
-}
-
-
-double smallest_q(struct image *image)
-{
- struct rvec q;
- double tt;
-
- q = get_q_for_panel(image->det->furthest_in_panel,
- image->det->furthest_in_fs,
- image->det->furthest_in_ss,
- &tt, 1.0/image->lambda);
-
- return modulus(q.u, q.v, q.w);
-}
-
-
-void get_pixel_extents(struct detector *det,
- double *min_x, double *min_y,
- double *max_x, double *max_y)
-{
- int i;
-
- *min_x = 0.0;
- *max_x = 0.0;
- *min_y = 0.0;
- *max_y = 0.0;
-
- /* To determine the maximum extents of the detector, put all four
- * corners of each panel through the transformations and watch for the
- * biggest */
-
- for ( i=0; i<det->n_panels; i++ ) {
-
- check_extents(det->panels[i], min_x, min_y, max_x, max_y,
- 0.0, 0.0);
-
- check_extents(det->panels[i], min_x, min_y, max_x, max_y,
- 0.0, det->panels[i].h+1);
-
- check_extents(det->panels[i], min_x, min_y, max_x, max_y,
- det->panels[i].w+1, 0.0);
-
- check_extents(det->panels[i], min_x, min_y, max_x, max_y,
- det->panels[i].w+1, det->panels[i].h+1);
-
-
- }
-}
-
-
-int write_detector_geometry_3(const char *geometry_data,
- const char *output_filename, struct detector *det,
- const char *additional_comment,
- int write_panel_coffset)
-{
- FILE *fh;
- int done = 0;
-
- if ( geometry_data == NULL ) return 2;
- if ( output_filename == NULL ) return 2;
- if ( det->n_panels < 1 ) return 3;
-
- fh = fopen(output_filename, "w");
- if ( fh == NULL ) return 1;
-
- if ( additional_comment != NULL ) {
- fputs("; ", fh);
- fputs(additional_comment, fh);
- fputs("\n", fh);
- }
-
- if ( write_panel_coffset ) {
- fputs("; Optimized panel offsets can be found at the "
- "end of the file\n", fh);
- }
-
- do {
-
- int n_bits;
- char **bits;
- int i;
- struct panel *p;
- char *line;
- const char *nl;
-
- /* Get the next line */
- nl = strchr(geometry_data, '\n');
- if ( nl != NULL ) {
- size_t len = nl - geometry_data;
- line = strndup(geometry_data, nl-geometry_data);
- line[len] = '\0';
- geometry_data += len+1;
- } else {
- /* Last line might now have newline at end */
- line = strdup(geometry_data);
- done = 1;
- }
-
- n_bits = assplode(line, "/=", &bits, ASSPLODE_NONE);
-
- if ( n_bits != 3 ) {
- if ( write_panel_coffset && (bits != NULL)
- && (strstr(bits[0], "coffset" ) != NULL) ) continue;
- fputs(line, fh);
- fputs("\n", fh);
- } else {
-
- p = find_panel_by_name(det, bits[0]);
-
- if ( p != NULL ) {
- rewrite_panel_fields(p, line, fh, bits,
- write_panel_coffset);
- } else {
- fputs(line, fh);
- fputs("\n", fh);
- }
- }
-
- for ( i=0; i<n_bits; i++ ) free(bits[i]);
-
- } while ( !done );
-
- if ( write_panel_coffset ) {
-
- int pi;
-
- fputs("\n", fh);
-
- for ( pi=0; pi<det->n_panels; pi++ ) {
- fprintf(fh, "%s/coffset = %f\n",
- det->panels[pi].name, det->panels[pi].coffset);
- }
- }
-
- return 0;
-}
-
-
-int write_detector_geometry_2(const char *geometry_filename,
- const char *output_filename, struct detector *det,
- const char *additional_comment,
- int write_panel_coffset)
-{
- int r;
- char *geometry_data = load_entire_file(geometry_filename);
- r = write_detector_geometry_3(geometry_data, output_filename, det,
- additional_comment, write_panel_coffset);
- free(geometry_data);
- return r;
-}
-
-
-int write_detector_geometry(const char *geometry_filename,
- const char *output_filename, struct detector *det)
-{
- return write_detector_geometry_2(geometry_filename, output_filename,
- det, NULL, 0);
-}
-
-
-/**
- * \param image An image structure
- * \param min Minimum value of 1/d to be marked as bad
- * \param max Maximum value of 1/d to be marked as bad
- *
- * Flags, in the bad pixel mask for \p image, every pixel whose resolution is
- * between \p min and \p max.
- *
- */
-
-void mark_resolution_range_as_bad(struct image *image,
- double min, double max)
-{
- int i;
-
- if ( isinf(min) && isinf(max) ) return; /* nothing to do */
-
- for ( i=0; i<image->det->n_panels; i++ ) {
-
- int fs, ss;
- struct panel *p = &image->det->panels[i];
-
- for ( ss=0; ss<p->h; ss++ ) {
- for ( fs=0; fs<p->w; fs++ ) {
- struct rvec q;
- double r;
- q = get_q_for_panel(p, fs, ss, NULL, 1.0/image->lambda);
- r = modulus(q.u, q.v, q.w);
- if ( (r >= min) && (r <= max) ) {
- image->bad[i][fs+p->w*ss] = 1;
- }
- }
- }
-
- }
-}
-
-
-static int safe_strcmp(const char *a, const char *b)
-{
- /* If both are NULL, they count as equal */
- if ( (a == NULL) && (b == NULL) ) return 0;
-
- /* Otherwise, if either is NULL then they're different */
- if ( a == NULL ) return 1;
- if ( b == NULL ) return 1;
-
- /* Otherwise, normal string comparison */
- return strcmp(a, b);
-}
-
-
-/**
- * \param det A detector structure
- * \param element If manually selected by the user, the HDF5 element being used.
- * Otherwise NULL.
- *
- * \returns Non-zero if the combination of \p det and \p element mean that all the
- * data comes from a single block.
- */
-int single_panel_data_source(struct detector *det, const char *element)
-{
- int pi;
- const char *first_datafrom = NULL;
- const char *curr_datafrom = NULL;
-
- if ( det->panels[0].data == NULL ) {
- first_datafrom = element; /* Might be NULL */
- } else {
- first_datafrom = det->panels[0].data;
- }
-
- for ( pi=1; pi<det->n_panels; pi++ ) {
-
- if ( det->panels[pi].data == NULL ) {
- curr_datafrom = element; /* Might be NULL */
- } else {
- curr_datafrom = det->panels[pi].data;
- }
-
- if ( safe_strcmp(curr_datafrom, first_datafrom) != 0 ) {
- return 0;
- }
-
- }
-
- return 1;
-}
-
-
-int multi_event_geometry(struct detector *det)
-{
- return (det->path_dim != 0) || (det->dim_dim != 0);
-}
diff --git a/libcrystfel/src/detector.h b/libcrystfel/src/detector.h
deleted file mode 100644
index 2176861f..00000000
--- a/libcrystfel/src/detector.h
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * detector.h
- *
- * Detector properties
- *
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
- * a research centre of the Helmholtz Association.
- * Copyright © 2012 Richard Kirian
- *
- * Authors:
- * 2009-2019 Thomas White <taw@physics.org>
- * 2011-2012 Richard Kirian <rkirian@asu.edu>
- * 2014 Valerio Mariani
- * 2011 Andrew Aquila
- *
- * This file is part of CrystFEL.
- *
- * CrystFEL is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * CrystFEL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifndef DETECTOR_H
-#define DETECTOR_H
-
-struct rigid_group;
-struct rg_collection;
-struct detector;
-struct panel;
-struct badregion;
-struct beam_params;
-struct hdfile;
-struct event;
-
-#include "hdf5-file.h"
-#include "image.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \file detector.h
- * Detector geometry structure and related functions.
- */
-
-
-struct rigid_group
-{
- char *name;
- struct panel **panels;
- int n_panels;
-};
-
-
-struct rg_collection
-{
- char *name;
- struct rigid_group **rigid_groups;
- int n_rigid_groups;
-};
-
-
-/**
- * Represents one panel of a detector
- */
-struct panel
-{
- /** Text name for panel (fixed length array) */
- char name[1024];
-
- /** \name Location of corner in units of the pixel size of this panel */
- /**@{*/
- double cnx;
- double cny;
- /**@}*/
-
- /** The offset to be applied from \ref clen */
- double coffset;
-
- /** The distance from the interaction point to the corner of the
- * first pixel */
- double clen;
-
- /** Location to get \ref clen from, e.g. from HDF5 file */
- char *clen_from;
-
- /** Location of mask data */
- char *mask;
-
- /** Filename for mask data */
- char *mask_file;
-
- /** Location of per-pixel saturation map */
- char *satmap;
-
- /** Filename for saturation map */
- char *satmap_file;
-
- /** Resolution in pixels per metre */
- double res;
-
- /** Readout direction (for filtering out clusters of peaks)
- * ('x' or 'y') */
- char badrow;
-
- /** Non-zero if panel should be considered entirely bad */
- int no_index;
-
- /** Number of detector intensity units per photon */
- double adu_per_photon;
-
- /** Treat pixel as unreliable if higher than this */
- double max_adu;
-
- /** Location of data in file */
- char *data;
-
- /** Number of detector intensity units per eV of photon energy */
- double adu_per_eV;
-
- /** Dimension structure */
- struct dim_structure *dim_structure;
-
- /** \name Transformation matrix from pixel coordinates to lab frame */
- /*@{*/
- double fsx;
- double fsy;
- double fsz;
- double ssx;
- double ssy;
- double ssz;
- /*@}*/
-
- /** \name Rail direction */
- /*@{*/
- double rail_x;
- double rail_y;
- double rail_z;
- /*@}*/
-
- /* Value of clen (without coffset) at which beam is centered */
- double clen_for_centering;
-
- /** \name Inverse of 2D part of transformation matrix */
- /*@{*/
- double xfs;
- double yfs;
- double xss;
- double yss;
- /*@}*/
-
- /** \name Position of the panel in the data block in the file.
- * The panels may get moved around when the file is loaded (see
- * hdf5_read2()), especially if the panels come from different HDF5
- * elements. */
- /*@{*/
- int orig_min_fs;
- int orig_max_fs;
- int orig_min_ss;
- int orig_max_ss;
- /*@}*/
-
- /** Width, calculated as max_fs-min_fs+1 */
- int w;
-
- /*** Height, calculated as max_ss-min_ss+1 */
- int h;
-};
-
-
-struct badregion
-{
- char name[1024];
- int is_fsss;
- char *panel;
-
- double min_x;
- double max_x;
- double min_y;
- double max_y;
-
- /* Specified INCLUSIVELY */
- int min_fs;
- int max_fs;
- int min_ss;
- int max_ss;
-
-};
-
-
-struct detector
-{
- struct panel *panels;
- int n_panels;
-
- struct badregion *bad;
- int n_bad;
-
- unsigned int mask_bad;
- unsigned int mask_good;
-
- struct rigid_group **rigid_groups;
- int n_rigid_groups;
-
- struct rg_collection **rigid_group_collections;
- int n_rg_collections;
-
- /* Location of the pixel furthest away from the beam position, which
- * will have the largest value of 2theta regardless of camera length
- * and wavelength */
- struct panel *furthest_out_panel;
- double furthest_out_fs;
- double furthest_out_ss;
-
- /* As above, but for the smallest 2theta */
- struct panel *furthest_in_panel;
- double furthest_in_fs;
- double furthest_in_ss;
-
- int path_dim;
- int dim_dim;
-
- struct panel defaults;
-};
-
-
-extern struct rvec get_q_for_panel(struct panel *p, double fs, double ss,
- double *ttp, double k);
-
-extern double get_tt(struct image *image, double xs, double ys, int *err);
-
-extern int in_bad_region(struct detector *det, struct panel *p,
- double fs, double ss);
-
-extern void record_image(struct image *image, int do_poisson, double background,
- gsl_rng *rng, double beam_radius, double nphotons);
-
-extern struct panel *find_orig_panel(struct detector *det,
- double fs, double ss);
-
-extern signed int find_orig_panel_number(struct detector *det,
- double fs, double ss);
-
-extern int panel_number(const struct detector *det, const struct panel *p);
-
-extern struct detector *get_detector_geometry(const char *filename,
- struct beam_params *beam);
-
-extern struct detector *get_detector_geometry_2(const char *filename,
- struct beam_params *beam,
- char **hdf5_peak_path);
-
-extern struct detector *get_detector_geometry_from_string(const char *string,
- struct beam_params *beam,
- char **hdf5_peak_path);
-
-extern void free_detector_geometry(struct detector *det);
-
-extern struct detector *simple_geometry(const struct image *image, int w, int h);
-
-extern void get_pixel_extents(struct detector *det,
- double *min_x, double *min_y,
- double *max_x, double *max_y);
-
-extern void fill_in_adu(struct image *image);
-extern void adjust_centering_for_rail(struct panel *p);
-
-extern int panel_is_in_rigid_group(const struct rigid_group *rg,
- struct panel *p);
-
-extern int rigid_group_is_in_collection(struct rg_collection *c,
- struct rigid_group *rg);
-
-extern struct detector *copy_geom(const struct detector *in);
-
-extern int reverse_2d_mapping(double x, double y, struct detector *det,
- struct panel **pp, double *pfs, double *pss);
-
-extern double largest_q(struct image *image);
-
-extern double smallest_q(struct image *image);
-
-extern struct panel *find_panel_by_name(struct detector *det, const char *name);
-
-extern int write_detector_geometry_2(const char *geometry_filename,
- const char *output_filename,
- struct detector *det,
- const char *additional_comment,
- int write_panel_coffset);
-
-extern int write_detector_geometry_3(const char *geometry_data,
- const char *output_filename,
- struct detector *det,
- const char *additional_comment,
- int write_panel_coffset);
-
-extern int write_detector_geometry(const char *geometry_filename,
- const char *output_filename,
- struct detector *det);
-
-extern void mark_resolution_range_as_bad(struct image *image,
- double min, double max);
-
-
-extern int single_panel_data_source(struct detector *det, const char *element);
-
-struct rg_collection *find_rigid_group_collection_by_name(struct detector *det,
- const char *name);
-
-extern int detector_has_clen_references(struct detector *det);
-
-extern int multi_event_geometry(struct detector *det);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* DETECTOR_H */
diff --git a/libcrystfel/src/detgeom.c b/libcrystfel/src/detgeom.c
new file mode 100644
index 00000000..5612a225
--- /dev/null
+++ b/libcrystfel/src/detgeom.c
@@ -0,0 +1,141 @@
+/*
+ * detgeom.c
+ *
+ * Utility functions for detgeom structure
+ *
+ * Copyright © 2019-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "detgeom.h"
+#include "utils.h"
+
+
+/**
+ * \file detgeom.h
+ */
+
+
+void detgeom_transform_coords(struct detgeom_panel *p,
+ double fs, double ss,
+ double wavelength,
+ double dx, double dy,
+ double *r)
+{
+ double xs, ys, zs;
+ double fac;
+
+ /* Calculate 3D position of given position, in pixels */
+ xs = p->cnx + fs*p->fsx + ss*p->ssx + dx*p->pixel_pitch;
+ ys = p->cny + fs*p->fsy + ss*p->ssy + dy*p->pixel_pitch;
+ zs = p->cnz + fs*p->fsz + ss*p->ssz;
+
+ fac = wavelength * sqrt(xs*xs + ys*ys + zs*zs);
+
+ r[0] = xs / fac;
+ r[1] = ys / fac;
+ r[2] = zs / fac - 1.0/wavelength;
+}
+
+
+void detgeom_free(struct detgeom *detgeom)
+{
+ int i;
+
+ for ( i=0; i<detgeom->n_panels; i++ ) {
+ free(detgeom->panels[i].name);
+ }
+
+ free(detgeom->panels);
+ free(detgeom);
+}
+
+
+static double panel_max_res(struct detgeom_panel *p,
+ double wavelength)
+{
+ double r[3];
+ double max_res = 0.0;
+
+ detgeom_transform_coords(p, 0, 0, wavelength, 0.0, 0.0, r);
+ max_res = biggest(max_res, modulus(r[0], r[1], r[2]));
+
+ detgeom_transform_coords(p, 0, p->h, wavelength, 0.0, 0.0, r);
+ max_res = biggest(max_res, modulus(r[0], r[1], r[2]));
+
+ detgeom_transform_coords(p, p->w, 0, wavelength, 0.0, 0.0, r);
+ max_res = biggest(max_res, modulus(r[0], r[1], r[2]));
+
+ detgeom_transform_coords(p, p->w, p->h, wavelength, 0.0, 0.0, r);
+ max_res = biggest(max_res, modulus(r[0], r[1], r[2]));
+
+ return max_res;
+}
+
+
+double detgeom_max_resolution(struct detgeom *detgeom,
+ double wavelength)
+{
+ int i;
+ double max_res = 0.0;
+
+ for ( i=0; i<detgeom->n_panels; i++ ) {
+
+ double panel_maxres;
+
+ panel_maxres = panel_max_res(&detgeom->panels[i],
+ wavelength);
+ if ( panel_maxres > max_res ) {
+ max_res = panel_maxres;
+ }
+ }
+
+ return max_res;
+}
+
+
+void show_panel(struct detgeom_panel *p)
+{
+ STATUS("Panel '%s':\n", p->name);
+ STATUS(" Size %i x %i px\n", p->w, p->h);
+ STATUS(" Transformation [cnx] + [%6.2f %6.2f] [fs] = [x]\n",
+ p->fsx, p->ssx);
+ STATUS(" [cny] + [%6.2f %6.2f] [ss] = [y]\n",
+ p->fsy, p->ssy);
+ STATUS(" [cnz] + [%6.2f %6.2f] = [z]\n",
+ p->fsz, p->ssz);
+ STATUS(" corner x,y,z = %f, %f, %f px\n",
+ p->cnx, p->cny, p->cnz);
+ STATUS(" = %f, %f, %f mm\n",
+ p->cnx*p->pixel_pitch*1e3,
+ p->cny*p->pixel_pitch*1e3,
+ p->cnz*p->pixel_pitch*1e3);
+ STATUS(" %f adu/photon, max %f adu\n",
+ p->adu_per_photon, p->max_adu);
+}
diff --git a/libcrystfel/src/detgeom.h b/libcrystfel/src/detgeom.h
new file mode 100644
index 00000000..5e3815ac
--- /dev/null
+++ b/libcrystfel/src/detgeom.h
@@ -0,0 +1,112 @@
+/*
+ * detgeom.h
+ *
+ * Detector geometry structure
+ *
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ * Copyright © 2012 Richard Kirian
+ *
+ * Authors:
+ * 2009-2020 Thomas White <taw@physics.org>
+ * 2011-2012 Richard Kirian <rkirian@asu.edu>
+ * 2014 Valerio Mariani
+ * 2011 Andrew Aquila
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DETGEOM_H
+#define DETGEOM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \file detgeom.h
+ * Detector geometry structure and related functions.
+ */
+
+
+/**
+ * Represents one panel of a detector
+ */
+struct detgeom_panel
+{
+ /** Text name for panel */
+ char *name;
+
+ /** \name Location of corner in units of the pixel size of this panel, \
+ * measured from the interaction point. */
+ /**@{*/
+ double cnx;
+ double cny;
+ double cnz;
+ /**@}*/
+
+ /** Pixel size in metres */
+ double pixel_pitch;
+
+ /** Number of detector intensity units per photon (or electron, etc) */
+ double adu_per_photon;
+
+ /** Treat pixel as unreliable if higher than this */
+ double max_adu;
+
+ /** \name Transformation matrix from pixel coordinates to lab frame */
+ /*@{*/
+ double fsx;
+ double fsy;
+ double fsz;
+ double ssx;
+ double ssy;
+ double ssz;
+ /*@}*/
+
+ /** \name Width and height of panel */
+ /*@{*/
+ int w;
+ int h;
+ /*@}*/
+};
+
+
+struct detgeom
+{
+ struct detgeom_panel *panels;
+ int n_panels;
+};
+
+extern void detgeom_transform_coords(struct detgeom_panel *p,
+ double fs, double ss,
+ double wavelength,
+ double dx, double dy,
+ double *r);
+
+extern void detgeom_free(struct detgeom *detgeom);
+
+extern double detgeom_max_resolution(struct detgeom *detgeom,
+ double wavelength);
+
+extern void show_panel(struct detgeom_panel *p);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DETGEOM_H */
diff --git a/libcrystfel/src/events.c b/libcrystfel/src/events.c
deleted file mode 100644
index 491f7811..00000000
--- a/libcrystfel/src/events.c
+++ /dev/null
@@ -1,636 +0,0 @@
-/*
- * events.c
- *
- * Event properties
- *
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
- * a research centre of the Helmholtz Association.
- *
- * Authors:
- * 2017 Thomas White
- * 2014 Valerio Mariani
- *
- * This file is part of CrystFEL.
- *
- * CrystFEL is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * CrystFEL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "events.h"
-#include "utils.h"
-
-#include <hdf5.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-/** \file events.h */
-
-struct event *initialize_event()
-{
-
- struct event *ev;
-
- ev = malloc(sizeof(struct event));
- ev->path_entries = NULL;
- ev->path_length = 0;
-
- ev->dim_entries = NULL;
- ev->dim_length = 0;
-
- return ev;
-
-}
-
-
-struct event_list *initialize_event_list()
-{
-
- struct event_list *ev_list;
-
- ev_list = malloc(sizeof(struct event_list));
-
- ev_list->events = NULL;
- ev_list->num_events = 0;
-
- return ev_list;
-
-}
-
-struct filename_plus_event *initialize_filename_plus_event()
-{
-
- struct filename_plus_event *fpe;
-
- fpe = malloc(sizeof(struct filename_plus_event));
-
- fpe->filename = NULL;
- fpe->ev = NULL;
-
- return fpe;
-}
-
-
-int event_cmp(struct event *ev1, struct event *ev2)
-{
- int pi;
- int di;
-
- if ( ev1->path_length != ev2->path_length ||
- ev1->dim_length != ev2->dim_length ) {
- return 1;
- }
-
- for ( pi=0; pi<ev1->path_length; pi++ ) {
- if ( strcmp(ev1->path_entries[pi], ev2->path_entries[pi]) != 0 ) {
- return 1;
- }
- }
-
- for ( di=0; di<ev1->dim_length; di++ ) {
- if ( ev1->path_entries[di] != ev2->path_entries[di] ) {
- return 1;
- }
- }
-
- return 0;
-
-}
-
-
-int add_non_existing_event_to_event_list(struct event_list *ev_list,
- struct event *ev)
-{
- int evi;
- int found = 0;
-
- for ( evi=0; evi<ev_list->num_events; evi++ ) {
- if (event_cmp(ev_list->events[evi], ev) == 0 ) {
- found = 1;
- break;
- }
- }
-
- if ( found == 0) {
- return append_event_to_event_list(ev_list, ev);
- }
-
- return 0;
-}
-
-
-int append_event_to_event_list(struct event_list *ev_list, struct event *ev)
-{
- struct event **new_el;
-
- new_el = realloc(ev_list->events,
- (1+ev_list->num_events)*sizeof(struct event*));
- if ( new_el == NULL ) return 1;
-
- ev_list->events = new_el;
- ev_list->events[ev_list->num_events] = copy_event(ev);
- ev_list->num_events +=1;
-
- return 0;
-}
-
-
-struct event *copy_event(struct event *ev)
-{
- struct event *new_ev;
- int pi, di;
-
- if ( ev == NULL ) return NULL;
-
- if ( ev->dim_length == 0 && ev->path_length == 0) {
-
- new_ev = initialize_event();
-
- } else {
-
- new_ev=malloc(sizeof(struct event));
-
- new_ev->path_entries = malloc(ev->path_length*sizeof(char *));
- new_ev->path_length = ev->path_length;
-
- new_ev->dim_entries = malloc(ev->dim_length*sizeof(int *));
- new_ev->dim_length = ev->dim_length;
-
- for ( pi=0; pi<new_ev->path_length; pi++ ) {
- new_ev->path_entries[pi] = strdup(ev->path_entries[pi]);
- }
-
- for ( di=0; di<new_ev->dim_length; di++ ) {
- new_ev->dim_entries[di] = ev->dim_entries[di];
- }
-
- }
- return new_ev;
-}
-
-
-struct event_list *copy_event_list(struct event_list *el)
-{
- int ei;
- struct event_list *el_copy;
- struct event **events_copy;
-
- el_copy = malloc(1);
- if ( el_copy == NULL ) {
- return NULL;
- }
-
- events_copy = malloc(el->num_events);
- if ( events_copy == NULL ) {
- free (el_copy);
- return NULL;
- }
- el_copy->events = events_copy;
-
- for ( ei=0; ei<el->num_events; ei++ ) {
- el_copy->events[ei]=copy_event(el->events[ei]);
- }
-
- el_copy->num_events = el->num_events;
-
- return el_copy;
-}
-
-
-static int events_equal(struct event *ev1, struct event *ev2)
-{
- int i;
-
- if ( ev1->path_length != ev2->path_length ) return 0;
- if ( ev1->dim_length != ev2->dim_length ) return 0;
-
- for ( i=0; i<ev1->path_length; i++ ) {
- if ( strcmp(ev1->path_entries[i], ev2->path_entries[i]) != 0 ) {
- return 0;
- }
- }
-
- for ( i=0; i<ev1->dim_length; i++ ) {
- if ( ev1->dim_entries[i] != ev2->dim_entries[i] ) return 0;
- }
-
- return 1;
-}
-
-
-/**
- * \param ev: An event structure
- * \param el: An event list
- *
- * \returns The indexing into \p el of the event matching \p ev, of el->num_events
- * if no such event is found.
- **/
-int find_event(struct event *ev, struct event_list *el)
-{
- int i;
-
- if ( ev == NULL ) return el->num_events;
-
- for ( i=0; i<el->num_events; i++ ) {
- if ( events_equal(ev, el->events[i]) ) return i;
- }
-
- return i;
-}
-
-
-void free_event(struct event *ev)
-{
- int pi;
-
- if ( ev == NULL ) return;
-
- if ( ev->path_length != 0 ) {
- for ( pi=0; pi<ev->path_length; pi++ ) {
- free(ev->path_entries[pi]);
- }
- }
- free(ev->dim_entries);
- free(ev);
-}
-
-
-void free_event_list(struct event_list *el)
-{
- int ei;
-
- for ( ei=0; ei<el->num_events; ei++ ) {
- free_event(el->events[ei]);
- }
- free(el);
-}
-
-
-void free_filename_plus_event(struct filename_plus_event *fpe)
-{
- free(fpe->filename);
-
- if ( fpe->ev != NULL ) {
- free_event(fpe->ev);
- }
-
- free(fpe);
-}
-
-
-char *get_event_string(struct event *ev)
-{
- char *evstr;
- int i;
- size_t ev_len;
-
- if ( ev == NULL ) return strdup("(none)");
-
- ev_len = 1; /* Zero terminator */
- for ( i=0; i<ev->path_length; i++ ) {
- ev_len += strlen(ev->path_entries[i]);
- ev_len += 1; /* Slash afterwards */
- }
- ev_len += 16*ev->dim_length; /* Max length of number plus slash */
- ev_len += 2; /* Double slash in middle */
-
- evstr = malloc(ev_len);
- if ( evstr == NULL ) return NULL;
- evstr[0] = '\0';
-
- for ( i=0; i<ev->path_length; i++ ) {
- if ( i > 0 ) strcat(evstr, "/");
- strcat(evstr, ev->path_entries[i]);
- }
-
- strcat(evstr, "//");
-
- for ( i=0; i<ev->dim_length; i++ ) {
- char num_buf[16];
- snprintf(num_buf, 16, "%i", ev->dim_entries[i]);
- if ( i > 0 ) strcat(evstr, "/");
- strcat(evstr, num_buf);
- }
-
- return evstr;
-}
-
-
-struct event *get_event_from_event_string(const char *ev_string)
-{
- struct event *ev;
- char *ev_sep;
- char buf_path[1024];
- char buf_dim[1024];
- char *sep;
- char *start;
-
- ev_sep = strstr(ev_string, "//");
- if ( ev_sep == NULL ) return NULL;
-
- strncpy(buf_path, ev_string, ev_sep-ev_string);
- buf_path[ev_sep-ev_string] = '\0';
-
- strncpy(buf_dim, ev_sep+2, strlen(ev_sep)-2);
- buf_dim[strlen(ev_sep)-2] = '\0';
-
- ev = initialize_event();
- if ( ev == NULL ) return NULL;
-
- if ( strlen(buf_path) !=0 ) {
- start = buf_path;
- do {
- char buf[2014];
-
- sep = strstr(start, "/");
-
- if ( sep != NULL ) {
- strncpy(buf, start, sep-start);
- buf[sep-start]='\0';
- push_path_entry_to_event(ev, buf);
- start = sep + 1;
-
- } else {
-
- sprintf(buf,"%s",start);
- push_path_entry_to_event(ev, buf);
-
- }
-
- } while (sep);
-
- }
-
- if ( strlen(buf_dim) !=0 ) {
-
- start = buf_dim;
-
- do {
-
- char buf[2014];
- int buf_int;
-
- sep = strstr(start, "/");
- if ( sep != NULL ) {
- strncpy(buf, start, sep-start);
- buf[sep-start]='\0';
- buf_int = atoi(buf);
- push_dim_entry_to_event(ev, buf_int);
- start = sep + 1;
-
- } else {
-
- sprintf(buf,"%s",start);
- buf_int = atoi(buf);
- push_dim_entry_to_event(ev, buf_int);
-
- }
-
- } while (sep);
-
- }
-
-
- return ev;
-}
-
-
-int push_path_entry_to_event(struct event *ev, const char *entry)
-{
- char **new_path_entries;
-
- new_path_entries = realloc(ev->path_entries,
- (1+ev->path_length)*sizeof(char *));
- if ( new_path_entries == NULL ) return 1;
-
- ev->path_entries = new_path_entries;
- ev->path_entries[ev->path_length] = strdup(entry);
- ev->path_length += 1;
-
- return 0;
-}
-
-
-int push_dim_entry_to_event(struct event *ev, int entry)
-{
- int *new_dim_entries;
-
- new_dim_entries = realloc(ev->dim_entries,
- (1+ev->dim_length)*sizeof(int));
- if ( new_dim_entries == NULL ) return 1;
-
- ev->dim_entries = new_dim_entries;
- ev->dim_entries[ev->dim_length] = entry;
- ev->dim_length += 1;
-
- return 0;
-}
-
-
-int pop_path_entry_from_event(struct event *ev)
-{
- char **new_path_entries;
-
- if ( ev->path_length == 0 ) return 1;
-
- free(ev->path_entries[ev->path_length-1]);
-
- if ( ev->path_length == 1 ) {
- ev->path_entries = NULL;
- ev->path_length = 0;
- return 0;
- }
-
- new_path_entries = realloc(ev->path_entries,
- (ev->path_length-1)*sizeof(char *));
-
- if ( new_path_entries == NULL ) return 1;
-
- ev->path_entries = new_path_entries;
- ev->path_length = ev->path_length-1;
-
- return 0;
-}
-
-
-int pop_dim_entry_from_event(struct event *ev)
-{
- int *new_dim_entries;
-
- if ( ev->dim_length == 0 ) {
- return 1;
- }
-
- if ( ev->dim_length == 1 ) {
- ev->dim_entries = NULL;
- ev->dim_length = 0;
- return 0;
- }
-
- new_dim_entries = realloc(ev->dim_entries,
- (ev->dim_length-1)*sizeof(int));
-
- if ( new_dim_entries == NULL) {
- return 1;
- }
-
- ev->dim_entries = new_dim_entries;
- ev->dim_length = ev->dim_length-1;
-
- return 0;
-}
-
-
-char *event_path_placeholder_subst(const char *entry, const char *data)
-{
-
- char *ph_loc;
- char *full_path;
- ptrdiff_t len_head;
- size_t len_entry, len_data;
-
- len_entry = strlen(entry);
- len_data = strlen(data);
- full_path = malloc(len_data + len_entry + 1);
- if ( full_path == NULL ) return NULL;
-
- ph_loc = strchr(data, '%');
- len_head = ph_loc - data;
- assert(len_head >= 0);
-
- strncpy(full_path, data, len_head);
- full_path[len_head] = '\0';
- strcat(full_path, entry);
- strcat(full_path, ph_loc+1);
-
- return full_path;
-}
-
-
-char *retrieve_full_path(struct event *ev, const char *data)
-{
- int ei ;
- char *return_value;
- char *pholder;
-
- return_value = strdup(data);
- pholder = strstr(return_value,"%");
- ei = 0;
-
- while ( pholder != NULL ) {
-
- char *tmp;
-
- /* Check we have enough things to put in the placeholders */
- if ( ei >= ev->path_length ) {
- ERROR("Too many placeholders ('%%') in location.\n");
- return NULL;
- }
-
- /* Substitute one placeholder */
- tmp = event_path_placeholder_subst(ev->path_entries[ei++],
- return_value);
-
- if ( tmp == NULL ) {
- ERROR("Couldn't substitute placeholder\n");
- return NULL;
- }
-
- /* Next time, we will substitute the next part of the path into
- * the partially substituted string */
- free(return_value);
- return_value = tmp;
-
- pholder = strstr(return_value, "%");
-
- }
-
- return return_value;
-}
-
-
-struct dim_structure *initialize_dim_structure()
-{
- struct dim_structure *hs;
-
- hs = malloc(sizeof(struct dim_structure));
- if ( hs == NULL ) return NULL;
-
- hs->dims = NULL;
- hs->num_dims = 0;
-
- return hs;
-}
-
-
-struct dim_structure *default_dim_structure()
-{
- struct dim_structure *hsd;
-
- hsd = initialize_dim_structure();
-
- set_dim_structure_entry(hsd, 0, "ss");
- set_dim_structure_entry(hsd, 1, "fs");
-
- return hsd;
-}
-
-
-void free_dim_structure(struct dim_structure *hsd)
-{
- if ( hsd == NULL ) return;
- free(hsd->dims);
- free(hsd);
-}
-
-
-static int parse_dim_structure_val(const char *val)
-{
- if ( strcmp(val,"%") == 0 ) {
- return HYSL_PLACEHOLDER;
- } else if ( strcmp(val,"ss") == 0 ) {
- return HYSL_SS;
- } else if ( strcmp(val,"fs") == 0 ) {
- return HYSL_FS;
- }
- return atoi(val);
-
-}
-
-
-int set_dim_structure_entry(struct dim_structure *hsd, int dim_entry,
- const char *val_string)
-{
- /* "dims" array needs element with zero index */
- if ( dim_entry >= hsd->num_dims ) {
-
- int di;
-
- int *new_dims = realloc(hsd->dims, (dim_entry+1)*sizeof(int));
- if ( new_dims == NULL ) return 1;
-
- /* Initialise the elements just allocated */
- for ( di=hsd->num_dims; di<=dim_entry; di++ ) {
- new_dims[di] = HYSL_UNDEFINED;
- }
-
- hsd->dims = new_dims;
- hsd->num_dims = dim_entry+1;
-
- }
-
- hsd->dims[dim_entry] = parse_dim_structure_val(val_string);
-
- return 0;
-}
diff --git a/libcrystfel/src/events.h b/libcrystfel/src/events.h
deleted file mode 100644
index b743f827..00000000
--- a/libcrystfel/src/events.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * events.h
- *
- * Event properties
- *
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
- * a research centre of the Helmholtz Association.
- *
- * Authors:
- * 2014 Valerio Mariani
- *
- * This file is part of CrystFEL.
- *
- * CrystFEL is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * CrystFEL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifndef EVENTS_H
-#define EVENTS_H
-
-/**
- * \file events.h
- * Event description structures
- */
-
-struct event
-{
- char **path_entries;
- int path_length;
- int *dim_entries;
- int dim_length;
-};
-
-struct event_list
-{
- struct event **events;
- int num_events;
-};
-
-struct filename_plus_event
-{
- char *filename;
- struct event *ev;
-};
-
-enum dimension_id
-{
- HYSL_UNDEFINED = -99,
- HYSL_PLACEHOLDER = -98,
- HYSL_FS = -1,
- HYSL_SS = -2
-};
-
-struct dim_structure
-{
- int *dims;
- int num_dims;
-};
-
-extern struct event *initialize_event(void);
-extern int push_path_entry_to_event(struct event *ev, const char *entry);
-extern int pop_path_entry_from_event(struct event *ev);
-extern int push_dim_entry_to_event(struct event *ev, int entry);
-extern int pop_dim_entry_from_event(struct event *ev);
-extern struct event *copy_event(struct event *ev);
-extern void free_event(struct event *ev);
-extern char *get_event_string(struct event *ev);
-extern struct event *get_event_from_event_string(const char *ev_string);
-extern char *event_path_placeholder_subst(const char *ev_name,
- const char *data);
-extern char *retrieve_full_path(struct event *ev, const char *data);
-
-
-extern struct filename_plus_event *initialize_filename_plus_event(void);
-extern void free_filename_plus_event(struct filename_plus_event *fpe);
-
-
-extern struct event_list *initialize_event_list(void);
-extern int append_event_to_event_list(struct event_list *ev_list,
- struct event *ev);
-extern int add_non_existing_event_to_event_list(struct event_list *ev_list,
- struct event *ev);
-extern struct event_list *copy_event_list(struct event_list *el);
-extern int find_event(struct event *ev, struct event_list *el);
-extern void free_event_list(struct event_list *el);
-
-
-extern struct dim_structure *initialize_dim_structure(void);
-extern struct dim_structure *default_dim_structure(void);
-extern int set_dim_structure_entry(struct dim_structure *hsd,
- int dim_entry, const char *val_string);
-extern void free_dim_structure_entry(struct dim_structure *hsd);
-extern void free_dim_structure(struct dim_structure *hsd);
-
-#endif /* EVENTS_H */
diff --git a/libcrystfel/src/filters.c b/libcrystfel/src/filters.c
index 352046aa..9d01bac3 100644
--- a/libcrystfel/src/filters.c
+++ b/libcrystfel/src/filters.c
@@ -3,11 +3,11 @@
*
* Image filtering
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2016 Thomas White <taw@physics.org>
+ * 2010-2020 Thomas White <taw@physics.org>
* 2013 Anton Barty <anton.barty@desy.de>
*
* This file is part of CrystFEL.
@@ -84,8 +84,8 @@ void filter_noise(struct image *image)
{
int i;
- for ( i=0; i<image->det->n_panels; i++ ) {
- struct panel *p = &image->det->panels[i];
+ for ( i=0; i<image->detgeom->n_panels; i++ ) {
+ struct detgeom_panel *p = &image->detgeom->panels[i];
filter_noise_in_panel(image->dp[i], p->w, p->h);
}
}
@@ -149,14 +149,14 @@ void filter_median(struct image *image, int size)
/* Determine local background
* (median over window width either side of current pixel) */
- for ( pn=0; pn<image->det->n_panels; pn++ ) {
+ for ( pn=0; pn<image->detgeom->n_panels; pn++ ) {
int fs, ss;
int i;
- struct panel *p;
+ struct detgeom_panel *p;
float *localBg;
- p = &image->det->panels[pn];
+ p = &image->detgeom->panels[pn];
localBg = calloc(p->w*p->h, sizeof(float));
if ( localBg == NULL ) {
diff --git a/libcrystfel/src/filters.h b/libcrystfel/src/filters.h
index 17c235b1..83b76b9b 100644
--- a/libcrystfel/src/filters.h
+++ b/libcrystfel/src/filters.h
@@ -1,13 +1,13 @@
/*
- * peaks.h
+ * filters.h
*
* Image filtering
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010,2012-2013 Thomas White <taw@physics.org>
+ * 2010-2019 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -29,10 +29,6 @@
#ifndef FILTERS_H
#define FILTERS_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/libcrystfel/src/fom.c b/libcrystfel/src/fom.c
new file mode 100644
index 00000000..af1ba8fe
--- /dev/null
+++ b/libcrystfel/src/fom.c
@@ -0,0 +1,1465 @@
+/*
+ * fom.c
+ *
+ * Figure of merit calculation
+ *
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2010-2021 Thomas White <taw@physics.org>
+ * 2013 Lorenzo Galli <lorenzo.galli@desy.de>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gsl/gsl_errno.h>
+#include <gsl/gsl_statistics.h>
+#include <gsl/gsl_fit.h>
+#include <assert.h>
+
+#include "utils.h"
+#include "fom.h"
+#include "cell.h"
+#include "cell-utils.h"
+#include "reflist.h"
+#include "reflist-utils.h"
+
+/**
+ * \file fom.h
+ */
+
+struct fom_context
+{
+ enum fom_type fom;
+ int nshells;
+ int *cts;
+
+ /* For R-factors */
+ double *num;
+ double *den;
+
+ /* For "double" R-factors */
+ double *num2;
+ double *den2;
+
+ /* For CCs */
+ double **vec1;
+ double **vec2;
+ int *n;
+ int nmax;
+
+ /* For "counting" things e.g. d1sig or d2sig */
+ int *n_within;
+
+ long int *n_meas;
+ long int *possible;
+};
+
+
+static struct fom_context *init_fom(enum fom_type fom, int nmax, int nshells)
+{
+ struct fom_context *fctx;
+ int i;
+
+ fctx = malloc(sizeof(struct fom_context));
+ if ( fctx == NULL ) return NULL;
+
+ fctx->fom = fom;
+ fctx->nshells = nshells;
+ fctx->cts = malloc(nshells*sizeof(int));
+ for ( i=0; i<nshells; i++ ) {
+ fctx->cts[i] = 0;
+ }
+
+ fctx->num = NULL;
+ fctx->den = NULL;
+ fctx->num2 = NULL;
+ fctx->den2 = NULL;
+ fctx->possible = NULL;
+
+ switch ( fctx->fom ) {
+
+ case FOM_RANORSPLIT :
+ fctx->num2 = malloc(nshells*sizeof(double));
+ fctx->den2 = malloc(nshells*sizeof(double));
+ if ( (fctx->num2 == NULL) || (fctx->den2 == NULL) ) return NULL;
+ for ( i=0; i<nshells; i++ ) {
+ fctx->num2[i] = 0.0;
+ fctx->den2[i] = 0.0;
+ }
+ /* Intentional fall-through (no break) */
+
+ case FOM_R1I :
+ case FOM_R1F :
+ case FOM_R2 :
+ case FOM_RSPLIT :
+ case FOM_RANO :
+ case FOM_MEAN_INTENSITY :
+ case FOM_SNR :
+ case FOM_REDUNDANCY :
+ fctx->num = malloc(nshells*sizeof(double));
+ fctx->den = malloc(nshells*sizeof(double));
+ if ( (fctx->num == NULL) || (fctx->den == NULL) ) return NULL;
+ for ( i=0; i<nshells; i++ ) {
+ fctx->num[i] = 0.0;
+ fctx->den[i] = 0.0;
+ }
+ break;
+
+ case FOM_COMPLETENESS :
+ /* Uses 'cts' and 'possible' only */
+ break;
+
+ case FOM_NUM_MEASUREMENTS :
+ fctx->n_meas = calloc(nshells, sizeof(long int));
+ if ( fctx->n_meas == NULL ) return NULL;
+ break;
+
+ case FOM_CC :
+ case FOM_CCSTAR :
+ case FOM_CCANO :
+ case FOM_CRDANO :
+ fctx->vec1 = malloc(nshells*sizeof(double *));
+ fctx->vec2 = malloc(nshells*sizeof(double *));
+ if ( (fctx->vec1 == NULL) || (fctx->vec2 == NULL) ) return NULL;
+ for ( i=0; i<nshells; i++ ) {
+ fctx->vec1[i] = malloc(nmax*sizeof(double));
+ if ( fctx->vec1[i] == NULL ) return NULL;
+ fctx->vec2[i] = malloc(nmax*sizeof(double));
+ if ( fctx->vec2[i] == NULL ) return NULL;
+ fctx->n = malloc(nshells*sizeof(int));
+ if ( fctx->n == NULL ) return NULL;
+ }
+ for ( i=0; i<nshells; i++ ) {
+ fctx->n[i] = 0;
+ }
+ fctx->nmax = nmax;
+ break;
+
+ case FOM_D1SIG :
+ case FOM_D2SIG :
+ fctx->n_within = malloc(nshells*sizeof(int));
+ if ( fctx->n_within == NULL ) return NULL;
+ for ( i=0; i<nshells; i++ ) {
+ fctx->n_within[i] = 0;
+ }
+ break;
+
+ }
+
+ return fctx;
+}
+
+
+static int add_to_fom(struct fom_context *fctx,
+ Reflection *refl1,
+ Reflection *refl2,
+ Reflection *refl1bij,
+ Reflection *refl2bij,
+ int bin)
+{
+ double i1, i2, i1bij, i2bij, sig1, sig2;
+ double im, imbij;
+ int bad = 0;
+
+ fctx->cts[bin]++;
+
+ switch ( fctx->fom ) {
+
+ case FOM_R1I :
+ i1 = get_intensity(refl1);
+ i2 = get_intensity(refl2);
+ fctx->num[bin] += fabs(i1 - i2);
+ fctx->den[bin] += i1;
+ break;
+
+ case FOM_R1F :
+ i1 = get_intensity(refl1);
+ i2 = get_intensity(refl2);
+ fctx->num[bin] += fabs(sqrt(i1) - sqrt(i2));
+ fctx->den[bin] += sqrt(i1);
+ break;
+
+ case FOM_R2 :
+ i1 = get_intensity(refl1);
+ i2 = get_intensity(refl2);
+ fctx->num[bin] += pow(i1 - i2, 2.0);
+ fctx->den[bin] += pow(i1, 2.0);
+ break;
+
+ case FOM_RSPLIT :
+ i1 = get_intensity(refl1);
+ i2 = get_intensity(refl2);
+ fctx->num[bin] += fabs(i1 - i2);
+ fctx->den[bin] += i1 + i2;
+ break;
+
+ case FOM_CC :
+ case FOM_CCSTAR :
+ assert(fctx->n[bin] < fctx->nmax);
+ i1 = get_intensity(refl1);
+ i2 = get_intensity(refl2);
+ fctx->vec1[bin][fctx->n[bin]] = i1;
+ fctx->vec2[bin][fctx->n[bin]] = i2;
+ fctx->n[bin]++;
+ break;
+
+ case FOM_CCANO :
+ case FOM_CRDANO :
+ assert(fctx->n[bin] < fctx->nmax);
+ i1 = get_intensity(refl1);
+ i2 = get_intensity(refl2);
+ i1bij = get_intensity(refl1bij);
+ i2bij = get_intensity(refl2bij);
+ fctx->vec1[bin][fctx->n[bin]] = i1 - i1bij;
+ fctx->vec2[bin][fctx->n[bin]] = i2 - i2bij;
+ fctx->n[bin]++;
+ break;
+
+ case FOM_RANORSPLIT :
+ i1 = get_intensity(refl1);
+ i2 = get_intensity(refl2);
+ fctx->num2[bin] += fabs(i1 - i2);
+ fctx->den2[bin] += i1 + i2;
+ /* Intentional fall-through (no break) */
+
+ case FOM_RANO :
+ i1 = get_intensity(refl1);
+ i2 = get_intensity(refl2);
+ i1bij = get_intensity(refl1bij);
+ i2bij = get_intensity(refl2bij);
+ im = (i1 + i2)/2.0;
+ imbij = (i1bij + i2bij)/2.0;
+ fctx->num[bin] += fabs(im - imbij);
+ fctx->den[bin] += im + imbij;
+ break;
+
+ case FOM_D1SIG :
+ i1 = get_intensity(refl1);
+ i2 = get_intensity(refl2);
+ sig1 = get_esd_intensity(refl1);
+ sig2 = get_esd_intensity(refl2);
+ if ( fabs(i1-i2) < sqrt(sig1*sig1 + sig2*sig2) ) {
+ fctx->n_within[bin]++;
+ }
+ break;
+
+ case FOM_D2SIG :
+ i1 = get_intensity(refl1);
+ i2 = get_intensity(refl2);
+ sig1 = get_esd_intensity(refl1);
+ sig2 = get_esd_intensity(refl2);
+ if ( fabs(i1-i2) < 2.0*sqrt(sig1*sig1 + sig2*sig2) ) {
+ fctx->n_within[bin]++;
+ }
+ break;
+
+ case FOM_NUM_MEASUREMENTS :
+ fctx->n_meas[bin] += get_redundancy(refl1);
+ break;
+
+ case FOM_REDUNDANCY :
+ fctx->num[bin] += get_redundancy(refl1);
+ fctx->den[bin] += 1.0;
+ break;
+
+ case FOM_SNR :
+ i1 = get_intensity(refl1);
+ sig1 = get_esd_intensity(refl1);
+ if ( isfinite(i1/sig1) ) {
+ fctx->num[bin] += i1/sig1;
+ fctx->den[bin] += 1.0;
+ } else {
+ bad = 1;
+ }
+ break;
+
+ case FOM_MEAN_INTENSITY :
+ i1 = get_intensity(refl1);
+ fctx->num[bin] += i1;
+ fctx->den[bin] += 1.0;
+ break;
+
+ case FOM_COMPLETENESS :
+ /* fctx->cts already incremented, as needed.
+ * Will calculate possible reflections later */
+ break;
+
+ }
+
+ return bad;
+}
+
+
+/**
+ * Calculates the overall value for the %fom_context
+ *
+ * You must have previously called fom_calculate()
+ */
+double fom_overall_value(struct fom_context *fctx)
+{
+ double overall_num = INFINITY;
+ double overall_den = 0.0;
+ double overall_num2 = INFINITY;
+ double overall_den2 = 0.0;
+ int i;
+ double *overall_vec1;
+ double *overall_vec2;
+ int overall_n;
+ double *overall_along_diagonal;
+ double *overall_perpend_diagonal;
+ double variance_signal;
+ double variance_error;
+ double cc = INFINITY;
+ long int total_meas = 0;
+ long int overall_cts = 0;
+ long int overall_possible = 0;
+
+ switch ( fctx->fom ) {
+
+ case FOM_R1I :
+ case FOM_R1F :
+ case FOM_R2 :
+ case FOM_RSPLIT :
+ case FOM_RANO :
+ case FOM_REDUNDANCY :
+ case FOM_SNR :
+ case FOM_MEAN_INTENSITY :
+ overall_num = 0.0;
+ overall_den = 0.0;
+ for ( i=0; i<fctx->nshells; i++ ) {
+ overall_num += fctx->num[i];
+ overall_den += fctx->den[i];
+ }
+ break;
+
+ case FOM_RANORSPLIT :
+ overall_num = 0.0;
+ overall_den = 0.0;
+ for ( i=0; i<fctx->nshells; i++ ) {
+ overall_num += fctx->num[i];
+ overall_den += fctx->den[i];
+ }
+ overall_num2 = 0.0;
+ overall_den2 = 0.0;
+ for ( i=0; i<fctx->nshells; i++ ) {
+ overall_num2 += fctx->num2[i];
+ overall_den2 += fctx->den2[i];
+ }
+ break;
+
+ case FOM_CC :
+ case FOM_CCSTAR :
+ case FOM_CCANO :
+ overall_vec1 = malloc(fctx->nmax*sizeof(double));
+ overall_vec2 = malloc(fctx->nmax*sizeof(double));
+ overall_n = 0;
+ for ( i=0; i<fctx->nshells; i++ ) {
+ int j;
+ for ( j=0; j<fctx->n[i]; j++ ) {
+ overall_vec1[overall_n] = fctx->vec1[i][j];
+ overall_vec2[overall_n] = fctx->vec2[i][j];
+ overall_n++;
+ }
+ }
+ cc = gsl_stats_correlation(overall_vec1, 1, overall_vec2, 1,
+ overall_n);
+ free(overall_vec1);
+ free(overall_vec2);
+ break;
+
+ case FOM_CRDANO :
+ overall_along_diagonal = malloc(fctx->nmax*sizeof(double));
+ overall_perpend_diagonal = malloc(fctx->nmax*sizeof(double));
+ overall_n = 0;
+ for ( i=0; i<fctx->nshells; i++ ) {
+ int j;
+ for ( j=0; j<fctx->n[i]; j++ ) {
+ overall_along_diagonal[overall_n] =
+ ( fctx->vec1[i][j] + fctx->vec2[i][j] )
+ / sqrt(2.0);
+ overall_perpend_diagonal[overall_n] =
+ ( fctx->vec1[i][j] - fctx->vec2[i][j] )
+ / sqrt(2.0);
+ overall_n++;
+ }
+ }
+ variance_signal = gsl_stats_variance_m(overall_along_diagonal,
+ 1, overall_n, 0.0);
+ variance_error = gsl_stats_variance_m(overall_perpend_diagonal,
+ 1, overall_n, 0.0);
+ cc = sqrt(variance_signal / variance_error );
+
+ free(overall_along_diagonal);
+ free(overall_perpend_diagonal);
+ break;
+
+ case FOM_D1SIG :
+ case FOM_D2SIG :
+ overall_num = 0.0;
+ overall_den = 0.0;
+ for ( i=0; i<fctx->nshells; i++ ) {
+ overall_num += fctx->n_within[i];
+ overall_den += fctx->cts[i];
+ }
+ break;
+
+ case FOM_NUM_MEASUREMENTS :
+ total_meas = 0;
+ for ( i=0; i<fctx->nshells; i++ ) {
+ total_meas += fctx->n_meas[i];
+ }
+ break;
+
+ case FOM_COMPLETENESS :
+ for ( i=0; i<fctx->nshells; i++ ) {
+ overall_cts += fctx->cts[i];
+ overall_possible += fctx->possible[i];
+ }
+ break;
+
+ }
+
+ switch ( fctx->fom ) {
+
+ case FOM_R1I :
+ case FOM_R1F :
+ case FOM_REDUNDANCY :
+ case FOM_SNR :
+ case FOM_MEAN_INTENSITY :
+ return overall_num/overall_den;
+
+ case FOM_COMPLETENESS :
+ return (double)overall_cts / overall_possible;
+
+ case FOM_NUM_MEASUREMENTS :
+ return total_meas;
+
+ case FOM_R2 :
+ return sqrt(overall_num/overall_den);
+
+ case FOM_RSPLIT :
+ return 2.0*(overall_num/overall_den) / sqrt(2.0);
+
+ case FOM_CC :
+ case FOM_CCANO :
+ case FOM_CRDANO :
+ return cc;
+
+ case FOM_CCSTAR :
+ return sqrt((2.0*cc)/(1.0+cc));
+
+ case FOM_RANO :
+ return 2.0*(overall_num/overall_den);
+
+ case FOM_RANORSPLIT :
+ return (2.0*(overall_num/overall_den)) /
+ (2.0*(overall_num2/overall_den2) / sqrt(2.0));
+
+ case FOM_D1SIG :
+ case FOM_D2SIG :
+ return overall_num/overall_den;
+
+ }
+
+ ERROR("This point is never reached.\n");
+ abort();
+}
+
+
+/**
+ * Calculates the figure of merit for the specified shell number.
+ * You must have previously called fom_calculate()
+ */
+double fom_shell_value(struct fom_context *fctx, int i)
+{
+ double cc;
+ int j;
+ double variance_signal;
+ double variance_error;
+ double *along_diagonal;
+ double *perpend_diagonal;
+
+ switch ( fctx->fom ) {
+
+ case FOM_R1I :
+ case FOM_R1F :
+ case FOM_REDUNDANCY :
+ case FOM_SNR :
+ case FOM_MEAN_INTENSITY :
+ return fctx->num[i]/fctx->den[i];
+
+ case FOM_R2 :
+ return sqrt(fctx->num[i]/fctx->den[i]);
+
+ case FOM_RSPLIT :
+ return 2.0*(fctx->num[i]/fctx->den[i]) / sqrt(2.0);
+
+ case FOM_CC :
+ case FOM_CCANO :
+ return gsl_stats_correlation(fctx->vec1[i], 1, fctx->vec2[i], 1,
+ fctx->n[i]);
+
+ case FOM_CCSTAR :
+ cc = gsl_stats_correlation(fctx->vec1[i], 1, fctx->vec2[i], 1,
+ fctx->n[i]);
+ return sqrt((2.0*cc)/(1.0+cc));
+
+ case FOM_RANO :
+ return 2.0 * fctx->num[i]/fctx->den[i];
+
+ case FOM_RANORSPLIT :
+ return (2.0*fctx->num[i]/fctx->den[i]) /
+ (2.0*(fctx->num2[i]/fctx->den2[i]) / sqrt(2.0));
+
+ case FOM_CRDANO :
+ along_diagonal = malloc(fctx->n[i] * sizeof(double));
+ perpend_diagonal = malloc(fctx->n[i] * sizeof(double));
+ for ( j=0; j<fctx->n[i]; j++ ) {
+ along_diagonal[j] = ( fctx->vec1[i][j] +
+ fctx->vec2[i][j] ) / sqrt(2.0);
+ perpend_diagonal[j] = ( fctx->vec1[i][j] -
+ fctx->vec2[i][j] ) / sqrt(2.0);
+ }
+ variance_signal = gsl_stats_variance_m(along_diagonal, 1,
+ fctx->n[i], 0.0);
+ variance_error = gsl_stats_variance_m(perpend_diagonal, 1,
+ fctx->n[i], 0.0);
+ free(along_diagonal);
+ free(perpend_diagonal);
+ return sqrt(variance_signal / variance_error);
+
+ case FOM_D1SIG :
+ case FOM_D2SIG :
+ return (double)fctx->n_within[i] / fctx->cts[i];
+
+ case FOM_NUM_MEASUREMENTS :
+ return fctx->n_meas[i];
+
+ case FOM_COMPLETENESS :
+ return (double)fctx->cts[i] / fctx->possible[i];
+
+ }
+
+ ERROR("This point is never reached.\n");
+ abort();
+}
+
+
+/**
+ * \param rmin: The minimum value of 1/d, in m^-1
+ * \param rmax: The maximum value of 1/d, in m^-1
+ * \param nshells: The number of shells to use
+ *
+ * Create a %fom_shells structure for the specified minimum and maximum
+ * resolution limits
+ *
+ * Returns the %fom_shells structure, or NULL on error.
+ */
+struct fom_shells *fom_make_resolution_shells(double rmin, double rmax,
+ int nshells)
+{
+ struct fom_shells *s;
+ double total_vol, vol_per_shell;
+ int i;
+
+ s = malloc(sizeof(struct fom_shells));
+ if ( s == NULL ) return NULL;
+
+ s->rmins = malloc(nshells*sizeof(double));
+ s->rmaxs = malloc(nshells*sizeof(double));
+
+ if ( (s->rmins==NULL) || (s->rmaxs==NULL) ) {
+ ERROR("Couldn't allocate memory for resolution shells.\n");
+ free(s);
+ return NULL;
+ }
+
+ s->nshells = nshells;
+
+ total_vol = pow(rmax, 3.0) - pow(rmin, 3.0);
+ vol_per_shell = total_vol / nshells;
+ s->rmins[0] = rmin;
+ for ( i=1; i<nshells; i++ ) {
+
+ double r;
+
+ r = vol_per_shell + pow(s->rmins[i-1], 3.0);
+ r = pow(r, 1.0/3.0);
+
+ /* Shells of constant volume */
+ s->rmaxs[i-1] = r;
+ s->rmins[i] = r;
+
+ }
+ s->rmaxs[nshells-1] = rmax;
+
+ return s;
+}
+
+
+/**
+ * \param s: A %fom_shells structure
+ * \param i: The shell number
+ *
+ * Returns the value of 1/d at the middle of the shell,
+ * i.e. the mean of the minimum and maximum 1/d values for the shell
+ */
+double fom_shell_centre(struct fom_shells *s, int i)
+{
+ return s->rmins[i] + (s->rmaxs[i] - s->rmins[i])/2.0;
+}
+
+
+static int get_bin(struct fom_shells *s, Reflection *refl, UnitCell *cell)
+{
+ double d;
+ int bin, j;
+ signed int h, k, l;
+
+ get_indices(refl, &h, &k, &l);
+ d = 2.0 * resolution(cell, h, k, l);
+
+ bin = -1;
+ for ( j=0; j<s->nshells; j++ ) {
+ if ( (d>s->rmins[j]) && (d<=s->rmaxs[j]) ) {
+ bin = j;
+ break;
+ }
+ }
+
+ /* Allow for slight rounding errors */
+ if ( (bin == -1) && (d <= s->rmins[0]) ) bin = 0;
+ if ( (bin == -1) && (d >= s->rmaxs[s->nshells-1]) ) bin = 0;
+ assert(bin != -1);
+
+ return bin;
+}
+
+
+static int wilson_scale(RefList *list1, RefList *list2, UnitCell *cell)
+{
+ Reflection *refl1;
+ Reflection *refl2;
+ RefListIterator *iter;
+ int max_n = 256;
+ int n = 0;
+ double *x;
+ double *y;
+ int r;
+ double G, B;
+ double c0, c1, cov00, cov01, cov11, chisq;
+
+ x = malloc(max_n*sizeof(double));
+ y = malloc(max_n*sizeof(double));
+ if ( (x==NULL) || (y==NULL) ) {
+ ERROR("Failed to allocate memory for scaling.\n");
+ return 1;
+ }
+
+ for ( refl1 = first_refl(list1, &iter);
+ refl1 != NULL;
+ refl1 = next_refl(refl1, iter) )
+ {
+ signed int h, k, l;
+ double Ih1, Ih2;
+ double res;
+
+ get_indices(refl1, &h, &k, &l);
+ res = resolution(cell, h, k, l);
+
+ refl2 = find_refl(list2, h, k, l);
+ assert(refl2 != NULL);
+
+ Ih1 = get_intensity(refl1);
+ Ih2 = get_intensity(refl2);
+
+ if ( (Ih1 <= 0.0) || (Ih2 <= 0.0) ) continue;
+ if ( isnan(Ih1) || isinf(Ih1) ) continue;
+ if ( isnan(Ih2) || isinf(Ih2) ) continue;
+
+ if ( n == max_n ) {
+ max_n *= 2;
+ x = realloc(x, max_n*sizeof(double));
+ y = realloc(y, max_n*sizeof(double));
+ if ( (x==NULL) || (y==NULL) ) {
+ ERROR("Failed to allocate memory for scaling.\n");
+ return 1;
+ }
+ }
+
+ x[n] = res*res;
+ y[n] = log(Ih1/Ih2);
+ n++;
+
+ }
+
+ if ( n < 2 ) {
+ ERROR("Not enough reflections for scaling\n");
+ return 1;
+ }
+
+ r = gsl_fit_linear(x, 1, y, 1, n, &c0, &c1,
+ &cov00, &cov01, &cov11, &chisq);
+
+ if ( r ) {
+ ERROR("Scaling failed.\n");
+ return 1;
+ }
+
+ G = exp(c0);
+ B = c1/2.0;
+
+ STATUS("Relative scale factor = %f, relative B factor = %f A^2\n",
+ G, B*1e20);
+ STATUS("A scale factor greater than 1 means that the second reflection "
+ "list is weaker than the first.\n");
+ STATUS("A positive relative B factor means that the second reflection "
+ "list falls off with resolution more quickly than the first.\n");
+
+ free(x);
+ free(y);
+
+ /* Apply the scaling factor */
+ for ( refl2 = first_refl(list2, &iter);
+ refl2 != NULL;
+ refl2 = next_refl(refl2, iter) )
+ {
+ signed int h, k, l;
+ double res;
+ double corr;
+
+ get_indices(refl2, &h, &k, &l);
+ res = resolution(cell, h, k, l);
+
+ corr = G * exp(2.0*B*res*res);
+ set_intensity(refl2, get_intensity(refl2)*corr);
+ set_esd_intensity(refl2, get_esd_intensity(refl2)*corr);
+
+ }
+ return 0;
+}
+
+
+static int calculate_possible(struct fom_context *fctx,
+ struct fom_shells *shells,
+ UnitCell *cell,
+ const SymOpList *sym)
+{
+ RefList *counted;
+ int hmax, kmax, lmax;
+ double ax, ay, az;
+ double bx, by, bz;
+ double cx, cy, cz;
+ signed int h, k, l;
+
+ fctx->possible = calloc(fctx->nshells, sizeof(long int));
+ if ( fctx->possible == NULL ) return 1;
+
+ counted = reflist_new();
+ if ( counted == NULL ) {
+ free(fctx->possible);
+ return 1;
+ }
+
+ cell_get_cartesian(cell, &ax, &ay, &az,
+ &bx, &by, &bz,
+ &cx, &cy, &cz);
+ hmax = shells->rmaxs[fctx->nshells-1] * modulus(ax, ay, az);
+ kmax = shells->rmaxs[fctx->nshells-1] * modulus(bx, by, bz);
+ lmax = shells->rmaxs[fctx->nshells-1] * modulus(cx, cy, cz);
+ for ( h=-hmax; h<=hmax; h++ ) {
+ for ( k=-kmax; k<=kmax; k++ ) {
+ for ( l=-lmax; l<=lmax; l++ ) {
+
+ double d;
+ signed int hs, ks, ls;
+ int bin;
+ int i;
+
+ get_asymm(sym, h, k, l, &hs, &ks, &ls);
+ d = 2.0 * resolution(cell, hs, ks, ls);
+
+ if ( forbidden_reflection(cell, h, k, l) ) continue;
+
+ bin = -1;
+ for ( i=0; i<fctx->nshells; i++ ) {
+ if ( (d>shells->rmins[i]) && (d<=shells->rmaxs[i]) ) {
+ bin = i;
+ break;
+ }
+ }
+ if ( bin == -1 ) continue;
+
+ if ( find_refl(counted, hs, ks, ls) != NULL ) continue;
+ add_refl(counted, hs, ks, ls);
+
+ fctx->possible[bin]++;
+
+ }
+ }
+ }
+ reflist_free(counted);
+
+ return 0;
+}
+
+
+int fom_is_anomalous(enum fom_type fom)
+{
+ switch ( fom ) {
+
+ case FOM_CCANO:
+ case FOM_RANO:
+ case FOM_CRDANO:
+ case FOM_RANORSPLIT:
+ return 1;
+
+ case FOM_R1I:
+ case FOM_R1F:
+ case FOM_R2:
+ case FOM_RSPLIT:
+ case FOM_CC:
+ case FOM_CCSTAR:
+ case FOM_D1SIG:
+ case FOM_D2SIG:
+ case FOM_NUM_MEASUREMENTS:
+ case FOM_REDUNDANCY:
+ case FOM_SNR:
+ case FOM_MEAN_INTENSITY:
+ case FOM_COMPLETENESS:
+ return 0;
+ }
+
+ ERROR("This point never reached\n");
+ abort();
+}
+
+
+int fom_is_comparison(enum fom_type fom)
+{
+ switch ( fom ) {
+
+ case FOM_CCANO:
+ case FOM_RANO:
+ case FOM_CRDANO:
+ case FOM_RANORSPLIT:
+ case FOM_R1I:
+ case FOM_R1F:
+ case FOM_R2:
+ case FOM_RSPLIT:
+ case FOM_CC:
+ case FOM_CCSTAR:
+ case FOM_D1SIG:
+ case FOM_D2SIG:
+ return 1;
+
+ case FOM_NUM_MEASUREMENTS:
+ case FOM_REDUNDANCY:
+ case FOM_SNR:
+ case FOM_MEAN_INTENSITY:
+ case FOM_COMPLETENESS:
+ return 0;
+ }
+
+ ERROR("This point never reached\n");
+ abort();
+}
+
+
+static int is_single_list(enum fom_type fom)
+{
+ switch ( fom ) {
+
+ case FOM_CCANO:
+ case FOM_RANO:
+ case FOM_CRDANO:
+ case FOM_RANORSPLIT:
+ case FOM_R1I:
+ case FOM_R1F:
+ case FOM_R2:
+ case FOM_RSPLIT:
+ case FOM_CC:
+ case FOM_CCSTAR:
+ case FOM_D1SIG:
+ case FOM_D2SIG:
+ return 0;
+
+ case FOM_NUM_MEASUREMENTS:
+ case FOM_REDUNDANCY:
+ case FOM_SNR:
+ case FOM_MEAN_INTENSITY:
+ case FOM_COMPLETENESS:
+ return 1;
+ }
+
+ ERROR("This point never reached\n");
+ abort();
+}
+
+
+/**
+ * \param list1: A %RefList
+ * \param list2: A %RefList
+ * \param cell: A %UnitCell
+ * \param shells: A %fom_shells structure
+ * \param fom: The figure of merit to calculate
+ * \param noscale: Non-zero to disable scaline of reflection lists
+ * \param sym: The symmetry of \p list1 and \p list2.
+ *
+ * Calculates the specified figure of merit, comparing the two reflection lists.
+ *
+ * The \p cell and \p sym must match both reflection lists. You should also have
+ * called fom_select_reflection_pairs() to pre-process the lists.
+ *
+ * If the figure of merit does not involve comparison (e.g. %FOM_SNR),
+ * then \p list1 will be used. In this case, \p list2 and \p noscale will be
+ * ignored. Use fom_select_reflections() instead of fom_select_reflection_pairs()
+ * in this case.
+ *
+ * \returns a %fom_context structure. Use fom_shell_value() et al., to
+ * extract the actual figure of merit values.
+ */
+struct fom_context *fom_calculate(RefList *list1, RefList *list2, UnitCell *cell,
+ struct fom_shells *shells, enum fom_type fom,
+ int noscale, const SymOpList *sym)
+{
+ Reflection *refl1;
+ RefListIterator *iter;
+ struct fom_context *fctx;
+ long int n_out = 0;
+ long int n_rej = 0;
+
+ fctx = init_fom(fom, num_reflections(list1), shells->nshells);
+
+ if ( fctx == NULL ) {
+ ERROR("Couldn't allocate memory for resolution shells.\n");
+ return NULL;
+ }
+
+ if ( !is_single_list(fom) ) {
+ if ( !noscale && wilson_scale(list1, list2, cell) ) {
+ ERROR("Error with scaling.\n");
+ return NULL;
+ }
+
+ for ( refl1 = first_refl(list1, &iter);
+ refl1 != NULL;
+ refl1 = next_refl(refl1, iter) )
+ {
+ Reflection *refl2;
+ signed int h, k, l;
+ set_flag(refl1, 0);
+ get_indices(refl1, &h, &k, &l);
+ refl2 = find_refl(list2, h, k, l);
+ assert(refl2 != NULL);
+ set_flag(refl2, 0);
+ }
+ }
+
+ for ( refl1 = first_refl(list1, &iter);
+ refl1 != NULL;
+ refl1 = next_refl(refl1, iter) )
+ {
+ signed int h, k, l;
+ int bin;
+ Reflection *refl2;
+ Reflection *refl1_bij = NULL;
+ Reflection *refl2_bij = NULL;
+
+ get_indices(refl1, &h, &k, &l);
+
+ if ( is_single_list(fom) ) {
+ refl2 = NULL;
+ } else {
+ refl2 = find_refl(list2, h, k, l);
+ if ( refl2 == NULL ) continue;
+ }
+
+ bin = get_bin(shells, refl1, cell);
+ if ( bin == -1 ) {
+ n_out++;
+ continue;
+ }
+
+ if ( fom_is_anomalous(fom) ) {
+
+ signed int hb, kb, lb;
+
+ if ( find_equiv_in_list(list1, -h, -k, -l, sym,
+ &hb, &kb, &lb) )
+ {
+ refl1_bij = find_refl(list1, hb, kb, lb);
+ }
+
+ if ( find_equiv_in_list(list2, -h, -k, -l, sym,
+ &hb, &kb, &lb) )
+ {
+ refl2_bij = find_refl(list2, hb, kb, lb);
+ }
+
+ /* Each reflection must only be counted once, whether
+ * we are visiting it now as "normal" or "bij" */
+ if ( get_flag(refl1) ) continue;
+ assert(!get_flag(refl2));
+ set_flag(refl1, 1);
+ set_flag(refl1_bij, 1);
+ set_flag(refl2, 1);
+ set_flag(refl2_bij, 1);
+
+ assert(refl1_bij != NULL);
+ assert(refl2_bij != NULL);
+
+ }
+
+ n_rej += add_to_fom(fctx, refl1, refl2, refl1_bij, refl2_bij, bin);
+
+ }
+ if ( n_out ) {
+ ERROR("WARNING: %i reflection pairs outside range.\n", n_out);
+ }
+ if ( n_rej ) {
+ if ( fom == FOM_SNR ) {
+ ERROR("WARNING: %li reflections had infinite or "
+ "invalid values of I/sigma(I).\n", n_rej);
+ } else {
+ ERROR("WARNING: %li reflections rejected by add_to_fom\n",
+ n_rej);
+ }
+ }
+
+ if ( fom == FOM_COMPLETENESS ) {
+ calculate_possible(fctx, shells, cell, sym);
+ }
+
+ return fctx;
+}
+
+
+/**
+ * \param list1: The first input %RefList
+ * \param list2: The second input %RefList
+ * \param plist1_acc: Pointer to location for accepted list
+ * \param plist2_acc: Pointer to location for accepted list
+ * \param cell: A %UnitCell
+ * \param sym: The symmetry of \p raw_list
+ * \param anom: Non-zero if you will calculate a FoM for anomalous signal
+ * \param rmin_fix: If positive, minimum resolution to use
+ * \param rmax_fix: If positive, maximum resolution to use
+ * \param sigma_cutoff: Minimum I/sigI value
+ * \param ignore_negs: Non-zero to filter out negative intensities
+ * \param zero_negs: Non-zero to set negative intensities to zero
+ * \param mul_cutoff: Minimum number of measurements per reflection
+ *
+ * Selects reflections suitable for use with fom_calculate().
+ *
+ * Use -INFINITY for \p sigma_cutoff to disable the check.
+ * Set \p mul_cutoff to zero to disable the check.
+ *
+ * \returns a %fom_rejections structure with the counts of reflections.
+ */
+struct fom_rejections fom_select_reflection_pairs(RefList *list1, RefList *list2,
+ RefList **plist1_acc,
+ RefList **plist2_acc,
+ UnitCell *cell, SymOpList *sym,
+ int anom, double rmin_fix, double rmax_fix,
+ double sigma_cutoff, int ignore_negs,
+ int zero_negs, int mul_cutoff)
+{
+ Reflection *refl1;
+ RefListIterator *iter;
+ struct fom_rejections rej;
+ RefList *list1_acc;
+ RefList *list2_acc;
+
+ rej.common = 0;
+ rej.low_snr = 0;
+ rej.negative_deleted = 0;
+ rej.negative_zeroed = 0;
+ rej.few_measurements = 0;
+ rej.outside_resolution_range = 0;
+ rej.no_bijvoet = 0;
+ rej.centric = 0;
+ rej.nan_inf_value = 0;
+
+ list1_acc = reflist_new();
+ list2_acc = reflist_new();
+
+ for ( refl1 = first_refl(list1, &iter);
+ refl1 != NULL;
+ refl1 = next_refl(refl1, iter) )
+ {
+ signed int h, k, l;
+ double val1, val2;
+ double esd1, esd2;
+ int mul1, mul2;
+ Reflection *refl2;
+ Reflection *refl1_acc;
+ Reflection *refl2_acc;
+
+ get_indices(refl1, &h, &k, &l);
+
+ refl2 = find_refl(list2, h, k, l);
+ if ( refl2 == NULL ) continue;
+
+ val1 = get_intensity(refl1);
+ val2 = get_intensity(refl2);
+
+ esd1 = get_esd_intensity(refl1);
+ esd2 = get_esd_intensity(refl2);
+
+ mul1 = get_redundancy(refl1);
+ mul2 = get_redundancy(refl2);
+
+ if ( !isfinite(val1) || !isfinite(val2)
+ || !isfinite(esd1) || !isfinite(esd2) )
+ {
+ rej.nan_inf_value++;
+ continue;
+ }
+
+ if ( (val1 < sigma_cutoff * esd1)
+ || (val2 < sigma_cutoff * esd2) )
+ {
+ rej.low_snr++;
+ continue;
+ }
+
+ if ( ignore_negs && ((val1 < 0.0) || (val2 < 0.0)) ) {
+ rej.negative_deleted++;
+ continue;
+ }
+
+ if ( (mul1 < mul_cutoff) || (mul2 < mul_cutoff) ) {
+ rej.few_measurements++;
+ continue;
+ }
+
+ if ( zero_negs ) {
+ int d = 0;
+ if ( val1 < 0.0 ) {
+ val1 = 0.0;
+ d = 1;
+ }
+ if ( val2 < 0.0 ) {
+ val2 = 0.0;
+ d = 1;
+ }
+ if ( d ) rej.negative_zeroed++;
+ continue;
+ }
+
+ if ( rmin_fix > 0.0 ) {
+ double res = 2.0*resolution(cell, h, k, l);
+ if ( res < rmin_fix ) {
+ rej.outside_resolution_range++;
+ continue;
+ }
+ }
+
+ if ( rmax_fix > 0.0 ) {
+ double res = 2.0*resolution(cell, h, k, l);
+ if ( res > rmax_fix ) {
+ rej.outside_resolution_range++;
+ continue;
+ }
+ }
+
+ refl1_acc = add_refl(list1_acc, h, k, l);
+ copy_data(refl1_acc, refl1);
+ set_intensity(refl1_acc, val1);
+
+ refl2_acc = add_refl(list2_acc, h, k, l);
+ copy_data(refl2_acc, refl2);
+ set_intensity(refl2_acc, val2);
+
+ rej.common++;
+
+ }
+
+ /* For anomalous figures of merit, we additionally require that we have
+ * all the Bijvoet pairs after the above rejection tests */
+ if ( anom ) {
+
+ list1 = list1_acc;
+ list2 = list2_acc;
+ list1_acc = reflist_new();
+ list2_acc = reflist_new();
+
+ rej.common = 0;
+
+ for ( refl1 = first_refl(list1, &iter);
+ refl1 != NULL;
+ refl1 = next_refl(refl1, iter) )
+ {
+ Reflection *refl1_bij = NULL;
+ Reflection *refl2_bij = NULL;
+ signed int h, k, l;
+ signed int hb, kb, lb;
+ Reflection *refl1_acc;
+ Reflection *refl2_acc;
+ Reflection *refl2;
+ double val1, val2;
+
+ get_indices(refl1, &h, &k, &l);
+
+ refl2 = find_refl(list2, h, k, l);
+ assert(refl2 != NULL);
+
+ val1 = get_intensity(refl1);
+ val2 = get_intensity(refl2);
+
+ if ( is_centric(h, k, l, sym) ) {
+ rej.centric++;
+ continue;
+ }
+
+ if ( find_equiv_in_list(list1, -h, -k, -l, sym,
+ &hb, &kb, &lb) )
+ {
+ refl1_bij = find_refl(list1, hb, kb, lb);
+ }
+
+ if ( find_equiv_in_list(list2, -h, -k, -l, sym,
+ &hb, &kb, &lb) )
+ {
+ refl2_bij = find_refl(list2, hb, kb, lb);
+ }
+
+ if ( (refl1_bij == NULL) || (refl2_bij == NULL) ) {
+ rej.no_bijvoet++;
+ continue;
+ }
+
+ refl1_acc = add_refl(list1_acc, h, k, l);
+ copy_data(refl1_acc, refl1);
+ set_intensity(refl1_acc, val1);
+
+ refl2_acc = add_refl(list2_acc, h, k, l);
+ copy_data(refl2_acc, refl2);
+ set_intensity(refl2_acc, val2);
+
+ rej.common++;
+ }
+ }
+
+ *plist1_acc = list1_acc;
+ *plist2_acc = list2_acc;
+ return rej;
+}
+
+
+/**
+ * \param raw_list: The input %RefList
+ * \param plist_acc: Pointer to location for accepted list
+ * \param cell: A %UnitCell
+ * \param sym: The symmetry of \p raw_list
+ * \param rmin_fix: If positive, minimum resolution to use
+ * \param rmax_fix: If positive, maximum resolution to use
+ * \param sigma_cutoff: Minimum I/sigI value
+ * \param ignore_negs: Non-zero to filter out negative intensities
+ * \param zero_negs: Non-zero to set negative intensities to zero
+ * \param mul_cutoff: Minimum number of measurements per reflection
+ *
+ * Use -INFINITY for \p sigma_cutoff to disable the check.
+ * Set \p mul_cutoff to zero to disable the check.
+ *
+ * \returns a %fom_rejections structure with the counts of reflections.
+ */
+struct fom_rejections fom_select_reflections(RefList *raw_list,
+ RefList **plist_acc,
+ UnitCell *cell, SymOpList *sym,
+ double rmin_fix, double rmax_fix,
+ double sigma_cutoff, int ignore_negs,
+ int zero_negs, int mul_cutoff)
+{
+ RefList *list;
+ Reflection *refl;
+ RefListIterator *iter;
+ struct fom_rejections rej;
+
+ *plist_acc = NULL;
+
+ rej.common = 0;
+ rej.low_snr = 0;
+ rej.negative_deleted = 0;
+ rej.negative_zeroed = 0;
+ rej.few_measurements = 0;
+ rej.outside_resolution_range = 0;
+ rej.no_bijvoet = 0;
+ rej.centric = 0;
+ rej.nan_inf_value = 0;
+
+ list = reflist_new();
+ if ( list == NULL ) return rej;
+
+ for ( refl = first_refl(raw_list, &iter);
+ refl != NULL;
+ refl = next_refl(refl, iter) ) {
+
+ signed int h, k, l;
+ double val, sig;
+ int ig = 0;
+ Reflection *new;
+
+ get_indices(refl, &h, &k, &l);
+
+ val = get_intensity(refl);
+ sig = get_esd_intensity(refl);
+
+ if ( !isfinite(val) || !isfinite(sig) ) {
+ rej.nan_inf_value++;
+ continue;
+ }
+
+ if ( val < sigma_cutoff * sig ) {
+ rej.low_snr++;
+ ig = 1;
+ }
+
+ if ( ignore_negs && (val < 0.0) ) {
+ rej.negative_deleted++;
+ ig = 1;
+ }
+
+ if ( zero_negs && (val < 0.0) ) {
+ set_intensity(refl, 0.0);
+ rej.negative_zeroed++;
+ }
+
+ if ( rmin_fix > 0.0 ) {
+ double res = 2.0*resolution(cell, h, k, l);
+ if ( res < rmin_fix ) {
+ rej.outside_resolution_range++;
+ continue;
+ }
+ }
+
+ if ( rmax_fix > 0.0 ) {
+ double res = 2.0*resolution(cell, h, k, l);
+ if ( res > rmax_fix ) {
+ rej.outside_resolution_range++;
+ continue;
+ }
+ }
+
+ if ( ig ) continue;
+
+ new = add_refl(list, h, k, l);
+ copy_data(new, refl);
+ }
+
+ *plist_acc = list;
+ return rej;
+}
+
+
+/**
+ * \param fctx: A %fom_context structure
+ *
+ * \returns the total number of unique reflections
+ */
+int fom_overall_num_reflections(struct fom_context *fctx)
+{
+ int i;
+ long int n = 0;
+
+ for ( i=0; i<fctx->nshells; i++ ) {
+ n += fctx->cts[i];
+ }
+ return n;
+}
+
+
+/**
+ * \param fctx: A %fom_context structure
+ * \param i: Shell number
+ *
+ * \returns the number of unique reflections in the shell
+ */
+int fom_shell_num_reflections(struct fom_context *fctx, int i)
+{
+ return fctx->cts[i];
+}
+
+
+/**
+ * \param fctx: A %fom_context structure
+ *
+ * This must only be called on a %fom_context for %FOM_COMPLETENESS.
+ *
+ * \returns the total number of reflections possible in all shells, taking into
+ * account symmetry and lattice absences, but not screw axis/glide place absences.
+ */
+int fom_overall_num_possible(struct fom_context *fctx)
+{
+ int i;
+ long int n = 0;
+
+ assert(fctx->fom == FOM_COMPLETENESS);
+
+ for ( i=0; i<fctx->nshells; i++ ) {
+ n += fctx->possible[i];
+ }
+ return n;
+}
+
+
+/**
+ * \param fctx: A %fom_context structure
+ * \param i: Shell number
+ *
+ * This must only be called on a %fom_context for %FOM_COMPLETENESS.
+ *
+ * \returns the number of reflections possible in the shell, taking into account
+ * symmetry and lattice absences, but not screw axis/glide place absences.
+ */
+int fom_shell_num_possible(struct fom_context *fctx, int i)
+{
+ assert(fctx->fom == FOM_COMPLETENESS);
+ return fctx->possible[i];
+}
+
+
+const char *fom_name(enum fom_type f)
+{
+ switch ( f ) {
+ case FOM_R1I : return "R1(I)";
+ case FOM_R1F : return "R1(F)";
+ case FOM_R2 : return "R2";
+ case FOM_RSPLIT : return "Rsplit";
+ case FOM_CC : return "CC";
+ case FOM_CCSTAR : return "CC*";
+ case FOM_CCANO : return "CCano";
+ case FOM_CRDANO : return "CRDano";
+ case FOM_RANO : return "Rano";
+ case FOM_RANORSPLIT : return "Rano/Rsplit";
+ case FOM_D1SIG : return "D<1sigma";
+ case FOM_D2SIG : return "D<2sigma";
+ case FOM_NUM_MEASUREMENTS : return "nMeas";
+ case FOM_REDUNDANCY : return "Redundancy";
+ case FOM_SNR : return "I/sigI";
+ case FOM_MEAN_INTENSITY : return "mean I";
+ case FOM_COMPLETENESS : return "Completeness";
+ default : return "unknown FoM";
+ }
+}
diff --git a/libcrystfel/src/fom.h b/libcrystfel/src/fom.h
new file mode 100644
index 00000000..08bc655b
--- /dev/null
+++ b/libcrystfel/src/fom.h
@@ -0,0 +1,141 @@
+/*
+ * fom.h
+ *
+ * Figure of merit calculation
+ *
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2010-2021 Thomas White <taw@physics.org>
+ * 2013 Lorenzo Galli <lorenzo.galli@desy.de>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef FOM_H
+#define FOM_H
+
+/**
+ * \file fom.h
+ * Figure of merit calculation
+ */
+
+#include <reflist.h>
+#include <symmetry.h>
+
+/**
+ * Contains counts of rejected reflections
+ */
+struct fom_rejections
+{
+ int common; /**< Number of common reflection pairs accepted */
+ int low_snr; /**< Reflections with I/sigI too low */
+ int negative_deleted; /**< Negative intensities which were deleted */
+ int negative_zeroed; /**< Negative intensities which were set to zero */
+ int few_measurements; /**< Reflections with too few measurements */
+ int outside_resolution_range; /**< Reflections outside resolution range */
+ int no_bijvoet; /**< Reflections with no Bijvoet partner */
+ int centric; /**< Reflections which are centric */
+ int nan_inf_value; /**< Reflections with NaN or infinite intensity */
+};
+
+/**
+ * An enumeration of possible figures of merit to calculate
+ */
+enum fom_type
+{
+ FOM_R1I,
+ FOM_R1F,
+ FOM_R2,
+ FOM_RSPLIT,
+ FOM_CC,
+ FOM_CCSTAR,
+ FOM_CCANO,
+ FOM_CRDANO,
+ FOM_RANO,
+ FOM_RANORSPLIT,
+ FOM_D1SIG,
+ FOM_D2SIG,
+ FOM_NUM_MEASUREMENTS,
+ FOM_REDUNDANCY,
+ FOM_SNR,
+ FOM_MEAN_INTENSITY,
+ FOM_COMPLETENESS,
+};
+
+struct fom_shells
+{
+ int nshells;
+ double *rmins;
+ double *rmaxs;
+};
+
+struct fom_context;
+
+extern struct fom_rejections fom_select_reflection_pairs(RefList *list1,
+ RefList *list2,
+ RefList **plist1_acc,
+ RefList **plist2_acc,
+ UnitCell *cell,
+ SymOpList *sym,
+ int anom,
+ double rmin_fix,
+ double rmax_fix,
+ double sigma_cutoff,
+ int ignore_negs,
+ int zero_negs,
+ int mul_cutoff);
+
+extern struct fom_rejections fom_select_reflections(RefList *list,
+ RefList **plist_acc,
+ UnitCell *cell,
+ SymOpList *sym,
+ double rmin_fix,
+ double rmax_fix,
+ double sigma_cutoff,
+ int ignore_negs,
+ int zero_negs,
+ int mul_cutoff);
+
+
+extern struct fom_context *fom_calculate(RefList *list1, RefList *list2,
+ UnitCell *cell,
+ struct fom_shells *shells,
+ enum fom_type fom, int noscale,
+ const SymOpList *sym);
+
+extern struct fom_shells *fom_make_resolution_shells(double rmin, double rmax,
+ int nshells);
+
+extern double fom_shell_centre(struct fom_shells *s, int i);
+
+extern double fom_overall_value(struct fom_context *fctx);
+extern double fom_shell_value(struct fom_context *fctx, int i);
+
+extern int fom_overall_num_reflections(struct fom_context *fctx);
+extern int fom_shell_num_reflections(struct fom_context *fctx, int i);
+
+extern int fom_overall_num_possible(struct fom_context *fctx);
+extern int fom_shell_num_possible(struct fom_context *fctx, int i);
+
+extern int fom_is_anomalous(enum fom_type f);
+extern int fom_is_comparison(enum fom_type f);
+
+extern const char *fom_name(enum fom_type f);
+
+#endif /* FOM */
diff --git a/libcrystfel/src/geometry.c b/libcrystfel/src/geometry.c
index 8f8a9672..adb95e69 100644
--- a/libcrystfel/src/geometry.c
+++ b/libcrystfel/src/geometry.c
@@ -3,11 +3,11 @@
*
* Geometry of diffraction
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2016 Thomas White <taw@physics.org>
+ * 2010-2021 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -52,7 +52,7 @@
/** \file geometry.h */
static int locate_peak_on_panel(double x, double y, double z, double k,
- struct panel *p,
+ struct detgeom_panel *p,
double *pfs, double *pss)
{
double ctt, tta, phi;
@@ -85,7 +85,7 @@ static int locate_peak_on_panel(double x, double y, double z, double k,
gsl_matrix_set(M, 1, 0, p->cny);
gsl_matrix_set(M, 1, 1, p->fsy);
gsl_matrix_set(M, 1, 2, p->ssy);
- gsl_matrix_set(M, 2, 0, p->clen*p->res);
+ gsl_matrix_set(M, 2, 0, p->cnz);
gsl_matrix_set(M, 2, 1, p->fsz);
gsl_matrix_set(M, 2, 2, p->ssz);
@@ -103,6 +103,10 @@ static int locate_peak_on_panel(double x, double y, double z, double k,
*pfs = fs; *pss = ss;
+ /* If "mu" is negative, then the reflection is in the
+ * wrong direction */
+ if ( one_over_mu < 0.0 ) return 0;
+
/* Now, is this on this panel? */
if ( fs < 0.0 ) return 0;
if ( fs >= p->w ) return 0;
@@ -113,7 +117,8 @@ static int locate_peak_on_panel(double x, double y, double z, double k,
}
static signed int locate_peak(double x, double y, double z, double k,
- struct detector *det, double *pfs, double *pss)
+ struct detgeom *det,
+ double *pfs, double *pss)
{
int i;
@@ -121,7 +126,7 @@ static signed int locate_peak(double x, double y, double z, double k,
for ( i=0; i<det->n_panels; i++ ) {
- struct panel *p;
+ struct detgeom_panel *p;
p = &det->panels[i];
@@ -379,29 +384,31 @@ static Reflection *check_reflection(struct image *image, Crystal *cryst,
/* If we are updating a previous reflection, assume it stays
* on the same panel and calculate the new position even if it's
* fallen off the edge of the panel. */
- if ( (image->det != NULL) && (updateme != NULL) ) {
+ if ( (image->detgeom != NULL) && (updateme != NULL) ) {
double fs, ss;
+ assert(get_panel_number(updateme) <= image->detgeom->n_panels);
locate_peak_on_panel(xl, yl, zl, mean_kpred,
- get_panel(updateme), &fs, &ss);
+ &image->detgeom->panels[get_panel_number(updateme)],
+ &fs, &ss);
set_detector_pos(refl, fs, ss);
}
- /* Otherwise, calculate position if we have a detector structure, and
+ /* otherwise, calculate position if we have a detector structure, and
* if we don't then just make do with partiality calculation */
- if ( (image->det != NULL) && (updateme == NULL) ) {
+ if ( (image->detgeom != NULL) && (updateme == NULL) ) {
- double fs, ss; /* Position on detector */
- signed int p; /* Panel number */
+ double fs, ss; /* position on detector */
+ signed int p; /* panel number */
p = locate_peak(xl, yl, zl, mean_kpred,
- image->det, &fs, &ss);
+ image->detgeom, &fs, &ss);
if ( p == -1 ) {
reflection_free(refl);
return NULL;
}
set_detector_pos(refl, fs, ss);
- set_panel(refl, &image->det->panels[p]);
+ set_panel_number(refl, p);
}
@@ -503,6 +510,7 @@ RefList *predict_to_res(Crystal *cryst, double max_res)
double mres;
signed int h, k, l;
UnitCell *cell;
+ struct image *image;
cell = crystal_get_cell(cryst);
if ( cell == NULL ) return NULL;
@@ -512,14 +520,15 @@ RefList *predict_to_res(Crystal *cryst, double max_res)
/* Cell angle check from Foadi and Evans (2011) */
if ( !cell_is_sensible(cell) ) {
ERROR("Invalid unit cell parameters given to"
- " find_intersections()\n");
+ " predict_to_res()\n");
cell_print(cell);
return NULL;
}
cell_get_cartesian(cell, &ax, &ay, &az, &bx, &by, &bz, &cx, &cy, &cz);
- mres = largest_q(crystal_get_image(cryst));
+ image = crystal_get_image(cryst);
+ mres = detgeom_max_resolution(image->detgeom, image->lambda);
if ( mres > max_res ) mres = max_res;
hmax = mres * modulus(ax, ay, az);
@@ -1076,7 +1085,8 @@ void polarisation_correction(RefList *list, UnitCell *cell,
/* Returns dx_h/dP, where P = any parameter */
-double x_gradient(int param, Reflection *refl, UnitCell *cell, struct panel *p)
+double x_gradient(int param, Reflection *refl, UnitCell *cell,
+ struct detgeom_panel *p)
{
signed int h, k, l;
double xl, zl, kpred;
@@ -1093,13 +1103,13 @@ double x_gradient(int param, Reflection *refl, UnitCell *cell, struct panel *p)
switch ( param ) {
case GPARAM_ASX :
- return h * p->clen / (kpred + zl);
+ return h * p->cnz * p->pixel_pitch / (kpred + zl);
case GPARAM_BSX :
- return k * p->clen / (kpred + zl);
+ return k * p->cnz * p->pixel_pitch / (kpred + zl);
case GPARAM_CSX :
- return l * p->clen / (kpred + zl);
+ return l * p->cnz * p->pixel_pitch / (kpred + zl);
case GPARAM_ASY :
return 0.0;
@@ -1111,13 +1121,13 @@ double x_gradient(int param, Reflection *refl, UnitCell *cell, struct panel *p)
return 0.0;
case GPARAM_ASZ :
- return -h * xl * p->clen / (kpred*kpred + 2.0*kpred*zl + zl*zl);
+ return -h * xl * p->cnz * p->pixel_pitch / (kpred*kpred + 2.0*kpred*zl + zl*zl);
case GPARAM_BSZ :
- return -k * xl * p->clen / (kpred*kpred + 2.0*kpred*zl + zl*zl);
+ return -k * xl * p->cnz * p->pixel_pitch / (kpred*kpred + 2.0*kpred*zl + zl*zl);
case GPARAM_CSZ :
- return -l * xl * p->clen / (kpred*kpred + 2.0*kpred*zl + zl*zl);
+ return -l * xl * p->cnz * p->pixel_pitch / (kpred*kpred + 2.0*kpred*zl + zl*zl);
case GPARAM_DETX :
return -1;
@@ -1136,7 +1146,8 @@ double x_gradient(int param, Reflection *refl, UnitCell *cell, struct panel *p)
/* Returns dy_h/dP, where P = any parameter */
-double y_gradient(int param, Reflection *refl, UnitCell *cell, struct panel *p)
+double y_gradient(int param, Reflection *refl, UnitCell *cell,
+ struct detgeom_panel *p)
{
signed int h, k, l;
double yl, zl, kpred;
@@ -1162,22 +1173,22 @@ double y_gradient(int param, Reflection *refl, UnitCell *cell, struct panel *p)
return 0.0;
case GPARAM_ASY :
- return h * p->clen / (kpred + zl);
+ return h * p->cnz * p->pixel_pitch / (kpred + zl);
case GPARAM_BSY :
- return k * p->clen / (kpred + zl);
+ return k * p->cnz * p->pixel_pitch / (kpred + zl);
case GPARAM_CSY :
- return l * p->clen / (kpred + zl);
+ return l * p->cnz * p->pixel_pitch / (kpred + zl);
case GPARAM_ASZ :
- return -h * yl * p->clen / (kpred*kpred + 2.0*kpred*zl + zl*zl);
+ return -h * yl * p->cnz * p->pixel_pitch / (kpred*kpred + 2.0*kpred*zl + zl*zl);
case GPARAM_BSZ :
- return -k * yl * p->clen / (kpred*kpred + 2.0*kpred*zl + zl*zl);
+ return -k * yl * p->cnz * p->pixel_pitch / (kpred*kpred + 2.0*kpred*zl + zl*zl);
case GPARAM_CSZ :
- return -l * yl * p->clen / (kpred*kpred + 2.0*kpred*zl + zl*zl);
+ return -l * yl * p->cnz * p->pixel_pitch / (kpred*kpred + 2.0*kpred*zl + zl*zl);
case GPARAM_DETX :
return 0;
diff --git a/libcrystfel/src/geometry.h b/libcrystfel/src/geometry.h
index afaa9d6c..19c6a23a 100644
--- a/libcrystfel/src/geometry.h
+++ b/libcrystfel/src/geometry.h
@@ -3,12 +3,12 @@
*
* Geometry of diffraction
*
- * Copyright © 2013-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2013-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2012 Richard Kirian
*
* Authors:
- * 2010-2016 Thomas White <taw@physics.org>
+ * 2010-2020 Thomas White <taw@physics.org>
* 2012 Richard Kirian
*
* This file is part of CrystFEL.
@@ -31,14 +31,10 @@
#ifndef GEOMETRY_H
#define GEOMETRY_H
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include "reflist.h"
#include "cell.h"
#include "crystal.h"
+#include "detgeom.h"
#ifdef __cplusplus
extern "C" {
@@ -122,9 +118,9 @@ extern double sphere_fraction(double rlow, double rhigh, double pr);
extern double gaussian_fraction(double rlow, double rhigh, double pr);
extern double x_gradient(int param, Reflection *refl, UnitCell *cell,
- struct panel *p);
+ struct detgeom_panel *p);
extern double y_gradient(int param, Reflection *refl, UnitCell *cell,
- struct panel *p);
+ struct detgeom_panel *p);
#ifdef __cplusplus
}
diff --git a/libcrystfel/src/hdf5-file.c b/libcrystfel/src/hdf5-file.c
deleted file mode 100644
index e2738a8b..00000000
--- a/libcrystfel/src/hdf5-file.c
+++ /dev/null
@@ -1,2785 +0,0 @@
-/*
- * hdf5-file.c
- *
- * Read/write HDF5 data files
- *
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
- * a research centre of the Helmholtz Association.
- *
- * Authors:
- * 2009-2016 Thomas White <taw@physics.org>
- * 2014 Valerio Mariani
- *
- * This file is part of CrystFEL.
- *
- * CrystFEL is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * CrystFEL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <hdf5.h>
-#include <assert.h>
-#include <unistd.h>
-
-#include "events.h"
-#include "image.h"
-#include "hdf5-file.h"
-#include "utils.h"
-
-/** \file hdf5-file.h */
-
-struct hdf5_write_location {
-
- const char *location;
- int n_panels;
- int *panel_idxs;
-
- int max_ss;
- int max_fs;
-
-};
-
-
-int split_group_and_object(const char *path, char **group, char **object)
-{
- const char *sep;
- const char *store;
-
- sep = path;
- store = sep;
- sep = strpbrk(sep + 1, "/");
- if ( sep != NULL ) {
- while ( 1 ) {
- store = sep;
- sep = strpbrk(sep + 1, "/");
- if ( sep == NULL ) {
- break;
- }
- }
- }
- if ( store == path ) {
- *group = NULL;
- *object = strdup(path);
- } else {
- *group = strndup(path, store - path);
- *object = strdup(store+1);
- }
- return 0;
-};
-
-
-struct hdfile {
-
- const char *path; /* Current data path */
-
- hid_t fh; /* HDF file handle */
- hid_t dh; /* Dataset handle */
-
- int data_open; /* True if dh is initialised */
-};
-
-
-struct hdfile *hdfile_open(const char *filename)
-{
- struct hdfile *f;
-
- f = malloc(sizeof(struct hdfile));
- if ( f == NULL ) return NULL;
-
- if ( access( filename, R_OK ) == -1 ) {
- ERROR("File does not exist or cannot be read: %s\n",
- filename);
- free(f);
- return NULL;
- }
-
- f->fh = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT);
- if ( f->fh < 0 ) {
- ERROR("Couldn't open file: %s\n", filename);
- free(f);
- return NULL;
- }
-
- f->data_open = 0;
- return f;
-}
-
-
-int hdfile_set_image(struct hdfile *f, const char *path)
-{
- f->dh = H5Dopen2(f->fh, path, H5P_DEFAULT);
- if ( f->dh < 0 ) {
- ERROR("Couldn't open dataset\n");
- return -1;
- }
- f->data_open = 1;
- return 0;
-}
-
-
-static int read_peak_count(struct hdfile *f, char *path, int line,
- int *num_peaks)
-{
-
- hid_t dh, sh, mh;
- hsize_t size[1];
- hsize_t max_size[1];
- hsize_t offset[1], count[1];
- hsize_t m_offset[1], m_count[1], dimmh[1];
-
-
- int tw, r;
-
- dh = H5Dopen2(f->fh, path, H5P_DEFAULT);
- if ( dh < 0 ) {
- ERROR("Data block %s not found.\n", path);
- return 1;
- }
-
- sh = H5Dget_space(dh);
- if ( sh < 0 ) {
- H5Dclose(dh);
- ERROR("Couldn't get dataspace for data.\n");
- return 1;
- }
-
- if ( H5Sget_simple_extent_ndims(sh) != 1 ) {
- ERROR("Data block %s has the wrong dimensionality (%i).\n",
- path, H5Sget_simple_extent_ndims(sh));
- H5Sclose(sh);
- H5Dclose(dh);
- return 1;
- }
-
- H5Sget_simple_extent_dims(sh, size, max_size);
-
- tw = size[0];
-
- if ( line > tw-1 ) {
- H5Sclose(sh);
- H5Dclose(dh);
- ERROR("Data block %s does not contain data for required event.\n",
- path);
- return 1;
- }
-
- offset[0] = line;
- count[0] = 1;
-
- r = H5Sselect_hyperslab(sh, H5S_SELECT_SET,
- offset, NULL, count, NULL);
- if ( r < 0 ) {
- ERROR("Error selecting file dataspace "
- "for data block %s\n", path);
- H5Dclose(dh);
- H5Sclose(sh);
- return 1;
- }
-
- m_offset[0] = 0;
- m_count[0] = 1;
- dimmh[0] = 1;
- mh = H5Screate_simple(1, dimmh, NULL);
- r = H5Sselect_hyperslab(mh, H5S_SELECT_SET,
- m_offset, NULL, m_count, NULL);
- if ( r < 0 ) {
- ERROR("Error selecting memory dataspace "
- "for data block %s\n", path);
- H5Dclose(dh);
- H5Sclose(sh);
- H5Sclose(mh);
- return 1;
- }
-
- r = H5Dread(dh, H5T_NATIVE_INT, mh,
- sh, H5P_DEFAULT, num_peaks);
- if ( r < 0 ) {
- ERROR("Couldn't read data for block %s, line %i\n", path, line);
- H5Dclose(dh);
- H5Sclose(sh);
- H5Sclose(mh);
- return 1;
- }
-
- H5Dclose(dh);
- H5Sclose(sh);
- H5Sclose(mh);
- return 0;
-}
-
-
-
-static float *read_hdf5_data(struct hdfile *f, char *path, int line)
-{
-
- hid_t dh, sh, mh;
- hsize_t size[2];
- hsize_t max_size[2];
- hsize_t offset[2], count[2];
- hsize_t m_offset[2], m_count[2], dimmh[2];
- float *buf;
- int tw, r;
-
- dh = H5Dopen2(f->fh, path, H5P_DEFAULT);
- if ( dh < 0 ) {
- ERROR("Data block (%s) not found.\n", path);
- return NULL;
- }
-
- sh = H5Dget_space(dh);
- if ( sh < 0 ) {
- H5Dclose(dh);
- ERROR("Couldn't get dataspace for data.\n");
- return NULL;
- }
-
- if ( H5Sget_simple_extent_ndims(sh) != 2 ) {
- ERROR("Data block %s has the wrong dimensionality (%i).\n",
- path, H5Sget_simple_extent_ndims(sh));
- H5Sclose(sh);
- H5Dclose(dh);
- return NULL;
- }
-
- H5Sget_simple_extent_dims(sh, size, max_size);
-
- tw = size[0];
- if ( line> tw-1 ) {
- H5Sclose(sh);
- H5Dclose(dh);
- ERROR("Data block %s does not contain data for required event.\n",
- path);
- return NULL;
- }
-
- offset[0] = line;
- offset[1] = 0;
- count[0] = 1;
- count[1] = size[1];
-
- r = H5Sselect_hyperslab(sh, H5S_SELECT_SET, offset, NULL, count, NULL);
- if ( r < 0 ) {
- ERROR("Error selecting file dataspace "
- "for data block %s\n", path);
- H5Dclose(dh);
- H5Sclose(sh);
- return NULL;
- }
-
- m_offset[0] = 0;
- m_offset[1] = 0;
- m_count[0] = 1;
- m_count[1] = size[1];
- dimmh[0] = 1;
- dimmh[1] = size[1];
-
- mh = H5Screate_simple(2, dimmh, NULL);
- r = H5Sselect_hyperslab(mh, H5S_SELECT_SET,
- m_offset, NULL, m_count, NULL);
- if ( r < 0 ) {
- ERROR("Error selecting memory dataspace "
- "for data block %s\n", path);
- H5Dclose(dh);
- H5Sclose(sh);
- H5Sclose(mh);
- return NULL;
- }
-
- buf = malloc(size[1]*sizeof(float));
- if ( buf == NULL ) return NULL;
- r = H5Dread(dh, H5T_NATIVE_FLOAT, mh, sh, H5P_DEFAULT, buf);
- if ( r < 0 ) {
- ERROR("Couldn't read data for block %s, line %i\n", path, line);
- H5Dclose(dh);
- H5Sclose(sh);
- H5Sclose(mh);
- return NULL;
- }
-
- H5Dclose(dh);
- H5Sclose(sh);
- H5Sclose(mh);
- return buf;
-}
-
-
-/**
- * \param image: An \ref image structure
- * \param f: An \ref hdfile structure
- * \param p: The HDF5 path to the peak data
- * \param fpe: A \ref filename_plus_event structure specifying the event
- * \param half_pixel_shift: Non-zero if 0.5 should be added to all peak coordinates
- *
- * Get peaks from HDF5, in "CXI format" (as in "CXIDB"). The data should be in
- * a set of arrays under \p p. The number of peaks should be in a 1D array at
- * \p p/nPeaks. The fast-scan and slow-scan coordinates should be in 2D arrays at
- * \p p/peakXPosRaw and \p p/peakYPosRaw respectively (sorry about the naming). The
- * first dimension of these arrays should be the event number (as given by
- * \p fpe). The intensities are expected to be at \p p/peakTotalIntensity in a
- * similar 2D array.
- *
- * CrystFEL considers all peak locations to be distances from the corner of the
- * detector panel, in pixel units, consistent with its description of detector
- * geometry (see 'man crystfel_geometry'). The software which generates the
- * CXI files, including Cheetah, may instead consider the peak locations to be
- * pixel indices in the data array. In this case, the peak coordinates should
- * have 0.5 added to them. This will be done if \p half_pixel_shift is non-zero.
- *
- * \returns Non-zero on error, zero otherwise.
- *
- */
-int get_peaks_cxi_2(struct image *image, struct hdfile *f, const char *p,
- struct filename_plus_event *fpe, int half_pixel_shift)
-{
- char path_n[1024];
- char path_x[1024];
- char path_y[1024];
- char path_i[1024];
- int r;
- int pk;
-
- int line = 0;
- int num_peaks;
-
- float *buf_x;
- float *buf_y;
- float *buf_i;
-
- double peak_offset = half_pixel_shift ? 0.5 : 0.0;
-
- if ( (fpe != NULL) && (fpe->ev != NULL)
- && (fpe->ev->dim_entries != NULL) )
- {
- line = fpe->ev->dim_entries[0];
- } else {
- ERROR("CXI format peak list format selected,"
- "but file has no event structure");
- return 1;
- }
-
- snprintf(path_n, 1024, "%s/nPeaks", p);
- snprintf(path_x, 1024, "%s/peakXPosRaw", p);
- snprintf(path_y, 1024, "%s/peakYPosRaw", p);
- snprintf(path_i, 1024, "%s/peakTotalIntensity", p);
-
- r = read_peak_count(f, path_n, line, &num_peaks);
- if ( r != 0 ) return 1;
-
- buf_x = read_hdf5_data(f, path_x, line);
- if ( r != 0 ) return 1;
-
- buf_y = read_hdf5_data(f, path_y, line);
- if ( r != 0 ) return 1;
-
- buf_i = read_hdf5_data(f, path_i, line);
- if ( r != 0 ) return 1;
-
- if ( image->features != NULL ) {
- image_feature_list_free(image->features);
- }
- image->features = image_feature_list_new();
-
- for ( pk=0; pk<num_peaks; pk++ ) {
-
- float fs, ss, val;
- struct panel *p;
-
- fs = buf_x[pk] + peak_offset;
- ss = buf_y[pk] + peak_offset;
- val = buf_i[pk];
-
- p = find_orig_panel(image->det, fs, ss);
- if ( p == NULL ) continue;
- if ( p->no_index ) continue;
-
- /* Convert coordinates to panel-relative */
- fs = fs - p->orig_min_fs;
- ss = ss - p->orig_min_ss;
-
- image_add_feature(image->features, fs, ss, p, image, val, NULL);
-
- }
-
- return 0;
-}
-
-
-/**
- * \param image: An \ref image structure
- * \param f: An \ref hdfile structure
- * \param p: The HDF5 path to the peak data
- * \param fpe: A \ref filename_plus_event structure specifying the event
- *
- * This is a wrapper function to preserve API compatibility with older CrystFEL
- * versions. Use \ref get_peaks_cxi_2 instead.
- *
- * This function is equivalent to get_peaks_cxi_2(\p image, \p f, \p p, \p fpe, 1).
- *
- * \returns Non-zero on error, zero otherwise.
- *
- */
-int get_peaks_cxi(struct image *image, struct hdfile *f, const char *p,
- struct filename_plus_event *fpe)
-{
- return get_peaks_cxi_2(image, f, p, fpe, 1);
-}
-
-
-/**
- * \param image: An \ref image structure
- * \param f: An \ref hdfile structure
- * \param p: The HDF5 path to the peak data
- * \param half_pixel_shift: Non-zero if 0.5 should be added to all peak coordinates
- *
- * Get peaks from HDF5. The peak list should be located at \p p in the HDF5 file,
- * a 2D array where the first dimension equals the number of peaks and second
- * dimension is three. The first two columns contain the fast scan and slow
- * scan coordinates, respectively, of the peaks. The third column contains the
- * intensities.
- *
- * CrystFEL considers all peak locations to be distances from the corner of the
- * detector panel, in pixel units, consistent with its description of detector
- * geometry (see 'man crystfel_geometry'). The software which generates the
- * CXI files, including Cheetah, may instead consider the peak locations to be
- * pixel indices in the data array. In this case, the peak coordinates should
- * have 0.5 added to them. This will be done if \p half_pixel_shift is non-zero.
- *
- * \returns Non-zero on error, zero otherwise.
- *
- */
-int get_peaks_2(struct image *image, struct hdfile *f, const char *p,
- int half_pixel_shift)
-{
- hid_t dh, sh;
- hsize_t size[2];
- hsize_t max_size[2];
- int i;
- float *buf;
- herr_t r;
- int tw;
- char *np;
- double peak_offset = half_pixel_shift ? 0.5 : 0.0;
-
- if ( image->event != NULL ) {
- np = retrieve_full_path(image->event, p);
- } else {
- np = strdup(p);
- }
-
- dh = H5Dopen2(f->fh, np, H5P_DEFAULT);
- if ( dh < 0 ) {
- ERROR("Peak list (%s) not found.\n", np);
- return 1;
- }
-
- sh = H5Dget_space(dh);
- if ( sh < 0 ) {
- H5Dclose(dh);
- ERROR("Couldn't get dataspace for peak list.\n");
- free(np);
- return 1;
- }
-
- if ( H5Sget_simple_extent_ndims(sh) != 2 ) {
- ERROR("Peak list has the wrong dimensionality (%i).\n",
- H5Sget_simple_extent_ndims(sh));
- H5Sclose(sh);
- H5Dclose(dh);
- free(np);
- return 1;
- }
-
- H5Sget_simple_extent_dims(sh, size, max_size);
-
- tw = size[1];
- if ( (tw != 3) && (tw != 4) ) {
- H5Sclose(sh);
- H5Dclose(dh);
- ERROR("Peak list has the wrong dimensions.\n");
- free(np);
- return 1;
- }
-
- buf = malloc(sizeof(float)*size[0]*size[1]);
- if ( buf == NULL ) {
- H5Sclose(sh);
- H5Dclose(dh);
- ERROR("Couldn't reserve memory for the peak list.\n");
- free(np);
- return 1;
- }
- r = H5Dread(dh, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL,
- H5P_DEFAULT, buf);
- if ( r < 0 ) {
- ERROR("Couldn't read peak list.\n");
- free(buf);
- free(np);
- return 1;
- }
-
- if ( image->features != NULL ) {
- image_feature_list_free(image->features);
- }
- image->features = image_feature_list_new();
-
- for ( i=0; i<size[0]; i++ ) {
-
- float fs, ss, val;
- struct panel *p;
-
- fs = buf[tw*i+0] + peak_offset;
- ss = buf[tw*i+1] + peak_offset;
- val = buf[tw*i+2];
-
- p = find_orig_panel(image->det, fs, ss);
- if ( p == NULL ) continue;
- if ( p->no_index ) continue;
-
- /* Convert coordinates to panel-relative */
- fs = fs - p->orig_min_fs;
- ss = ss - p->orig_min_ss;
-
- image_add_feature(image->features, fs, ss, p, image, val,
- NULL);
-
- }
-
- free(buf);
- free(np);
- H5Sclose(sh);
- H5Dclose(dh);
-
- return 0;
-}
-
-
-/**
- * \param image: An \ref image structure
- * \param f: An \ref hdfile structure
- * \param p: The HDF5 path to the peak data
- *
- * This is a wrapper function to preserve API compatibility with older CrystFEL
- * versions. Use \ref get_peaks_2 instead.
- *
- * This function is equivalent to \ref get_peaks_2(\p image, \p f, \p p, 1).
- *
- * \returns Non-zero on error, zero otherwise.
- *
- */
-int get_peaks(struct image *image, struct hdfile *f, const char *p)
-{
- return get_peaks_2(image, f, p, 1);
-}
-
-
-static void cleanup(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);
-
- }
-
-}
-
-
-void hdfile_close(struct hdfile *f)
-{
-
- if ( f->data_open ) {
- H5Dclose(f->dh);
- }
-
- cleanup(f->fh);
-
- H5Fclose(f->fh);
-
- free(f);
-}
-
-
-/* Deprecated */
-int hdf5_write(const char *filename, const void *data,
- int width, int height, int type)
-{
- hid_t fh, gh, sh, dh; /* File, group, dataspace and data handles */
- herr_t r;
- hsize_t size[2];
-
- fh = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
- if ( fh < 0 ) {
- ERROR("Couldn't create file: %s\n", filename);
- return 1;
- }
-
- gh = H5Gcreate2(fh, "data", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
- if ( gh < 0 ) {
- ERROR("Couldn't create group\n");
- H5Fclose(fh);
- return 1;
- }
-
- /* Note the "swap" here, according to section 3.2.5,
- * "C versus Fortran Dataspaces", of the HDF5 user's guide. */
- size[0] = height;
- size[1] = width;
- sh = H5Screate_simple(2, size, NULL);
-
- dh = H5Dcreate2(gh, "data", type, sh,
- H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
- if ( dh < 0 ) {
- ERROR("Couldn't create dataset\n");
- H5Fclose(fh);
- return 1;
- }
-
- /* Muppet check */
- H5Sget_simple_extent_dims(sh, size, NULL);
-
- r = H5Dwrite(dh, type, H5S_ALL,
- H5S_ALL, H5P_DEFAULT, data);
- if ( r < 0 ) {
- ERROR("Couldn't write data\n");
- H5Dclose(dh);
- H5Fclose(fh);
- return 1;
- }
- H5Dclose(dh);
- H5Gclose(gh);
- H5Fclose(fh);
-
- return 0;
-}
-
-
-static void add_panel_to_location(struct hdf5_write_location *loc,
- struct panel *p, int pi)
-{
- int *new_panel_idxs;
-
- new_panel_idxs = realloc(loc->panel_idxs,
- (loc->n_panels+1)*sizeof(int));
- if ( new_panel_idxs == NULL ) {
- ERROR("Error while managing write location list.\n");
- return;
- }
- loc->panel_idxs = new_panel_idxs;
- loc->panel_idxs[loc->n_panels] = pi;
- loc->n_panels += 1;
- if ( p->orig_max_fs > loc->max_fs ) {
- loc->max_fs = p->orig_max_fs;
- }
- if ( p->orig_max_ss > loc->max_ss ) {
- loc->max_ss = p->orig_max_ss;
- }
-}
-
-
-static void add_panel_location(struct panel *p, const char *p_location, int pi,
- struct hdf5_write_location **plocations,
- int *pnum_locations)
-{
- int li;
- int num_locations = *pnum_locations;
- struct hdf5_write_location *locations = *plocations;
- int done = 0;
-
- /* Does this HDF5 path already exist in the location list?
- * If so, add the new panel to it (with a unique index, we hope) */
- for ( li=0; li<num_locations; li++ ) {
- if ( strcmp(p_location, locations[li].location) == 0 ) {
- add_panel_to_location(&locations[li], p, pi);
- done = 1;
- }
- }
-
- /* If not, add a new location to ths list */
- if ( !done ) {
-
- struct hdf5_write_location *new_locations;
- size_t nsz;
-
- nsz = (num_locations+1)*sizeof(struct hdf5_write_location);
- new_locations = realloc(locations, nsz);
- if ( new_locations == NULL ) {
- ERROR("Failed to grow location list.\n");
- return;
- }
- locations = new_locations;
-
- locations[num_locations].max_ss = p->orig_max_ss;
- locations[num_locations].max_fs = p->orig_max_fs;
- locations[num_locations].location = p_location;
- locations[num_locations].panel_idxs = malloc(sizeof(int));
- if ( locations[num_locations].panel_idxs == NULL ) {
- ERROR("Failed to allocate single idx (!)\n");
- return;
- }
- locations[num_locations].panel_idxs[0] = pi;
- locations[num_locations].n_panels = 1;
-
- num_locations += 1;
-
- }
-
- *plocations = locations;
- *pnum_locations = num_locations;
-}
-
-
-static struct hdf5_write_location *make_location_list(struct detector *det,
- const char *def_location,
- int *pnum_locations)
-{
- int pi;
- struct hdf5_write_location *locations = NULL;
- int num_locations = 0;
-
- for ( pi=0; pi<det->n_panels; pi++ ) {
-
- struct panel *p;
- const char *p_location;
-
- p = &det->panels[pi];
-
- if ( p->data == NULL ) {
- p_location = def_location;
- } else {
- p_location = p->data;
- }
-
- add_panel_location(p, p_location, pi,
- &locations, &num_locations);
-
- }
-
- *pnum_locations = num_locations;
- return locations;
-}
-
-
-static void write_location(hid_t fh, struct detector *det, float **dp,
- struct hdf5_write_location *loc)
-{
- hid_t sh, dh, ph;
- hid_t dh_dataspace;
- hsize_t size[2];
- int pi;
-
- /* Note the "swap" here, according to section 3.2.5,
- * "C versus Fortran Dataspaces", of the HDF5 user's guide. */
- size[0] = loc->max_ss+1;
- size[1] = loc->max_fs+1;
- sh = H5Screate_simple(2, size, NULL);
-
- ph = H5Pcreate(H5P_LINK_CREATE);
- H5Pset_create_intermediate_group(ph, 1);
-
- dh = H5Dcreate2(fh, loc->location, H5T_NATIVE_FLOAT, sh,
- ph, H5P_DEFAULT, H5P_DEFAULT);
- if ( dh < 0 ) {
- ERROR("Couldn't create dataset\n");
- H5Fclose(fh);
- return;
- }
-
- H5Sget_simple_extent_dims(sh, size, NULL);
-
- for ( pi=0; pi<loc->n_panels; pi++ ) {
-
- hsize_t f_offset[2], f_count[2], dims[2];
- hid_t memspace;
- struct panel p;
- int r;
-
- p = det->panels[loc->panel_idxs[pi]];
-
- f_offset[0] = p.orig_min_ss;
- f_offset[1] = p.orig_min_fs;
- f_count[0] = p.orig_max_ss - p.orig_min_ss +1;
- f_count[1] = p.orig_max_fs - p.orig_min_fs +1;
-
- dh_dataspace = H5Dget_space(dh);
- r = H5Sselect_hyperslab(dh_dataspace, H5S_SELECT_SET,
- f_offset, NULL, f_count, NULL);
- if ( r < 0 ) {
- ERROR("Error selecting file dataspace "
- "for panel %s\n", p.name);
- H5Pclose(ph);
- H5Dclose(dh);
- H5Sclose(dh_dataspace);
- H5Sclose(sh);
- H5Fclose(fh);
- return;
- }
-
- dims[0] = p.h;
- dims[1] = p.w;
- memspace = H5Screate_simple(2, dims, NULL);
-
- r = H5Dwrite(dh, H5T_NATIVE_FLOAT, memspace, dh_dataspace,
- H5P_DEFAULT, dp[loc->panel_idxs[pi]]);
- if ( r < 0 ) {
- ERROR("Couldn't write data\n");
- H5Pclose(ph);
- H5Dclose(dh);
- H5Sclose(dh_dataspace);
- H5Sclose(memspace);
- H5Sclose(sh);
- H5Fclose(fh);
- return;
- }
-
- H5Sclose(dh_dataspace);
- H5Sclose(memspace);
- }
- H5Pclose(ph);
- H5Sclose(sh);
- H5Dclose(dh);
-}
-
-
-static void write_photon_energy(hid_t fh, double eV, const char *ph_en_loc)
-{
- hid_t ph, sh, dh;
- hsize_t size1d[1];
- int r;
-
- ph = H5Pcreate(H5P_LINK_CREATE);
- H5Pset_create_intermediate_group(ph, 1);
-
- size1d[0] = 1;
- sh = H5Screate_simple(1, size1d, NULL);
-
- dh = H5Dcreate2(fh, ph_en_loc, H5T_NATIVE_DOUBLE, sh,
- ph, H5S_ALL, H5P_DEFAULT);
- if ( dh < 0 ) {
- ERROR("Couldn't create dataset for photon energy.\n");
- return;
- }
- r = H5Dwrite(dh, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, &eV);
- if ( r < 0 ) {
- ERROR("Couldn't write photon energy.\n");
- /* carry on */
- }
-
- H5Pclose(ph);
- H5Dclose(dh);
-}
-
-
-static void write_spectrum(hid_t fh, Spectrum *s)
-{
- herr_t r;
- double *arr;
- int i;
- hid_t sh, dh, ph;
- double kmin, kmax, step;
- const hsize_t n = 1024;
-
- ph = H5Pcreate(H5P_LINK_CREATE);
- H5Pset_create_intermediate_group(ph, 1);
-
- arr = malloc(n*sizeof(double));
- if ( arr == NULL ) {
- ERROR("Failed to allocate memory for spectrum.\n");
- return;
- }
-
- /* Save the wavelength values */
- spectrum_get_range(s, &kmin, &kmax);
- step = (kmax-kmin)/n;
- for ( i=0; i<n; i++ ) {
- arr[i] = 1.0e10/(kmin+i*step);
- }
-
- sh = H5Screate_simple(1, &n, NULL);
-
- dh = H5Dcreate2(fh, "/spectrum/wavelengths_A", H5T_NATIVE_DOUBLE,
- sh, ph, H5S_ALL, H5P_DEFAULT);
- if ( dh < 0 ) {
- ERROR("Failed to create dataset for spectrum wavelengths.\n");
- return;
- }
- r = H5Dwrite(dh, H5T_NATIVE_DOUBLE, H5S_ALL,
- H5S_ALL, H5P_DEFAULT, arr);
- if ( r < 0 ) {
- ERROR("Failed to write spectrum wavelengths.\n");
- return;
- }
- H5Dclose(dh);
-
- /* Save the probability density values */
- for ( i=0; i<n; i++ ) {
- arr[i] = spectrum_get_density_at_k(s, kmin+i*step);
- }
-
- dh = H5Dcreate2(fh, "/spectrum/pdf", H5T_NATIVE_DOUBLE, sh,
- H5P_DEFAULT, H5S_ALL, H5P_DEFAULT);
- if ( dh < 0 ) {
- ERROR("Failed to create dataset for spectrum p.d.f.\n");
- return;
- }
- r = H5Dwrite(dh, H5T_NATIVE_DOUBLE, H5S_ALL,
- H5S_ALL, H5P_DEFAULT, arr);
- if ( r < 0 ) {
- ERROR("Failed to write spectrum p.d.f.\n");
- return;
- }
-
- H5Dclose(dh);
- H5Pclose(ph);
- free(arr);
-}
-
-
-int hdf5_write_image(const char *filename, const struct image *image,
- char *element)
-{
- hid_t fh;
- int li;
- char *default_location;
- struct hdf5_write_location *locations;
- int num_locations;
- const char *ph_en_loc;
-
- if ( image->det == NULL ) {
- ERROR("Geometry not available\n");
- return 1;
- }
-
- fh = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
- if ( fh < 0 ) {
- ERROR("Couldn't create file: %s\n", filename);
- return 1;
- }
-
- if ( element != NULL ) {
- default_location = strdup(element);
- } else {
- default_location = strdup("/data/data");
- }
-
- locations = make_location_list(image->det, default_location,
- &num_locations);
-
- for ( li=0; li<num_locations; li++ ) {
- write_location(fh, image->det, image->dp, &locations[li]);
- }
-
- if ( image->beam == NULL
- || (image->beam != NULL && image->beam->photon_energy_from == NULL) ) {
- ph_en_loc = "photon_energy_eV";
- } else {
- ph_en_loc = image->beam->photon_energy_from;
- }
-
- write_photon_energy(fh, ph_lambda_to_eV(image->lambda), ph_en_loc);
-
- if ( image->spectrum != NULL ) {
- write_spectrum(fh, image->spectrum);
- }
-
- H5Fclose(fh);
- free(default_location);
- for ( li=0; li<num_locations; li ++ ) {
- free(locations[li].panel_idxs);
- }
- free(locations);
- return 0;
-}
-
-
-static void debodge_saturation(struct hdfile *f, struct image *image)
-{
- hid_t dh, sh;
- hsize_t size[2];
- hsize_t max_size[2];
- int i;
- float *buf;
- herr_t r;
-
- dh = H5Dopen2(f->fh, "/processing/hitfinder/peakinfo_saturated",
- H5P_DEFAULT);
-
- if ( dh < 0 ) {
- /* This isn't an error */
- return;
- }
-
- sh = H5Dget_space(dh);
- if ( sh < 0 ) {
- H5Dclose(dh);
- ERROR("Couldn't get dataspace for saturation table.\n");
- return;
- }
-
- if ( H5Sget_simple_extent_ndims(sh) != 2 ) {
- H5Sclose(sh);
- H5Dclose(dh);
- return;
- }
-
- H5Sget_simple_extent_dims(sh, size, max_size);
-
- if ( size[1] != 3 ) {
- H5Sclose(sh);
- H5Dclose(dh);
- ERROR("Saturation table has the wrong dimensions.\n");
- return;
- }
-
- buf = malloc(sizeof(float)*size[0]*size[1]);
- if ( buf == NULL ) {
- H5Sclose(sh);
- H5Dclose(dh);
- ERROR("Couldn't reserve memory for saturation table.\n");
- return;
- }
- r = H5Dread(dh, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf);
- if ( r < 0 ) {
- ERROR("Couldn't read saturation table.\n");
- free(buf);
- return;
- }
-
- for ( i=0; i<size[0]; i++ ) {
-
- unsigned int fs, ss;
- float val;
- struct panel *p;
- signed int pn;
-
- fs = buf[3*i+0];
- ss = buf[3*i+1];
- val = buf[3*i+2];
-
- /* Turn "original" position into "panel" position */
- pn = find_orig_panel_number(image->det, fs, ss);
- if ( pn == -1 ) {
- ERROR("Failed to find panel!\n");
- continue;
- }
- p = &image->det->panels[pn];
-
- image->dp[pn][fs+p->w*ss] = val/5.0;
- image->dp[pn][fs+1+p->w*ss] = val/5.0;
- image->dp[pn][fs-1+p->w*ss] = val/5.0;
- image->dp[pn][fs+p->w*(ss-1)] = val/5.0;
- image->dp[pn][fs+p->w*(ss+1)] = val/5.0;
-
- }
-
- free(buf);
- H5Sclose(sh);
- H5Dclose(dh);
-}
-
-
-static int *make_badmask(int *flags, struct detector *det, float *data,
- struct panel *p)
-{
- int *badmap;
- int fs, ss;
-
- badmap = malloc(p->w*p->h*sizeof(int));
- if ( badmap == NULL ) {
- ERROR("Failed to allocate bad mask for panel %s\n",
- p->name);
- return NULL;
- }
-
- /* Defaults, then bad pixels arising from bad regions or panels */
- for ( ss=0; ss<p->h; ss++ ) {
- for ( fs=0; fs<p->w; fs++ ) {
-
- int bad = 0;
-
- if ( p->no_index ) bad = 1;
-
- if ( in_bad_region(det, p, fs, ss) ) {
- bad = 1;
- }
-
- badmap[fs+p->w*ss] = bad;
- }
- }
-
- /* Bad pixels from mask */
- if ( flags != NULL ) {
- for ( ss=0; ss<p->h; ss++ ) {
- for ( fs=0; fs<p->w; fs++ ) {
-
- int f = flags[fs+p->w*ss];
- int bad = badmap[fs+p->w*ss];
- float val = data[fs+p->w*ss];
-
- /* Bad if it's missing any of the "good" bits */
- if ( (f & det->mask_good) != det->mask_good ) bad = 1;
-
- /* Bad if it has any of the "bad" bits. */
- if ( f & det->mask_bad ) bad = 1;
-
- /* Bad if pixel value is NaN or inf */
- if ( isnan(val) || isinf(val) ) bad = 1;
-
- badmap[fs+p->w*ss] = bad;
-
- }
- }
- }
-
- return badmap;
-}
-
-
-int hdfile_get_value(struct hdfile *f, const char *name, struct event *ev,
- void *val, hid_t memtype)
-{
- hid_t dh;
- hid_t type;
- hid_t class;
- hid_t sh;
- hid_t ms;
- hsize_t *f_offset = NULL;
- hsize_t *f_count = NULL;
- hsize_t m_offset[1];
- hsize_t m_count[1];
- hsize_t msdims[1];
- hsize_t size[64];
- herr_t r;
- herr_t check;
- int check_pe;
- int dim_flag;
- int ndims;
- int i;
- char *subst_name = NULL;
-
- if ( (ev != NULL) && (ev->path_length != 0) ) {
- subst_name = retrieve_full_path(ev, name);
- } else {
- subst_name = strdup(name);
- }
-
- check_pe = check_path_existence(f->fh, subst_name);
- if ( check_pe == 0 ) {
- ERROR("No such event-based float field '%s'\n", subst_name);
- return 1;
- }
-
- dh = H5Dopen2(f->fh, subst_name, H5P_DEFAULT);
- type = H5Dget_type(dh);
- class = H5Tget_class(type);
-
- if ( (class != H5T_FLOAT) && (class != H5T_INTEGER) ) {
- ERROR("Not a floating point or integer value.\n");
- H5Tclose(type);
- H5Dclose(dh);
- return 1;
- }
-
- /* Get the dimensionality. We have to cope with scalars expressed as
- * arrays with all dimensions 1, as well as zero-d arrays. */
- sh = H5Dget_space(dh);
- ndims = H5Sget_simple_extent_ndims(sh);
- if ( ndims > 64 ) {
- ERROR("Too many dimensions for hdfile_get_value\n");
- H5Tclose(type);
- H5Dclose(dh);
- return 1;
- }
- H5Sget_simple_extent_dims(sh, size, NULL);
-
- m_offset[0] = 0;
- m_count[0] = 1;
- msdims[0] = 1;
- ms = H5Screate_simple(1,msdims,NULL);
-
- /* Check that the size in all dimensions is 1
- * or that one of the dimensions has the same
- * size as the hyperplane events */
-
- dim_flag = 0;
-
- for ( i=0; i<ndims; i++ ) {
- if ( size[i] == 1 ) continue;
- if ( ( i==0 ) && (ev != NULL) && (ev->dim_length > 0)
- && (size[i] > ev->dim_entries[0]) )
- {
- dim_flag = 1;
- } else {
- H5Tclose(type);
- H5Dclose(dh);
- return 1;
- }
- }
-
- if ( dim_flag == 0 ) {
-
- if ( H5Dread(dh, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, val) < 0 ) {
- ERROR("Couldn't read value.\n");
- H5Tclose(type);
- H5Dclose(dh);
- return 1;
- }
-
- } else {
-
- f_offset = malloc(ndims*sizeof(hsize_t));
- f_count = malloc(ndims*sizeof(hsize_t));
-
- for ( i=0; i<ndims; i++ ) {
-
- if ( i == 0 ) {
- f_offset[i] = ev->dim_entries[0];
- f_count[i] = 1;
- } else {
- f_offset[i] = 0;
- f_count[i] = 0;
- }
-
- }
-
- check = H5Sselect_hyperslab(sh, H5S_SELECT_SET,
- f_offset, NULL, f_count, NULL);
- if ( check <0 ) {
- ERROR("Error selecting dataspace for float value");
- free(f_offset);
- free(f_count);
- return 1;
- }
-
- ms = H5Screate_simple(1,msdims,NULL);
- check = H5Sselect_hyperslab(ms, H5S_SELECT_SET,
- m_offset, NULL, m_count, NULL);
- if ( check < 0 ) {
- ERROR("Error selecting memory dataspace for float value");
- free(f_offset);
- free(f_count);
- return 1;
- }
-
- r = H5Dread(dh, memtype, ms, sh, H5P_DEFAULT, val);
- if ( r < 0 ) {
- ERROR("Couldn't read value.\n");
- H5Tclose(type);
- H5Dclose(dh);
- return 1;
- }
-
- }
-
- free(subst_name);
-
- return 0;
-}
-
-
-static void hdfile_fill_in_beam_parameters(struct beam_params *beam,
- struct hdfile *f,
- struct event *ev,
- struct image *image)
-{
- double eV;
-
- if ( beam->photon_energy_from == NULL ) {
-
- /* Explicit value given */
- eV = beam->photon_energy;
-
- } else {
-
- int r;
-
- r = hdfile_get_value(f, beam->photon_energy_from,
- ev, &eV, H5T_NATIVE_DOUBLE);
- if ( r ) {
- ERROR("Failed to read '%s'\n",
- beam->photon_energy_from);
- }
-
- }
-
- image->lambda = ph_en_to_lambda(eV_to_J(eV))*beam->photon_energy_scale;
-}
-
-
-static void hdfile_fill_in_clen(struct detector *det, struct hdfile *f,
- struct event *ev)
-{
- int i;
-
- for ( i=0; i<det->n_panels; i++ ) {
-
- struct panel *p = &det->panels[i];
-
- if ( p->clen_from != NULL ) {
-
- double val;
- int r;
-
- r = hdfile_get_value(f, p->clen_from, ev, &val,
- H5T_NATIVE_DOUBLE);
- if ( r ) {
- ERROR("Failed to read '%s'\n", p->clen_from);
- } else {
- p->clen = val * 1.0e-3;
- }
-
- }
-
- adjust_centering_for_rail(p);
-
- }
-}
-
-
-int hdf5_read(struct hdfile *f, struct image *image, const char *element,
- int satcorr)
-{
- herr_t r;
- float *buf;
- int fail;
- hsize_t *size;
- hsize_t *max_size;
- hid_t sh;
- int sh_dim;
- int w, h;
-
- if ( element == NULL ) {
- fail = hdfile_set_first_image(f, "/");
- } else {
- fail = hdfile_set_image(f, element);
- }
-
- if ( fail ) {
- ERROR("Couldn't select path\n");
- return 1;
- }
-
- sh = H5Dget_space(f->dh);
- sh_dim = H5Sget_simple_extent_ndims(sh);
-
- if ( sh_dim != 2 ) {
- ERROR("Dataset is not two-dimensional\n");
- return -1;
- }
-
- size = malloc(sh_dim*sizeof(hsize_t));
- max_size = malloc(sh_dim*sizeof(hsize_t));
- H5Sget_simple_extent_dims(sh, size, max_size);
- H5Sclose(sh);
- w = size[1];
- h = size[0];
- free(size);
- free(max_size);
-
- buf = malloc(sizeof(float)*w*h);
- r = H5Dread(f->dh, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL,
- H5P_DEFAULT, buf);
- if ( r < 0 ) {
- ERROR("Couldn't read data\n");
- free(buf);
- return 1;
- }
-
- if ( image->det != NULL ) {
- ERROR("WARNING: hdf5_read() called with geometry structure.\n");
- }
- image->det = simple_geometry(image, w, h);
- image->dp = malloc(sizeof(double *));
- if ( image->dp == NULL ) {
- ERROR("Failed to allocate memory for image data!\n");
- return 1;
- }
- image->dp[0] = buf;
-
- if ( satcorr ) debodge_saturation(f, image);
-
- if ( image->beam != NULL ) {
-
- hdfile_fill_in_beam_parameters(image->beam, f, NULL, image);
-
- if ( image->lambda > 1000 ) {
- /* Error message covers a silly value in the beam file
- * or in the HDF5 file. */
- ERROR("WARNING: Missing or nonsensical wavelength "
- "(%e m) for %s.\n",
- image->lambda, image->filename);
- }
-
- }
-
- fill_in_adu(image);
-
- return 0;
-}
-
-
-static hsize_t *first_two_dims(hsize_t *in, struct dim_structure *ds)
-{
- int i, j;
- hsize_t *out = malloc(2*sizeof(hsize_t));
-
- if ( out == NULL ) return NULL;
-
- j = 0;
- for ( i=0; i<ds->num_dims; i++ ) {
- if ( (ds->dims[i] == HYSL_FS) || (ds->dims[i] == HYSL_SS) ) {
- out[j++] = in[i];
- }
- }
- return out;
-}
-
-
-static int load_satmap(struct hdfile *f, struct event *ev, struct panel *p,
- hsize_t *in_f_offset, hsize_t *in_f_count,
- struct dim_structure *dim_struct,
- float *satmap)
-{
- char *loc; /* Sat map location after possible substitution */
- hid_t satmap_dataspace, satmap_dh;
- int exists;
- int check, r;
- hid_t memspace;
- hsize_t dimsm[2];
- hid_t fh;
- hsize_t *f_offset, *f_count;
-
- if ( p->satmap_file != NULL ) {
-
- fh = H5Fopen(p->satmap_file, H5F_ACC_RDONLY, H5P_DEFAULT);
- if ( fh < 0 ) {
- ERROR("Couldn't open satmap file '%s'\n", p->satmap_file);
- return 1;
- }
-
- /* If we have an external map file, we assume it to be a simple
- * 2D job */
- f_offset = first_two_dims(in_f_offset, dim_struct);
- f_count = first_two_dims(in_f_count, dim_struct);
-
- } else {
-
- /* Otherwise, we assume it has the same dimensions as the
- * image data itself */
- fh = f->fh;
- f_offset = in_f_offset;
- f_count = in_f_count;
- }
-
- if ( ev != NULL ) {
- loc = retrieve_full_path(ev, p->satmap);
- } else {
- loc = strdup(p->satmap);
- }
-
- exists = check_path_existence(fh, loc);
- if ( !exists ) {
- ERROR("Cannot find satmap for panel %s\n", p->name);
- goto err;
- }
-
- satmap_dh = H5Dopen2(fh, loc, H5P_DEFAULT);
- if ( satmap_dh <= 0 ) {
- ERROR("Couldn't open satmap for panel %s\n", p->name);
- goto err;
- }
-
- satmap_dataspace = H5Dget_space(satmap_dh);
- check = H5Sselect_hyperslab(satmap_dataspace, H5S_SELECT_SET,
- f_offset, NULL, f_count, NULL);
- if ( check < 0 ) {
- ERROR("Error selecting satmap dataspace for panel %s\n",
- p->name);
- goto err;
- }
-
- dimsm[0] = p->h;
- dimsm[1] = p->w;
- memspace = H5Screate_simple(2, dimsm, NULL);
- if ( check < 0 ) {
- ERROR("Error selecting satmap memory dataspace for panel %s\n",
- p->name);
- goto err;
- }
-
- r = H5Dread(satmap_dh, H5T_NATIVE_FLOAT, memspace,
- satmap_dataspace, H5P_DEFAULT, satmap);
- if ( r < 0 ) {
- ERROR("Couldn't read satmap for panel %s\n", p->name);
- goto err;
- }
-
- H5Sclose(satmap_dataspace);
- H5Dclose(satmap_dh);
- free(loc);
-
- return 0;
-
-err:
- if ( p->satmap_file != NULL ) H5Fclose(fh);
- free(loc);
- return 1;
-}
-
-
-
-static int load_mask(struct hdfile *f, struct event *ev, struct panel *p,
- int *flags,
- hsize_t *in_f_offset, hsize_t *in_f_count,
- struct dim_structure *dim_struct)
-{
- char *mask; /* Mask location after possible substitution */
- hid_t mask_dataspace, mask_dh;
- int exists;
- int check, r;
- hid_t memspace;
- hsize_t dimsm[2];
- hid_t fh;
- hsize_t *f_offset, *f_count;
-
- if ( p->mask_file != NULL ) {
-
- fh = H5Fopen(p->mask_file, H5F_ACC_RDONLY, H5P_DEFAULT);
- if ( fh < 0 ) {
- ERROR("Couldn't open mask file '%s'\n", p->mask_file);
- return 1;
- }
-
- /* If we have an external map file, we assume it to be a simple
- * 2D job */
- f_offset = first_two_dims(in_f_offset, dim_struct);
- f_count = first_two_dims(in_f_count, dim_struct);
-
- } else {
- fh = f->fh;
- f_offset = in_f_offset;
- f_count = in_f_count;
- }
-
- if ( ev != NULL ) {
- mask = retrieve_full_path(ev, p->mask);
- } else {
- mask = strdup(p->mask);
- }
-
- exists = check_path_existence(fh, mask);
- if ( !exists ) {
- ERROR("Cannot find flags for panel %s\n", p->name);
- goto err;
- }
-
- mask_dh = H5Dopen2(fh, mask, H5P_DEFAULT);
- if ( mask_dh <= 0 ) {
- ERROR("Couldn't open flags for panel %s\n", p->name);
- goto err;
- }
-
- mask_dataspace = H5Dget_space(mask_dh);
- check = H5Sselect_hyperslab(mask_dataspace, H5S_SELECT_SET,
- f_offset, NULL, f_count, NULL);
- if ( check < 0 ) {
- ERROR("Error selecting mask dataspace for panel %s\n", p->name);
- goto err;
- }
-
- dimsm[0] = p->h;
- dimsm[1] = p->w;
- memspace = H5Screate_simple(2, dimsm, NULL);
- if ( check < 0 ) {
- ERROR("Error selecting memory dataspace for panel %s\n", p->name);
- goto err;
- }
-
- r = H5Dread(mask_dh, H5T_NATIVE_INT, memspace,
- mask_dataspace, H5P_DEFAULT, flags);
- if ( r < 0 ) {
- ERROR("Couldn't read flags for panel %s\n", p->name);
- goto err;
- }
-
- H5Sclose(mask_dataspace);
- H5Dclose(mask_dh);
- free(mask);
-
- return 0;
-
-err:
- if ( p->mask_file != NULL ) H5Fclose(fh);
- free(mask);
- return 1;
-}
-
-
-int hdf5_read2(struct hdfile *f, struct image *image, struct event *ev,
- int satcorr)
-{
- herr_t r;
- int pi;
- int i;
-
- if ( image->det == NULL ) {
- ERROR("Geometry not available\n");
- return 1;
- }
-
- image->dp = malloc(image->det->n_panels*sizeof(float *));
- image->bad = malloc(image->det->n_panels*sizeof(int *));
- image->sat = malloc(image->det->n_panels*sizeof(float *));
- if ( (image->dp==NULL) || (image->bad==NULL) || (image->sat==NULL) ) {
- ERROR("Failed to allocate data arrays.\n");
- return 1;
- }
-
- for ( pi=0; pi<image->det->n_panels; pi++ ) {
-
- hsize_t *f_offset, *f_count;
- int hsi;
- struct dim_structure *hsd;
- herr_t check;
- hid_t dataspace, memspace;
- int fail;
- struct panel *p;
- hsize_t dims[2];
-
- p = &image->det->panels[pi];
-
- if ( ev != NULL ) {
-
- int exists;
- char *panel_full_path;
-
- panel_full_path = retrieve_full_path(ev, p->data);
-
- exists = check_path_existence(f->fh, panel_full_path);
- if ( !exists ) {
- ERROR("Cannot find data for panel %s\n",
- p->name);
- free(image->dp);
- free(image->bad);
- free(image->sat);
- return 1;
- }
-
- fail = hdfile_set_image(f, panel_full_path);
-
- free(panel_full_path);
-
- } else {
-
- if ( p->data == NULL ) {
-
- fail = hdfile_set_first_image(f, "/");
-
- } else {
-
- int exists;
- exists = check_path_existence(f->fh, p->data);
- if ( !exists ) {
- ERROR("Cannot find data for panel %s\n",
- p->name);
- free(image->dp);
- free(image->bad);
- free(image->sat);
- return 1;
- }
- fail = hdfile_set_image(f, p->data);
-
- }
-
- }
- if ( fail ) {
- ERROR("Couldn't select path for panel %s\n",
- p->name);
- free(image->dp);
- free(image->bad);
- free(image->sat);
- return 1;
- }
-
- /* Determine where to read the data from in the file */
- hsd = image->det->panels[pi].dim_structure;
- f_offset = malloc(hsd->num_dims*sizeof(hsize_t));
- f_count = malloc(hsd->num_dims*sizeof(hsize_t));
- if ( (f_offset == NULL) || (f_count == NULL ) ) {
- ERROR("Failed to allocate offset or count.\n");
- free(image->dp);
- free(image->bad);
- free(image->sat);
- return 1;
- }
- for ( hsi=0; hsi<hsd->num_dims; hsi++ ) {
-
- if ( hsd->dims[hsi] == HYSL_FS ) {
- f_offset[hsi] = p->orig_min_fs;
- f_count[hsi] = p->orig_max_fs - p->orig_min_fs+1;
- } else if ( hsd->dims[hsi] == HYSL_SS ) {
- f_offset[hsi] = p->orig_min_ss;
- f_count[hsi] = p->orig_max_ss - p->orig_min_ss+1;
- } else if (hsd->dims[hsi] == HYSL_PLACEHOLDER ) {
- f_offset[hsi] = ev->dim_entries[0];
- f_count[hsi] = 1;
- } else {
- f_offset[hsi] = hsd->dims[hsi];
- f_count[hsi] = 1;
- }
-
- }
-
- /* Set up dataspace for file */
- dataspace = H5Dget_space(f->dh);
- check = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET,
- f_offset, NULL, f_count, NULL);
- if ( check < 0 ) {
- ERROR("Error selecting file dataspace for panel %s\n",
- p->name);
- free(image->dp);
- free(image->bad);
- free(image->sat);
- return 1;
- }
-
- dims[0] = p->h;
- dims[1] = p->w;
- memspace = H5Screate_simple(2, dims, NULL);
-
- image->dp[pi] = malloc(p->w*p->h*sizeof(float));
- image->sat[pi] = malloc(p->w*p->h*sizeof(float));
- if ( (image->dp[pi] == NULL) || (image->sat[pi] == NULL) ) {
- ERROR("Failed to allocate panel %s\n", p->name);
- free(f_offset);
- free(f_count);
- free(image->dp);
- free(image->bad);
- free(image->sat);
- return 1;
- }
- for ( i=0; i<p->w*p->h; i++ ) image->sat[pi][i] = INFINITY;
-
- r = H5Dread(f->dh, H5T_NATIVE_FLOAT, memspace, dataspace,
- H5P_DEFAULT, image->dp[pi]);
- if ( r < 0 ) {
- ERROR("Couldn't read data for panel %s\n",
- p->name);
- free(f_offset);
- free(f_count);
- for ( i=0; i<=pi; i++ ) {
- free(image->dp[i]);
- free(image->sat[i]);
- }
- free(image->dp);
- free(image->bad);
- free(image->sat);
- return 1;
- }
-
- if ( p->mask != NULL ) {
- int *flags = malloc(p->w*p->h*sizeof(int));
- if ( !load_mask(f, ev, p, flags, f_offset, f_count, hsd) ) {
- image->bad[pi] = make_badmask(flags, image->det,
- image->dp[pi], p);
- } else {
- image->bad[pi] = make_badmask(NULL, image->det,
- image->dp[pi], p);
- }
- free(flags);
- } else {
- image->bad[pi] = make_badmask(NULL, image->det,
- image->dp[pi], p);
- }
-
- if ( p->satmap != NULL ) {
- if ( load_satmap(f, ev, p, f_offset, f_count, hsd,
- image->sat[pi]) )
- {
- ERROR("Failed to load sat map for panel %s\n",
- p->name);
- }
- }
-
- H5Sclose(dataspace);
- free(f_offset);
- free(f_count);
-
- }
-
- H5Dclose(f->dh);
- f->data_open = 0;
- hdfile_fill_in_clen(image->det, f, ev);
-
- if ( satcorr ) debodge_saturation(f, image);
-
- if ( image->beam != NULL ) {
-
- hdfile_fill_in_beam_parameters(image->beam, f, ev, image);
-
- if ( (image->lambda > 1.0) || (image->lambda < 1e-20) ) {
-
- ERROR("WARNING: Nonsensical wavelength (%e m) value "
- "for file: %s, event: %s.\n",
- image->lambda, image->filename,
- get_event_string(image->event));
- }
-
- }
-
- fill_in_adu(image);
-
- return 0;
-}
-
-
-static int looks_like_image(hid_t h)
-{
- hid_t sh;
- hsize_t size[2];
- hsize_t max_size[2];
-
- sh = H5Dget_space(h);
- if ( sh < 0 ) return 0;
-
- if ( H5Sget_simple_extent_ndims(sh) != 2 ) {
- H5Sclose(sh);
- return 0;
- }
-
- H5Sget_simple_extent_dims(sh, size, max_size);
- H5Sclose(sh);
-
- if ( ( size[0] > 64 ) && ( size[1] > 64 ) ) return 1;
-
- return 0;
-}
-
-
-int hdfile_is_scalar(struct hdfile *f, const char *name, int verbose)
-{
- hid_t dh;
- hid_t sh;
- hsize_t size[3];
- hid_t type;
- int ndims;
- int i;
- int check;
-
- check = check_path_existence(f->fh, name);
- if ( check == 0 ) {
- ERROR("No such scalar field '%s'\n", name);
- return 0;
- }
-
- dh = H5Dopen2(f->fh, name, H5P_DEFAULT);
- type = H5Dget_type(dh);
-
- /* Get the dimensionality. We have to cope with scalars expressed as
- * arrays with all dimensions 1, as well as zero-d arrays. */
- sh = H5Dget_space(dh);
- ndims = H5Sget_simple_extent_ndims(sh);
- if ( ndims > 3 ) {
- if ( verbose ) {
- ERROR("Too many dimensions (%i).\n", ndims);
- }
- H5Sclose(sh);
- H5Tclose(type);
- H5Dclose(dh);
- return 0;
- }
-
- /* Check that the size in all dimensions is 1 */
- H5Sget_simple_extent_dims(sh, size, NULL);
- H5Sclose(sh);
- H5Tclose(type);
- H5Dclose(dh);
- for ( i=0; i<ndims; i++ ) {
- if ( size[i] != 1 ) {
- if ( verbose ) {
- ERROR("%s not a scalar value (ndims=%i,"
- "size[%i]=%i)\n",
- name, ndims, i, (int)size[i]);
- }
- return 0;
- }
- }
-
- return 1;
-}
-
-
-struct copy_hdf5_field
-{
- char **fields;
- int n_fields;
- int max_fields;
-};
-
-
-struct copy_hdf5_field *new_copy_hdf5_field_list()
-{
- struct copy_hdf5_field *n;
-
- n = calloc(1, sizeof(struct copy_hdf5_field));
- if ( n == NULL ) return NULL;
-
- n->max_fields = 32;
- n->fields = malloc(n->max_fields*sizeof(char *));
- if ( n->fields == NULL ) {
- free(n);
- return NULL;
- }
-
- return n;
-}
-
-
-void free_copy_hdf5_field_list(struct copy_hdf5_field *n)
-{
- int i;
- for ( i=0; i<n->n_fields; i++ ) {
- free(n->fields[i]);
- }
- free(n->fields);
- free(n);
-}
-
-
-void add_copy_hdf5_field(struct copy_hdf5_field *copyme,
- const char *name)
-{
- int i;
-
- /* Already on the list? Don't re-add if so. */
- for ( i=0; i<copyme->n_fields; i++ ) {
- if ( strcmp(copyme->fields[i], name) == 0 ) return;
- }
-
- /* Need more space? */
- if ( copyme->n_fields == copyme->max_fields ) {
-
- char **nfields;
- int nmax = copyme->max_fields + 32;
-
- nfields = realloc(copyme->fields, nmax*sizeof(char *));
- if ( nfields == NULL ) {
- ERROR("Failed to allocate space for new HDF5 field.\n");
- return;
- }
-
- copyme->max_fields = nmax;
- copyme->fields = nfields;
-
- }
-
- copyme->fields[copyme->n_fields] = strdup(name);
- if ( copyme->fields[copyme->n_fields] == NULL ) {
- ERROR("Failed to add field for copying '%s'\n", name);
- return;
- }
-
- copyme->n_fields++;
-}
-
-
-void copy_hdf5_fields(struct hdfile *f, const struct copy_hdf5_field *copyme,
- FILE *fh, struct event *ev)
-{
- int i;
-
- if ( copyme == NULL ) return;
-
- for ( i=0; i<copyme->n_fields; i++ ) {
-
- char *val;
- char *field;
-
- field = copyme->fields[i];
- val = hdfile_get_string_value(f, field, ev);
-
- if ( field[0] == '/' ) {
- fprintf(fh, "hdf5%s = %s\n", field, val);
- } else {
- fprintf(fh, "hdf5/%s = %s\n", field, val);
- }
-
- free(val);
-
- }
-}
-
-
-static int make_dataspaces(hid_t dh, struct event *ev, hid_t *memspace,
- hid_t *filespace)
-{
- hsize_t *f_offset, *f_count;
- hsize_t *m_offset, *m_count;
- hid_t sh, mh;
- int ndims;
- int i;
-
- if ( ev == NULL ) {
- ERROR("Can't make dataspaces: no event ID\n");
- return 1;
- }
-
- /* Check that there are at least as many dim entries as dimensions */
- sh = H5Dget_space(dh);
- ndims = H5Sget_simple_extent_ndims(sh);
- if ( ndims > ev->dim_length ) {
- return 1;
- }
-
- /* Now set up arrays of offsets and counts in files and memory */
- f_offset = malloc(sizeof(hsize_t)*ndims);
- f_count = malloc(sizeof(hsize_t)*ndims);
- m_offset = malloc(sizeof(hsize_t)*ndims);
- m_count = malloc(sizeof(hsize_t)*ndims);
- if ( (f_offset == NULL) || (f_count == NULL)
- || (m_offset == NULL) || (m_count == NULL) ) return 1;
-
- for ( i=0; i<ev->dim_length; i++ ) {
- f_offset[i] = ev->dim_entries[i];
- f_count[i] = 1;
- m_offset[i] = 0;
- m_count[i] = 1;
- }
-
- if ( H5Sselect_hyperslab(sh, H5S_SELECT_SET,
- f_offset, NULL, f_count, NULL) ) return 1;
-
- free(f_offset);
- free(f_count);
-
- mh = H5Screate_simple(ndims, m_count, NULL);
- if ( H5Sselect_hyperslab(mh, H5S_SELECT_SET,
- m_offset, NULL, m_count, NULL) ) return 1;
- free(m_offset);
- free(m_count);
-
- *memspace = mh;
- *filespace = sh;
-
- return 0;
-}
-
-
-static char *read_vlen_string(hid_t dh, struct event *ev)
-{
- hid_t memspace, filespace;
- herr_t r;
- char *tmp;
- hid_t type;
-
- if ( make_dataspaces(dh, ev, &memspace, &filespace) ) {
- return strdup("[couldn't make dataspaces - variable len]");
- }
-
- type = H5Dget_type(dh);
- r = H5Dread(dh, type, memspace, filespace, H5P_DEFAULT, &tmp);
- H5Tclose(type);
- if ( r < 0 ) {
- return strdup("[couldn't read vlen string]");
- }
-
- H5Sclose(memspace);
- H5Sclose(filespace);
-
- /* Variable strings are 0-terminated */
- chomp(tmp);
- return tmp;
-}
-
-
-static char *read_fixed_string(hid_t dh, struct event *ev)
-{
- hid_t memspace, filespace;
- herr_t r;
- hid_t sh, type;
- size_t size;
- char *tmp;
-
- type = H5Dget_type(dh);
- size = H5Tget_size(type);
- tmp = malloc(size+1);
- if ( tmp == NULL ) {
- H5Tclose(type);
- return strdup("[couldn't allocate string]");
- }
-
- if ( ev == NULL ) {
-
- /* Try a simple fixed-length string */
- sh = H5Dget_space(dh);
- if ( H5Sget_simple_extent_ndims(sh) ) {
- H5Tclose(type);
- return strdup("[non-scalar string]");
- }
-
- sh = H5Screate(H5S_SCALAR);
- r = H5Dread(dh, type, sh, H5S_ALL, H5P_DEFAULT, tmp);
- H5Sclose(sh);
- if ( r < 0 ) {
- free(tmp);
- H5Tclose(type);
- return strdup("[couldn't read scalar string]");
- } else {
- H5Tclose(type);
- tmp[size] = '\0';
- chomp(tmp);
- return tmp;
- }
- }
-
- if ( make_dataspaces(dh, ev, &memspace, &filespace) ) {
- H5Tclose(type);
- return strdup("[couldn't make dataspaces - fixed len]");
- }
-
- r = H5Dread(dh, type, memspace, filespace, H5P_DEFAULT, tmp);
- if ( r < 0 ) {
- H5Tclose(type);
- return strdup("[couldn't read string]");
- }
-
- H5Tclose(type);
- H5Sclose(memspace);
- H5Sclose(filespace);
-
- tmp[size] = '\0';
- chomp(tmp);
- return tmp;
-}
-
-
-static char *read_general_string(hid_t dh, struct event *ev)
-{
- htri_t v;
- hid_t type;
-
- type = H5Dget_type(dh);
- v = H5Tis_variable_str(type);
- H5Tclose(type);
-
- if ( v < 0 ) {
- return strdup("[unrecognised string type]");
-
- } else if ( v > 0 ) {
- /* Variable length string */
- return read_vlen_string(dh, ev);
-
- } else {
- /* Fixed-length string */
- return read_fixed_string(dh, ev);
-
- }
-}
-
-
-char *hdfile_get_string_value(struct hdfile *f, const char *name,
- struct event *ev)
-{
- hid_t dh;
- hid_t type;
- hid_t class;
- int buf_i;
- double buf_f;
- char *tmp = NULL;
- char *subst_name = NULL;
-
- if ( (ev != NULL) && (ev->path_length != 0) ) {
- subst_name = retrieve_full_path(ev, name);
- } else {
- subst_name = strdup(name);
- }
-
- dh = H5Dopen2(f->fh, subst_name, H5P_DEFAULT);
- if ( dh < 0 ) {
- free(subst_name);
- return strdup("[couldn't read string]");
- }
-
- type = H5Dget_type(dh);
- class = H5Tget_class(type);
- H5Tclose(type);
-
- if ( class == H5T_STRING ) {
-
- free(subst_name);
- tmp = read_general_string(dh, ev);
- H5Dclose(dh);
- return tmp;
-
- } else {
-
- int r;
-
- H5Dclose(dh);
-
- switch ( class ) {
-
- case H5T_FLOAT :
- r = hdfile_get_value(f, subst_name, ev, &buf_f,
- H5T_NATIVE_DOUBLE);
- free(subst_name);
- if ( r == 0 ) {
- tmp = malloc(256);
- if ( tmp == NULL ) {
- ERROR("Failed to allocate float\n");
- return NULL;
- }
- snprintf(tmp, 255, "%f", buf_f);
- return tmp;
- } else {
- return NULL;
- }
- break;
-
- case H5T_INTEGER :
- r = hdfile_get_value(f, subst_name, ev, &buf_i,
- H5T_NATIVE_INT);
- free(subst_name);
- if ( r == 0 ) {
- tmp = malloc(256);
- if ( tmp == NULL ) {
- ERROR("Failed to allocate int buf!\n");
- return NULL;
- }
- snprintf(tmp, 255, "%d", buf_i);
- return tmp;
-
- } else {
- return NULL;
- }
- break;
-
- default :
- ERROR("Unrecognised type: %s\n", subst_name);
- free(subst_name);
- return NULL;
- }
-
- }
-}
-
-
-char **hdfile_read_group(struct hdfile *f, int *n, const char *parent,
- int **p_is_group, int **p_is_image)
-{
- hid_t gh;
- hsize_t num;
- char **res;
- int i;
- int *is_group;
- int *is_image;
- H5G_info_t ginfo;
-
- gh = H5Gopen2(f->fh, parent, H5P_DEFAULT);
- if ( gh < 0 ) {
- *n = 0;
- return NULL;
- }
-
- if ( H5Gget_info(gh, &ginfo) < 0 ) {
- /* Whoopsie */
- *n = 0;
- return NULL;
- }
- num = ginfo.nlinks;
- *n = num;
- if ( num == 0 ) return NULL;
-
- res = malloc(num*sizeof(char *));
- is_image = malloc(num*sizeof(int));
- is_group = malloc(num*sizeof(int));
- *p_is_image = is_image;
- *p_is_group = is_group;
-
- for ( i=0; i<num; i++ ) {
-
- char buf[256];
- hid_t dh;
- H5I_type_t type;
-
- H5Lget_name_by_idx(gh, ".", H5_INDEX_NAME, H5_ITER_NATIVE,
- i, buf, 255, H5P_DEFAULT);
- res[i] = malloc(512);
- if ( strlen(parent) > 1 ) {
- snprintf(res[i], 511, "%s/%s", parent, buf);
- } else {
- snprintf(res[i], 511, "%s%s", parent, buf);
- } /* ick */
-
- is_image[i] = 0;
- is_group[i] = 0;
- dh = H5Oopen(gh, buf, H5P_DEFAULT);
- if ( dh < 0 ) continue;
- type = H5Iget_type(dh);
-
- if ( type == H5I_GROUP ) {
- is_group[i] = 1;
- } else if ( type == H5I_DATASET ) {
- is_image[i] = looks_like_image(dh);
- }
- H5Oclose(dh);
-
- }
-
- H5Gclose(gh);
-
- return res;
-}
-
-
-int hdfile_set_first_image(struct hdfile *f, const char *group)
-{
- char **names;
- int *is_group;
- int *is_image;
- int n, i, j;
-
- names = hdfile_read_group(f, &n, group, &is_group, &is_image);
- if ( n == 0 ) return 1;
-
- for ( i=0; i<n; i++ ) {
-
- if ( is_image[i] ) {
- hdfile_set_image(f, names[i]);
- for ( j=0; j<n; j++ ) free(names[j]);
- free(is_image);
- free(is_group);
- free(names);
- return 0;
- } else if ( is_group[i] ) {
- if ( !hdfile_set_first_image(f, names[i]) ) {
- for ( j=0; j<n; j++ ) free(names[j]);
- free(is_image);
- free(is_group);
- free(names);
- return 0;
- }
- }
-
- }
-
- for ( j=0; j<n; j++ ) free(names[j]);
- free(is_image);
- free(is_group);
- free(names);
-
- return 1;
-}
-
-
-struct parse_params {
- struct hdfile *hdfile;
- int path_dim;
- const char *path;
- struct event *curr_event;
- struct event_list *ev_list;
- int top_level;
-};
-
-
-int check_path_existence(hid_t fh, const char *path)
-{
-
- char buffer[256];
- char buffer_full_path[2048];
- herr_t herrt;
- struct H5O_info_t ob_info;
- char *path_copy = strdup(path);
- char *start = path_copy;
- char *sep = NULL;
-
- buffer[0] = '\0';
- buffer_full_path[0] = '\0';
-
- if ( strcmp(path_copy, "/" ) == 0 ) {
- return 1;
- }
-
- do {
-
- int check;
-
- sep = strstr(start, "/");
- if ( sep != NULL && strlen(sep) == 1 ) {
- ERROR("Error: Data path ends with a / symbol\n");
- free(path_copy);
- return 1;
- }
-
- if ( sep != NULL ) {
-
- if ( sep == start ) {
- start = sep+1;
- strcat(buffer_full_path, "/");
- continue;
- }
-
- strncpy(buffer, start, sep-start);
- buffer[sep-start] = '\0';
- strcat(buffer_full_path, buffer);
-
- check = H5Lexists(fh, buffer_full_path, H5P_DEFAULT);
- if ( check == 0 ) {
- return 0;
- } else {
- herrt = H5Oget_info_by_name(fh, buffer_full_path,
- &ob_info,
- H5P_DEFAULT);
- if ( herrt < 0 ) {
- return -1;
- }
- if ( ob_info.type != H5O_TYPE_GROUP ) {
- return 0;
- }
-
- start = sep+1;
- strcat(buffer_full_path, "/");
-
- }
-
- } else {
-
- strcpy(buffer, start);
- strcat(buffer_full_path, buffer);
-
- check = H5Lexists(fh, buffer_full_path, H5P_DEFAULT);
- if ( check == 0 ) {
- return 0;
- }
-
- }
- } while (sep);
-
- free(path_copy);
- return 1;
-
-}
-
-
-static herr_t parse_file_event_structure(hid_t loc_id, char *name,
- const H5L_info_t *info,
- struct parse_params *pp)
-
-{
- char *substituted_path;
- char *ph_loc;
- char *truncated_path;
- htri_t check;
- herr_t herrt_iterate, herrt_info;
- struct H5O_info_t object_info;
-
- if ( !pp->top_level ) {
-
- int fail_push;
-
- fail_push = push_path_entry_to_event(pp->curr_event, name);
- if ( fail_push ) {
- return -1;
- }
-
- substituted_path = event_path_placeholder_subst(name, pp->path);
-
- } else {
- substituted_path = strdup(pp->path);
- }
-
- if ( pp->top_level == 1 ) {
- pp->top_level = 0;
- }
-
- truncated_path = strdup(substituted_path);
- ph_loc = strstr(substituted_path,"%");
- if ( ph_loc != NULL) {
- truncated_path[ph_loc-substituted_path] = '\0';
- }
-
- herrt_iterate = 0;
- herrt_info = 0;
-
- check = check_path_existence(pp->hdfile->fh, truncated_path);
- if ( check == 0 ) {
- pop_path_entry_from_event(pp->curr_event);
- return 0;
- } else {
-
- herrt_info = H5Oget_info_by_name(pp->hdfile->fh, truncated_path,
- &object_info, H5P_DEFAULT);
- if ( herrt_info < 0 ) {
- free(truncated_path);
- free(substituted_path);
- return -1;
- }
-
- if ( pp->curr_event->path_length == pp->path_dim
- && object_info.type == H5O_TYPE_DATASET )
- {
-
- int fail_append;
-
- fail_append = append_event_to_event_list(pp->ev_list,
- pp->curr_event);
- if ( fail_append ) {
- free(truncated_path);
- free(substituted_path);
- return -1;
- }
-
- pop_path_entry_from_event(pp->curr_event);
- return 0;
-
- } else {
-
- pp->path = substituted_path;
-
- if ( object_info.type == H5O_TYPE_GROUP ) {
-
- herrt_iterate = H5Literate_by_name(pp->hdfile->fh,
- truncated_path, H5_INDEX_NAME,
- H5_ITER_NATIVE, NULL,
- (H5L_iterate_t)parse_file_event_structure,
- (void *)pp, H5P_DEFAULT);
- }
- }
- }
-
- pop_path_entry_from_event(pp->curr_event);
-
- free(truncated_path);
- free(substituted_path);
-
- return herrt_iterate;
-}
-
-
-static int fill_paths(struct hdfile *hdfile, struct detector *det, int pi,
- struct event_list *master_el)
-{
- struct parse_params pparams;
- struct event *empty_event;
- struct event_list *panel_ev_list;
- int ei;
- int check;
-
- empty_event = initialize_event();
- panel_ev_list = initialize_event_list();
- if ( (empty_event == NULL) || (panel_ev_list == NULL) )
- {
- ERROR("Failed to allocate memory for event list.\n");
- return 1;
- }
-
- pparams.path = det->panels[pi].data;
- pparams.hdfile = hdfile;
- pparams.path_dim = det->path_dim;
- pparams.curr_event = empty_event;
- pparams.top_level = 1;
- pparams.ev_list = panel_ev_list;
-
- check = parse_file_event_structure(hdfile->fh, NULL, NULL, &pparams);
- if ( check < 0 ) {
- free_event(empty_event);
- free_event_list(panel_ev_list);
- return 1;
- }
-
- for ( ei=0; ei<panel_ev_list->num_events; ei++ ) {
-
- int fail_add;
-
- fail_add = add_non_existing_event_to_event_list(master_el,
- panel_ev_list->events[ei]);
- if ( fail_add ) {
- free_event(empty_event);
- free_event_list(panel_ev_list);
- return 1;
- }
-
- }
-
- free_event(empty_event);
- free_event_list(panel_ev_list);
-
- return 0;
-}
-
-
-static int check_dims(struct hdfile *hdfile, struct panel *p, struct event *ev,
- struct event_list *events, int *global_path_dim)
-{
- char *full_panel_path;
- hid_t dh;
- hid_t sh;
- int dims;
- hsize_t *size;
- hsize_t *max_size;
- int hsdi;
- int panel_path_dim = 0;
- struct dim_structure *panel_dim_structure;
-
- /* Get the full path for this panel in this event */
- full_panel_path = retrieve_full_path(ev, p->data);
-
- dh = H5Dopen2(hdfile->fh, full_panel_path, H5P_DEFAULT);
- if ( dh < 0 ) {
- ERROR("Error opening '%s'\n", full_panel_path);
- ERROR("Failed to enumerate events. "
- "Check your geometry file.\n");
- return 1;
- }
-
- sh = H5Dget_space(dh);
- dims = H5Sget_simple_extent_ndims(sh);
- size = malloc(dims*sizeof(hsize_t));
- max_size = malloc(dims*sizeof(hsize_t));
- if ( (size==NULL) || (max_size==NULL) ) {
- ERROR("Failed to allocate memory for dimensions\n");
- return 1;
- }
-
- dims = H5Sget_simple_extent_dims(sh, size, max_size);
-
- panel_dim_structure = p->dim_structure;
- for ( hsdi=0; hsdi<panel_dim_structure->num_dims; hsdi++ ) {
- if ( panel_dim_structure->dims[hsdi] == HYSL_PLACEHOLDER ) {
- panel_path_dim = size[hsdi];
- break;
- }
- }
-
- if ( *global_path_dim == -1 ) {
-
- *global_path_dim = panel_path_dim;
-
- } else if ( panel_path_dim != *global_path_dim ) {
-
- ERROR("All panels must have the same number of frames\n");
- ERROR("Panel %s has %i frames in one dimension, but the first "
- "panel has %i.\n",
- p->name, panel_path_dim, *global_path_dim);
- free(size);
- free(max_size);
- return 1;
- }
-
- H5Sclose(sh);
- H5Dclose(dh);
-
- return 0;
-}
-
-
-struct event_list *fill_event_list(struct hdfile *hdfile, struct detector *det)
-{
- struct event_list *master_el;
-
- master_el = initialize_event_list();
- if ( master_el == NULL ) {
- ERROR("Failed to allocate event list.\n");
- return NULL;
- }
-
- /* First expand any placeholders in the HDF5 paths */
- if ( det->path_dim != 0 ) {
- int pi;
- for ( pi=0; pi<det->n_panels; pi++ ) {
- if ( fill_paths(hdfile, det, pi, master_el) ) {
- ERROR("Failed to enumerate paths.\n");
- return NULL;
- }
- }
- }
-
- /* Now enumerate the placeholder dimensions */
- if ( det->dim_dim > 0 ) {
-
- struct event_list *master_el_with_dims;
- int evi;
-
- /* If there were no HDF5 path placeholders, add a dummy event */
- if ( master_el->num_events == 0 ) {
- struct event *empty_ev;
- empty_ev = initialize_event();
- append_event_to_event_list(master_el, empty_ev);
- free(empty_ev);
- }
-
- master_el_with_dims = initialize_event_list();
-
- /* For each event so far, expand the dimensions */
- for ( evi=0; evi<master_el->num_events; evi++ ) {
-
- int pi;
- int global_path_dim = -1;
- int mlwd;
-
- /* Check the dimensionality of each panel */
- for ( pi=0; pi<det->n_panels; pi++ ) {
- if ( check_dims(hdfile, &det->panels[pi],
- master_el->events[evi],
- master_el_with_dims,
- &global_path_dim) )
- {
- ERROR("Failed to enumerate dims.\n");
- return NULL;
- }
- }
-
- /* Add this dimensionality to all events */
- for ( mlwd=0; mlwd<global_path_dim; mlwd++ ) {
-
- struct event *mlwd_ev;
-
- mlwd_ev = copy_event(master_el->events[evi]);
- push_dim_entry_to_event(mlwd_ev, mlwd);
- append_event_to_event_list(master_el_with_dims,
- mlwd_ev);
- free_event(mlwd_ev);
- }
-
- }
-
- free_event_list(master_el);
- return master_el_with_dims;
-
- } else {
-
- return master_el;
-
- }
-}
diff --git a/libcrystfel/src/hdf5-file.h b/libcrystfel/src/hdf5-file.h
deleted file mode 100644
index 99f231e1..00000000
--- a/libcrystfel/src/hdf5-file.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * hdf5-file.h
- *
- * Read/write HDF5 data files
- *
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
- * a research centre of the Helmholtz Association.
- *
- * Authors:
- * 2009-2017 Thomas White <taw@physics.org>
- * 2014 Valerio Mariani
-
- *
- * This file is part of CrystFEL.
- *
- * CrystFEL is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * CrystFEL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifndef HDF5_H
-#define HDF5_H
-
-struct event_list;
-
-#include <stdint.h>
-#include <hdf5.h>
-#include "image.h"
-#include "events.h"
-
-struct hdfile;
-struct copy_hdf5_field;
-
-#include "image.h"
-#include "events.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * \file hdf5-file.h
- * HDF5 abstraction layer
- */
-
-extern int hdf5_write(const char *filename, const void *data,
- int width, int height, int type);
-
-extern int hdf5_write_image(const char *filename, const struct image *image,
- char *element);
-
-extern int hdf5_read(struct hdfile *f, struct image *image,
- const char* element, int satcorr);
-
-extern int hdf5_read2(struct hdfile *f, struct image *image,
- struct event *ev, int satcorr);
-
-extern int check_path_existence(hid_t fh, const char *path);
-
-extern struct hdfile *hdfile_open(const char *filename);
-int hdfile_set_image(struct hdfile *f, const char *path);
-
-extern int16_t *hdfile_get_image_binned(struct hdfile *hdfile,
- int binning, int16_t *maxp);
-extern char **hdfile_read_group(struct hdfile *f, int *n, const char *parent,
- int **p_is_group, int **p_is_image);
-extern int hdfile_set_first_image(struct hdfile *f, const char *group);
-extern void hdfile_close(struct hdfile *f);
-
-extern int get_peaks(struct image *image, struct hdfile *f, const char *p);
-
-extern int get_peaks_2(struct image *image, struct hdfile *f, const char *p,
- int half_pixel_shift);
-
-extern int get_peaks_cxi(struct image *image, struct hdfile *f, const char *p,
- struct filename_plus_event *fpe);
-
-extern int get_peaks_cxi_2(struct image *image, struct hdfile *f, const char *p,
- struct filename_plus_event *fpe,
- int half_pixel_shift);
-
-extern struct copy_hdf5_field *new_copy_hdf5_field_list(void);
-extern void free_copy_hdf5_field_list(struct copy_hdf5_field *f);
-
-extern void copy_hdf5_fields(struct hdfile *f,
- const struct copy_hdf5_field *copyme,
- FILE *fh, struct event *ev);
-extern void add_copy_hdf5_field(struct copy_hdf5_field *copyme,
- const char *name);
-extern struct event_list *fill_event_list(struct hdfile* hdfile,
- struct detector* det);
-
-extern int hdfile_get_value(struct hdfile *f, const char *name,
- struct event *ev, void *val, hid_t memtype);
-extern int hdfile_is_scalar(struct hdfile *f, const char *name, int verbose);
-extern char *hdfile_get_string_value(struct hdfile *f, const char *name,
- struct event *ev);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* HDF5_H */
diff --git a/libcrystfel/src/image-cbf.c b/libcrystfel/src/image-cbf.c
new file mode 100644
index 00000000..c9de17df
--- /dev/null
+++ b/libcrystfel/src/image-cbf.c
@@ -0,0 +1,634 @@
+/*
+ * image-cbf.c
+ *
+ * Image loading, CBF parts
+ *
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <zlib.h>
+#include <unistd.h>
+
+#include "image.h"
+#include "utils.h"
+#include "detgeom.h"
+
+#include "datatemplate.h"
+#include "datatemplate_priv.h"
+
+static void add_out(float val, float *data_out, int nmemb_out,
+ int *outpos, int *nrej)
+{
+ if ( *outpos < nmemb_out ) {
+ data_out[(*outpos)++] = val;
+ } else {
+ (*nrej)++;
+ }
+}
+
+
+/* Reverses byte offset compression and converts to single precision float.
+ * Note that this compression scheme specifies the data format of the input
+ * data, therefore the X-Binary-Element-Type is completely ignored. */
+static void decode_cbf_byte_offset(float *data_out, int nmemb_out,
+ const int8_t *data_in, const size_t n)
+{
+ int inpos = 0;
+ int outpos = 0;
+ int nrej = 0;
+ float val = 0.0;
+
+ while ( inpos < n ) {
+
+ int64_t delta = data_in[inpos++];
+
+ if ( (delta >= -127) && (delta <= 127) ) {
+ val += delta;
+ add_out(val, data_out, nmemb_out, &outpos, &nrej);
+ continue;
+ }
+
+ delta = *(int16_t *)(data_in+inpos);
+ inpos += 2;
+
+ if ( (delta >= -32767) && (delta <= 32767) ) {
+ val += delta;
+ add_out(val, data_out, nmemb_out, &outpos, &nrej);
+ continue;
+ }
+
+ delta = *(int32_t *)(data_in+inpos);
+ inpos += 4;
+
+ if ( (delta >= -2147483647) && (delta <= 2147483647) ) {
+ val += delta;
+ add_out(val, data_out, nmemb_out, &outpos, &nrej);
+ continue;
+ }
+
+ delta = *(int64_t *)(data_in+inpos);
+ inpos += 8;
+ val += delta;
+ add_out(val, data_out, nmemb_out, &outpos, &nrej);
+
+ }
+
+ if ( nrej > 0 ) {
+ STATUS("%i elements rejected\n", nrej);
+ }
+}
+
+
+static int binary_start(char *data)
+{
+ char *datac = data;
+ if ( (datac[0] == (char)0x0c) && (datac[1] == (char)0x1a)
+ && (datac[2] == (char)0x04) && (datac[3] == (char)0xd5) ) return 1;
+ return 0;
+}
+
+
+enum cbf_data_conversion
+{
+ CBF_NO_CONVERSION,
+ CBF_BYTE_OFFSET,
+ CBF_PACKED,
+ CBF_CANONICAL
+};
+
+enum cbf_data_type
+{
+ CBF_NO_TYPE,
+ CBF_ELEMENT_U8,
+ CBF_ELEMENT_S8,
+ CBF_ELEMENT_U16,
+ CBF_ELEMENT_S16,
+ CBF_ELEMENT_U32,
+ CBF_ELEMENT_S32,
+ CBF_ELEMENT_F32,
+ CBF_ELEMENT_F64,
+};
+
+
+static enum cbf_data_type parse_element_type(const char *t)
+{
+ if ( strstr(t, "signed 8-bit integer") != NULL )
+ {
+ return CBF_ELEMENT_S8;
+ }
+
+ if ( strstr(t, "unsigned 8-bit integer") != NULL )
+ {
+ return CBF_ELEMENT_U8;
+ }
+
+ if ( strstr(t, "signed 16-bit integer") != NULL )
+ {
+ return CBF_ELEMENT_S16;
+ }
+
+ if ( strstr(t, "unsigned 16-bit integer") != NULL )
+ {
+ return CBF_ELEMENT_U16;
+ }
+
+ if ( strstr(t, "signed 32-bit integer") != NULL )
+ {
+ return CBF_ELEMENT_S32;
+ }
+
+ if ( strstr(t, "unsigned 32-bit integer") != NULL )
+ {
+ return CBF_ELEMENT_U32;
+ }
+
+ if ( strstr(t, "signed 32-bit real IEEE") != NULL )
+ {
+ return CBF_ELEMENT_F32;
+ }
+
+ if ( strstr(t, "signed 64-bit real IEEE") != NULL )
+ {
+ return CBF_ELEMENT_F64;
+ }
+
+ /* complex type is unsupported */
+
+ return CBF_NO_TYPE;
+}
+
+
+static size_t element_size(enum cbf_data_type t)
+{
+ switch ( t ) {
+ case CBF_ELEMENT_S8 : return 1;
+ case CBF_ELEMENT_U8 : return 1;
+ case CBF_ELEMENT_S16 : return 2;
+ case CBF_ELEMENT_U16 : return 2;
+ case CBF_ELEMENT_S32 : return 4;
+ case CBF_ELEMENT_U32 : return 4;
+ case CBF_ELEMENT_F32 : return 4;
+ case CBF_ELEMENT_F64 : return 8;
+ default : return 0;
+ }
+}
+
+
+
+static int convert_type(float *data_out, long nmemb_exp,
+ enum cbf_data_type eltype,
+ void *data_in, size_t data_in_len)
+{
+ long int i;
+ long int o = 0;
+ size_t elsize = element_size(eltype);
+
+ if ( elsize == 0 ) return 1;
+
+ if ( nmemb_exp * elsize > data_in_len ) {
+ ERROR("Not enough CBF data for image size/type!\n");
+ return 1;
+ }
+
+ for ( i=0; i<nmemb_exp; i++ ) {
+ switch ( eltype ) {
+
+ case CBF_ELEMENT_S8:
+ data_out[o++] = ((int8_t *)data_in)[i];
+ break;
+
+ case CBF_ELEMENT_U8:
+ data_out[o++] = ((uint8_t *)data_in)[i];
+ break;
+
+ case CBF_ELEMENT_S16:
+ data_out[o++] = ((int16_t *)data_in)[i];
+ break;
+
+ case CBF_ELEMENT_U16:
+ data_out[o++] = ((uint16_t *)data_in)[i];
+ break;
+
+ case CBF_ELEMENT_S32:
+ data_out[o++] = ((int32_t *)data_in)[i];
+ break;
+
+ case CBF_ELEMENT_U32:
+ data_out[o++] = ((uint32_t *)data_in)[i];
+ break;
+
+ case CBF_ELEMENT_F32:
+ data_out[o++] = ((float *)data_in)[i];
+ break;
+
+ case CBF_ELEMENT_F64:
+ data_out[o++] = ((double *)data_in)[i];
+ break;
+
+ case CBF_NO_TYPE:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
+static float *read_cbf_data(const char *filename, int gz, int *w, int *h)
+{
+ FILE *fh;
+ void *buf = NULL;
+ char *rval;
+ size_t data_compressed_len = 0;
+ float *data_out = NULL;
+ enum cbf_data_conversion data_conversion = CBF_NO_CONVERSION;
+ enum cbf_data_type data_type = CBF_ELEMENT_U32; /* ITG (2006) 2.3.3.3 */
+ int in_binary_section = 0;
+
+ *w = 0;
+ *h = 0;
+
+ if ( !gz ) {
+
+ fh = fopen(filename, "rb");
+ if ( fh == NULL ) {
+ ERROR("Failed to open '%s'\n", filename);
+ return NULL;
+ }
+
+ } else {
+
+ gzFile gzfh;
+ size_t len, len_read;
+ const size_t bufinc = 8*1024*1024; /* Allocate buffer in 8Mb chunks */
+ size_t bufsz = bufinc;
+
+ gzfh = gzopen(filename, "rb");
+ if ( gzfh == NULL ) return NULL;
+
+ /* Set larger buffer size for hopefully faster uncompression */
+ gzbuffer(gzfh, 128*1024);
+
+ buf = malloc(bufsz);
+ if ( buf == NULL ) return NULL;
+
+ len = 0;
+ do {
+
+ len_read = gzread(gzfh, buf+len, bufinc);
+ if ( len_read == -1 ) return NULL;
+ len += len_read;
+
+ if ( len_read == bufinc ) {
+ bufsz += bufinc;
+ buf = realloc(buf, bufsz);
+ if ( buf == NULL ) return NULL;
+ }
+
+ } while ( len_read == bufinc );
+
+ fh = fmemopen(buf, len, "rb");
+ if ( fh == NULL ) return NULL;
+
+ gzclose(gzfh);
+
+ }
+
+ /* This is really horrible, but there are at least three different types
+ * of header mingled together (CIF, MIME, DECTRIS), so a real parser
+ * would be very complicated and much more likely to have weird bugs. */
+ do {
+
+ char line[1024];
+ long line_start;
+
+ line_start = ftell(fh);
+ rval = fgets(line, 1023, fh);
+ if ( rval == NULL ) break;
+ chomp(line);
+
+ if ( strcmp(line, "--CIF-BINARY-FORMAT-SECTION--") == 0 ) {
+ in_binary_section = 1;
+ }
+
+ if ( strcmp(line, "--CIF-BINARY-FORMAT-SECTION----") == 0 ) {
+ in_binary_section = 0;
+ }
+
+ if ( in_binary_section ) {
+
+ if ( strncmp(line, "X-Binary-Size: ", 15) == 0 ) {
+ data_compressed_len = atoi(line+15);
+ }
+
+ if ( strncmp(line, "X-Binary-Element-Byte-Order: ", 29) == 0 ) {
+ const char *elbo = line+29;
+ if ( strcmp(elbo, "LITTLE_ENDIAN") != 0 ) {
+ ERROR("Unsupported endianness: %s\n", elbo);
+ free(buf);
+ fclose(fh);
+ return NULL;
+ }
+ }
+
+ /* Try to spot compression algorithm */
+ if ( strstr(line, "conversions=\"x-CBF_BYTE_OFFSET\"") != NULL ) {
+ data_conversion = CBF_BYTE_OFFSET;
+ } else if ( strstr(line, "conversions=\"x-CBF_CANONICAL\"") != NULL ) {
+ data_conversion = CBF_CANONICAL;
+ } else if ( strstr(line, "conversions=\"x-CBF_PACKED\"") != NULL ) {
+ data_conversion = CBF_PACKED;
+ } else if ( strstr(line, "conversions=") != NULL ) {
+ ERROR("Unrecognised CBF content conversion: %s\n", line);
+ free(buf);
+ fclose(fh);
+ return NULL;
+ }
+
+ /* Likewise, element type */
+ if ( strncmp(line, "X-Binary-Element-Type: ", 23) == 0 )
+ {
+ const char *eltype = (line+23);
+ data_type = parse_element_type(eltype);
+ if ( data_type == CBF_NO_TYPE ) {
+ ERROR("Unrecognised element type: %s\n",
+ eltype);
+ free(buf);
+ fclose(fh);
+ return NULL;
+ }
+ }
+
+ if ( strncmp(line, "X-Binary-Size-Fastest-Dimension: ", 33) == 0 ) {
+ *w = atoi(line+33);
+ }
+
+ if ( strncmp(line, "X-Binary-Size-Second-Dimension: ", 32) == 0 ) {
+ *h = atoi(line+32);
+ }
+
+ }
+
+ if ( in_binary_section && binary_start(line) ) {
+
+ size_t len_read;
+ int nmemb_exp;
+ void *data_compressed;
+ int r = 0;
+
+ if ( data_compressed_len == 0 ) {
+ ERROR("Found CBF data before X-Binary-Size!\n");
+ free(buf);
+ fclose(fh);
+ return NULL;
+ }
+
+ if ( (*w == 0) || (*h == 0) ) {
+ ERROR("Found CBF data before dimensions!\n");
+ free(buf);
+ fclose(fh);
+ return NULL;
+ }
+
+ if ( data_compressed_len > 100*1024*1024 ) {
+ ERROR("Stated CBF data size too big\n");
+ free(buf);
+ fclose(fh);
+ return NULL;
+ }
+
+ data_compressed = malloc(data_compressed_len);
+ if ( data_compressed == NULL ) {
+ ERROR("Failed to allocate memory for CBF data\n");
+ free(buf);
+ fclose(fh);
+ return NULL;
+ }
+
+ fseek(fh, line_start+4, SEEK_SET);
+ len_read = fread(data_compressed, 1, data_compressed_len, fh);
+ if ( len_read < data_compressed_len ) {
+ ERROR("Couldn't read entire CBF data\n");
+ free(buf);
+ free(data_compressed);
+ fclose(fh);
+ return NULL;
+ }
+
+ nmemb_exp = (*w) * (*h);
+ data_out = malloc(nmemb_exp*sizeof(float));
+ if ( data_out == NULL ) {
+ ERROR("Failed to allocate memory for CBF data\n");
+ free(buf);
+ free(data_compressed);
+ fclose(fh);
+ return NULL;
+ }
+
+ switch ( data_conversion ) {
+
+ case CBF_NO_CONVERSION:
+ r = convert_type(data_out, nmemb_exp, data_type,
+ data_compressed,
+ data_compressed_len);
+ break;
+
+ case CBF_BYTE_OFFSET:
+ decode_cbf_byte_offset(data_out, nmemb_exp,
+ data_compressed,
+ data_compressed_len);
+ break;
+
+ case CBF_PACKED:
+ case CBF_CANONICAL:
+ ERROR("Don't yet know how to decompress "
+ "CBF_PACKED or CBF_CANONICAL\n");
+ free(buf);
+ free(data_compressed);
+ fclose(fh);
+ return NULL;
+
+ }
+
+ free(data_compressed);
+
+ if ( r ) {
+ free(buf);
+ free(data_out);
+ fclose(fh);
+ return NULL;
+ }
+
+ free(buf);
+ fclose(fh);
+ return data_out;
+
+ }
+
+ } while ( rval != NULL );
+
+ ERROR("Reached end of CBF file before finding data.\n");
+ free(buf); /* might be NULL */
+ return NULL;
+}
+
+
+signed int is_cbf_file(const char *filename)
+{
+ FILE *fh;
+ char line[1024];
+
+ fh = fopen(filename, "r");
+ if ( fh == NULL ) return -1;
+
+ if ( fgets(line, 1024, fh) == NULL ) return 0;
+ fclose(fh);
+
+ if ( strstr(line, "CBF") == NULL ) {
+ return 0;
+ }
+
+ return 1;
+}
+
+
+signed int is_cbfgz_file(const char *filename)
+{
+ gzFile gzfh;
+ char line[1024];
+
+ gzfh = gzopen(filename, "rb");
+ if ( gzfh == NULL ) return -1;
+ if ( gzgets(gzfh, line, 1024) == NULL ) return 0;
+ gzclose(gzfh);
+
+ if ( strstr(line, "CBF") == NULL ) {
+ return 0;
+ }
+
+ return 1;
+}
+
+
+int image_cbf_read_mask(struct panel_template *p,
+ const char *filename, const char *event,
+ int gz, int *bad, int mask_good, int mask_bad)
+{
+ ERROR("Mask loading from CBF not yet supported\n");
+ return 1;
+}
+
+
+static int unpack_panels(struct image *image,
+ const DataTemplate *dtempl,
+ float *data, int data_width, int data_height)
+{
+ int pi;
+
+ image->dp = malloc(dtempl->n_panels * sizeof(float *));
+ if ( image->dp == NULL ) {
+ ERROR("Failed to allocate panels.\n");
+ return 1;
+ }
+
+ for ( pi=0; pi<dtempl->n_panels; pi++ ) {
+
+ struct panel_template *p;
+ int fs, ss;
+ int p_w, p_h;
+
+ p = &dtempl->panels[pi];
+ p_w = p->orig_max_fs - p->orig_min_fs + 1;
+ p_h = p->orig_max_ss - p->orig_min_ss + 1;
+ image->dp[pi] = malloc(p_w*p_h*sizeof(float));
+ if ( image->dp[pi] == NULL ) {
+ ERROR("Failed to allocate panel\n");
+ return 1;
+ }
+
+ if ( (p->orig_min_fs + p_w > data_width)
+ || (p->orig_min_ss + p_h > data_height) )
+ {
+ ERROR("Panel %s is outside range of data in CBF file\n",
+ p->name);
+ return 1;
+ }
+
+ for ( ss=0; ss<p_h; ss++ ) {
+ for ( fs=0; fs<p_w; fs++ ) {
+
+ int idx;
+ int cfs, css;
+
+ cfs = fs+p->orig_min_fs;
+ css = ss+p->orig_min_ss;
+ idx = cfs + css*data_width;
+
+ image->dp[pi][fs+p_w*ss] = data[idx];
+
+ }
+ }
+
+ }
+
+ return 0;
+}
+
+
+int image_cbf_read(struct image *image,
+ const DataTemplate *dtempl,
+ const char *filename,
+ const char *event,
+ int gz)
+{
+ float *data;
+ int w, h;
+
+ if ( access(filename, R_OK) == -1 ) {
+ ERROR("File does not exist or cannot be read: %s\n", filename);
+ return 1;
+ }
+
+ data = read_cbf_data(filename, gz, &w, &h);
+ if ( data == NULL ) {
+ ERROR("Failed to read CBF data\n");
+ return 1;
+ }
+
+ unpack_panels(image, dtempl, data, w, h);
+ free(data);
+
+ //cbf_fill_in_beam_parameters(image->beam, f, image);
+ //cbf_fill_in_clen(image->det, f);
+ //fill_in_adu(image);
+
+ return 0;
+}
diff --git a/libcrystfel/src/image-cbf.h b/libcrystfel/src/image-cbf.h
new file mode 100644
index 00000000..ca79a1a3
--- /dev/null
+++ b/libcrystfel/src/image-cbf.h
@@ -0,0 +1,56 @@
+/*
+ * image-cbf.h
+ *
+ * Image loading, CBF parts
+ *
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/* NB This file is NOT part of the public API, and should NOT
+ * be installed, but rather stays in the libcrystfel source folder. */
+
+#ifndef IMAGE_CBF_H
+#define IMAGE_CBF_H
+
+#include "datatemplate_priv.h"
+
+extern signed int is_cbf_file(const char *filename);
+
+extern signed int is_cbfgz_file(const char *filename);
+
+extern int load_mask_cbf(struct panel_template *p,
+ const char *filename, const char *event,
+ int gz, int *bad, int mask_good, int mask_bad);
+
+extern int image_cbf_read(struct image *image,
+ const DataTemplate *dtempl,
+ const char *filename,
+ const char *event,
+ int gz);
+
+extern int image_cbf_read_mask(struct panel_template *p,
+ const char *filename, const char *event,
+ int gz, int *bad,
+ int mask_good, int mask_bad);
+
+#endif /* IMAGE_CBF_H */
diff --git a/libcrystfel/src/image-hdf5.c b/libcrystfel/src/image-hdf5.c
new file mode 100644
index 00000000..ac987970
--- /dev/null
+++ b/libcrystfel/src/image-hdf5.c
@@ -0,0 +1,2007 @@
+/*
+ * image-hdf5.c
+ *
+ * Image loading, HDF5 parts
+ *
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ * 2014-2018 Valerio Mariani
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <hdf5.h>
+#include <unistd.h>
+
+#include "image.h"
+#include "utils.h"
+#include "detgeom.h"
+
+#include "datatemplate.h"
+#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.
+ *
+ * Not part of public API. Not "static" for testing. */
+char **read_path_parts(const char *ev_orig, int *pn_plvals)
+{
+ char **plvals;
+ char *ev;
+ int n_plvals = 0;
+ char *start;
+
+ plvals = malloc(MAX_PATH_PARTS*sizeof(char *));
+ if ( plvals == NULL ) return NULL;
+
+ if ( ev_orig == NULL ) {
+ /* No ev -> no path parts */
+ *pn_plvals = 0;
+ return plvals;
+ }
+
+ ev = strdup(ev_orig);
+ if ( ev == NULL ) return NULL;
+
+ start = ev;
+ do {
+
+ char *sep;
+
+ sep = strchr(start, '/');
+
+ if ( sep == NULL ) {
+ /* This would be very strange, because it
+ * must at least have // */
+ ERROR("Couldn't read path parts ('%s')\n",
+ start);
+ free(ev);
+ free(plvals);
+ return NULL;
+ }
+
+ /* Remaining string starts with '/' is end condition */
+ if ( sep == start ) break;
+
+ if ( n_plvals == MAX_PATH_PARTS ) {
+ ERROR("Too many path parts: %s\n", ev_orig);
+ free(ev);
+ free(plvals);
+ return NULL;
+ }
+
+ sep[0] = '\0';
+ plvals[n_plvals++] = strdup(start);
+
+ start = sep+1;
+
+ } while ( 1 );
+
+ free(ev);
+ *pn_plvals = n_plvals;
+ return plvals;
+}
+
+
+/* Get the dimension parts of the event ID
+ * e.g. ev_orig = abc/def/ghi//5/2/7
+ * -> [5, 2, 7], with *pn_dvals=3
+ *
+ * Not part of public API. Not "static" for testing. */
+int *read_dim_parts(const char *ev_orig, int *pn_dvals)
+
+{
+ char *ev;
+ int n_dvals = 0;
+ int *dvals;
+ char *start;
+ int done;
+
+ if ( ev_orig == NULL ) ev_orig = "//";
+
+ /* Valid event ID? (Just the part after //, please) */
+ ev = strstr(ev_orig, "//");
+ if ( ev == NULL ) return NULL;
+
+ dvals = malloc(MAX_DIMS*sizeof(int));
+ if ( dvals == NULL ) return NULL;
+
+ if ( ev[2] == '\0' ) {
+ /* No dimension parts - early bailout */
+ *pn_dvals = 0;
+ return dvals; /* NB Not NULL */
+ }
+
+ ev = strdup(ev+2);
+ if ( ev == NULL ) return NULL;
+
+ start = ev;
+ done = 0;
+ do {
+
+ char *sep = strchr(start, '/');
+
+ if ( sep != NULL ) {
+ sep[0] = '\0';
+ } else {
+ done = 1;
+ }
+
+ if ( n_dvals == MAX_PATH_PARTS ) {
+ ERROR("Too many path parts: %s\n", ev_orig);
+ free(ev);
+ free(dvals);
+ return NULL;
+ }
+
+ if ( start[0] == '\0' ) {
+ ERROR("Missing dimension: %s\n", ev_orig);
+ free(ev);
+ free(dvals);
+ return NULL;
+ }
+
+ dvals[n_dvals++] = atoi(start);
+
+ start = sep+1;
+
+ } while ( !done );
+
+ free(ev);
+ *pn_dvals = n_dvals;
+ return dvals;
+}
+
+
+static int imh_num_path_placeholders(const char *pattern)
+{
+ size_t l, i;
+ int n_pl_exp = 0;
+
+ l = strlen(pattern);
+ for ( i=0; i<l; i++ ) {
+ if ( pattern[i] == '%' ) n_pl_exp++;
+ }
+ return n_pl_exp;
+}
+
+
+/* ev = abc/def/ghi//5/2/7
+ * pattern = /data/%/somewhere/%/%/data
+ * output = /data/abc/somewhere/def/ghi/data
+ *
+ * Not part of public API. Not "static" for testing.
+ */
+char *substitute_path(const char *ev, const char *pattern)
+{
+ char **plvals;
+ int n_plvals;
+ int n_pl_exp;
+ size_t total_len;
+ int i;
+ char *subs;
+ const char *start;
+ const char *pl_pos;
+
+ if ( pattern == NULL ) {
+ ERROR("Pattern cannot be NULL\n");
+ return NULL;
+ }
+
+ plvals = read_path_parts(ev, &n_plvals);
+ if ( plvals == NULL ) return NULL;
+
+ n_pl_exp = imh_num_path_placeholders(pattern);
+
+ if ( n_plvals != n_pl_exp ) {
+ ERROR("Wrong number of path placeholders: "
+ "'%s' (%i) into '%s' (%i)\n",
+ ev, n_plvals, pattern, n_pl_exp);
+ return NULL;
+ }
+
+ if ( n_pl_exp == 0 ) {
+ /* No placeholders in path */
+ for ( i=0; i<n_plvals; i++ ) {
+ free(plvals[i]);
+ }
+ free(plvals);
+ return strdup(pattern);
+ }
+
+ total_len = strlen(pattern) - n_pl_exp;
+ for ( i=0; i<n_plvals; i++ ) {
+ total_len += strlen(plvals[i]);
+ }
+ subs = malloc(total_len+1);
+ if ( subs == NULL ) {
+ free(plvals);
+ return NULL;
+ }
+
+ pl_pos = strchr(pattern, '%');
+ if ( pl_pos == NULL ) {
+ ERROR("Expected a placeholder char (%): '%s'\n",
+ pattern);
+ return NULL;
+ }
+ strncpy(subs, pattern, pl_pos-pattern);
+ subs[pl_pos-pattern] = '\0';
+
+ start = pl_pos+1;
+ for ( i=0; i<n_plvals; i++ ) {
+
+ /* Add the placeholder's value */
+ strcat(subs, plvals[i]);
+ free(plvals[i]);
+
+ /* Add the chars up to the next placeholder... */
+ pl_pos = strchr(start, '%');
+ if ( pl_pos == NULL ) {
+ /* ... or the end */
+ pl_pos = start+strlen(start);
+ }
+ strncat(subs, start, pl_pos-start);
+ start = pl_pos+1;
+ }
+
+ free(plvals);
+
+ return subs;
+}
+
+
+static void make_placeholder_skip(signed int *dt_dims,
+ signed int *panel_dims)
+{
+ int i;
+ int n_dt = 0;
+ for ( i=0; i<MAX_DIMS; i++ ) {
+ if ( panel_dims[i] != DIM_PLACEHOLDER ) {
+ dt_dims[n_dt++] = panel_dims[i];
+ }
+ }
+}
+
+
+static int imh_num_placeholders(const struct panel_template *p)
+{
+ int i;
+ int n_pl = 0;
+ for ( i=0; i<MAX_DIMS; i++ ) {
+ if ( p->dims[i] == DIM_PLACEHOLDER ) n_pl++;
+ }
+ return n_pl;
+}
+
+
+static int total_dimensions(const struct panel_template *p)
+{
+ int i;
+ int n_dim = 0;
+ for ( i=0; i<MAX_DIMS; i++ ) {
+ if ( p->dims[i] != DIM_UNDEFINED ) n_dim++;
+ }
+ return n_dim;
+}
+
+
+static int load_hdf5_hyperslab(struct panel_template *p,
+ const char *filename,
+ const char *event,
+ void **pdata,
+ hid_t el_type, size_t el_size,
+ int skip_placeholders_ok,
+ const char *path_spec)
+{
+ hid_t fh;
+ int total_dt_dims;
+ int plh_dt_dims;
+ int dt_dims[MAX_DIMS];
+ int n_dt_dims;
+ herr_t r;
+ hsize_t *f_offset, *f_count;
+ hid_t dh;
+ herr_t check;
+ hid_t dataspace, memspace;
+ hsize_t dims[2];
+ char *panel_full_path;
+ void *data;
+ int ndims;
+ int dim;
+ int *dim_vals;
+ int n_dim_vals;
+ int pl_pos;
+
+ if ( access(filename, R_OK) == -1 ) {
+ ERROR("File does not exist or cannot be read: %s\n",
+ filename);
+ return 1;
+ }
+
+ fh = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT);
+ if ( fh < 0 ) {
+ ERROR("Couldn't open file: %s\n", filename);
+ return 1;
+ }
+
+ panel_full_path = substitute_path(event, path_spec);
+ if ( panel_full_path == NULL ) {
+ ERROR("Invalid path substitution: '%s' '%s'\n",
+ event, path_spec);
+ close_hdf5(fh);
+ return 1;
+ }
+
+ dh = H5Dopen2(fh, panel_full_path, H5P_DEFAULT);
+ if ( dh < 0 ) {
+ ERROR("Cannot open data for panel %s (%s) in file %s\n",
+ p->name, panel_full_path, filename);
+ free(panel_full_path);
+ close_hdf5(fh);
+ return 1;
+ }
+
+ free(panel_full_path);
+
+ /* Set up dataspace for file
+ * (determine where to read the data from) */
+ dataspace = H5Dget_space(dh);
+ ndims = H5Sget_simple_extent_ndims(dataspace);
+ if ( ndims < 0 ) {
+ ERROR("Failed to get number of dimensions for panel %s\n",
+ p->name);
+ close_hdf5(fh);
+ return 1;
+ }
+
+ /* Does the array have the expected number of dimensions? */
+ total_dt_dims = total_dimensions(p);
+ plh_dt_dims = imh_num_placeholders(p);
+ if ( ndims != total_dt_dims ) {
+ /* If the dimensions match after excluding
+ * placeholders, it's OK - probably a static mask
+ * in a multi-event file. */
+ if ( skip_placeholders_ok
+ && (ndims == total_dt_dims - plh_dt_dims) )
+ {
+ make_placeholder_skip(dt_dims, p->dims);
+ n_dt_dims = total_dt_dims - plh_dt_dims;
+ } else {
+ ERROR("Unexpected number of dimensions for "
+ "panel %s (%i, but expected %i or %i)\n",
+ p->name, ndims, total_dt_dims,
+ total_dt_dims - plh_dt_dims);
+ close_hdf5(fh);
+ return 1;
+ }
+ } else {
+ int i;
+ for ( i=0; i<MAX_DIMS; i++ ) {
+ dt_dims[i] = p->dims[i];
+ }
+ n_dt_dims = total_dt_dims;
+ }
+
+ f_offset = malloc(ndims*sizeof(hsize_t));
+ f_count = malloc(ndims*sizeof(hsize_t));
+ if ( (f_offset == NULL) || (f_count == NULL ) ) {
+ ERROR("Failed to allocate offset or count.\n");
+ close_hdf5(fh);
+ return 1;
+ }
+
+ /* Get those placeholder values from the event ID */
+ dim_vals = read_dim_parts(event, &n_dim_vals);
+
+ pl_pos = 0;
+ for ( dim=0; dim<n_dt_dims; dim++ ) {
+
+ switch ( dt_dims[dim] ) {
+
+ case DIM_FS:
+ f_offset[dim] = p->orig_min_fs;
+ f_count[dim] = p->orig_max_fs - p->orig_min_fs+1;
+ break;
+
+ case DIM_SS:
+ f_offset[dim] = p->orig_min_ss;
+ f_count[dim] = p->orig_max_ss - p->orig_min_ss+1;
+ break;
+
+ case DIM_PLACEHOLDER:
+ f_offset[dim] = dim_vals[pl_pos++];
+ f_count[dim] = 1;
+ break;
+
+ case DIM_UNDEFINED:
+ ERROR("Undefined dimension found!\n");
+ break;
+
+ default:
+ /* Fixed value */
+ f_offset[dim] = dt_dims[dim];
+ f_count[dim] = 1;
+ break;
+
+ }
+ }
+
+ free(dim_vals);
+
+ check = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET,
+ f_offset, NULL, f_count, NULL);
+ if ( check < 0 ) {
+ ERROR("Error selecting file dataspace for panel %s\n",
+ p->name);
+ free(f_offset);
+ free(f_count);
+ close_hdf5(fh);
+ return 1;
+ }
+
+ dims[0] = p->orig_max_ss - p->orig_min_ss + 1;
+ dims[1] = p->orig_max_fs - p->orig_min_fs + 1;
+ memspace = H5Screate_simple(2, dims, NULL);
+
+ data = malloc(dims[0]*dims[1]*el_size);
+ if ( data == NULL ) {
+ ERROR("Failed to allocate panel %s\n", p->name);
+ free(f_offset);
+ free(f_count);
+ close_hdf5(fh);
+ return 1;
+ }
+
+ r = H5Dread(dh, el_type, memspace, dataspace,
+ H5P_DEFAULT, data);
+ if ( r < 0 ) {
+ ERROR("Couldn't read data for panel %s\n",
+ p->name);
+ free(f_offset);
+ free(f_count);
+ free(data);
+ close_hdf5(fh);
+ return 1;
+ }
+
+ free(f_offset);
+ free(f_count);
+ close_hdf5(fh);
+
+ *pdata = data;
+ return 0;
+}
+
+
+int image_hdf5_read(struct image *image,
+ const DataTemplate *dtempl,
+ const char *filename,
+ const char *event)
+{
+ int i;
+
+ image->dp = malloc(dtempl->n_panels*sizeof(float *));
+ if ( image->dp == NULL ) {
+ ERROR("Failed to allocate data array.\n");
+ return 1;
+ }
+
+ if ( event == NULL ) {
+ event = "//";
+ }
+
+ /* Set all pointers to NULL for easier clean-up */
+ for ( i=0; i<dtempl->n_panels; i++ ) image->dp[i] = NULL;
+
+ for ( i=0; i<dtempl->n_panels; i++ ) {
+ if ( load_hdf5_hyperslab(&dtempl->panels[i], filename,
+ event, (void *)&image->dp[i],
+ H5T_NATIVE_FLOAT,
+ sizeof(float), 0,
+ dtempl->panels[i].data) )
+ {
+ ERROR("Failed to load panel data\n");
+ return 1;
+ }
+ }
+
+ image->filename = strdup(filename);
+ image->ev = safe_strdup(event);
+
+ return 0;
+}
+
+
+int image_hdf5_read_mask(struct panel_template *p,
+ const char *filename, const char *event,
+ int *bad, const char *mask_location,
+ int mask_good, int mask_bad)
+{
+ int p_w, p_h;
+ int *mask = NULL;
+ long unsigned int j;
+
+ p_w = p->orig_max_fs - p->orig_min_fs + 1;
+ p_h = p->orig_max_ss - p->orig_min_ss + 1;
+
+ if ( load_hdf5_hyperslab(p, filename, event,
+ (void *)&mask, H5T_NATIVE_INT,
+ sizeof(int), 1, mask_location) )
+ {
+ ERROR("Failed to load mask data\n");
+ free(mask);
+ return 1;
+ }
+
+ for ( j=0; j<p_w*p_h; j++ ) {
+
+ /* Bad if it's missing any of the "good" bits */
+ if ( (mask[j] & mask_good) != mask_good ) bad[j] = 1;
+
+ /* Bad if it has any of the "bad" bits. */
+ if ( mask[j] & mask_bad ) bad[j] = 1;
+
+ }
+
+ free(mask);
+ return 0;
+}
+
+
+double image_hdf5_get_value(const char *name, const char *filename,
+ const char *event)
+{
+ hid_t dh;
+ hid_t type;
+ hid_t class;
+ hid_t sh;
+ hid_t ms;
+ hsize_t *f_offset = NULL;
+ hsize_t *f_count = NULL;
+ hsize_t m_offset[1];
+ hsize_t m_count[1];
+ hsize_t msdims[1];
+ hsize_t size[64];
+ herr_t r;
+ herr_t check;
+ int ndims;
+ int i;
+ char *subst_name = NULL;
+ hid_t fh;
+ double val;
+ int *dim_vals;
+ int n_dim_vals;
+ int dim_val_pos;
+
+ if ( access(filename, R_OK) == -1 ) {
+ ERROR("File does not exist or cannot be read: %s\n", filename);
+ return NAN;
+ }
+
+ fh = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT);
+ if ( fh < 0 ) {
+ ERROR("Couldn't open file: %s\n", filename);
+ return NAN;
+ }
+
+ subst_name = substitute_path(event, name);
+ if ( subst_name == NULL ) {
+ ERROR("Invalid event ID '%s'\n", event);
+ close_hdf5(fh);
+ return NAN;
+ }
+
+ dh = H5Dopen2(fh, subst_name, H5P_DEFAULT);
+ if ( dh < 0 ) {
+ ERROR("No such numeric field '%s'\n", subst_name);
+ close_hdf5(fh);
+ return NAN;
+ }
+
+ type = H5Dget_type(dh);
+ class = H5Tget_class(type);
+
+ if ( (class != H5T_FLOAT) && (class != H5T_INTEGER) ) {
+ ERROR("Not a floating point or integer value.\n");
+ close_hdf5(fh);
+ return NAN;
+ }
+
+ /* Get the dimensionality. We have to cope with scalars expressed as
+ * arrays with all dimensions 1, as well as zero-d arrays. */
+ sh = H5Dget_space(dh);
+ ndims = H5Sget_simple_extent_ndims(sh);
+ if ( ndims > 64 ) {
+ ERROR("Too many dimensions for numeric value\n");
+ close_hdf5(fh);
+ return NAN;
+ }
+ H5Sget_simple_extent_dims(sh, size, NULL);
+
+ /* We want to read the value as a scalar */
+ m_offset[0] = 0;
+ m_count[0] = 1;
+ msdims[0] = 1;
+ ms = H5Screate_simple(1, msdims, NULL);
+
+ if ( ndims == 0 ) {
+ /* Easy case, because value is a scalar */
+ r = H5Dread(dh, H5T_NATIVE_DOUBLE, ms, sh, H5P_DEFAULT, &val);
+ if ( r < 0 ) {
+ ERROR("Couldn't read scalar value from %s.\n",
+ subst_name);
+ free(subst_name);
+ close_hdf5(fh);
+ return NAN;
+ }
+ return val;
+ }
+
+ dim_vals = read_dim_parts(event, &n_dim_vals);
+ if ( dim_vals == NULL ) {
+ ERROR("Couldn't parse event '%s'\n");
+ close_hdf5(fh);
+ return NAN;
+ }
+
+ f_offset = malloc(ndims*sizeof(hsize_t));
+ f_count = malloc(ndims*sizeof(hsize_t));
+ if ( (f_offset == NULL) || (f_count == NULL) ) {
+ ERROR("Couldn't allocate dimension arrays\n");
+ close_hdf5(fh);
+ return NAN;
+ }
+
+ /* Every dimension of the dataset must either be size 1 or
+ * large enough to contain the next value from the event ID */
+ dim_val_pos = 0;
+ for ( i=0; i<ndims; i++ ) {
+
+ if ( size[i] != 1 ) {
+
+ if ( size[i] <= dim_vals[dim_val_pos] ) {
+ ERROR("Array of scalar values is too "
+ "small (%s, dim %i, ev value %i,"
+ " size %i)\n",
+ subst_name, i,
+ dim_vals[dim_val_pos], size[i]);
+ close_hdf5(fh);
+ return NAN;
+ }
+
+ f_offset[i] = dim_vals[dim_val_pos];
+ f_count[i] = 1;
+ dim_val_pos++;
+
+ } else {
+
+ f_offset[i] = 0;
+ f_count[i] = 1;
+
+ }
+
+ }
+
+ check = H5Sselect_hyperslab(sh, H5S_SELECT_SET,
+ f_offset, NULL, f_count, NULL);
+ if ( check <0 ) {
+ ERROR("Error selecting dataspace for float value\n");
+ free(f_offset);
+ free(f_count);
+ close_hdf5(fh);
+ return NAN;
+ }
+
+ ms = H5Screate_simple(1,msdims,NULL);
+ check = H5Sselect_hyperslab(ms, H5S_SELECT_SET,
+ m_offset, NULL, m_count, NULL);
+ if ( check < 0 ) {
+ ERROR("Error selecting memory dataspace for float value\n");
+ free(f_offset);
+ free(f_count);
+ close_hdf5(fh);
+ return NAN;
+ }
+
+ r = H5Dread(dh, H5T_NATIVE_DOUBLE, ms, sh, H5P_DEFAULT, &val);
+ if ( r < 0 ) {
+ ERROR("Couldn't read value.\n");
+ close_hdf5(fh);
+ return NAN;
+ }
+
+ free(f_offset);
+ free(f_count);
+ free(subst_name);
+ close_hdf5(fh);
+
+ return val;
+}
+
+
+static int read_peak_count(hid_t fh, char *path, int line,
+ int *num_peaks)
+{
+
+ hid_t dh, sh, mh;
+ hsize_t size[1];
+ hsize_t max_size[1];
+ hsize_t offset[1], count[1];
+ hsize_t m_offset[1], m_count[1], dimmh[1];
+ int tw, r;
+
+ dh = H5Dopen2(fh, path, H5P_DEFAULT);
+ if ( dh < 0 ) {
+ ERROR("Data block %s not found.\n", path);
+ return 1;
+ }
+
+ sh = H5Dget_space(dh);
+ if ( sh < 0 ) {
+ H5Dclose(dh);
+ ERROR("Couldn't get dataspace for data.\n");
+ return 1;
+ }
+
+ if ( H5Sget_simple_extent_ndims(sh) != 1 ) {
+ ERROR("Data block %s has the wrong dimensionality (%i).\n",
+ path, H5Sget_simple_extent_ndims(sh));
+ H5Sclose(sh);
+ H5Dclose(dh);
+ return 1;
+ }
+
+ H5Sget_simple_extent_dims(sh, size, max_size);
+
+ tw = size[0];
+
+ if ( line > tw-1 ) {
+ H5Sclose(sh);
+ H5Dclose(dh);
+ ERROR("Data block %s does not contain data for required event.\n",
+ path);
+ return 1;
+ }
+
+ offset[0] = line;
+ count[0] = 1;
+
+ r = H5Sselect_hyperslab(sh, H5S_SELECT_SET,
+ offset, NULL, count, NULL);
+ if ( r < 0 ) {
+ ERROR("Error selecting file dataspace "
+ "for data block %s\n", path);
+ H5Dclose(dh);
+ H5Sclose(sh);
+ return 1;
+ }
+
+ m_offset[0] = 0;
+ m_count[0] = 1;
+ dimmh[0] = 1;
+ mh = H5Screate_simple(1, dimmh, NULL);
+ r = H5Sselect_hyperslab(mh, H5S_SELECT_SET,
+ m_offset, NULL, m_count, NULL);
+ if ( r < 0 ) {
+ ERROR("Error selecting memory dataspace "
+ "for data block %s\n", path);
+ H5Dclose(dh);
+ H5Sclose(sh);
+ H5Sclose(mh);
+ return 1;
+ }
+
+ r = H5Dread(dh, H5T_NATIVE_INT, mh,
+ sh, H5P_DEFAULT, num_peaks);
+ if ( r < 0 ) {
+ ERROR("Couldn't read data for block %s, line %i\n", path, line);
+ H5Dclose(dh);
+ H5Sclose(sh);
+ H5Sclose(mh);
+ return 1;
+ }
+
+ H5Dclose(dh);
+ H5Sclose(sh);
+ H5Sclose(mh);
+ return 0;
+}
+
+
+static float *read_peak_line(hid_t fh, char *path, int line)
+{
+
+ hid_t dh, sh, mh;
+ hsize_t size[2];
+ hsize_t max_size[2];
+ hsize_t offset[2], count[2];
+ hsize_t m_offset[2], m_count[2], dimmh[2];
+ float *buf;
+ int tw, r;
+
+ dh = H5Dopen2(fh, path, H5P_DEFAULT);
+ if ( dh < 0 ) {
+ ERROR("Data block (%s) not found.\n", path);
+ return NULL;
+ }
+
+ sh = H5Dget_space(dh);
+ if ( sh < 0 ) {
+ H5Dclose(dh);
+ ERROR("Couldn't get dataspace for data.\n");
+ return NULL;
+ }
+
+ if ( H5Sget_simple_extent_ndims(sh) != 2 ) {
+ ERROR("Data block %s has the wrong dimensionality (%i).\n",
+ path, H5Sget_simple_extent_ndims(sh));
+ H5Sclose(sh);
+ H5Dclose(dh);
+ return NULL;
+ }
+
+ H5Sget_simple_extent_dims(sh, size, max_size);
+
+ tw = size[0];
+ if ( line> tw-1 ) {
+ H5Sclose(sh);
+ H5Dclose(dh);
+ ERROR("Data block %s does not contain data for required event.\n",
+ path);
+ return NULL;
+ }
+
+ offset[0] = line;
+ offset[1] = 0;
+ count[0] = 1;
+ count[1] = size[1];
+
+ r = H5Sselect_hyperslab(sh, H5S_SELECT_SET, offset, NULL, count, NULL);
+ if ( r < 0 ) {
+ ERROR("Error selecting file dataspace "
+ "for data block %s\n", path);
+ H5Dclose(dh);
+ H5Sclose(sh);
+ return NULL;
+ }
+
+ m_offset[0] = 0;
+ m_offset[1] = 0;
+ m_count[0] = 1;
+ m_count[1] = size[1];
+ dimmh[0] = 1;
+ dimmh[1] = size[1];
+
+ mh = H5Screate_simple(2, dimmh, NULL);
+ r = H5Sselect_hyperslab(mh, H5S_SELECT_SET,
+ m_offset, NULL, m_count, NULL);
+ if ( r < 0 ) {
+ ERROR("Error selecting memory dataspace "
+ "for data block %s\n", path);
+ H5Dclose(dh);
+ H5Sclose(sh);
+ H5Sclose(mh);
+ return NULL;
+ }
+
+ buf = malloc(size[1]*sizeof(float));
+ if ( buf == NULL ) return NULL;
+ r = H5Dread(dh, H5T_NATIVE_FLOAT, mh, sh, H5P_DEFAULT, buf);
+ if ( r < 0 ) {
+ ERROR("Couldn't read data for block %s, line %i\n", path, line);
+ H5Dclose(dh);
+ H5Sclose(sh);
+ H5Sclose(mh);
+ return NULL;
+ }
+
+ H5Dclose(dh);
+ H5Sclose(sh);
+ H5Sclose(mh);
+ return buf;
+}
+
+
+ImageFeatureList *image_hdf5_read_peaks_cxi(const DataTemplate *dtempl,
+ const char *filename,
+ const char *event,
+ int half_pixel_shift)
+{
+ ImageFeatureList *features;
+ hid_t fh;
+ char path_n[1024];
+ char path_x[1024];
+ char path_y[1024];
+ char path_i[1024];
+ int r;
+ int pk;
+ char *subst_name;
+ int line;
+ int num_peaks;
+ float *buf_x;
+ float *buf_y;
+ float *buf_i;
+ int *dim_vals;
+ int n_dim_vals;
+
+ double peak_offset = half_pixel_shift ? 0.5 : 0.0;
+
+ if ( access(filename, R_OK) == -1 ) {
+ ERROR("File does not exist or cannot be read: %s\n",
+ filename);
+ return NULL;
+ }
+
+ subst_name = substitute_path(event, dtempl->peak_list);
+ if ( subst_name == NULL ) {
+ ERROR("Invalid peak path %s\n", subst_name);
+ return NULL;
+ }
+
+ dim_vals = read_dim_parts(event, &n_dim_vals);
+ if ( dim_vals == NULL ) {
+ ERROR("Couldn't parse event '%s'\n");
+ return NULL;
+ }
+
+ if ( n_dim_vals < 1 ) {
+ ERROR("Not enough dimensions in event ID to use CXI "
+ "peak lists (%i)\n", n_dim_vals);
+ return NULL;
+ }
+
+ line = dim_vals[0];
+ free(dim_vals);
+
+ snprintf(path_n, 1024, "%s/nPeaks", subst_name);
+ snprintf(path_x, 1024, "%s/peakXPosRaw", subst_name);
+ snprintf(path_y, 1024, "%s/peakYPosRaw", subst_name);
+ snprintf(path_i, 1024, "%s/peakTotalIntensity", subst_name);
+
+ fh = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT);
+ if ( fh < 0 ) {
+ ERROR("Couldn't open file: %s\n", filename);
+ return NULL;
+ }
+
+ r = read_peak_count(fh, path_n, line, &num_peaks);
+ if ( r != 0 ) {
+ close_hdf5(fh);
+ return NULL;
+ }
+
+ buf_x = read_peak_line(fh, path_x, line);
+ if ( r != 0 ) {
+ close_hdf5(fh);
+ return NULL;
+ }
+
+ buf_y = read_peak_line(fh, path_y, line);
+ if ( r != 0 ) {
+ close_hdf5(fh);
+ return NULL;
+ }
+
+ buf_i = read_peak_line(fh, path_i, line);
+ if ( r != 0 ) {
+ close_hdf5(fh);
+ return NULL;
+ }
+
+ features = image_feature_list_new();
+
+ for ( pk=0; pk<num_peaks; pk++ ) {
+
+ float fs, ss, val;
+ int pn;
+
+ fs = buf_x[pk] + peak_offset;
+ ss = buf_y[pk] + peak_offset;
+ val = buf_i[pk];
+
+ if ( data_template_file_to_panel_coords(dtempl,
+ &fs, &ss,
+ &pn) )
+ {
+ ERROR("Failed to convert %i,%i to "
+ "panel-relative coordinates\n", fs, ss);
+ } else {
+ image_add_feature(features, fs, ss, pn,
+ NULL, val, NULL);
+ }
+
+ }
+
+ close_hdf5(fh);
+
+ return features;
+}
+
+
+ImageFeatureList *image_hdf5_read_peaks_hdf5(const DataTemplate *dtempl,
+ const char *filename,
+ const char *event,
+ int half_pixel_shift)
+{
+ hid_t fh, dh, sh;
+ hsize_t size[2];
+ hsize_t max_size[2];
+ int i;
+ float *buf;
+ herr_t r;
+ int tw;
+ char *subst_name;
+ ImageFeatureList *features;
+ double peak_offset = half_pixel_shift ? 0.5 : 0.0;
+
+ if ( dtempl->peak_list == NULL ) {
+ ERROR("Peak location is not given in geometry file.\n");
+ return NULL;
+ }
+
+ if ( access(filename, R_OK) == -1 ) {
+ ERROR("File does not exist or cannot be read: %s\n",
+ filename);
+ return NULL;
+ }
+
+ fh = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT);
+ if ( fh < 0 ) {
+ ERROR("Couldn't open file: %s\n", filename);
+ return NULL;
+ }
+
+ subst_name = substitute_path(event, dtempl->peak_list);
+ if ( subst_name == NULL ) {
+ ERROR("Invalid peak path: '%s' '%s'\n",
+ event, dtempl->peak_list);
+ close_hdf5(fh);
+ return NULL;
+ }
+
+ dh = H5Dopen2(fh, subst_name, H5P_DEFAULT);
+ if ( dh < 0 ) {
+ ERROR("Peak list (%s) not found.\n", subst_name);
+ free(subst_name);
+ close_hdf5(fh);
+ return NULL;
+ }
+ free(subst_name);
+
+ sh = H5Dget_space(dh);
+ if ( sh < 0 ) {
+ ERROR("Couldn't get dataspace for peak list.\n");
+ close_hdf5(fh);
+ return NULL;
+ }
+
+ if ( H5Sget_simple_extent_ndims(sh) != 2 ) {
+ ERROR("Peak list has the wrong dimensionality (%i).\n",
+ H5Sget_simple_extent_ndims(sh));
+ close_hdf5(fh);
+ return NULL;
+ }
+
+ H5Sget_simple_extent_dims(sh, size, max_size);
+ H5Sclose(sh);
+
+ tw = size[1];
+ if ( (tw != 3) && (tw != 4) ) {
+ ERROR("Peak list has the wrong dimensions.\n");
+ close_hdf5(fh);
+ return NULL;
+ }
+
+ buf = malloc(sizeof(float)*size[0]*size[1]);
+ if ( buf == NULL ) {
+ ERROR("Couldn't reserve memory for the peak list.\n");
+ close_hdf5(fh);
+ return NULL;
+ }
+ r = H5Dread(dh, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL,
+ H5P_DEFAULT, buf);
+ if ( r < 0 ) {
+ ERROR("Couldn't read peak list.\n");
+ close_hdf5(fh);
+ return NULL;
+ }
+
+ features = image_feature_list_new();
+ if ( features == NULL ) {
+ ERROR("Failed to allocate peak list\n");
+ close_hdf5(fh);
+ return NULL;
+ }
+
+ for ( i=0; i<size[0]; i++ ) {
+
+ float fs, ss, val;
+ int pn;
+
+ fs = buf[tw*i+0] + peak_offset;
+ ss = buf[tw*i+1] + peak_offset;
+ val = buf[tw*i+2];
+
+ if ( data_template_file_to_panel_coords(dtempl,
+ &fs, &ss,
+ &pn) )
+ {
+ ERROR("Failed to convert %i,%i to "
+ "panel-relative coordinates\n", fs, ss);
+ } else {
+ image_add_feature(features, fs, ss, pn,
+ NULL, val, NULL);
+ }
+
+ }
+
+ free(buf);
+ close_hdf5(fh);
+
+ return features;
+}
+
+
+/* This could be extended, later, to include patterns other than just
+ * a literal string (no placeholders) and just %. However, pattern
+ * matching is in general not that easy. */
+static char *matches_pattern(const char *name, const char *pattern,
+ const char *ev_str_old)
+{
+ if ( strcmp(pattern, "%") == 0 ) {
+ char *nstr = malloc(strlen(ev_str_old)+strlen(name)+2);
+ if ( nstr == NULL ) {
+ ERROR("Couldn't allocate memory\n");
+ return NULL;
+ }
+ strcpy(nstr, ev_str_old);
+ strcat(nstr, "/");
+ strcat(nstr, name);
+ return nstr;
+ } else {
+ if ( strcmp(name, pattern) == 0 ) {
+ return strdup(ev_str_old);
+ } else {
+ return NULL;
+ }
+ }
+}
+
+
+/* Private structure, just to avoid passing char *** around */
+struct ev_list
+{
+ char **events;
+ int n_events;
+ int max_events;
+};
+
+
+static int add_ev_to_list(struct ev_list *list, char *ev_str)
+{
+ if ( list->n_events == list->max_events ) {
+ char **new_events = realloc(list->events,
+ (list->max_events+128)*sizeof(char *));
+ if ( new_events == NULL ) return 1;
+ list->max_events += 128;
+ list->events = new_events;
+ }
+
+ list->events[list->n_events++] = strdup(ev_str);
+
+ return 0;
+}
+
+
+static char *demunge_event(const char *orig)
+{
+ size_t len = strlen(orig);
+ char *slash;
+
+ if ( len == 0 ) return strdup("//");
+
+ slash = malloc(len+3);
+ if ( slash == NULL ) return NULL;
+ strcpy(slash, orig+1);
+ strcat(slash, "//");
+ return slash;
+}
+
+
+static int rec_expand_paths(hid_t gh, struct ev_list *list,
+ const char *ev_str,
+ char **pattern_bits, int n_pattern_bits)
+{
+ int i;
+ H5G_info_t group_info;
+
+ if ( H5Gget_info(gh, &group_info) < 0 ) {
+ ERROR("Couldn't get group info\n");
+ return 1;
+ }
+
+ for ( i=0; i<group_info.nlinks; i++ ) {
+
+ ssize_t size;
+ char *name;
+ H5O_info_t obj_info;
+ char *ev_str_new;
+
+ size = H5Lget_name_by_idx(gh, ".", H5_INDEX_NAME,
+ H5_ITER_INC, i, NULL, 0,
+ H5P_DEFAULT);
+ if ( (size < 0) || (size > 20000) ) {
+ ERROR("Couldn't get link name\n");
+ return 1;
+ }
+
+ name = malloc(size+1);
+ if ( name == NULL ) {
+ ERROR("Couldn't allocate memory\n");
+ return 1;
+ }
+
+ if ( H5Lget_name_by_idx(gh, ".", H5_INDEX_NAME,
+ H5_ITER_INC, i, name, size+1,
+ H5P_DEFAULT) < 0 )
+ {
+ ERROR("Couldn't get name\n");
+ return 1;
+ }
+
+ ev_str_new = matches_pattern(name, pattern_bits[0],
+ ev_str);
+ if ( ev_str_new == NULL ) {
+ free(name);
+ continue;
+ }
+
+ if ( H5Oget_info_by_idx(gh, ".", H5_INDEX_NAME,
+ H5_ITER_INC, i, &obj_info, 0) < 0 )
+ {
+ ERROR("Couldn't get info\n");
+ free(name);
+ free(ev_str_new);
+ return 1;
+ }
+
+ if ( obj_info.type == H5O_TYPE_GROUP ) {
+
+ hid_t child_gh;
+
+ if ( n_pattern_bits == 1 ) {
+ ERROR("Pattern doesn't match file"
+ " (too short)\n");
+ free(name);
+ free(ev_str_new);
+ return 1;
+ }
+
+ child_gh = H5Gopen1(gh, name);
+ if ( child_gh < 0 ) {
+ ERROR("Couldn't open '%s'\n", name);
+ free(name);
+ free(ev_str_new);
+ return 1;
+ }
+
+ if ( rec_expand_paths(child_gh, list,
+ ev_str_new,
+ &pattern_bits[1],
+ n_pattern_bits - 1) )
+ {
+ free(name);
+ free(ev_str_new);
+ return 1;
+ }
+
+ free(ev_str_new);
+ H5Gclose(child_gh);
+
+ } else if ( obj_info.type == H5O_TYPE_DATASET ) {
+
+ char *addme;
+
+ if ( n_pattern_bits != 1 ) {
+ ERROR("Pattern doesn't match file"
+ " (too long by %i)\n",
+ n_pattern_bits);
+ free(name);
+ free(ev_str_new);
+ return 1;
+ }
+
+ addme = demunge_event(ev_str_new);
+ if ( addme != NULL ) {
+ add_ev_to_list(list, addme);
+ free(addme);
+ }
+ free(ev_str_new);
+
+ }
+
+ free(name);
+
+ }
+
+ return 0;
+}
+
+
+/* Not "static" so that ev_enumX can test it.
+ * Not part of public API! */
+char **expand_paths(hid_t fh, char *pattern, int *n_evs)
+{
+ int n_sep;
+ size_t len;
+ char **pattern_bits;
+ struct ev_list list;
+ int i;
+ char *start;
+
+ if ( pattern == NULL ) return NULL;
+ if ( pattern[0] != '/' ) return NULL;
+
+ /* Chop up the pattern into path bits */
+ len = strlen(pattern);
+ n_sep = 0;
+ for ( i=0; i<len; i++ ) {
+ if ( pattern[i] == '/' ) n_sep++;
+ }
+
+ pattern_bits = malloc(n_sep*sizeof(char *));
+ if ( pattern_bits == NULL ) return NULL;
+
+ start = pattern+1;
+ for ( i=0; i<n_sep; i++ ) {
+ char *sep = strchr(start, '/');
+ if ( sep == NULL ) {
+ sep = start+strlen(start);
+ }
+ pattern_bits[i] = strndup(start, sep-start);
+ if ( pattern_bits[i] == NULL ) return NULL;
+ start = sep+1;
+ }
+
+ list.n_events = 0;
+ list.max_events = 0;
+ list.events = NULL;
+
+ rec_expand_paths(fh, &list, "", pattern_bits, n_sep);
+
+ for ( i=0; i<n_sep; i++ ) {
+ free(pattern_bits[i]);
+ }
+ free(pattern_bits);
+
+ *n_evs = list.n_events;
+ return list.events;
+}
+
+
+static int rec_expand_dims(struct ev_list *list,
+ int *placeholder_sizes,
+ int n_placeholder_dims,
+ char *path_ev)
+{
+ int i;
+ char *dim_ev;
+ size_t len;
+
+ len = strlen(path_ev);
+ dim_ev = malloc(len+16);
+ if ( dim_ev == NULL ) return 1;
+
+ if ( n_placeholder_dims == 1 ) {
+ for ( i=0; i<placeholder_sizes[0]; i++ ) {
+ snprintf(dim_ev, 16, "%s/%i", path_ev, i);
+ if ( add_ev_to_list(list, dim_ev) ) return 1;
+ }
+ } else {
+
+ for ( i=0; i<placeholder_sizes[0]; i++ ) {
+ snprintf(dim_ev, 16, "%s/%i", path_ev, i);
+ if ( rec_expand_dims(list,
+ &placeholder_sizes[1],
+ n_placeholder_dims - 1,
+ dim_ev) ) return 1;
+ }
+
+ }
+
+ free(dim_ev);
+ return 0;
+}
+
+
+static char **expand_dims(int *placeholder_sizes,
+ int n_placeholder_dims,
+ char *path_ev,
+ int *n_evs)
+{
+ struct ev_list list;
+
+ list.n_events = 0;
+ list.max_events = 0;
+ list.events = NULL;
+
+ if ( rec_expand_dims(&list, placeholder_sizes,
+ n_placeholder_dims, path_ev) )
+ {
+ *n_evs = 0;
+ return NULL;
+ }
+
+ *n_evs = list.n_events;
+ return list.events;
+}
+
+
+static int n_dims_expected(struct panel_template *p)
+{
+ int i;
+ int n_dims = 0;
+ for ( i=0; i<MAX_DIMS; i++ ) {
+ if ( p->dims[i] != DIM_UNDEFINED ) n_dims++;
+ }
+ return n_dims;
+}
+
+
+char **image_hdf5_expand_frames(const DataTemplate *dtempl,
+ const char *filename,
+ int *pn_frames)
+{
+ char **path_evs;
+ int n_path_evs;
+ hid_t fh;
+ int i;
+ int dims_expected;
+ struct ev_list full_evs;
+
+ if ( dtempl->n_panels == 0 ) return NULL;
+
+ full_evs.events = NULL;
+ full_evs.n_events = 0;
+ full_evs.max_events = 0;
+
+ /* If the DataTemplate already says that one frame will be
+ * found per file, short-circuit this whole affair */
+ if ( (imh_num_placeholders(&dtempl->panels[0]) == 0)
+ && (imh_num_path_placeholders(dtempl->panels[0].data) == 0) )
+ {
+ add_ev_to_list(&full_evs, "//");
+ *pn_frames = full_evs.n_events;
+ return full_evs.events;
+ }
+
+
+ fh = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT);
+ if ( fh < 0 ) {
+ ERROR("Couldn't open file '%s'\n", filename);
+ return NULL;
+ }
+
+ /* First, expand placeholders in the HDF5 paths.
+ *
+ * Since we require the number of placeholders to be the same
+ * for all panels, and the placeholders will be substituted
+ * with the same values for each panel (since they come from
+ * the same event ID), this only needs to be done for the
+ * first panel. */
+ path_evs = expand_paths(fh, dtempl->panels[0].data,
+ &n_path_evs);
+ if ( path_evs == NULL ) {
+ ERROR("Failed to enumerate paths.\n");
+ close_hdf5(fh);
+ return NULL;
+ }
+
+ dims_expected = n_dims_expected(&dtempl->panels[0]);
+
+ /* For each expanded path, enumerate the placeholder
+ * dimensions. Once again, since the number of placeholders
+ * must be the same for each panel, and the substituted values
+ * will be the same, this only needs to be done for one panel.
+ */
+ for ( i=0; i<n_path_evs; i++ ) {
+
+ hid_t dh, sh;
+ char *path;
+ hsize_t *size;
+ int dims;
+ int *placeholder_sizes;
+ int n_placeholder_dims;
+ int j;
+ struct panel_template *p = &dtempl->panels[0];
+
+ path = substitute_path(path_evs[i], p->data);
+ if ( path == NULL ) {
+ ERROR("Path substitution failed during "
+ "expansion of '%s' with partial event "
+ "ID '%s'\n",
+ p->data, path_evs[i]);
+ return NULL;
+ }
+
+ dh = H5Dopen2(fh, path, H5P_DEFAULT);
+ if ( dh < 0 ) {
+ ERROR("Error opening '%s'\n", path);
+ ERROR("Failed to enumerate events. "
+ "Check your geometry file.\n");
+ close_hdf5(fh);
+ return NULL;
+ }
+
+ sh = H5Dget_space(dh);
+ dims = H5Sget_simple_extent_ndims(sh);
+ if ( dims != dims_expected ) {
+ ERROR("Unexpected number of dimensions"
+ "(%s has %i, expected %i)\n",
+ path, dims, dims_expected);
+ close_hdf5(fh);
+ return NULL;
+ }
+
+ size = malloc(dims*sizeof(hsize_t));
+ placeholder_sizes = malloc(dims*sizeof(int));
+ if ( (size == NULL) || (placeholder_sizes == NULL) ) {
+ ERROR("Failed to allocate dimensions\n");
+ close_hdf5(fh);
+ return NULL;
+ }
+
+ if ( H5Sget_simple_extent_dims(sh, size, NULL) < 0 ) {
+ ERROR("Failed to get size\n");
+ close_hdf5(fh);
+ return NULL;
+ }
+
+ n_placeholder_dims = 0;
+ for ( j=0; j<dims; j++ ) {
+ if ( p->dims[j] == DIM_PLACEHOLDER ) {
+ placeholder_sizes[n_placeholder_dims++] = size[j];
+ }
+ }
+ free(size);
+
+ /* Path event ID ends with //, but expand_dims will
+ * add a slash. So, remove one slash */
+ if ( n_placeholder_dims > 0 ) {
+
+ char **evs_this_path;
+ int n_evs_this_path;
+
+ path_evs[i][strlen(path_evs[i])-1] = '\0';
+ evs_this_path = expand_dims(placeholder_sizes,
+ n_placeholder_dims,
+ path_evs[i],
+ &n_evs_this_path);
+
+ for ( j=0; j<n_evs_this_path; j++ ) {
+ add_ev_to_list(&full_evs, evs_this_path[j]);
+ free(evs_this_path[j]);
+ }
+
+ free(evs_this_path);
+
+ } else {
+
+ /* Easy case with no dims to expand */
+ add_ev_to_list(&full_evs, path_evs[i]);
+
+ }
+
+ free(placeholder_sizes);
+ free(path);
+ free(path_evs[i]);
+
+ }
+
+ close_hdf5(fh);
+ free(path_evs);
+ *pn_frames = full_evs.n_events;
+ return full_evs.events;
+}
+
+
+int is_hdf5_file(const char *filename)
+{
+ const char *ext = NULL;
+
+ ext = filename_extension(filename, NULL);
+ if ( ext == NULL ) return 0;
+
+ return ( (strcmp(ext, ".h5") == 0)
+ || (strcmp(ext, ".cxi") == 0) );
+}
+
+
+/***************************** Writing *****************************/
+
+struct hdf5_write_location {
+
+ const char *location;
+ int n_panels;
+ int *panel_idxs;
+
+ int max_ss;
+ int max_fs;
+
+};
+
+
+static void add_panel_to_location(struct hdf5_write_location *loc,
+ struct panel_template *p, int pi)
+{
+ int *new_panel_idxs;
+
+ new_panel_idxs = realloc(loc->panel_idxs,
+ (loc->n_panels+1)*sizeof(int));
+ if ( new_panel_idxs == NULL ) {
+ ERROR("Error while managing write location list.\n");
+ return;
+ }
+ loc->panel_idxs = new_panel_idxs;
+ loc->panel_idxs[loc->n_panels] = pi;
+ loc->n_panels += 1;
+ if ( p->orig_max_fs > loc->max_fs ) {
+ loc->max_fs = p->orig_max_fs;
+ }
+ if ( p->orig_max_ss > loc->max_ss ) {
+ loc->max_ss = p->orig_max_ss;
+ }
+}
+
+
+static void add_panel_location(struct panel_template *p,
+ const char *p_location, int pi,
+ struct hdf5_write_location **plocations,
+ int *pnum_locations)
+{
+ int li;
+ int num_locations = *pnum_locations;
+ struct hdf5_write_location *locations = *plocations;
+ int done = 0;
+
+ /* Does this HDF5 path already exist in the location list?
+ * If so, add the new panel to it (with a unique index, we hope) */
+ for ( li=0; li<num_locations; li++ ) {
+ if ( strcmp(p_location, locations[li].location) == 0 ) {
+ add_panel_to_location(&locations[li], p, pi);
+ done = 1;
+ }
+ }
+
+ /* If not, add a new location to ths list */
+ if ( !done ) {
+
+ struct hdf5_write_location *new_locations;
+ size_t nsz;
+
+ nsz = (num_locations+1)*sizeof(struct hdf5_write_location);
+ new_locations = realloc(locations, nsz);
+ if ( new_locations == NULL ) {
+ ERROR("Failed to grow location list.\n");
+ return;
+ }
+ locations = new_locations;
+
+ locations[num_locations].max_ss = p->orig_max_ss;
+ locations[num_locations].max_fs = p->orig_max_fs;
+ locations[num_locations].location = p_location;
+ locations[num_locations].panel_idxs = malloc(sizeof(int));
+ if ( locations[num_locations].panel_idxs == NULL ) {
+ ERROR("Failed to allocate single idx (!)\n");
+ return;
+ }
+ locations[num_locations].panel_idxs[0] = pi;
+ locations[num_locations].n_panels = 1;
+
+ num_locations += 1;
+
+ }
+
+ *plocations = locations;
+ *pnum_locations = num_locations;
+}
+
+
+static struct hdf5_write_location *make_location_list(const DataTemplate *dtempl,
+ int *pnum_locations)
+{
+ int pi;
+ struct hdf5_write_location *locations = NULL;
+ int num_locations = 0;
+
+ for ( pi=0; pi<dtempl->n_panels; pi++ ) {
+
+ struct panel_template *p;
+ const char *p_location;
+
+ p = &dtempl->panels[pi];
+
+ assert(p->data != NULL);
+ p_location = p->data;
+
+ add_panel_location(p, p_location, pi,
+ &locations, &num_locations);
+
+ }
+
+ *pnum_locations = num_locations;
+ return locations;
+}
+
+
+static void write_location(hid_t fh, const DataTemplate *dtempl,
+ float **dp,
+ struct hdf5_write_location *loc)
+{
+ hid_t sh, dh, ph;
+ hid_t dh_dataspace;
+ hsize_t size[2];
+ int pi;
+
+ /* Note the "swap" here, according to section 3.2.5,
+ * "C versus Fortran Dataspaces", of the HDF5 user's guide. */
+ size[0] = loc->max_ss+1;
+ size[1] = loc->max_fs+1;
+ sh = H5Screate_simple(2, size, NULL);
+
+ ph = H5Pcreate(H5P_LINK_CREATE);
+ H5Pset_create_intermediate_group(ph, 1);
+
+ dh = H5Dcreate2(fh, loc->location, H5T_NATIVE_FLOAT, sh,
+ ph, H5P_DEFAULT, H5P_DEFAULT);
+ if ( dh < 0 ) {
+ ERROR("Couldn't create dataset\n");
+ H5Fclose(fh);
+ return;
+ }
+
+ H5Sget_simple_extent_dims(sh, size, NULL);
+
+ for ( pi=0; pi<loc->n_panels; pi++ ) {
+
+ hsize_t f_offset[2], f_count[2], dims[2];
+ hid_t memspace;
+ struct panel_template *p;
+ int r;
+
+ p = &dtempl->panels[loc->panel_idxs[pi]];
+
+ f_offset[0] = p->orig_min_ss;
+ f_offset[1] = p->orig_min_fs;
+ f_count[0] = p->orig_max_ss - p->orig_min_ss +1;
+ f_count[1] = p->orig_max_fs - p->orig_min_fs +1;
+
+ dh_dataspace = H5Dget_space(dh);
+ r = H5Sselect_hyperslab(dh_dataspace, H5S_SELECT_SET,
+ f_offset, NULL, f_count, NULL);
+ if ( r < 0 ) {
+ ERROR("Error selecting file dataspace "
+ "for panel %s\n", p->name);
+ H5Pclose(ph);
+ H5Dclose(dh);
+ H5Sclose(dh_dataspace);
+ H5Sclose(sh);
+ H5Fclose(fh);
+ return;
+ }
+
+ dims[0] = PANEL_HEIGHT(p);
+ dims[1] = PANEL_WIDTH(p);
+ memspace = H5Screate_simple(2, dims, NULL);
+
+ r = H5Dwrite(dh, H5T_NATIVE_FLOAT, memspace, dh_dataspace,
+ H5P_DEFAULT, dp[loc->panel_idxs[pi]]);
+ if ( r < 0 ) {
+ ERROR("Couldn't write data\n");
+ H5Pclose(ph);
+ H5Dclose(dh);
+ H5Sclose(dh_dataspace);
+ H5Sclose(memspace);
+ H5Sclose(sh);
+ H5Fclose(fh);
+ return;
+ }
+
+ H5Sclose(dh_dataspace);
+ H5Sclose(memspace);
+ }
+ H5Pclose(ph);
+ H5Sclose(sh);
+ H5Dclose(dh);
+}
+
+
+static void write_wavelength(hid_t fh, double wl,
+ const DataTemplate *dtempl)
+{
+ hid_t ph, sh, dh;
+ hsize_t size1d[1];
+ int r;
+
+ ph = H5Pcreate(H5P_LINK_CREATE);
+ H5Pset_create_intermediate_group(ph, 1);
+
+ size1d[0] = 1;
+ sh = H5Screate_simple(1, size1d, NULL);
+
+ dh = H5Dcreate2(fh, "/wavelength", H5T_NATIVE_DOUBLE, sh,
+ ph, H5S_ALL, H5P_DEFAULT);
+ if ( dh < 0 ) {
+ ERROR("Couldn't create dataset for photon energy.\n");
+ return;
+ }
+ r = H5Dwrite(dh, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL,
+ H5P_DEFAULT, &wl);
+ if ( r < 0 ) {
+ ERROR("Couldn't write photon energy.\n");
+ /* carry on */
+ }
+
+ H5Pclose(ph);
+ H5Dclose(dh);
+}
+
+
+static void write_spectrum(hid_t fh, Spectrum *s,
+ const DataTemplate *dtempl)
+{
+ herr_t r;
+ double *arr;
+ int i;
+ hid_t sh, dh, ph;
+ double kmin, kmax, step;
+ const hsize_t n = 1024;
+
+ ph = H5Pcreate(H5P_LINK_CREATE);
+ H5Pset_create_intermediate_group(ph, 1);
+
+ arr = malloc(n*sizeof(double));
+ if ( arr == NULL ) {
+ ERROR("Failed to allocate memory for spectrum.\n");
+ return;
+ }
+
+ /* Save the wavelength values */
+ spectrum_get_range(s, &kmin, &kmax);
+ step = (kmax-kmin)/n;
+ for ( i=0; i<n; i++ ) {
+ arr[i] = 1.0e10/(kmin+i*step);
+ }
+
+ sh = H5Screate_simple(1, &n, NULL);
+
+ dh = H5Dcreate2(fh, "/spectrum/wavelengths_A", H5T_NATIVE_DOUBLE,
+ sh, ph, H5S_ALL, H5P_DEFAULT);
+ if ( dh < 0 ) {
+ ERROR("Failed to create dataset for spectrum wavelengths.\n");
+ return;
+ }
+ r = H5Dwrite(dh, H5T_NATIVE_DOUBLE, H5S_ALL,
+ H5S_ALL, H5P_DEFAULT, arr);
+ if ( r < 0 ) {
+ ERROR("Failed to write spectrum wavelengths.\n");
+ return;
+ }
+ H5Dclose(dh);
+
+ /* Save the probability density values */
+ for ( i=0; i<n; i++ ) {
+ arr[i] = spectrum_get_density_at_k(s, kmin+i*step);
+ }
+
+ dh = H5Dcreate2(fh, "/spectrum/pdf", H5T_NATIVE_DOUBLE, sh,
+ H5P_DEFAULT, H5S_ALL, H5P_DEFAULT);
+ if ( dh < 0 ) {
+ ERROR("Failed to create dataset for spectrum p.d.f.\n");
+ return;
+ }
+ r = H5Dwrite(dh, H5T_NATIVE_DOUBLE, H5S_ALL,
+ H5S_ALL, H5P_DEFAULT, arr);
+ if ( r < 0 ) {
+ ERROR("Failed to write spectrum p.d.f.\n");
+ return;
+ }
+
+ H5Dclose(dh);
+ H5Pclose(ph);
+ free(arr);
+}
+
+
+int image_hdf5_write(const struct image *image,
+ const DataTemplate *dtempl,
+ const char *filename)
+{
+ hid_t fh;
+ int li;
+ struct hdf5_write_location *locations;
+ int num_locations;
+
+ if ( dtempl == NULL ) return 1;
+
+ fh = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ if ( fh < 0 ) {
+ ERROR("Couldn't create file: %s\n", filename);
+ return 1;
+ }
+
+ locations = make_location_list(dtempl, &num_locations);
+
+ for ( li=0; li<num_locations; li++ ) {
+ write_location(fh, dtempl, image->dp, &locations[li]);
+ }
+
+ write_wavelength(fh, image->lambda, dtempl);
+
+ if ( image->spectrum != NULL ) {
+ write_spectrum(fh, image->spectrum, dtempl);
+ }
+
+ H5Fclose(fh);
+ for ( li=0; li<num_locations; li ++ ) {
+ free(locations[li].panel_idxs);
+ }
+ free(locations);
+ return 0;
+}
diff --git a/libcrystfel/src/image-hdf5.h b/libcrystfel/src/image-hdf5.h
new file mode 100644
index 00000000..efb8a3b7
--- /dev/null
+++ b/libcrystfel/src/image-hdf5.h
@@ -0,0 +1,72 @@
+/*
+ * image-hdf5.h
+ *
+ * Image loading, HDF5 parts
+ *
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/* NB This file is NOT part of the public API, and should NOT
+ * be installed, but rather stays in the libcrystfel source folder. */
+
+#ifndef IMAGE_HDF5_H
+#define IMAGE_HDF5_H
+
+#include "datatemplate_priv.h"
+
+extern double image_hdf5_get_value(const char *from,
+ const char *filename,
+ const char *ev);
+
+extern int image_hdf5_read(struct image *image,
+ const DataTemplate *dtempl,
+ const char *filename,
+ const char *event);
+
+extern int image_hdf5_read_mask(struct panel_template *p,
+ const char *filename,
+ const char *event, int *bad,
+ const char *mask_location,
+ int mask_good, int mask_bad);
+
+extern ImageFeatureList *image_hdf5_read_peaks_cxi(const DataTemplate *dtempl,
+ const char *filename,
+ const char *event,
+ int half_pixel_shift);
+
+extern ImageFeatureList *image_hdf5_read_peaks_hdf5(const DataTemplate *dtempl,
+ const char *filename,
+ const char *event,
+ int half_pixel_shift);
+
+extern char **image_hdf5_expand_frames(const DataTemplate *dtempl,
+ const char *filename,
+ int *n_frames);
+
+extern int is_hdf5_file(const char *filename);
+
+extern int image_hdf5_write(const struct image *image,
+ const DataTemplate *dtempl,
+ const char *filename);
+
+#endif /* IMAGE_HDF5_H */
diff --git a/libcrystfel/src/image-msgpack.c b/libcrystfel/src/image-msgpack.c
new file mode 100644
index 00000000..420ecfb4
--- /dev/null
+++ b/libcrystfel/src/image-msgpack.c
@@ -0,0 +1,315 @@
+/*
+ * image-msgpack.c
+ *
+ * Image loading, MessagePack parts
+ *
+ * Copyright © 2017-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2018-2020 Thomas White <taw@physics.org>
+ * 2014 Valerio Mariani
+ * 2017 Stijn de Graaf
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <assert.h>
+#include <unistd.h>
+#include <zmq.h>
+#include <msgpack.h>
+
+#include <image.h>
+#include <utils.h>
+#include <msgpack.h>
+
+#include "datatemplate_priv.h"
+
+
+static msgpack_object *find_msgpack_kv(msgpack_object *obj, const char *key)
+{
+ int i;
+
+ if ( obj == NULL ) return NULL;
+ if ( obj->type != MSGPACK_OBJECT_MAP ) return NULL;
+
+ for ( i=0; i<obj->via.map.size; i++ ) {
+ const char *kstr;
+ size_t klen;
+ assert(obj->via.map.ptr[i].key.type == MSGPACK_OBJECT_STR);
+ kstr = obj->via.map.ptr[i].key.via.str.ptr;
+ klen = obj->via.map.ptr[i].key.via.str.size;
+ if ( strncmp(kstr, key, klen) == 0 ) {
+ return &obj->via.map.ptr[i].val;
+ }
+ }
+ return NULL;
+}
+
+
+/**
+ * image_msgpack_read_peaks
+ * @dtempl: A %DataTemplate
+ * @obj: A %msgpack_object containing data
+ * @half_pixel_shift: Non-zero if 0.5 should be added to all peak coordinates
+ *
+ * Get peaks from msgpack_object. The data should be in a map, with the value
+ * given by "peak_list" as an array of arrays. The first of these should contain
+ * the list of fs positions of the peaks, the second the ss positions, and the
+ * third the intensities of the peaks.
+ *
+ * http://c.msgpack.org/c/ provides documentation on msgpack objects
+ *
+ * CrystFEL considers all peak locations to be distances from the corner of the
+ * detector panel, in pixel units, consistent with its description of detector
+ * geometry (see 'man crystfel_geometry'). The software which generates the
+ * CXI files, including Cheetah, may instead consider the peak locations to be
+ * pixel indices in the data array. In this case, the peak coordinates should
+ * have 0.5 added to them. This will be done if @half_pixel_shift is non-zero.
+ *
+ * Returns: a newly-allocated %ImageFeatureList.
+ *
+ */
+ImageFeatureList *image_msgpack_read_peaks(const DataTemplate *dtempl,
+ msgpack_object *obj,
+ int half_pixel_shift)
+{
+ ImageFeatureList *features;
+ int num_peaks;
+ int pk;
+ msgpack_object *peak_list;
+ msgpack_object *peak_x;
+ msgpack_object *peak_y;
+ msgpack_object *peak_i;
+ double peak_offset = half_pixel_shift ? 0.5 : 0.0;
+
+ if ( obj == NULL ) {
+ ERROR("No MessagePack object to get peaks from.\n");
+ return NULL;
+ }
+
+ /* Object has structure:
+ * {
+ * "peak_list": [[peak_x], [peak_y], [peak_i]]
+ * "key2":val2,
+ * ...
+ * }
+ */
+ peak_list = find_msgpack_kv(obj, "peak_list");
+ peak_x = &peak_list->via.array.ptr[0];
+ peak_y = &peak_list->via.array.ptr[1];
+ peak_i = &peak_list->via.array.ptr[2];
+
+ /* Length of peak_x array gives number of peaks */
+ num_peaks = peak_x->via.array.size;
+
+ features = image_feature_list_new();
+
+ for ( pk=0; pk<num_peaks; pk++ ) {
+
+ float fs, ss, val;
+ int pn;
+
+ /* Retrieve data from peak_list and apply half_pixel_shift,
+ * if appropriate */
+ fs = peak_x->via.array.ptr[pk].via.f64 + peak_offset;
+ ss = peak_y->via.array.ptr[pk].via.f64 + peak_offset;
+ val = peak_i->via.array.ptr[pk].via.f64;
+
+ /* Convert coordinates to panel-relative */
+ if ( data_template_file_to_panel_coords(dtempl, &fs, &ss, &pn) ) {
+ ERROR("Peak not in panel!\n");
+ } else {
+ image_add_feature(features, fs, ss, pn,
+ NULL, val, NULL);
+ }
+ }
+
+ return features;
+}
+
+
+static int unpack_slab(struct image *image,
+ const DataTemplate *dtempl,
+ double *data,
+ int data_width, int data_height)
+{
+ int pi;
+
+ image->dp = malloc(dtempl->n_panels*sizeof(float *));
+ if ( image->dp == NULL ) {
+ ERROR("Failed to allocate data arrays.\n");
+ return 1;
+ }
+
+ for ( pi=0; pi<dtempl->n_panels; pi++ ) {
+
+ struct panel_template *p;
+ int fs, ss;
+ int p_w, p_h;
+
+ p = &dtempl->panels[pi];
+ p_w = p->orig_max_fs - p->orig_min_fs + 1;
+ p_h = p->orig_max_ss - p->orig_min_ss + 1;
+
+ image->dp[pi] = malloc(p_w*p_h*sizeof(float));
+ if ( image->dp[pi] == NULL ) {
+ ERROR("Failed to allocate panel\n");
+ return 1;
+ }
+
+ if ( (p->orig_min_fs + p_w > data_width)
+ || (p->orig_min_ss + p_h > data_height) )
+ {
+ ERROR("Panel %s is outside range of data provided\n",
+ p->name);
+ return 1;
+ }
+
+ for ( ss=0; ss<p_h; ss++) {
+ for ( fs=0; fs<p_w; fs++) {
+
+ int idx;
+ int cfs, css;
+
+ cfs = fs+p->orig_min_fs;
+ css = ss+p->orig_min_ss;
+ idx = cfs + css*data_width;
+
+ image->dp[pi][fs+p_w*ss] = data[idx];
+
+ }
+ }
+
+ }
+
+ return 0;
+}
+
+
+static double *find_msgpack_data(msgpack_object *obj, int *width, int *height)
+{
+ msgpack_object *corr_data_obj;
+ msgpack_object *data_obj;
+ msgpack_object *shape_obj;
+ double *data;
+
+ corr_data_obj = find_msgpack_kv(obj, "corr_data");
+ if ( corr_data_obj == NULL ) {
+ ERROR("No corr_data MessagePack object found.\n");
+ return NULL;
+ }
+
+ data_obj = find_msgpack_kv(corr_data_obj, "data");
+ if ( data_obj == NULL ) {
+ ERROR("No data MessagePack object found inside corr_data.\n");
+ return NULL;
+ }
+ if ( data_obj->type != MSGPACK_OBJECT_STR ) {
+ ERROR("corr_data.data isn't a binary object.\n");
+ return NULL;
+ }
+ data = (double *)data_obj->via.str.ptr;
+
+ shape_obj = find_msgpack_kv(corr_data_obj, "shape");
+ if ( shape_obj == NULL ) {
+ ERROR("No shape MessagePack object found inside corr_data.\n");
+ return NULL;
+ }
+ if ( shape_obj->type != MSGPACK_OBJECT_ARRAY ) {
+ ERROR("corr_data.shape isn't an array object.\n");
+ return NULL;
+ }
+ if ( shape_obj->via.array.size != 2 ) {
+ ERROR("corr_data.shape is wrong size (%i, should be 2)\n",
+ shape_obj->via.array.size);
+ return NULL;
+ }
+ if ( shape_obj->via.array.ptr[0].type != MSGPACK_OBJECT_POSITIVE_INTEGER ) {
+ ERROR("corr_data.shape contains wrong type of element.\n");
+ return NULL;
+ }
+ *height = shape_obj->via.array.ptr[0].via.i64;
+ *width = shape_obj->via.array.ptr[1].via.i64;
+ return data;
+}
+
+
+/* Unpacks the raw panel data from a msgpack_object, applies panel geometry,
+ * and stores the resulting data in an image struct. Object has structure
+ * {
+ * "corr_data":
+ * {
+ * "data": binary_data,
+ * "shape": [data_height, data_width],
+ * ...
+ * ...
+ * },
+ * "key2": val2,
+ * ...
+ * ...
+ * }
+ */
+struct image *image_msgpack_read(DataTemplate *dtempl,
+ msgpack_object *obj,
+ int no_image_data,
+ int no_mask_data)
+{
+ struct image *image;
+ int data_width, data_height;
+ double *data;
+
+ if ( obj == NULL ) {
+ ERROR("No MessagePack object!\n");
+ return NULL;
+ }
+
+ if ( dtempl == NULL ) {
+ ERROR("NULL data template!\n");
+ return NULL;
+ }
+
+ image = image_new();
+ if ( image == NULL ) {
+ ERROR("Couldn't allocate image structure.\n");
+ return NULL;
+ }
+
+ if ( !no_image_data ) {
+ data = find_msgpack_data(obj,
+ &data_width, &data_height);
+ if ( data == NULL ) {
+ ERROR("No image data in MessagePack object.\n");
+ return NULL;
+ }
+ unpack_slab(image, dtempl, data,
+ data_width, data_height);
+ } else {
+ image_set_zero_data(image, dtempl);
+ }
+
+ image_set_zero_mask(image, dtempl);
+
+ return image;
+}
diff --git a/libcrystfel/src/image-msgpack.h b/libcrystfel/src/image-msgpack.h
new file mode 100644
index 00000000..a8e5af34
--- /dev/null
+++ b/libcrystfel/src/image-msgpack.h
@@ -0,0 +1,64 @@
+/*
+ * image-msgpack.h
+ *
+ * Image loading, MessagePack parts
+ *
+ * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef IMAGE_MSGPACK_H
+#define IMAGE_MSGPACK_H
+
+#include "datatemplate.h"
+
+#if defined(HAVE_MSGPACK)
+
+#include <msgpack.h>
+
+extern struct image *image_msgpack_read(DataTemplate *dtempl,
+ msgpack_object *obj,
+ int no_image_data);
+
+extern ImageFeatureList *image_msgpack_read_peaks(const DataTemplate *dtempl,
+ msgpack_object *obj,
+ int half_pixel_shift);
+
+#else /* defined(HAVE_MSGPACK) */
+
+static UNUSED struct image *image_msgpack_read(DataTemplate *dtempl,
+ void *obj,
+ int no_image_data)
+{
+ return NULL;
+}
+
+static UNUSED ImageFeatureList *image_msgpack_read_peaks(const DataTemplate *dtempl,
+ void *obj,
+ int half_pixel_shift)
+{
+ return NULL;
+}
+
+#endif /* defined(HAVE_MSGPACK) */
+
+#endif /* IMAGE_MSGPACK_H */
diff --git a/libcrystfel/src/image.c b/libcrystfel/src/image.c
index 6358a9d0..db47f75d 100644
--- a/libcrystfel/src/image.c
+++ b/libcrystfel/src/image.c
@@ -3,12 +3,12 @@
*
* Handle images and image features
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
* 2014 Kenneth Beyerlein <kenneth.beyerlein@desy.de>
- * 2011-2017 Thomas White <taw@physics.org>
+ * 2011-2021 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -27,30 +27,27 @@
*
*/
+#ifdef HAVE_CONFIG_H
#include <config.h>
+#endif
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <stdio.h>
-#include <hdf5.h>
-#include <zlib.h>
+#include <sys/stat.h>
+#include <fenv.h>
#include "image.h"
#include "utils.h"
-#include "events.h"
-#include "hdf5-file.h"
-#include "detector.h"
+#include "detgeom.h"
+#include "image-hdf5.h"
+#include "image-cbf.h"
-/** \file image.h */
-
-struct imagefile
-{
- enum imagefile_type type;
- char *filename;
- struct hdfile *hdfile;
-};
+#include "datatemplate.h"
+#include "datatemplate_priv.h"
+/** \file image.h */
struct _imagefeaturelist
{
@@ -61,7 +58,7 @@ struct _imagefeaturelist
void image_add_feature(ImageFeatureList *flist, double fs, double ss,
- struct panel *p,
+ int pn,
struct image *parent, double intensity, const char *name)
{
if ( flist->n_features == flist->max_features ) {
@@ -75,9 +72,8 @@ void image_add_feature(ImageFeatureList *flist, double fs, double ss,
flist->features[flist->n_features].fs = fs;
flist->features[flist->n_features].ss = ss;
- flist->features[flist->n_features].p = p;
+ flist->features[flist->n_features].pn = pn;
flist->features[flist->n_features].intensity = intensity;
- flist->features[flist->n_features].parent = parent;
flist->features[flist->n_features].name = name;
flist->n_features++;
@@ -107,10 +103,7 @@ static int comp(const void *a, const void *b)
}
-/**
- * Strongest first.
- */
-ImageFeatureList *sort_peaks(ImageFeatureList *flist)
+ImageFeatureList *image_feature_list_copy(const ImageFeatureList *flist)
{
ImageFeatureList *n;
int nf, i;
@@ -128,30 +121,40 @@ ImageFeatureList *sort_peaks(ImageFeatureList *flist)
nf = 0;
for ( i=0; i<flist->n_features; i++ ) {
- struct imagefeature *f;
- f = image_get_feature(flist, i);
+ const struct imagefeature *f;
+ f = image_get_feature_const(flist, i);
if ( f == NULL ) continue;
n->features[nf++] = flist->features[i];
}
n->n_features = nf;
- qsort(n->features, nf, sizeof(struct imagefeature), comp);
+ return n;
+}
+
+/**
+ * Strongest first.
+ */
+ImageFeatureList *sort_peaks(ImageFeatureList *flist)
+{
+ ImageFeatureList *n = image_feature_list_copy(flist);
+ qsort(n->features, image_feature_count(n),
+ sizeof(struct imagefeature), comp);
return n;
}
void image_feature_list_free(ImageFeatureList *flist)
{
- if ( !flist ) return;
- if ( flist->features ) free(flist->features);
+ if ( flist == NULL ) return;
+ free(flist->features);
free(flist);
}
struct imagefeature *image_feature_closest(ImageFeatureList *flist,
double fs, double ss,
- struct panel *p, double *d, int *idx)
+ int pn, double *d, int *idx)
{
int i;
double dmin = +HUGE_VAL;
@@ -161,7 +164,7 @@ struct imagefeature *image_feature_closest(ImageFeatureList *flist,
double ds;
- if ( p != flist->features[i].p ) continue;
+ if ( pn != flist->features[i].pn ) continue;
ds = distance(flist->features[i].fs, flist->features[i].ss,
fs, ss);
@@ -184,53 +187,21 @@ struct imagefeature *image_feature_closest(ImageFeatureList *flist,
}
-Reflection *image_reflection_closest(RefList *rlist,
- double fs, double ss, struct panel *p,
- struct detector *det,
- double *d)
+int image_feature_count(ImageFeatureList *flist)
{
-
- double dmin = HUGE_VAL;
- Reflection *closest = NULL;
- Reflection *refl;
- RefListIterator *iter;
-
- for ( refl = first_refl(rlist, &iter);
- refl != NULL;
- refl = next_refl(refl, iter) )
- {
- double ds;
- struct panel *p2;
- double rfs, rss;
-
- get_detector_pos(refl, &rfs, &rss);
- p2 = get_panel(refl);
-
- if ( p != p2 ) continue;
-
- ds = distance(rfs, rss, fs, ss);
-
- if ( ds < dmin ) {
- dmin = ds;
- closest = refl;
- }
-
- }
-
- if ( dmin < +HUGE_VAL ) {
- *d = dmin;
- return closest;
- }
-
- *d = +INFINITY;
- return NULL;
+ if ( flist == NULL ) return 0;
+ return flist->n_features;
}
-int image_feature_count(ImageFeatureList *flist)
+const struct imagefeature *image_get_feature_const(const ImageFeatureList *flist,
+ int idx)
{
- if ( flist == NULL ) return 0;
- return flist->n_features;
+ /* Sanity check */
+ if ( flist == NULL ) return NULL;
+ if ( idx >= flist->n_features ) return NULL;
+
+ return &flist->features[idx];
}
@@ -310,929 +281,909 @@ void free_all_crystals(struct image *image)
}
-/**************************** Image field lists *******************************/
-
-struct imagefile_field_list
+static double get_value(struct image *image, const char *from,
+ int *is_literal_number)
{
- char **fields;
- int n_fields;
- int max_fields;
-};
-
+ double val;
+ char *rval;
-struct imagefile_field_list *new_imagefile_field_list()
-{
- struct imagefile_field_list *n;
+ if ( from == NULL ) return NAN;
- n = calloc(1, sizeof(struct imagefile_field_list));
- if ( n == NULL ) return NULL;
+ val = strtod(from, &rval);
+ if ( (*rval == '\0') && (rval != from) ) {
+ if ( is_literal_number != NULL ) {
+ *is_literal_number = 1;
+ }
+ return val;
+ }
- n->max_fields = 32;
- n->fields = malloc(n->max_fields*sizeof(char *));
- if ( n->fields == NULL ) {
- free(n);
- return NULL;
+ if ( image == NULL ) {
+ ERROR("Attempt to retrieve a header value without an image\n");
+ return NAN;
}
- return n;
-}
+ if ( is_hdf5_file(image->filename) ) {
+ return image_hdf5_get_value(from,
+ image->filename,
+ image->ev);
+ } else if ( is_cbf_file(image->filename) ) {
+ /* FIXME: From headers */
+ return NAN;
-void free_imagefile_field_list(struct imagefile_field_list *n)
-{
- int i;
- for ( i=0; i<n->n_fields; i++ ) {
- free(n->fields[i]);
+ } else if ( is_cbfgz_file(image->filename) ) {
+ /* FIXME: From headers */
+ return NAN;
+
+ } else {
+ ERROR("Unrecognised file type: %s\n", image->filename);
+ return NAN;
}
- free(n->fields);
- free(n);
}
-void add_imagefile_field(struct imagefile_field_list *copyme, const char *name)
+static char *get_value_and_units(struct image *image, const char *from,
+ double *pvalue,
+ int *is_literal_number)
{
- int i;
+ char *sp;
+ char *fromcpy;
+ char *unitscpy;
- /* Already on the list? Don't re-add if so. */
- for ( i=0; i<copyme->n_fields; i++ ) {
- if ( strcmp(copyme->fields[i], name) == 0 ) return;
+ if ( from == NULL ) {
+ *pvalue = NAN;
+ return NULL;
}
- /* Need more space? */
- if ( copyme->n_fields == copyme->max_fields ) {
+ fromcpy = strdup(from);
+ if ( fromcpy == NULL ) {
+ *pvalue = NAN;
+ return NULL;
+ }
- char **nfields;
- int nmax = copyme->max_fields + 32;
+ sp = strchr(fromcpy, ' ');
+ if ( sp == NULL ) {
+ unitscpy = NULL;
+ } else {
+ unitscpy = strdup(sp+1);
+ sp[0] = '\0';
+ }
- nfields = realloc(copyme->fields, nmax*sizeof(char *));
- if ( nfields == NULL ) {
- ERROR("Failed to allocate space for new HDF5 field.\n");
- return;
- }
+ *pvalue = get_value(image, fromcpy, is_literal_number);
+ free(fromcpy);
- copyme->max_fields = nmax;
- copyme->fields = nfields;
+ return unitscpy;
+}
- }
- copyme->fields[copyme->n_fields] = strdup(name);
- if ( copyme->fields[copyme->n_fields] == NULL ) {
- ERROR("Failed to add field for copying '%s'\n", name);
- return;
+/* default_scale is a value to be used if both of the following
+ * conditions are met:
+ *
+ * 1. The value is a reference to image headers/metadata,
+ * rather than a literal number.
+ * 2. No units are specified in the number.
+ *
+ * This is totally horrible. Sorry. Blame history.
+ */
+static double im_get_length(struct image *image, const char *from,
+ double default_scale)
+{
+ char *units;
+ double value;
+ double scale;
+ int is_literal_number = 0;
+
+ if ( from == NULL ) return NAN;
+
+ units = get_value_and_units(image, from,
+ &value, &is_literal_number);
+ if ( units == NULL ) {
+ if ( is_literal_number ) {
+ scale = 1.0;
+ } else {
+ scale = default_scale;
+ }
+ } else {
+ if ( strcmp(units, "mm") == 0 ) {
+ scale = 1e-3;
+ } else if ( strcmp(units, "m") == 0 ) {
+ scale = 1.0;
+ } else {
+ ERROR("Invalid length unit '%s'\n", units);
+ free(units);
+ return NAN;
+ }
}
- copyme->n_fields++;
+ free(units);
+ return value * scale;
}
-/******************************* CBF files ************************************/
-
-static int unpack_panels(struct image *image, float *data, int data_width,
- int data_height)
+int create_detgeom(struct image *image, const DataTemplate *dtempl)
{
- int pi;
+ struct detgeom *detgeom;
+ int i;
- /* FIXME: Load these masks from an HDF5 file, if filenames are
- * given in the geometry file */
- uint16_t *flags = NULL;
- float *sat = NULL;
-
- image->dp = malloc(image->det->n_panels * sizeof(float *));
- image->bad = malloc(image->det->n_panels * sizeof(int *));
- image->sat = malloc(image->det->n_panels * sizeof(float *));
- if ( (image->dp == NULL) || (image->bad == NULL)
- || (image->sat == NULL) )
- {
- ERROR("Failed to allocate panels.\n");
+ if ( dtempl == NULL ) {
+ ERROR("NULL data template!\n");
return 1;
}
- for ( pi=0; pi<image->det->n_panels; pi++ ) {
-
- struct panel *p;
- int fs, ss;
+ detgeom = malloc(sizeof(struct detgeom));
+ if ( detgeom == NULL ) return 1;
- p = &image->det->panels[pi];
- image->dp[pi] = malloc(p->w*p->h*sizeof(float));
- image->bad[pi] = calloc(p->w*p->h, sizeof(int));
- image->sat[pi] = malloc(p->w*p->h*sizeof(float));
- if ( (image->dp[pi] == NULL) || (image->bad[pi] == NULL)
- || (image->sat[pi] == NULL) )
- {
- ERROR("Failed to allocate panel\n");
- return 1;
- }
+ detgeom->panels = malloc(dtempl->n_panels*sizeof(struct detgeom_panel));
+ if ( detgeom->panels == NULL ) return 1;
- if ( p->mask != NULL ) {
- ERROR("WARNING: Bad pixel masks do not currently work "
- "with CBF files\n");
- ERROR(" (bad pixel regions specified in the geometry "
- "file will be used, however)\n");
- }
+ detgeom->n_panels = dtempl->n_panels;
- if ( p->satmap != NULL ) {
- ERROR("WARNING: Saturation maps do not currently work "
- "with CBF files\n");
- }
+ for ( i=0; i<dtempl->n_panels; i++ ) {
- if ( (p->orig_min_fs + p->w > data_width)
- || (p->orig_min_ss + p->h > data_height) )
- {
- ERROR("Panel %s is outside range of data in CBF file\n",
- p->name);
- return 1;
- }
-
- for ( ss=0; ss<p->h; ss++ ) {
- for ( fs=0; fs<p->w; fs++ ) {
+ double shift_x, shift_y;
- int idx;
- int cfs, css;
- int bad = 0;
+ detgeom->panels[i].name = safe_strdup(dtempl->panels[i].name);
- cfs = fs+p->orig_min_fs;
- css = ss+p->orig_min_ss;
- idx = cfs + css*data_width;
+ detgeom->panels[i].pixel_pitch = dtempl->panels[i].pixel_pitch;
- image->dp[pi][fs+p->w*ss] = data[idx];
+ /* NB cnx,cny are in pixels, cnz is in m */
+ detgeom->panels[i].cnx = dtempl->panels[i].cnx;
+ detgeom->panels[i].cny = dtempl->panels[i].cny;
+ detgeom->panels[i].cnz = im_get_length(image,
+ dtempl->panels[i].cnz_from,
+ 1e-3);
- if ( sat != NULL ) {
- image->sat[pi][fs+p->w*ss] = sat[idx];
- } else {
- image->sat[pi][fs+p->w*ss] = INFINITY;
- }
+ /* Apply offset (in m) and then convert cnz from
+ * m to pixels */
+ detgeom->panels[i].cnz += dtempl->panels[i].cnz_offset;
+ detgeom->panels[i].cnz /= detgeom->panels[i].pixel_pitch;
- if ( p->no_index ) bad = 1;
+ /* Apply overall shift (already in m) */
+ shift_x = im_get_length(image, dtempl->shift_x_from, 1.0);
+ shift_y = im_get_length(image, dtempl->shift_y_from, 1.0);
- if ( in_bad_region(image->det, p, cfs, css) ) {
- bad = 1;
- }
+ if ( !isnan(shift_x) ) {
+ detgeom->panels[i].cnx += shift_x;
+ }
+ if ( !isnan(shift_y) ) {
+ detgeom->panels[i].cny += shift_y;
+ }
- if ( isnan(data[idx]) || isinf(data[idx]) ) bad = 1;
+ detgeom->panels[i].max_adu = dtempl->panels[i].max_adu;
- if ( flags != NULL ) {
+ switch ( dtempl->panels[i].adu_scale_unit ) {
- int f;
+ case ADU_PER_PHOTON:
+ detgeom->panels[i].adu_per_photon = dtempl->panels[i].adu_scale;
+ break;
- f = flags[idx];
+ case ADU_PER_EV:
+ detgeom->panels[i].adu_per_photon = dtempl->panels[i].adu_scale
+ * ph_lambda_to_eV(image->lambda);
+ break;
- /* Bad if it's missing any of the "good" bits */
- if ( (f & image->det->mask_good)
- != image->det->mask_good ) bad = 1;
+ default:
+ detgeom->panels[i].adu_per_photon = 1.0;
+ ERROR("Invalid ADU/ph scale unit (%i)\n",
+ dtempl->panels[i].adu_scale_unit);
+ break;
- /* Bad if it has any of the "bad" bits. */
- if ( f & image->det->mask_bad ) bad = 1;
+ }
- }
- image->bad[pi][fs+p->w*ss] = bad;
+ detgeom->panels[i].w = dtempl->panels[i].orig_max_fs
+ - dtempl->panels[i].orig_min_fs + 1;
+ detgeom->panels[i].h = dtempl->panels[i].orig_max_ss
+ - dtempl->panels[i].orig_min_ss + 1;
- }
- }
+ detgeom->panels[i].fsx = dtempl->panels[i].fsx;
+ detgeom->panels[i].fsy = dtempl->panels[i].fsy;
+ detgeom->panels[i].fsz = dtempl->panels[i].fsz;
+ detgeom->panels[i].ssx = dtempl->panels[i].ssx;
+ detgeom->panels[i].ssy = dtempl->panels[i].ssy;
+ detgeom->panels[i].ssz = dtempl->panels[i].ssz;
}
+ image->detgeom = detgeom;
+
return 0;
}
-static void cbf_fill_in_beam_parameters(struct beam_params *beam,
- struct imagefile *f,
- struct image *image)
+int image_set_zero_data(struct image *image,
+ const DataTemplate *dtempl)
{
- double eV;
+ int pi;
- if ( beam->photon_energy_from == NULL ) {
+ image->dp = malloc(dtempl->n_panels*sizeof(float *));
+ if ( image->dp == NULL ) return 1;
- /* Explicit value given */
- eV = beam->photon_energy;
+ for ( pi=0; pi<dtempl->n_panels; pi++ ) {
- } else {
+ struct panel_template *p;
+ int p_w, p_h;
+
+ p = &dtempl->panels[pi];
+ p_w = p->orig_max_fs - p->orig_min_fs + 1;
+ p_h = p->orig_max_ss - p->orig_min_ss + 1;
- ERROR("Can't get photon energy from CBF yet.\n");
- eV = 0.0;
+ image->dp[pi] = calloc(p_w*p_h, sizeof(float));
+ if ( image->dp[pi] == NULL ) return 1;
}
- image->lambda = ph_en_to_lambda(eV_to_J(eV))*beam->photon_energy_scale;
+ return 0;
}
-static void cbf_fill_in_clen(struct detector *det, struct imagefile *f)
+int image_set_zero_mask(struct image *image,
+ const DataTemplate *dtempl)
{
- int i;
-
- for ( i=0; i<det->n_panels; i++ ) {
+ int pi;
- struct panel *p = &det->panels[i];
+ image->bad = malloc(dtempl->n_panels*sizeof(int *));
+ image->sat = malloc(dtempl->n_panels*sizeof(float *));
+ if ( (image->bad == NULL) || (image->sat == NULL) ) return 1;
- if ( p->clen_from != NULL ) {
+ for ( pi=0; pi<dtempl->n_panels; pi++ ) {
- ERROR("Can't get clen from CBF yet.\n");
+ struct panel_template *p;
+ int p_w, p_h;
+ long int i;
- }
+ p = &dtempl->panels[pi];
+ p_w = p->orig_max_fs - p->orig_min_fs + 1;
+ p_h = p->orig_max_ss - p->orig_min_ss + 1;
- adjust_centering_for_rail(p);
+ image->bad[pi] = calloc(p_w*p_h, sizeof(int));
+ image->sat[pi] = calloc(p_w*p_h, sizeof(float));
+ if ( image->bad[pi] == NULL ) return 1;
+ if ( image->sat[pi] == NULL ) return 1;
+ for ( i=0; i<p_w*p_h; i++ ) {
+ image->sat[pi][i] = INFINITY;
+ }
}
-}
-
-static void add_out(float val, float *data_out, int nmemb_out,
- int *outpos, int *nrej)
-{
- if ( *outpos < nmemb_out ) {
- data_out[(*outpos)++] = val;
- } else {
- (*nrej)++;
- }
+ return 0;
}
-/* Reverses byte offset compression and converts to single precision float.
- * Note that this compression scheme specifies the data format of the input
- * data, therefore the X-Binary-Element-Type is completely ignored. */
-static void decode_cbf_byte_offset(float *data_out, int nmemb_out,
- const int8_t *data_in, const size_t n)
+static int file_exists(const char *filename)
{
- int inpos = 0;
- int outpos = 0;
- int nrej = 0;
- float val = 0.0;
-
- while ( inpos < n ) {
+ struct stat statbuf;
+ int r;
- int64_t delta = data_in[inpos++];
+ r = stat(filename, &statbuf);
+ if ( r != 0 ) {
+ return 0;
+ }
- if ( (delta >= -127) && (delta <= 127) ) {
- val += delta;
- add_out(val, data_out, nmemb_out, &outpos, &nrej);
- continue;
- }
+ return 1;
+}
- delta = *(int16_t *)(data_in+inpos);
- inpos += 2;
- if ( (delta >= -32767) && (delta <= 32767) ) {
- val += delta;
- add_out(val, data_out, nmemb_out, &outpos, &nrej);
- continue;
- }
+static int image_read_image_data(struct image *image,
+ const DataTemplate *dtempl,
+ const char *filename,
+ const char *event)
+{
+ if ( !file_exists(filename) ) {
+ ERROR("File not found: %s\n", filename);
+ return image_set_zero_data(image, dtempl);
+ }
- delta = *(int32_t *)(data_in+inpos);
- inpos += 4;
+ if ( is_hdf5_file(filename) ) {
+ return image_hdf5_read(image, dtempl, filename, event);
- if ( (delta >= -2147483647) && (delta <= 2147483647) ) {
- val += delta;
- add_out(val, data_out, nmemb_out, &outpos, &nrej);
- continue;
- }
+ } else if ( is_cbf_file(filename) ) {
+ return image_cbf_read(image, dtempl, filename, event, 0);
- delta = *(int64_t *)(data_in+inpos);
- inpos += 8;
- val += delta;
- add_out(val, data_out, nmemb_out, &outpos, &nrej);
+ } else if ( is_cbfgz_file(filename) ) {
+ return image_cbf_read(image, dtempl, filename, event, 1);
}
- if ( nrej > 0 ) {
- STATUS("%i elements rejected\n", nrej);
- }
+ ERROR("Unrecognised file type: %s\n", filename);
+ return 1;
}
-static int binary_start(char *data)
+static void set_image_parameters(struct image *image,
+ const DataTemplate *dtempl)
{
- char *datac = data;
- if ( (datac[0] == (char)0x0c) && (datac[1] == (char)0x1a)
- && (datac[2] == (char)0x04) && (datac[3] == (char)0xd5) ) return 1;
- return 0;
-}
+ /* Wavelength might be needed to create detgeom (adu_per_eV) */
+ image->lambda = convert_to_m(get_value(image,
+ dtempl->wavelength_from,
+ NULL),
+ dtempl->wavelength_unit);
+ image->bw = dtempl->bandwidth;
-enum cbf_data_conversion
-{
- CBF_NO_CONVERSION,
- CBF_BYTE_OFFSET,
- CBF_PACKED,
- CBF_CANONICAL
-};
+ /* FIXME: Possibly load spectrum from file */
+ image->spectrum = spectrum_generate_gaussian(image->lambda,
+ image->bw);
-enum cbf_data_type
-{
- CBF_NO_TYPE,
- CBF_ELEMENT_U8,
- CBF_ELEMENT_S8,
- CBF_ELEMENT_U16,
- CBF_ELEMENT_S16,
- CBF_ELEMENT_U32,
- CBF_ELEMENT_S32,
- CBF_ELEMENT_F32,
- CBF_ELEMENT_F64,
-};
+}
-static enum cbf_data_type parse_element_type(const char *t)
+static void mark_flagged_pixels_lessthan(float *dp, int *bad,
+ long int n, float val)
{
- if ( strstr(t, "signed 8-bit integer") != NULL )
- {
- return CBF_ELEMENT_S8;
+ long int i;
+ for ( i=0; i<n; i++ ) {
+ if ( dp[i] < val ) bad[i] = 1;
}
+}
- if ( strstr(t, "unsigned 8-bit integer") != NULL )
- {
- return CBF_ELEMENT_U8;
- }
- if ( strstr(t, "signed 16-bit integer") != NULL )
- {
- return CBF_ELEMENT_S16;
+static void mark_flagged_pixels_morethan(float *dp, int *bad,
+ long int n, float val)
+{
+ long int i;
+ for ( i=0; i<n; i++ ) {
+ if ( dp[i] > val ) bad[i] = 1;
}
+}
- if ( strstr(t, "unsigned 16-bit integer") != NULL )
- {
- return CBF_ELEMENT_U16;
- }
- if ( strstr(t, "signed 32-bit integer") != NULL )
- {
- return CBF_ELEMENT_S32;
- }
-
- if ( strstr(t, "unsigned 32-bit integer") != NULL )
- {
- return CBF_ELEMENT_U32;
- }
+static void mark_flagged_pixels_equal(float *dp, int *bad,
+ long int n, float val)
+{
+ long int i;
+ fenv_t envp;
- if ( strstr(t, "signed 32-bit real IEEE") != NULL )
- {
- return CBF_ELEMENT_F32;
- }
+ fegetenv(&envp);
+ fesetround(1); /* Round to nearest (for flag_value) */
- if ( strstr(t, "signed 64-bit real IEEE") != NULL )
- {
- return CBF_ELEMENT_F64;
+ for ( i=0; i<n; i++ ) {
+ if ( rint(dp[i]) == val ) bad[i] = 1;
}
- /* complex type is unsupported */
-
- return CBF_NO_TYPE;
+ fesetenv(&envp);
}
-static size_t element_size(enum cbf_data_type t)
+static void mark_flagged_pixels_naninf(float *dp, int *bad,
+ long int n)
{
- switch ( t ) {
- case CBF_ELEMENT_S8 : return 1;
- case CBF_ELEMENT_U8 : return 1;
- case CBF_ELEMENT_S16 : return 2;
- case CBF_ELEMENT_U16 : return 2;
- case CBF_ELEMENT_S32 : return 4;
- case CBF_ELEMENT_U32 : return 4;
- case CBF_ELEMENT_F32 : return 4;
- case CBF_ELEMENT_F64 : return 8;
- default : return 0;
+ long int i;
+ for ( i=0; i<n; i++ ) {
+ float val = dp[i];
+ if ( isnan(val) || isinf(val) ) bad[i] = 1;
}
}
-
-static int convert_type(float *data_out, long nmemb_exp,
- enum cbf_data_type eltype,
- void *data_in, size_t data_in_len)
+static void mark_flagged_pixels(struct panel_template *p,
+ float *dp, int *bad)
{
- long int i;
- long int o = 0;
- size_t elsize = element_size(eltype);
-
- if ( elsize == 0 ) return 1;
-
- if ( nmemb_exp * elsize > data_in_len ) {
- ERROR("Not enough CBF data for image size/type!\n");
- return 1;
- }
+ int p_w, p_h;
+ long int n;
+ int i;
- for ( i=0; i<nmemb_exp; i++ ) {
- switch ( eltype ) {
+ p_w = p->orig_max_fs - p->orig_min_fs + 1;
+ p_h = p->orig_max_ss - p->orig_min_ss + 1;
+ n = p_w * p_h;
- case CBF_ELEMENT_S8:
- data_out[o++] = ((int8_t *)data_in)[i];
- break;
+ mark_flagged_pixels_naninf(dp, bad, n);
- case CBF_ELEMENT_U8:
- data_out[o++] = ((uint8_t *)data_in)[i];
- break;
+ for ( i=0; i<MAX_FLAG_VALUES; i++ ) {
- case CBF_ELEMENT_S16:
- data_out[o++] = ((int16_t *)data_in)[i];
- break;
+ float fv = p->flag_values[i];
- case CBF_ELEMENT_U16:
- data_out[o++] = ((uint16_t *)data_in)[i];
- break;
+ switch ( p->flag_types[i] ) {
- case CBF_ELEMENT_S32:
- data_out[o++] = ((int32_t *)data_in)[i];
+ case FLAG_NOTHING:
break;
- case CBF_ELEMENT_U32:
- data_out[o++] = ((uint32_t *)data_in)[i];
+ case FLAG_LESSTHAN:
+ mark_flagged_pixels_lessthan(dp, bad, n, fv);
break;
- case CBF_ELEMENT_F32:
- data_out[o++] = ((float *)data_in)[i];
+ case FLAG_MORETHAN:
+ mark_flagged_pixels_morethan(dp, bad, n, fv);
break;
- case CBF_ELEMENT_F64:
- data_out[o++] = ((double *)data_in)[i];
+ case FLAG_EQUAL:
+ mark_flagged_pixels_equal(dp, bad, n, fv);
break;
- case CBF_NO_TYPE:
- break;
}
}
-
- return 0;
}
-static float *read_cbf_data(struct imagefile *f, int *w, int *h)
+static int region_within_panel(struct dt_badregion *region,
+ struct detgeom_panel *panel)
{
- FILE *fh;
- void *buf = NULL;
- char *rval;
- size_t data_compressed_len = 0;
- float *data_out = NULL;
- enum cbf_data_conversion data_conversion = CBF_NO_CONVERSION;
- enum cbf_data_type data_type = CBF_ELEMENT_U32; /* ITG (2006) 2.3.3.3 */
- int in_binary_section = 0;
+ assert(region->is_fsss);
- *w = 0;
- *h = 0;
+ if ( region->min_fs < 0 ) return 0;
+ if ( region->min_ss < 0 ) return 0;
+ if ( region->max_fs >= panel->w ) return 0;
+ if ( region->max_ss >= panel->h ) return 0;
+ return 1;
+}
- if ( f->type == IMAGEFILE_CBF ) {
- fh = fopen(f->filename, "rb");
- if ( fh == NULL ) {
- ERROR("Failed to open '%s'\n", f->filename);
- return NULL;
- }
+static void draw_bad_region_fsss(struct dt_badregion *region,
+ int **bad,
+ struct detgeom *detgeom)
+{
+ struct detgeom_panel *panel;
+ int fs, ss;
- } else if ( f->type == IMAGEFILE_CBFGZ ) {
+ panel = &detgeom->panels[region->panel_number];
- gzFile gzfh;
- size_t len, len_read;
- const size_t bufinc = 8*1024*1024; /* Allocate buffer in 8Mb chunks */
- size_t bufsz = bufinc;
+ if ( !region_within_panel(region, panel) ) {
+ ERROR("Bad pixel region %s is (partially) outside panel - ignoring it\n",
+ region->name);
+ return;
+ }
- gzfh = gzopen(f->filename, "rb");
- if ( gzfh == NULL ) return NULL;
+ for ( ss=region->min_ss; ss<=region->max_ss; ss++ ) {
+ for ( fs=region->min_fs; fs<=region->max_fs; fs++ ) {
+ bad[region->panel_number][fs+ss*panel->w] = 1;
+ }
+ }
+}
- #ifdef HAVE_GZBUFFER
- /* Set larger buffer size for hopefully faster uncompression */
- gzbuffer(gzfh, 128*1024);
- #endif
- buf = malloc(bufsz);
- if ( buf == NULL ) return NULL;
+static void draw_bad_region_xy(struct dt_badregion *region,
+ int **bad,
+ struct detgeom *detgeom)
+{
+ int i;
- len = 0;
- do {
+ for ( i=0; i<detgeom->n_panels; i++ ) {
- len_read = gzread(gzfh, buf+len, bufinc);
- if ( len_read == -1 ) return NULL;
- len += len_read;
+ int fs, ss;
- if ( len_read == bufinc ) {
- bufsz += bufinc;
- buf = realloc(buf, bufsz);
- if ( buf == NULL ) return NULL;
- }
+ struct detgeom_panel *p = &detgeom->panels[i];
+ for ( ss=0; ss<p->h; ss++ ) {
+ for ( fs=0; fs<p->w; fs++ ) {
- } while ( len_read == bufinc );
+ double x, y;
- fh = fmemopen(buf, len, "rb");
- if ( fh == NULL ) return NULL;
+ x = fs*p->fsx + ss*p->ssx + p->cnx;
+ y = fs*p->fsy + ss*p->ssy + p->cny;
- gzclose(gzfh);
+ if ( (x > region->min_x )
+ && (x < region->max_x)
+ && (y > region->min_y)
+ && (y < region->max_y) )
+ {
+ bad[i][fs+ss*p->w] = 1;
+ }
- } else {
- /* Don't know how we ended up here */
- return NULL;
+ }
+ }
}
+}
- /* This is really horrible, but there are at least three different types
- * of header mingled together (CIF, MIME, DECTRIS), so a real parser
- * would be very complicated and much more likely to have weird bugs. */
- do {
-
- char line[1024];
- long line_start;
- line_start = ftell(fh);
- rval = fgets(line, 1023, fh);
- if ( rval == NULL ) break;
- chomp(line);
+static void mark_bad_regions(struct image *image,
+ const DataTemplate *dtempl)
+{
+ int i;
- if ( strcmp(line, "--CIF-BINARY-FORMAT-SECTION--") == 0 ) {
- in_binary_section = 1;
+ for ( i=0; i<dtempl->n_bad; i++ ) {
+ if ( dtempl->bad[i].is_fsss ) {
+ draw_bad_region_fsss(&dtempl->bad[i],
+ image->bad,
+ image->detgeom);
+ } else {
+ draw_bad_region_xy(&dtempl->bad[i],
+ image->bad,
+ image->detgeom);
}
+ }
+}
- if ( strcmp(line, "--CIF-BINARY-FORMAT-SECTION----") == 0 ) {
- in_binary_section = 0;
- }
- if ( in_binary_section ) {
+static int load_mask(struct panel_template *p,
+ const char *mask_fn,
+ const char *ev,
+ int *bad,
+ const char *mask_location,
+ unsigned int mask_good,
+ unsigned int mask_bad)
+{
+ if ( is_hdf5_file(mask_fn) ) {
+ image_hdf5_read_mask(p, mask_fn, ev, bad, mask_location,
+ mask_good, mask_bad);
- if ( strncmp(line, "X-Binary-Size: ", 15) == 0 ) {
- data_compressed_len = atoi(line+15);
- }
+ } else if ( is_cbf_file(mask_fn) ) {
+ image_cbf_read_mask(p, mask_fn, ev, 0, bad,
+ mask_good, mask_bad);
- if ( strncmp(line, "X-Binary-Element-Byte-Order: ", 29) == 0 ) {
- const char *elbo = line+29;
- if ( strcmp(elbo, "LITTLE_ENDIAN") != 0 ) {
- ERROR("Unsupported endianness: %s\n", elbo);
- free(buf);
- fclose(fh);
- return NULL;
- }
- }
+ } else if ( is_cbfgz_file(mask_fn) ) {
+ image_cbf_read_mask(p, mask_fn, ev, 1, bad,
+ mask_good, mask_bad);
- /* Try to spot compression algorithm */
- if ( strstr(line, "conversions=\"x-CBF_BYTE_OFFSET\"") != NULL ) {
- data_conversion = CBF_BYTE_OFFSET;
- } else if ( strstr(line, "conversions=\"x-CBF_CANONICAL\"") != NULL ) {
- data_conversion = CBF_CANONICAL;
- } else if ( strstr(line, "conversions=\"x-CBF_PACKED\"") != NULL ) {
- data_conversion = CBF_PACKED;
- } else if ( strstr(line, "conversions=") != NULL ) {
- ERROR("Unrecognised CBF content conversion: %s\n", line);
- free(buf);
- fclose(fh);
- return NULL;
- }
+ } else {
+ ERROR("Unrecognised mask file type (%s)\n", mask_fn);
+ return 1;
+ }
- /* Likewise, element type */
- if ( strncmp(line, "X-Binary-Element-Type: ", 23) == 0 )
- {
- const char *eltype = (line+23);
- data_type = parse_element_type(eltype);
- if ( data_type == CBF_NO_TYPE ) {
- ERROR("Unrecognised element type: %s\n",
- eltype);
- free(buf);
- fclose(fh);
- return NULL;
- }
- }
+ return 0;
+}
- if ( strncmp(line, "X-Binary-Size-Fastest-Dimension: ", 33) == 0 ) {
- *w = atoi(line+33);
- }
- if ( strncmp(line, "X-Binary-Size-Second-Dimension: ", 32) == 0 ) {
- *h = atoi(line+32);
- }
+static int create_badmap(struct image *image,
+ const DataTemplate *dtempl,
+ int no_mask_data)
+{
+ int i;
- }
+ image->bad = malloc(dtempl->n_panels * sizeof(int *));
+ if ( image->bad == NULL ) {
+ ERROR("Failed to allocate bad pixel mask\n");
+ return 1;
+ }
- if ( in_binary_section && binary_start(line) ) {
+ for ( i=0; i<dtempl->n_panels; i++ ) {
- size_t len_read;
- int nmemb_exp;
- void *data_compressed;
- int r = 0;
+ int p_w, p_h;
+ struct panel_template *p = &dtempl->panels[i];
- if ( data_compressed_len == 0 ) {
- ERROR("Found CBF data before X-Binary-Size!\n");
- free(buf);
- fclose(fh);
- return NULL;
- }
+ p_w = p->orig_max_fs - p->orig_min_fs + 1;
+ p_h = p->orig_max_ss - p->orig_min_ss + 1;
- if ( (*w == 0) || (*h == 0) ) {
- ERROR("Found CBF data before dimensions!\n");
- free(buf);
- fclose(fh);
- return NULL;
- }
+ image->bad[i] = calloc(p_w*p_h, sizeof(int));
+ if ( image->bad[i] == NULL ) {
+ ERROR("Failed to allocate bad pixel mask\n");
+ return 1;
+ }
- if ( data_compressed_len > 100*1024*1024 ) {
- ERROR("Stated CBF data size too big\n");
- free(buf);
- fclose(fh);
- return NULL;
- }
+ /* Panel marked as bad? */
+ if ( p->bad ) {
+ /* NB this sets every element to 0x1111,
+ * but that's OK - value is still 'true'. */
+ memset(image->bad[i], 1, p_w*p_h);
+ }
- data_compressed = malloc(data_compressed_len);
- if ( data_compressed == NULL ) {
- ERROR("Failed to allocate memory for CBF data\n");
- free(buf);
- fclose(fh);
- return NULL;
- }
+ /* Add bad regions (skip if panel is bad anyway) */
+ if ( !p->bad ) {
+ mark_flagged_pixels(p, image->dp[i],
+ image->bad[i]);
+ }
- fseek(fh, line_start+4, SEEK_SET);
- len_read = fread(data_compressed, 1, data_compressed_len, fh);
- if ( len_read < data_compressed_len ) {
- ERROR("Couldn't read entire CBF data\n");
- free(buf);
- free(data_compressed);
- fclose(fh);
- return NULL;
- }
+ /* Load masks (skip if panel is bad anyway) */
+ if ( (!no_mask_data) && (!p->bad) ) {
- nmemb_exp = (*w) * (*h);
- data_out = malloc(nmemb_exp*sizeof(float));
- if ( data_out == NULL ) {
- ERROR("Failed to allocate memory for CBF data\n");
- free(buf);
- free(data_compressed);
- fclose(fh);
- return NULL;
- }
+ int j;
- switch ( data_conversion ) {
-
- case CBF_NO_CONVERSION:
- r = convert_type(data_out, nmemb_exp, data_type,
- data_compressed,
- data_compressed_len);
- break;
-
- case CBF_BYTE_OFFSET:
- decode_cbf_byte_offset(data_out, nmemb_exp,
- data_compressed,
- data_compressed_len);
- break;
-
- case CBF_PACKED:
- case CBF_CANONICAL:
- ERROR("Don't yet know how to decompress "
- "CBF_PACKED or CBF_CANONICAL\n");
- free(buf);
- free(data_compressed);
- fclose(fh);
- return NULL;
+ for ( j=0; j<MAX_MASKS; j++ ) {
- }
+ const char *mask_fn;
- free(data_compressed);
+ if ( p->masks[j].data_location == NULL ) {
+ continue;
+ }
- if ( r ) {
- free(buf);
- free(data_out);
- fclose(fh);
- return NULL;
- }
+ if ( p->masks[j].filename == NULL ) {
+ mask_fn = image->filename;
+ } else {
+ mask_fn = p->masks[j].filename;
+ }
- free(buf);
- fclose(fh);
- return data_out;
+ load_mask(p, mask_fn, image->ev, image->bad[i],
+ p->masks[j].data_location,
+ p->masks[j].good_bits,
+ p->masks[j].bad_bits);
+ }
}
+ }
- } while ( rval != NULL );
+ mark_bad_regions(image, dtempl);
- ERROR("Reached end of CBF file before finding data.\n");
- free(buf); /* might be NULL */
- return NULL;
+ return 0;
}
-static int read_cbf(struct imagefile *f, struct image *image)
+static int create_satmap(struct image *image,
+ const DataTemplate *dtempl)
{
- float *data;
- int w, h;
-
- data = read_cbf_data(f, &w, &h);
- if ( data == NULL ) {
- ERROR("Failed to read CBF data\n");
- return 1;
- }
-
- unpack_panels(image, data, w, h);
- free(data);
-
- if ( image->beam != NULL ) {
- cbf_fill_in_beam_parameters(image->beam, f, image);
- if ( image->lambda > 1000 ) {
- ERROR("WARNING: Missing or nonsensical wavelength "
- "(%e m) for %s.\n",
- image->lambda, image->filename);
- }
- }
- cbf_fill_in_clen(image->det, f);
- fill_in_adu(image);
-
+ /* FIXME: Implementation */
return 0;
}
-static int read_cbf_simple(struct imagefile *f, struct image *image)
+/**
+ * Create an image structure, suitable for simulation.
+ *
+ * WARNING: This is probably not the routine you are looking for!
+ * If you use this routine anywhere other than a simulation program, then
+ * you are abusing the API and can expect breakage. In particular, your
+ * program will only work when the experiment is completely described by
+ * the DataTemplate, with no values whatsoever coming from image headers.
+ *
+ * \returns the new image structure.
+ *
+ */
+struct image *image_create_for_simulation(const DataTemplate *dtempl)
{
- float *data;
- int w, h;
+ struct image *image;
- data = read_cbf_data(f, &w, &h);
- if ( data == NULL ) {
- ERROR("Failed to read CBF data\n");
- return 1;
+ if ( dtempl == NULL ) {
+ ERROR("NULL data template!\n");
+ return NULL;
}
- image->det = simple_geometry(image, w, h);
- image->dp = malloc(sizeof(float *));
- if ( image->dp == NULL ) {
- ERROR("Failed to allocate dp array\n");
- return 1;
+ image = image_new();
+ if ( image == NULL ) {
+ ERROR("Couldn't allocate image structure.\n");
+ return NULL;
}
- image->dp[0] = data;
+ if ( image_set_zero_data(image, dtempl) ) {
+ image_free(image);
+ return NULL;
+ }
- if ( image->beam != NULL ) {
- cbf_fill_in_beam_parameters(image->beam, f, image);
- if ( image->lambda > 1000 ) {
- ERROR("WARNING: Missing or nonsensical wavelength "
- "(%e m) for %s.\n",
- image->lambda, image->filename);
- }
+ set_image_parameters(image, dtempl);
+
+ if ( create_detgeom(image, dtempl) ) {
+ image_free(image);
+ return NULL;
}
- cbf_fill_in_clen(image->det, f);
- fill_in_adu(image);
- return 0;
-}
+ if ( create_badmap(image, dtempl, 1) ) {
+ image_free(image);
+ return NULL;
+ }
+ if ( create_satmap(image, dtempl) ) {
+ image_free(image);
+ return NULL;
+ }
-/****************************** Image files ***********************************/
+ return image;
+}
-signed int is_cbf_file(const char *filename)
+struct image *image_read(const DataTemplate *dtempl,
+ const char *filename,
+ const char *event,
+ int no_image_data,
+ int no_mask_data)
{
- FILE *fh;
- char line[1024];
+ struct image *image;
+ int r;
- fh = fopen(filename, "r");
- if ( fh == NULL ) return -1;
+ if ( dtempl == NULL ) {
+ ERROR("NULL data template!\n");
+ return NULL;
+ }
- if ( fgets(line, 1024, fh) == NULL ) return -1;
- fclose(fh);
+ image = image_new();
+ if ( image == NULL ) {
+ ERROR("Couldn't allocate image structure.\n");
+ return NULL;
+ }
- if ( strstr(line, "CBF") == NULL ) {
- return 0;
+ image->filename = strdup(filename);
+ if ( event != NULL ) {
+ image->ev = strdup(event);
+ } else {
+ image->ev = strdup("//"); /* Null event */
}
- return 1;
-}
+ /* Load the image data */
+ if ( !no_image_data ) {
+ r = image_read_image_data(image, dtempl,
+ filename, event);
+ } else {
+ r = image_set_zero_data(image, dtempl);
+ }
+ if ( r ) {
+ image_free(image);
+ return NULL;
+ }
+ set_image_parameters(image, dtempl);
-signed int is_cbfgz_file(const char *filename)
-{
- gzFile gzfh;
- char line[1024];
+ if ( create_detgeom(image, dtempl) ) {
+ image_free(image);
+ return NULL;
+ }
- gzfh = gzopen(filename, "rb");
- if ( gzfh == NULL ) return -1;
- if ( gzgets(gzfh, line, 1024) == NULL ) return -1;
- gzclose(gzfh);
+ if ( create_badmap(image, dtempl, no_mask_data) ) {
+ image_free(image);
+ return NULL;
+ }
- if ( strstr(line, "CBF") == NULL ) {
- return 0;
+ if ( create_satmap(image, dtempl) ) {
+ image_free(image);
+ return NULL;
}
- return 1;
+ return image;
}
-struct imagefile *imagefile_open(const char *filename)
+void image_free(struct image *image)
{
- struct imagefile *f;
+ int i, np;
+
+ if ( image == NULL ) return;
+ image_feature_list_free(image->features);
+ free_all_crystals(image);
+ spectrum_free(image->spectrum);
+ free(image->filename);
+ free(image->ev);
+
+ if ( image->detgeom != NULL ) {
+ np = image->detgeom->n_panels;
+ detgeom_free(image->detgeom);
+ } else {
+ np = 0;
+ }
- f = malloc(sizeof(struct imagefile));
- if ( f == NULL ) return NULL;
+ for ( i=0; i<np; i++ ) {
+ if ( image->dp != NULL ) free(image->dp[i]);
+ if ( image->sat != NULL ) free(image->sat[i]);
+ if ( image->bad != NULL ) free(image->bad[i]);
+ }
- if ( H5Fis_hdf5(filename) > 0 ) {
+ free(image->dp);
+ free(image->sat);
+ free(image->bad);
- /* This is an HDF5, pass through to HDF5 layer */
- f->type = IMAGEFILE_HDF5;
- f->hdfile = hdfile_open(filename);
+ free(image);
+}
- if ( f->hdfile == NULL ) {
- free(f);
- return NULL;
- }
- } else if ( is_cbf_file(filename) > 0 ) {
+struct image *image_new()
+{
+ struct image *image;
+
+ image = malloc(sizeof(struct image));
+ if ( image == NULL ) return NULL;
+
+ image->dp = NULL;
+ image->bad = NULL;
+ image->sat = NULL;
+ image->hit = 0;
+ image->crystals = NULL;
+ image->n_crystals = 0;
+ image->indexed_by = INDEXING_NONE;
+ image->detgeom = NULL;
+ image->filename = NULL;
+ image->ev = NULL;
+ image->copied_headers = NULL;
+ image->id = 0;
+ image->serial = 0;
+ image->spectrum = NULL;
+ image->lambda = -1.0;
+ image->div = 0.0;
+ image->bw = -1.0;
+ image->peak_resolution = -1.0;
+ image->features = NULL;
+
+ return image;
+}
- f->type = IMAGEFILE_CBF;
- } else if ( is_cbfgz_file(filename) ) {
+ImageFeatureList *image_read_peaks(const DataTemplate *dtempl,
+ const char *filename,
+ const char *event,
+ int half_pixel_shift)
+{
+ if ( is_hdf5_file(filename) ) {
- f->type = IMAGEFILE_CBFGZ;
+ enum peak_layout layout;
- } else {
+ if ( dtempl->peak_list_type == PEAK_LIST_AUTO ) {
- ERROR("Unrecognised file type: %s\n", filename);
- return NULL;
+ const char *ext;
+ ext = filename_extension(filename, NULL);
- }
+ if ( strcmp(ext, ".cxi") == 0 ) {
+ layout = PEAK_LIST_CXI;
+ } else if ( strcmp(ext, ".h5") == 0 ) {
+ layout = PEAK_LIST_LIST3;
+ } else {
+ ERROR("Couldn't determine peak list layout.\n");
+ ERROR("Specify peak_layout = cxi or list3n in geometry file.\n");
+ return NULL;
+ }
- f->filename = strdup(filename);
- return f;
-}
+ } else {
+ layout = dtempl->peak_list_type;
+ }
+ switch ( layout ) {
-int imagefile_read(struct imagefile *f, struct image *image,
- struct event *event)
-{
- if ( f->type == IMAGEFILE_HDF5 ) {
- return hdf5_read2(f->hdfile, image, event, 0);
- } else if ( f->type == IMAGEFILE_CBF ) {
- return read_cbf(f, image);
- } else if ( f->type == IMAGEFILE_CBFGZ ) {
- return read_cbf(f, image);
- } else {
- ERROR("Unknown file type %i\n", f->type);
- return 1;
- }
-}
+ case PEAK_LIST_CXI :
+ return image_hdf5_read_peaks_cxi(dtempl,
+ filename,
+ event,
+ half_pixel_shift);
+ case PEAK_LIST_LIST3 :
+ return image_hdf5_read_peaks_hdf5(dtempl,
+ filename,
+ event,
+ half_pixel_shift);
-/* Read a simple file, no multi-event, no prior geometry etc, and
- * generate a geometry for it */
-int imagefile_read_simple(struct imagefile *f, struct image *image)
-{
- if ( f->type == IMAGEFILE_HDF5 ) {
- return hdf5_read(f->hdfile, image, NULL, 0);
- } else if ( f->type == IMAGEFILE_CBF ) {
- return read_cbf_simple(f, image);
- } else if ( f->type == IMAGEFILE_CBFGZ ) {
- return read_cbf_simple(f, image);
- } else {
- ERROR("Unknown file type %i\n", f->type);
- return 1;
- }
-}
+ default :
+ ERROR("Invalid peak list type %i\n", layout);
+ return NULL;
+ }
-enum imagefile_type imagefile_get_type(struct imagefile *f)
-{
- assert(f != NULL);
- return f->type;
+ } else {
+ ERROR("Peak lists can only be read from HDF5 files\n");
+ return NULL;
+ }
}
-struct hdfile *imagefile_get_hdfile(struct imagefile *f)
+char **image_expand_frames(const DataTemplate *dtempl,
+ const char *filename, int *n_frames)
{
- if ( f == NULL ) return NULL;
-
- if ( f->type != IMAGEFILE_HDF5 ) {
- ERROR("Not an HDF5 file!\n");
+ if ( !file_exists(filename) ) {
+ ERROR("File not found: %s\n", filename);
return NULL;
}
- return f->hdfile;
+ if ( is_hdf5_file(filename) ) {
+ return image_hdf5_expand_frames(dtempl, filename,
+ n_frames);
+ } else {
+ char **list;
+ list = malloc(sizeof(char *));
+ if ( list == NULL ) return NULL;
+ list[0] = strdup("//");
+ if ( list[0] == NULL ) return NULL;
+ *n_frames = 1;
+ return list;
+ }
}
-void imagefile_copy_fields(struct imagefile *f,
- const struct imagefile_field_list *copyme,
- FILE *fh, struct event *ev)
+void mark_resolution_range_as_bad(struct image *image,
+ double min, double max)
{
int i;
- if ( copyme == NULL ) return;
+ if ( isinf(min) && isinf(max) ) return; /* nothing to do */
- for ( i=0; i<copyme->n_fields; i++ ) {
+ for ( i=0; i<image->detgeom->n_panels; i++ ) {
- char *val;
- char *field;
-
- field = copyme->fields[i];
+ int fs, ss;
+ struct detgeom_panel *p = &image->detgeom->panels[i];
- if ( f->type == IMAGEFILE_HDF5 ) {
- val = hdfile_get_string_value(f->hdfile, field, ev);
- if ( field[0] == '/' ) {
- fprintf(fh, "hdf5%s = %s\n", field, val);
- } else {
- fprintf(fh, "hdf5/%s = %s\n", field, val);
+ for ( ss=0; ss<p->h; ss++ ) {
+ for ( fs=0; fs<p->w; fs++ ) {
+ double q[3];
+ double r;
+ detgeom_transform_coords(p, fs, ss,
+ image->lambda,
+ 0.0, 0.0, q);
+ r = modulus(q[0], q[1], q[2]);
+ if ( (r >= min) && (r <= max) ) {
+ image->bad[i][fs+p->w*ss] = 1;
+ }
}
- free(val);
-
- } else {
- STATUS("Mock CBF variable\n");
- fprintf(fh, "cbf/%s = %s\n", field, "(FIXME)");
}
-
}
}
-void imagefile_close(struct imagefile *f)
+int image_write(const struct image *image,
+ const DataTemplate *dtempl,
+ const char *filename)
{
- if ( f->type == IMAGEFILE_HDF5 ) {
- hdfile_close(f->hdfile);
+ if ( is_hdf5_file(filename) ) {
+ return image_hdf5_write(image, dtempl, filename);
}
- free(f->filename);
- free(f);
+
+ ERROR("Can only write to HDF5 files.\n");
+ return 1;
}
diff --git a/libcrystfel/src/image.h b/libcrystfel/src/image.h
index d3bb56e5..c3b55ba0 100644
--- a/libcrystfel/src/image.h
+++ b/libcrystfel/src/image.h
@@ -3,11 +3,11 @@
*
* Handle images and image features
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2009-2019 Thomas White <taw@physics.org>
+ * 2009-2020 Thomas White <taw@physics.org>
* 2014 Valerio Mariani
*
*
@@ -28,33 +28,23 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#ifndef IMAGE_H
#define IMAGE_H
-struct detector;
-
#include <stdint.h>
#include <complex.h>
#include <sys/types.h>
struct imagefeature;
-struct sample;
struct image;
-struct imagefile;
-struct imagefile_field_list;
#include "utils.h"
#include "cell.h"
-#include "detector.h"
#include "reflist.h"
#include "crystal.h"
#include "index.h"
-#include "events.h"
#include "spectrum.h"
+#include "datatemplate.h"
/**
* \file image.h
@@ -65,8 +55,6 @@ struct imagefile_field_list;
/** Represents a peak in an image. */
struct imagefeature {
- struct image *parent; /**< Pointer to image */
-
/** \name Coordinates on panel (fast scan, slow scan)
* Note carefully that these are the distances, measured in pixels,
* from the corner of the panel. They are NOT pixel indices.
@@ -77,44 +65,17 @@ struct imagefeature {
double ss;
/**@}*/
- struct panel *p; /**< Pointer to panel */
+ int pn; /**< Panel number */
double intensity; /**< Intensity */
- /** \name Reciprocal space coordinates (m^-1) of this feature */
- /** @{ */
- double rx;
- double ry;
- double rz;
- /** @} */
-
const char *name; /**< Text name, e.g. "5,3,-1" */
};
-/** An enum representing the image file formats we can handle */
-enum imagefile_type
-{
- IMAGEFILE_HDF5, /**< HDF5 file (single or multiple frames per file) */
- IMAGEFILE_CBF, /**< CBF file */
- IMAGEFILE_CBFGZ /**< gzipped CBF file, i.e. "file.cbf.gz" */
-};
-
-
/** An opaque type representing a list of image features */
typedef struct _imagefeaturelist ImageFeatureList;
-struct beam_params
-{
- double photon_energy; /**< eV per photon */
- char *photon_energy_from; /**< HDF5 dataset name */
- double photon_energy_scale; /**< Scale factor for photon energy, if it
- * comes from an image header */
- double bandwidth; /**< FWHM bandwidth as a fraction of
- * wavelength */
-};
-
-
struct image
{
/** The image data, by panel */
@@ -142,25 +103,16 @@ struct image
int n_indexing_tries;
/** The detector structure */
- struct detector *det;
-
- /** The nominal beam parameters (or where to get them) */
- struct beam_params *beam;
+ struct detgeom *detgeom;
/** \name The filename and event ID for the image
* @{ */
char *filename;
- struct event *event;
+ char *ev;
/** @} */
- /** A list of image file headers to copy to the stream */
- const struct imagefile_field_list *copyme;
-
/** A list of metadata read from the stream */
- struct stuff_from_stream *stuff_from_stream;
-
- /** Mean of the camera length values for all panels */
- double avg_clen;
+ char *copied_headers;
/** ID number of the worker processing handling this image */
int id;
@@ -198,7 +150,7 @@ extern ImageFeatureList *image_feature_list_new(void);
extern void image_feature_list_free(ImageFeatureList *flist);
extern void image_add_feature(ImageFeatureList *flist, double x, double y,
- struct panel *p,
+ int pn,
struct image *parent, double intensity,
const char *name);
@@ -206,42 +158,53 @@ extern void image_remove_feature(ImageFeatureList *flist, int idx);
extern struct imagefeature *image_feature_closest(ImageFeatureList *flist,
double fs, double ss,
- struct panel *p,
+ int pn,
double *d, int *idx);
-extern Reflection *image_reflection_closest(RefList *rlist,
- double fs, double ss,
- struct panel *p,
- struct detector *det,
- double *d);
-
extern int image_feature_count(ImageFeatureList *flist);
extern struct imagefeature *image_get_feature(ImageFeatureList *flist, int idx);
+extern const struct imagefeature *image_get_feature_const(const ImageFeatureList *flist,
+ int idx);
extern ImageFeatureList *sort_peaks(ImageFeatureList *flist);
+extern ImageFeatureList *image_feature_list_copy(const ImageFeatureList *flist);
extern void image_add_crystal(struct image *image, Crystal *cryst);
extern int remove_flagged_crystals(struct image *image);
extern void free_all_crystals(struct image *image);
-/* Image files */
-extern struct imagefile *imagefile_open(const char *filename);
-extern int imagefile_read(struct imagefile *f, struct image *image,
- struct event *event);
-extern int imagefile_read_simple(struct imagefile *f, struct image *image);
-extern struct hdfile *imagefile_get_hdfile(struct imagefile *f);
-extern enum imagefile_type imagefile_get_type(struct imagefile *f);
-extern void imagefile_copy_fields(struct imagefile *f,
- const struct imagefile_field_list *copyme,
- FILE *fh, struct event *ev);
-extern void imagefile_close(struct imagefile *f);
-extern signed int is_cbf_file(const char *filename);
-
-/* Field lists */
-extern struct imagefile_field_list *new_imagefile_field_list(void);
-extern void free_imagefile_field_list(struct imagefile_field_list *f);
-
-extern void add_imagefile_field(struct imagefile_field_list *copyme,
- const char *name);
+extern void mark_resolution_range_as_bad(struct image *image,
+ double min, double max);
+
+extern struct image *image_new(void);
+extern struct image *image_read(const DataTemplate *dtempl,
+ const char *filename,
+ const char *event,
+ int no_image_data,
+ int no_mask_data);
+extern struct image *image_create_for_simulation(const DataTemplate *dtempl);
+extern void image_free(struct image *image);
+
+extern ImageFeatureList *image_read_peaks(const DataTemplate *dtempl,
+ const char *filename,
+ const char *event,
+ int half_pixel_shift);
+
+extern char **image_expand_frames(const DataTemplate *dtempl,
+ const char *filename, int *nframes);
+
+extern int image_set_zero_data(struct image *image,
+ const DataTemplate *dtempl);
+
+extern int image_set_zero_mask(struct image *image,
+ const DataTemplate *dtempl);
+
+extern int image_write(const struct image *image,
+ const DataTemplate *dtempl,
+ const char *filename);
+
+/* Use within libcrystfel only */
+extern int create_detgeom(struct image *image,
+ const DataTemplate *dtempl);
#ifdef __cplusplus
}
diff --git a/libcrystfel/src/index.c b/libcrystfel/src/index.c
index 7b03ba3e..58e90437 100644
--- a/libcrystfel/src/index.c
+++ b/libcrystfel/src/index.c
@@ -3,12 +3,12 @@
*
* Perform indexing (somehow)
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2012 Lorenzo Galli
*
* Authors:
- * 2010-2017 Thomas White <taw@physics.org>
+ * 2010-2021 Thomas White <taw@physics.org>
* 2010-2011 Richard Kirian <rkirian@asu.edu>
* 2012 Lorenzo Galli
* 2013 Cornelius Gati <cornelius.gati@cfel.de>
@@ -47,19 +47,18 @@
#include "image.h"
#include "utils.h"
#include "peaks.h"
-#include "dirax.h"
-#include "asdf.h"
-#include "mosflm.h"
-#include "xds.h"
-#include "detector.h"
#include "index.h"
#include "geometry.h"
#include "cell-utils.h"
-#include "felix.h"
#include "predict-refine.h"
-#include "taketwo.h"
-#include "xgandalf.h"
-#include "pinkindexer.h"
+#include "indexers/dirax.h"
+#include "indexers/asdf.h"
+#include "indexers/mosflm.h"
+#include "indexers/xds.h"
+#include "indexers/felix.h"
+#include "indexers/taketwo.h"
+#include "indexers/xgandalf.h"
+#include "indexers/pinkindexer.h"
#include "fromfile.h"
#include "uthash.h"
@@ -72,6 +71,8 @@ struct _indexingprivate
IndexingFlags flags;
UnitCell *target_cell;
double tolerance[6];
+ double wavelength_estimate;
+ int n_threads;
int n_methods;
IndexingMethod *methods;
@@ -113,7 +114,8 @@ static void show_indexing_flags(IndexingFlags flags)
onoff(flags & INDEXING_RETRY));
}
-static char *base_indexer_str(IndexingMethod indm)
+
+char *base_indexer_str(IndexingMethod indm)
{
char *str;
@@ -199,7 +201,7 @@ static char *friendly_indexer_name(IndexingMethod m)
static void *prepare_method(IndexingMethod *m, UnitCell *cell,
- struct detector *det, struct beam_params *beam,
+ double wavelength_estimate,
struct xgandalf_options *xgandalf_opts,
struct pinkIndexer_options* pinkIndexer_opts,
struct felix_options *felix_opts,
@@ -250,7 +252,7 @@ static void *prepare_method(IndexingMethod *m, UnitCell *cell,
case INDEXING_PINKINDEXER :
priv = pinkIndexer_prepare(m, cell, pinkIndexer_opts,
- det, beam);
+ wavelength_estimate);
break;
default :
@@ -280,23 +282,16 @@ static void *prepare_method(IndexingMethod *m, UnitCell *cell,
}
-IndexingPrivate *setup_indexing(const char *method_list, UnitCell *cell,
- struct detector *det, struct beam_params *beam,
- float *tols, IndexingFlags flags,
- struct taketwo_options *ttopts,
- struct xgandalf_options *xgandalf_opts,
- struct pinkIndexer_options *pinkIndexer_opts,
- struct felix_options *felix_opts,
- char *filename)
+IndexingMethod *parse_indexing_methods(const char *method_list,
+ int *pn)
{
int i, n;
char **method_strings;
- IndexingPrivate *ipriv;
+ IndexingMethod *methods;
- /* Parse indexing methods */
n = assplode(method_list, ",", &method_strings, ASSPLODE_NONE);
- IndexingMethod *methods = malloc(n * sizeof(IndexingMethod));
+ methods = malloc(n * sizeof(IndexingMethod));
if ( methods == NULL ) {
ERROR("Failed to allocate indexing method list\n");
return NULL;
@@ -323,6 +318,30 @@ IndexingPrivate *setup_indexing(const char *method_list, UnitCell *cell,
}
free(method_strings);
+ *pn = n;
+ return methods;
+}
+
+
+/* 'tols' is in frac (not %) and radians */
+IndexingPrivate *setup_indexing(const char *method_list,
+ UnitCell *cell,
+ float *tols,
+ IndexingFlags flags,
+ double wavelength_estimate,
+ int n_threads,
+ struct taketwo_options *ttopts,
+ struct xgandalf_options *xgandalf_opts,
+ struct pinkIndexer_options *pinkIndexer_opts,
+ struct felix_options *felix_opts,
+ char *filename)
+{
+ IndexingPrivate *ipriv;
+ IndexingMethod *methods;
+ int n, i;
+
+ methods = parse_indexing_methods(method_list, &n);
+
/* No cell parameters -> no cell checking, no prior cell */
if ( !cell_has_parameters(cell) ) {
@@ -380,7 +399,7 @@ IndexingPrivate *setup_indexing(const char *method_list, UnitCell *cell,
int j;
ipriv->engine_private[i] = prepare_method(&methods[i], cell,
- det, beam,
+ wavelength_estimate,
xgandalf_opts,
pinkIndexer_opts,
felix_opts,
@@ -424,6 +443,8 @@ IndexingPrivate *setup_indexing(const char *method_list, UnitCell *cell,
ipriv->methods = methods;
ipriv->n_methods = n;
ipriv->flags = flags;
+ ipriv->wavelength_estimate = wavelength_estimate;
+ ipriv->n_threads = n_threads;
if ( cell != NULL ) {
ipriv->target_cell = cell_new_from_cell(cell);
@@ -518,29 +539,6 @@ void cleanup_indexing(IndexingPrivate *ipriv)
}
-void map_all_peaks(struct image *image)
-{
- int i, n;
-
- n = image_feature_count(image->features);
-
- /* Map positions to 3D */
- for ( i=0; i<n; i++ ) {
-
- struct imagefeature *f;
- struct rvec r;
-
- f = image_get_feature(image->features, i);
- if ( f == NULL ) continue;
-
- r = get_q_for_panel(f->p, f->fs, f->ss,
- NULL, 1.0/image->lambda);
- f->rx = r.u; f->ry = r.v; f->rz = r.w;
-
- }
-}
-
-
/* Return 0 for cell OK, 1 for cell incorrect */
static int check_cell(IndexingFlags flags, Crystal *cr, UnitCell *target,
double *tolerance)
@@ -551,10 +549,14 @@ static int check_cell(IndexingFlags flags, Crystal *cr, UnitCell *target,
/* Check at all? */
if ( !(flags & INDEXING_CHECK_CELL) ) return 0;
- if ( !right_handed(target) ) STATUS("WARNING: reference cell is left handed\n");
- if ( !right_handed(crystal_get_cell(cr)) ) STATUS("WARNING: unmatched cell is left handed\n");
+ if ( !right_handed(target) ) {
+ STATUS("WARNING: reference cell is left handed\n");
+ }
+ if ( !right_handed(crystal_get_cell(cr)) ) {
+ STATUS("WARNING: unmatched cell is left handed\n");
+ }
out = compare_reindexed_cell_parameters(crystal_get_cell(cr), target,
- tolerance, &rm);
+ tolerance, &rm);
if ( out != NULL ) {
@@ -573,6 +575,12 @@ static int check_cell(IndexingFlags flags, Crystal *cr, UnitCell *target,
cell_set_lattice_type(out, cell_get_lattice_type(target));
cell_set_unique_axis(out, cell_get_unique_axis(target));
+ /* Correct P to R centering, for the same reason */
+ if ( (cell_get_centering(target) == 'R')
+ && (cell_get_centering(out) == 'P') ) {
+ cell_set_centering(out, 'R');
+ }
+
return 0;
}
@@ -580,6 +588,16 @@ static int check_cell(IndexingFlags flags, Crystal *cr, UnitCell *target,
}
+#ifdef MEASURE_INDEX_TIME
+static float real_time()
+{
+ struct timespec tp;
+ clock_gettime(CLOCK_MONOTONIC_RAW, &tp);
+ return tp.tv_sec + tp.tv_nsec*1e-9;
+}
+#endif
+
+
/* Return non-zero for "success" */
static int try_indexer(struct image *image, IndexingMethod indm,
IndexingPrivate *ipriv, void *mpriv, char *last_task)
@@ -588,6 +606,12 @@ static int try_indexer(struct image *image, IndexingMethod indm,
int n_bad = 0;
int n_before = image->n_crystals;
+ #ifdef MEASURE_INDEX_TIME
+ float time_start;
+ float time_end;
+ time_start = real_time();
+ #endif
+
switch ( indm & INDEXING_METHOD_MASK ) {
case INDEXING_NONE :
@@ -631,7 +655,7 @@ static int try_indexer(struct image *image, IndexingMethod indm,
case INDEXING_PINKINDEXER :
set_last_task(last_task, "indexing:pinkindexer");
- r = run_pinkIndexer(image, mpriv);
+ r = run_pinkIndexer(image, mpriv, ipriv->n_threads);
break;
case INDEXING_XGANDALF :
@@ -647,6 +671,10 @@ static int try_indexer(struct image *image, IndexingMethod indm,
set_last_task(last_task, "indexing:finalisation");
+ #ifdef MEASURE_INDEX_TIME
+ time_end = real_time();
+ #endif
+
/* Stop a really difficult to debug situation in its tracks */
if ( image->n_crystals - n_before != r ) {
ERROR("Whoops, indexer didn't return the right number "
@@ -710,6 +738,7 @@ static int try_indexer(struct image *image, IndexingMethod indm,
for ( j=0; j<this_crystal; j++ ) {
Crystal *that_cr = image->crystals[j];
+ /* 'tols' is in frac (not %) and radians */
const double tols[] = {0.1, 0.1, 0.1,
deg2rad(5.0),
deg2rad(5.0),
@@ -731,6 +760,16 @@ static int try_indexer(struct image *image, IndexingMethod indm,
n_bad = remove_flagged_crystals(image);
assert(r >= n_bad);
+ #ifdef MEASURE_INDEX_TIME
+ printf("%s took %f s, %i crystals found of which %i accepted. %s %s\n",
+ indexer_str(indm & INDEXING_METHOD_MASK),
+ time_end - time_start,
+ r, r - n_bad,
+ image->filename,
+ image->ev);
+ fflush(stdout);
+ #endif
+
return r - n_bad;
}
@@ -765,6 +804,7 @@ static int delete_explained_peaks(struct image *image, Crystal *cr)
double ax, ay, az;
double bx, by, bz;
double cx, cy, cz;
+ double dx, dy;
const double min_dist = 0.25;
int i, nspots = 0, nindexed = 0;
@@ -775,11 +815,13 @@ static int delete_explained_peaks(struct image *image, Crystal *cr)
cell_get_cartesian(crystal_get_cell(cr), &ax, &ay, &az,
&bx, &by, &bz, &cx, &cy, &cz);
+ crystal_get_det_shift(cr, &dx, &dy);
+
/* Loop over peaks, checking proximity to nearest reflection */
for ( i=0; i<image_feature_count(image->features); i++ ) {
struct imagefeature *f;
- struct rvec q;
+ double q[3];
double h, k, l, hd, kd, ld;
double dsq;
@@ -788,14 +830,15 @@ static int delete_explained_peaks(struct image *image, Crystal *cr)
nspots++;
/* Reciprocal space position of found peak */
- q = get_q_for_panel(f->p, f->fs, f->ss,
- NULL, 1.0/image->lambda);
+ detgeom_transform_coords(&image->detgeom->panels[f->pn],
+ f->fs, f->ss, image->lambda, dx, dy,
+ q);
/* Decimal and fractional Miller indices of nearest
* reciprocal lattice point */
- hd = q.u * ax + q.v * ay + q.w * az;
- kd = q.u * bx + q.v * by + q.w * bz;
- ld = q.u * cx + q.v * cy + q.w * cz;
+ hd = q[0] * ax + q[1] * ay + q[2] * az;
+ kd = q[0] * bx + q[1] * by + q[2] * bz;
+ ld = q[0] * cx + q[1] * cy + q[2] * cz;
h = lrint(hd);
k = lrint(kd);
l = lrint(ld);
@@ -875,14 +918,23 @@ void index_pattern_3(struct image *image, IndexingPrivate *ipriv, int *ping,
if ( ipriv == NULL ) return;
- if ( ipriv->methods[0] != INDEXING_FILE){
- map_all_peaks(image);
- orig = image->features;
- }
-
image->crystals = NULL;
image->n_crystals = 0;
+ if ( !isnan(ipriv->wavelength_estimate) ) {
+ if ( !within_tolerance(image->lambda,
+ ipriv->wavelength_estimate,
+ 10.0) )
+ {
+ ERROR("WARNING: Wavelength for %s %s (%e) differs by "
+ "more than 10%% from estimated value (%e)\n",
+ image->filename, image->ev,
+ image->lambda, ipriv->wavelength_estimate);
+ }
+ }
+
+ orig = image->features;
+
for ( n=0; n<ipriv->n_methods; n++ ) {
int done = 0;
@@ -921,13 +973,6 @@ void index_pattern_3(struct image *image, IndexingPrivate *ipriv, int *ping,
}
- if ( ipriv->methods[0] == INDEXING_FILE){
- map_all_peaks(image);
- }
- else{
- image->features = orig;
- }
-
if ( n < ipriv->n_methods ) {
image->indexed_by = ipriv->methods[n];
} else {
@@ -1144,13 +1189,13 @@ char *detect_indexing_methods(UnitCell *cell)
if ( methods == NULL ) return NULL;
methods[0] = '\0';
+ do_probe(taketwo_probe, cell, methods);
+ do_probe(xgandalf_probe, cell, methods);
do_probe(mosflm_probe, cell, methods);
- do_probe(dirax_probe, cell, methods);
do_probe(asdf_probe, cell, methods);
+ do_probe(dirax_probe, cell, methods);
do_probe(xds_probe, cell, methods);
- do_probe(xgandalf_probe, cell, methods);
- /* Don't automatically use TakeTwo, Felix or PinkIndexer (yet) */
- //do_probe(taketwo_probe, cell, methods);
+
//do_probe(felix_probe, cell, methods);
//do_probe(pinkIndexer_probe, cell, methods);
@@ -1161,3 +1206,15 @@ char *detect_indexing_methods(UnitCell *cell)
return methods;
}
+
+
+void default_method_options(TakeTwoOptions **ttopts,
+ XGandalfOptions **xgandalf_opts,
+ PinkIndexerOptions **pinkIndexer_opts,
+ FelixOptions **felix_opts)
+{
+ taketwo_default_options(ttopts);
+ xgandalf_default_options(xgandalf_opts);
+ pinkIndexer_default_options(pinkIndexer_opts);
+ felix_default_options(felix_opts);
+}
diff --git a/libcrystfel/src/index.h b/libcrystfel/src/index.h
index bd5be68e..92406604 100644
--- a/libcrystfel/src/index.h
+++ b/libcrystfel/src/index.h
@@ -3,13 +3,13 @@
*
* Perform indexing (somehow)
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2012 Richard Kirian
* Copyright © 2012 Lorenzo Galli
*
* Authors:
- * 2010-2017 Thomas White <taw@physics.org>
+ * 2010-2021 Thomas White <taw@physics.org>
* 2010 Richard Kirian
* 2012 Lorenzo Galli
* 2015 Kenneth Beyerlein <kenneth.beyerlein@desy.de>
@@ -34,10 +34,6 @@
#ifndef INDEX_H
#define INDEX_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
/**
* \file index.h
* The indexing subsystem
@@ -144,18 +140,35 @@ extern char *indexer_str(IndexingMethod indm);
extern IndexingMethod get_indm_from_string(const char *method);
extern IndexingMethod get_indm_from_string_2(const char *method, int *err);
-#include "detector.h"
+extern IndexingMethod *parse_indexing_methods(const char *method_list,
+ int *pn);
+extern char *base_indexer_str(IndexingMethod indm);
+
#include "cell.h"
#include "image.h"
-#include "taketwo.h"
-#include "xgandalf.h"
-#include "pinkindexer.h"
-#include "felix.h"
-
-extern IndexingPrivate *setup_indexing(const char *methods, UnitCell *cell,
- struct detector *det,
- struct beam_params *beam, float *ltl,
+#include "datatemplate.h"
+
+typedef struct felix_options FelixOptions;
+typedef struct taketwo_options TakeTwoOptions;
+typedef struct xgandalf_options XGandalfOptions;
+typedef struct pinkIndexer_options PinkIndexerOptions;
+
+extern struct argp felix_argp;
+extern struct argp pinkIndexer_argp;
+extern struct argp taketwo_argp;
+extern struct argp xgandalf_argp;
+
+extern void default_method_options(TakeTwoOptions **ttopts,
+ XGandalfOptions **xgandalf_opts,
+ PinkIndexerOptions **pinkIndexer_opts,
+ FelixOptions **felix_opts);
+
+extern IndexingPrivate *setup_indexing(const char *methods,
+ UnitCell *cell,
+ float *ltl,
IndexingFlags flags,
+ double wavelength_estimate,
+ int n_threads,
struct taketwo_options *ttopts,
struct xgandalf_options *xgandalf_opts,
struct pinkIndexer_options *pinkIndexer_opts,
diff --git a/libcrystfel/src/asdf.c b/libcrystfel/src/indexers/asdf.c
index 7185172d..0c57f9f0 100644
--- a/libcrystfel/src/asdf.c
+++ b/libcrystfel/src/indexers/asdf.c
@@ -4,12 +4,12 @@
* Alexandra's Superior Direction Finder, or
* Algorithm Similar to DirAx, FFT-based
*
- * Copyright © 2014-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2014-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
* 2014-2015 Alexandra Tolstikova <alexandra.tolstikova@desy.de>
- * 2015,2017 Thomas White <taw@physics.org>
+ * 2015-2017 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -42,19 +42,27 @@
#include <gsl/gsl_linalg.h>
#include <gsl/gsl_multifit.h>
#include <gsl/gsl_fit.h>
-#include <fftw3.h>
#include "image.h"
-#include "dirax.h"
#include "utils.h"
#include "peaks.h"
#include "cell-utils.h"
#include "asdf.h"
+#include "cell.h"
/**
* \file asdf.h
*/
+#ifdef HAVE_FFTW
+
+#define FFTW_NO_Complex /* Please use "double[2]", not C99 "complex",
+ * despite complex.h possibly already being
+ * included. For more information, refer to:
+ * http://www.fftw.org/doc/Complex-numbers.html */
+
+#include <fftw3.h>
+
struct fftw_vars {
int N;
fftw_plan p;
@@ -794,15 +802,18 @@ static int find_cell(struct tvector *tvectors, int N_tvectors, double IndexFit,
int i_min = sl < 2 * N_tvectors ? 0 : sl - 2 * N_tvectors;
int i_max = sl < N_tvectors ? sl : N_tvectors;
- for ( i = i_min; i < i_max; i++) if (tvectors[i].n > acl ) {
+ for ( i = i_min; i < i_max; i++) {
+
+ if (tvectors[i].n <= acl ) continue;
int j_min = sl - N_tvectors - 2 * i - 1 < 0 ?
i + 1 : sl - N_tvectors - i;
int j_max = sl - N_tvectors - i < 0 ?
sl - i : N_tvectors;
- for ( j = j_min; j < j_max; j++ )
- if ( tvectors[j].n > acl ) {
+ for ( j = j_min; j < j_max; j++ ) {
+
+ if ( tvectors[j].n <= acl ) continue;
k = sl - i - j - 1;
@@ -1083,7 +1094,7 @@ int run_asdf(struct image *image, void *ipriv)
d_max = max(a, b, c) * 3 * 1e10;
- double volume = cell_get_volume(dp->template) / 1e30;
+ double volume = cell_get_volume(dp->template) * 1e30;
/* Divide volume constraints by number of lattice points per
* unit cell since asdf always finds primitive cell */
@@ -1105,14 +1116,19 @@ int run_asdf(struct image *image, void *ipriv)
for ( i=0; i<n; i++ ) {
struct imagefeature *f;
+ double r[3];
f = image_get_feature(image->features, i);
if ( f == NULL ) continue;
+ detgeom_transform_coords(&image->detgeom->panels[f->pn],
+ f->fs, f->ss, image->lambda,
+ 0.0, 0.0, r);
+
reflections[N_reflections] = gsl_vector_alloc(3);
- gsl_vector_set(reflections[N_reflections], 0, f->rx/1e10);
- gsl_vector_set(reflections[N_reflections], 1, f->ry/1e10);
- gsl_vector_set(reflections[N_reflections], 2, f->rz/1e10);
+ gsl_vector_set(reflections[N_reflections], 0, r[0]/1e10);
+ gsl_vector_set(reflections[N_reflections], 1, r[1]/1e10);
+ gsl_vector_set(reflections[N_reflections], 2, r[2]/1e10);
N_reflections++;
}
@@ -1200,3 +1216,32 @@ const char *asdf_probe(UnitCell *cell)
{
return "asdf";
}
+
+#else /* HAVE_FFTW */
+
+int run_asdf(struct image *image, void *ipriv)
+{
+ ERROR("This copy of CrystFEL was compiled without FFTW support.\n");
+ return 0;
+}
+
+
+void *asdf_prepare(IndexingMethod *indm, UnitCell *cell)
+{
+ ERROR("This copy of CrystFEL was compiled without FFTW support.\n");
+ ERROR("To use asdf indexing, recompile with FFTW.\n");
+ return NULL;
+}
+
+
+const char *asdf_probe(UnitCell *cell)
+{
+ return NULL;
+}
+
+
+void asdf_cleanup(void *pp)
+{
+}
+
+#endif /* HAVE_FFTW */
diff --git a/libcrystfel/src/asdf.h b/libcrystfel/src/indexers/asdf.h
index d900c192..98095e3c 100644
--- a/libcrystfel/src/asdf.h
+++ b/libcrystfel/src/indexers/asdf.h
@@ -4,12 +4,12 @@
* Alexandra's Superior Direction Finder, or
* Algorithm Similar to DirAx, FFT-based
*
- * Copyright © 2014-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2014-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
* 2014-2015 Alexandra Tolstikova <alexandra.tolstikova@desy.de>
- * 2015,2017 Thomas White <taw@physics.org>
+ * 2015-2021 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -31,10 +31,6 @@
#ifndef ASDF_H
#define ASDF_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include "index.h"
#ifdef __cplusplus
@@ -46,8 +42,6 @@ extern "C" {
* The ASDF indexing algorithm.
*/
-#ifdef HAVE_FFTW
-
extern int run_asdf(struct image *image, void *ipriv);
extern void *asdf_prepare(IndexingMethod *indm, UnitCell *cell);
@@ -55,37 +49,6 @@ extern const char *asdf_probe(UnitCell *cell);
extern void asdf_cleanup(void *pp);
-#else /* HAVE_FFTW */
-
-int run_asdf(struct image *image, void *ipriv)
-{
- ERROR("This copy of CrystFEL was compiled without FFTW support.\n");
- return 0;
-}
-
-
-void *asdf_prepare(IndexingMethod *indm, UnitCell *cell)
-{
- ERROR("This copy of CrystFEL was compiled without FFTW support.\n");
- ERROR("To use asdf indexing, recompile with FFTW.\n");
- return NULL;
-}
-
-
-const char *asdf_probe(UnitCell *cell)
-{
- return NULL;
-}
-
-
-void asdf_cleanup(void *pp)
-{
-}
-
-
-#endif /* HAVE_FFTW */
-
-
#ifdef __cplusplus
}
#endif
diff --git a/libcrystfel/src/dirax.c b/libcrystfel/src/indexers/dirax.c
index 24be87ba..4b59f6cb 100644
--- a/libcrystfel/src/dirax.c
+++ b/libcrystfel/src/indexers/dirax.c
@@ -3,11 +3,11 @@
*
* Invoke the DirAx auto-indexing program
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2014,2017 Thomas White <taw@physics.org>
+ * 2010-2021 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -490,12 +490,17 @@ static void write_drx(struct image *image)
for ( i=0; i<image_feature_count(image->features); i++ ) {
struct imagefeature *f;
+ double r[3];
f = image_get_feature(image->features, i);
if ( f == NULL ) continue;
+ detgeom_transform_coords(&image->detgeom->panels[f->pn],
+ f->fs, f->ss, image->lambda,
+ 0.0, 0.0, r);
+
fprintf(fh, "%10f %10f %10f %8f\n",
- f->rx/1e10, f->ry/1e10, f->rz/1e10, 1.0);
+ r[0]/1e10, r[1]/1e10, r[2]/1e10, 1.0);
}
fclose(fh);
diff --git a/libcrystfel/src/dirax.h b/libcrystfel/src/indexers/dirax.h
index 33dc1189..2bb560bb 100644
--- a/libcrystfel/src/dirax.h
+++ b/libcrystfel/src/indexers/dirax.h
@@ -3,11 +3,11 @@
*
* Invoke the DirAx auto-indexing program
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010,2012-2014,2017 Thomas White <taw@physics.org>
+ * 2010-2017 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -29,10 +29,6 @@
#ifndef DIRAX_H
#define DIRAX_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include "index.h"
#ifdef __cplusplus
diff --git a/libcrystfel/src/felix.c b/libcrystfel/src/indexers/felix.c
index 2e4898e6..89de5f70 100644
--- a/libcrystfel/src/felix.c
+++ b/libcrystfel/src/indexers/felix.c
@@ -3,11 +3,11 @@
*
* Invoke Felix for multi-crystal autoindexing.
*
- * Copyright © 2015-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2015-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2015-2018 Thomas White <taw@physics.org>
+ * 2015-2021 Thomas White <taw@physics.org>
* 2015 Kenneth Beyerlein <kenneth.beyerlein@desy.de>
*
* This file is part of CrystFEL.
@@ -364,14 +364,19 @@ static void write_gve(struct image *image, struct felix_private *gp)
for ( i=0; i<image_feature_count(image->features); i++ ) {
struct imagefeature *f;
+ double r[3];
f = image_get_feature(image->features, i);
if ( f == NULL ) continue;
+ detgeom_transform_coords(&image->detgeom->panels[f->pn],
+ f->fs, f->ss, image->lambda,
+ 0.0, 0.0, r);
+
fprintf(fh, "%.6f %.6f %.6f 0 0 %.6f %.6f %.6f 0\n",
- f->rz/1e10, f->rx/1e10, f->ry/1e10,
- modulus(f->rx, f->ry, f->rz)/1e10, /* dstar */
- rad2deg(atan2(f->ry, f->rx)), 0.0); /* eta, omega */
+ r[2]/1e10, r[0]/1e10, r[1]/1e10,
+ modulus(r[0], r[1], r[2])/1e10, /* dstar */
+ rad2deg(atan2(r[1], r[0])), 0.0); /* eta, omega */
}
fclose(fh);
@@ -384,7 +389,6 @@ static char *write_ini(struct image *image, struct felix_private *gp)
char *filename;
char gveFilename[1024];
char logFilename[1024];
- double tt;
filename = malloc(1024);
if ( filename == NULL ) return NULL;
@@ -400,11 +404,6 @@ static char *write_ini(struct image *image, struct felix_private *gp)
return NULL;
}
- get_q_for_panel(image->det->furthest_out_panel,
- image->det->furthest_out_fs,
- image->det->furthest_out_ss,
- &tt, 1.0/image->lambda);
-
fprintf(fh, "spacegroup %i\n", gp->spacegroup);
fprintf(fh, "tthrange %f %f\n", rad2deg(gp->tthrange_min),
rad2deg(gp->tthrange_max));
@@ -806,7 +805,7 @@ const char *felix_probe(UnitCell *cell)
}
-static void show_help()
+static void felix_show_help()
{
printf("Parameters for the Felix indexing algorithm:\n"
" --felix-domega Degree range of omega (moscaicity) to consider.\n"
@@ -838,30 +837,45 @@ static void show_help()
}
-static error_t parse_arg(int key, char *arg, struct argp_state *state)
+int felix_default_options(FelixOptions **opts_ptr)
+{
+ FelixOptions *opts;
+
+ opts = malloc(sizeof(struct felix_options));
+ if ( opts == NULL ) return ENOMEM;
+
+ opts->ttmin = -1.0;
+ opts->ttmax = -1.0;
+ opts->min_visits = 0;
+ opts->min_completeness = -1.0;
+ opts->max_uniqueness = -1.0;
+ opts->n_voxels = 0;
+ opts->fraction_max_visits = -1.0;
+ opts->sigma = -1.0;
+ opts->domega = -1.0;
+ opts->max_internal_angle = -1.0;
+
+ *opts_ptr = opts;
+ return 0;
+}
+
+
+static error_t felix_parse_arg(int key, char *arg,
+ struct argp_state *state)
{
struct felix_options **opts_ptr = state->input;
float tmp;
+ int r;
switch ( key ) {
case ARGP_KEY_INIT :
- *opts_ptr = malloc(sizeof(struct felix_options));
- if ( *opts_ptr == NULL ) return ENOMEM;
- (*opts_ptr)->ttmin = -1.0;
- (*opts_ptr)->ttmax = -1.0;
- (*opts_ptr)->min_visits = 0;
- (*opts_ptr)->min_completeness = -1.0;
- (*opts_ptr)->max_uniqueness = -1.0;
- (*opts_ptr)->n_voxels = 0;
- (*opts_ptr)->fraction_max_visits = -1.0;
- (*opts_ptr)->sigma = -1.0;
- (*opts_ptr)->domega = -1.0;
- (*opts_ptr)->max_internal_angle = -1.0;
+ r = felix_default_options(opts_ptr);
+ if ( r ) return r;
break;
case 1 :
- show_help();
+ felix_show_help();
return EINVAL;
case 2 :
@@ -945,7 +959,7 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
}
-static struct argp_option options[] = {
+static struct argp_option felix_options[] = {
{"help-felix", 1, NULL, OPTION_NO_USAGE,
"Show options for Felix indexing algorithm", 99},
@@ -964,4 +978,5 @@ static struct argp_option options[] = {
};
-struct argp felix_argp = { options, parse_arg, NULL, NULL, NULL, NULL, NULL };
+struct argp felix_argp = { felix_options, felix_parse_arg,
+ NULL, NULL, NULL, NULL, NULL };
diff --git a/libcrystfel/src/felix.h b/libcrystfel/src/indexers/felix.h
index 4a992548..83179d6f 100644
--- a/libcrystfel/src/felix.h
+++ b/libcrystfel/src/indexers/felix.h
@@ -3,12 +3,12 @@
*
* Invoke Felix for multi-crystal autoindexing
*
- * Copyright © 2013-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2013-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2013,2017 Thomas White <taw@physics.org>
- * 2013-2014 Kenneth Beyerlein <kenneth.beyerlein@desy.de>
+ * 2010-2017 Thomas White <taw@physics.org>
+ * 2013-2014 Kenneth Beyerlein <kenneth.beyerlein@desy.de>
*
* This file is part of CrystFEL.
*
@@ -30,10 +30,6 @@
#ifndef FELIX_H
#define FELIX_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include <argp.h>
#include "cell.h"
@@ -43,8 +39,7 @@
* Felix indexer interface
*/
-typedef struct felix_options FelixOptions;
-extern struct argp felix_argp;
+extern int felix_default_options(FelixOptions **opts_ptr);
extern void *felix_prepare(IndexingMethod *indm, UnitCell *cell,
struct felix_options *opts);
diff --git a/libcrystfel/src/mosflm.c b/libcrystfel/src/indexers/mosflm.c
index ef282cbe..b0e0b121 100644
--- a/libcrystfel/src/mosflm.c
+++ b/libcrystfel/src/indexers/mosflm.c
@@ -3,7 +3,7 @@
*
* Invoke the DPS auto-indexing algorithm through MOSFLM
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2012 Richard Kirian
*
@@ -201,10 +201,11 @@ static void mosflm_parseline(const char *line, struct image *image,
}
-/* This is the opposite of spacegroup_for_lattice() below.
+/* This is the opposite of mosflm_spacegroup_for_lattice() below.
* Note that this is not general, just a set of rules for interpreting MOSFLM's
* output. */
-static LatticeType spacegroup_to_lattice(const char *sg, char *ua, char *cen)
+static LatticeType mosflm_spacegroup_to_lattice(const char *sg,
+ char *ua, char *cen)
{
LatticeType latt;
@@ -298,7 +299,7 @@ static int read_newmat(struct mosflm_data *mosflm, const char *filename,
return 1;
}
//STATUS("MOSFLM says '%s'\n", symm);
- latt = spacegroup_to_lattice(symm+5, &ua, &cen);
+ latt = mosflm_spacegroup_to_lattice(symm+5, &ua, &cen);
/* MOSFLM "A" matrix is multiplied by lambda, so fix this */
c = 1.0/image->lambda;
@@ -356,16 +357,21 @@ static void write_spt(struct image *image, const char *filename)
struct imagefeature *f;
double ttx, tty, x, y;
+ double r[3];
f = image_get_feature(image->features, i);
if ( f == NULL ) continue;
+ detgeom_transform_coords(&image->detgeom->panels[f->pn],
+ f->fs, f->ss, image->lambda,
+ 0.0, 0.0, r);
+
ttx = angle_between_2d(0.0, 1.0,
- f->rx, 1.0/image->lambda + f->rz);
+ r[0], 1.0/image->lambda + r[2]);
tty = angle_between_2d(0.0, 1.0,
- f->ry, 1.0/image->lambda + f->rz);
- if ( f->rx < 0.0 ) ttx *= -1.0;
- if ( f->ry < 0.0 ) tty *= -1.0;
+ r[1], 1.0/image->lambda + r[2]);
+ if ( r[0] < 0.0 ) ttx *= -1.0;
+ if ( r[1] < 0.0 ) tty *= -1.0;
x = -tan(ttx)*FAKE_CLEN;
y = tan(tty)*FAKE_CLEN;
@@ -437,7 +443,7 @@ static void mosflm_sendline(const char *line, struct mosflm_data *mosflm)
/* Turn what we know about the unit cell into something which we can give to
* MOSFLM to make it give us only indexing results compatible with the cell. */
-static char *spacegroup_for_lattice(UnitCell *cell)
+static char *mosflm_spacegroup_for_lattice(UnitCell *cell)
{
LatticeType latt;
char centering;
@@ -530,7 +536,7 @@ static void mosflm_send_next(struct image *image, struct mosflm_data *mosflm)
mosflm_sendline("CRYSTAL R\n", mosflm);
}
- symm = spacegroup_for_lattice(mosflm->mp->template);
+ symm = mosflm_spacegroup_for_lattice(mosflm->mp->template);
snprintf(tmp, 255, "SYMM %s\n", symm);
//STATUS("Asking MOSFLM for '%s'\n", symm);
free(symm);
@@ -754,8 +760,8 @@ int run_mosflm(struct image *image, void *ipriv)
t.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
tcsetattr(STDIN_FILENO, TCSANOW, &t);
- execlp("mosflm", "mosflm", (char *)NULL);
- execlp("ipmosflm", "ipmosflm", (char *)NULL);
+ execlp("mosflm", "mosflm", "-n", (char *)NULL);
+ execlp("ipmosflm", "ipmosflm", "-n", (char *)NULL);
ERROR("Invocation: Failed to invoke MOSFLM: %s\n",
strerror(errno));
_exit(0);
diff --git a/libcrystfel/src/mosflm.h b/libcrystfel/src/indexers/mosflm.h
index b6d708f5..0c64090b 100644
--- a/libcrystfel/src/mosflm.h
+++ b/libcrystfel/src/indexers/mosflm.h
@@ -3,13 +3,13 @@
*
* Invoke the DPS auto-indexing algorithm through MOSFLM
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2012 Richard Kirian
*
* Authors:
- * 2010 Richard Kirian <rkirian@asu.edu>
- * 2012-2014,2017 Thomas White <taw@physics.org>
+ * 2010 Richard Kirian <rkirian@asu.edu>
+ * 2012-2017 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -31,10 +31,6 @@
#ifndef MOSFLM_H
#define MOSFLM_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include "index.h"
#ifdef __cplusplus
diff --git a/libcrystfel/src/pinkindexer.c b/libcrystfel/src/indexers/pinkindexer.c
index 22208885..b0b5a9fa 100644
--- a/libcrystfel/src/pinkindexer.c
+++ b/libcrystfel/src/indexers/pinkindexer.c
@@ -3,11 +3,12 @@
*
* Interface to PinkIndexer
*
- * Copyright © 2017-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2017-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
* 2017-2019 Yaroslav Gevorkov <yaroslav.gevorkov@desy.de>
+ * 2021 Thomas White <thomas.white@desy.de>
*
* This file is part of CrystFEL.
*
@@ -26,34 +27,46 @@
*
*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include "pinkindexer.h"
-#ifdef HAVE_PINKINDEXER
#include <stdlib.h>
+#include <sys/errno.h>
+#include <argp.h>
#include "utils.h"
#include "cell-utils.h"
#include "peaks.h"
-#include "pinkIndexer/adaptions/crystfel/Lattice.h"
-#include "pinkIndexer/adaptions/crystfel/ExperimentSettings.h"
-#include "pinkIndexer/adaptions/crystfel/PinkIndexer.h"
-#define MAX_MULTI_LATTICE_COUNT 8
+#define FAKE_CLEN (0.25)
+
+struct pinkIndexer_options {
+ unsigned int considered_peaks_count;
+ unsigned int angle_resolution;
+ unsigned int refinement_type;
+ float maxResolutionForIndexing_1_per_A;
+ float tolerance;
+ float reflectionRadius; /* In m^-1 */
+ float customBandwidth;
+ float maxRefinementDisbalance;
+};
+
+#ifdef HAVE_PINKINDEXER
+
+#include <pinkIndexer/adaptions/crystfel/Lattice.h>
+#include <pinkIndexer/adaptions/crystfel/ExperimentSettings.h>
+#include <pinkIndexer/adaptions/crystfel/PinkIndexer.h>
struct pinkIndexer_private_data {
PinkIndexer *pinkIndexer;
- reciprocalPeaks_1_per_A_t reciprocalPeaks_1_per_A;
- float *intensities;
IndexingMethod indm;
UnitCell *cellTemplate;
- int threadCount;
- int multi;
- int min_peaks;
-
- int no_check_indexed;
float maxRefinementDisbalance;
@@ -66,132 +79,182 @@ struct pinkIndexer_private_data {
static void reduceReciprocalCell(UnitCell* cell, LatticeTransform_t* appliedReductionTransform);
static void restoreReciprocalCell(UnitCell *cell, LatticeTransform_t* appliedReductionTransform);
static void makeRightHanded(UnitCell* cell);
-static void update_detector(struct detector *det, double xoffs, double yoffs);
-int run_pinkIndexer(struct image *image, void *ipriv)
+
+static double mean_clen(struct detgeom *dg)
{
- struct pinkIndexer_private_data* pinkIndexer_private_data = (struct pinkIndexer_private_data*) ipriv;
- reciprocalPeaks_1_per_A_t* reciprocalPeaks_1_per_A = &(pinkIndexer_private_data->reciprocalPeaks_1_per_A);
- float *intensities = pinkIndexer_private_data->intensities;
-
- int peakCountMax = image_feature_count(image->features);
- if (peakCountMax < 5) {
- int goodLatticesCount = 0;
- return goodLatticesCount;
+ int i;
+ double total = 0.0;
+ for ( i=0; i<dg->n_panels; i++ ) {
+ total += dg->panels[i].cnz;
}
- reciprocalPeaks_1_per_A->peakCount = 0;
- for (int i = 0; i < peakCountMax && i < MAX_PEAK_COUNT_FOR_INDEXER; i++) {
- struct imagefeature *f;
- f = image_get_feature(image->features, i);
- if (f == NULL) {
- continue;
+ return total / dg->n_panels;
+}
+
+
+static void scale_detector_shift(double fake_clen,
+ struct detgeom *dg,
+ double inx, double iny,
+ double *pdx, double *pdy)
+{
+ int i;
+ double mean = mean_clen(dg);
+ for ( i=0; i<dg->n_panels; i++ ) {
+ if ( !within_tolerance(dg->panels[i].cnz, mean, 2.0) ) {
+ ERROR("WARNING: Detector is not flat enough to apply "
+ "detector position offset\n");
+ *pdx = 0.0;
+ *pdy = 0.0;
+ return;
}
+ }
+ *pdx = (mean/fake_clen)*inx;
+ *pdy = (mean/fake_clen)*iny;
+}
+
- reciprocalPeaks_1_per_A->coordinates_x[reciprocalPeaks_1_per_A->peakCount] = f->rz * 1e-10;
- reciprocalPeaks_1_per_A->coordinates_y[reciprocalPeaks_1_per_A->peakCount] = f->rx * 1e-10;
- reciprocalPeaks_1_per_A->coordinates_z[reciprocalPeaks_1_per_A->peakCount] = f->ry * 1e-10;
- intensities[reciprocalPeaks_1_per_A->peakCount] = (float) (f->intensity);
- reciprocalPeaks_1_per_A->peakCount++;
+int run_pinkIndexer(struct image *image, void *ipriv, int n_threads)
+{
+ struct pinkIndexer_private_data *pinkIndexer_private_data = ipriv;
+ reciprocalPeaks_1_per_A_t reciprocalPeaks_1_per_A;
+ float *intensities;
+ int npk;
+ int i;
+
+ /* FIXME: Check if wavelength is too far from estimate */
+
+ npk = image_feature_count(image->features);
+ if ( npk < 5 ) return 0;
+
+ if ( npk > MAX_PEAK_COUNT_FOR_INDEXER ) {
+ npk = MAX_PEAK_COUNT_FOR_INDEXER;
+ }
+
+ reciprocalPeaks_1_per_A.peakCount = 0;
+ intensities = malloc(npk*sizeof(float));
+ allocReciprocalPeaks(&reciprocalPeaks_1_per_A);
+ if ( intensities == NULL ) return 0;
+
+ for ( i=0; i<npk; i++ ) {
+
+ struct imagefeature *f;
+ double r[3];
+
+ f = image_get_feature(image->features, i);
+ if ( f == NULL ) continue;
+
+ detgeom_transform_coords(&image->detgeom->panels[f->pn],
+ f->fs, f->ss, image->lambda,
+ 0.0, 0.0, r);
+ reciprocalPeaks_1_per_A.coordinates_x[reciprocalPeaks_1_per_A.peakCount] = r[2] * 1e-10;
+ reciprocalPeaks_1_per_A.coordinates_y[reciprocalPeaks_1_per_A.peakCount] = r[0] * 1e-10;
+ reciprocalPeaks_1_per_A.coordinates_z[reciprocalPeaks_1_per_A.peakCount] = r[1] * 1e-10;
+ intensities[reciprocalPeaks_1_per_A.peakCount] = f->intensity;
+ reciprocalPeaks_1_per_A.peakCount++;
}
int indexed = 0;
- Lattice_t indexedLattice[MAX_MULTI_LATTICE_COUNT];
- float center_shift[MAX_MULTI_LATTICE_COUNT][2];
+ float center_shift[2];
+ Lattice_t indexedLattice;
+ int matchedPeaksCount = PinkIndexer_indexPattern(pinkIndexer_private_data->pinkIndexer,
+ &indexedLattice,
+ center_shift,
+ &reciprocalPeaks_1_per_A,
+ intensities,
+ pinkIndexer_private_data->maxRefinementDisbalance,
+ n_threads);
+ free(intensities);
+ freeReciprocalPeaks(reciprocalPeaks_1_per_A);
- do {
- int peakCount = reciprocalPeaks_1_per_A->peakCount;
- int matchedPeaksCount = PinkIndexer_indexPattern(pinkIndexer_private_data->pinkIndexer,
- &(indexedLattice[indexed]), center_shift[indexed], reciprocalPeaks_1_per_A, intensities,
- pinkIndexer_private_data->maxRefinementDisbalance,
- pinkIndexer_private_data->threadCount);
+ if ( matchedPeaksCount == -1 ) {
- if(matchedPeaksCount == -1){
- STATUS("WARNING: Indexing solution was rejected due to too large disbalance of the refinement."
- "If you see this message often, check the documentation for the parameter "
- "--pinkIndexer-max-refinement-disbalance\n");
+ STATUS("WARNING: Indexing solution was rejected due to too "
+ "large imbalance of the refinement.\n"
+ "If you see this message often, check the documentation "
+ "for parameter --pinkIndexer-max-refinement-disbalance\n");
- matchedPeaksCount = 0;
- }
+ } else {
- printf("matchedPeaksCount %d from %d\n",matchedPeaksCount,peakCount);
- if ((matchedPeaksCount >= 25 && matchedPeaksCount >= peakCount * 0.30)
- || matchedPeaksCount >= peakCount * 0.4
- || matchedPeaksCount >= 70
- || pinkIndexer_private_data->no_check_indexed == 1)
- {
- UnitCell *uc;
- uc = cell_new();
+ UnitCell *uc;
+ UnitCell *new_cell_trans;
- Lattice_t *l = &(indexedLattice[indexed]);
+ uc = cell_new();
- cell_set_reciprocal(uc, l->ay * 1e10, l->az * 1e10, l->ax * 1e10,
- l->by * 1e10, l->bz * 1e10, l->bx * 1e10,
- l->cy * 1e10, l->cz * 1e10, l->cx * 1e10);
+ cell_set_reciprocal(uc, indexedLattice.ay * 1e10,
+ indexedLattice.az * 1e10,
+ indexedLattice.ax * 1e10,
+ indexedLattice.by * 1e10,
+ indexedLattice.bz * 1e10,
+ indexedLattice.bx * 1e10,
+ indexedLattice.cy * 1e10,
+ indexedLattice.cz * 1e10,
+ indexedLattice.cx * 1e10);
- restoreReciprocalCell(uc, &pinkIndexer_private_data->latticeReductionTransform);
+ restoreReciprocalCell(uc, &pinkIndexer_private_data->latticeReductionTransform);
- UnitCell *new_cell_trans = cell_transform_intmat(uc, pinkIndexer_private_data->centeringTransformation);
- cell_free(uc);
- uc = new_cell_trans;
+ new_cell_trans = cell_transform_intmat(uc, pinkIndexer_private_data->centeringTransformation);
+ cell_free(uc);
- cell_set_lattice_type(new_cell_trans, cell_get_lattice_type(pinkIndexer_private_data->cellTemplate));
- cell_set_centering(new_cell_trans, cell_get_centering(pinkIndexer_private_data->cellTemplate));
- cell_set_unique_axis(new_cell_trans, cell_get_unique_axis(pinkIndexer_private_data->cellTemplate));
+ cell_set_lattice_type(new_cell_trans,
+ cell_get_lattice_type(pinkIndexer_private_data->cellTemplate));
+ cell_set_centering(new_cell_trans,
+ cell_get_centering(pinkIndexer_private_data->cellTemplate));
+ cell_set_unique_axis(new_cell_trans,
+ cell_get_unique_axis(pinkIndexer_private_data->cellTemplate));
- if (validate_cell(uc)) {
- ERROR("pinkIndexer: problem with returned cell!\n");
- }
+ if ( validate_cell(new_cell_trans) ) {
+ ERROR("pinkIndexer: problem with returned cell!\n");
+ } else {
- Crystal * cr = crystal_new();
- if (cr == NULL) {
+ double dx, dy;
+ Crystal *cr = crystal_new();
+ if ( cr == NULL ) {
ERROR("Failed to allocate crystal.\n");
return 0;
}
- crystal_set_cell(cr, uc);
- crystal_set_det_shift(cr, center_shift[indexed][0], center_shift[indexed][1]);
- update_detector(image->det, center_shift[indexed][0], center_shift[indexed][1]);
+ crystal_set_cell(cr, new_cell_trans);
+ scale_detector_shift(FAKE_CLEN,
+ image->detgeom,
+ center_shift[0],
+ center_shift[1],
+ &dx, &dy);
+ crystal_set_det_shift(cr, dx, dy);
image_add_crystal(image, cr);
indexed++;
- } else {
- break;
}
- } while (pinkIndexer_private_data->multi
- && indexed <= MAX_MULTI_LATTICE_COUNT
- && reciprocalPeaks_1_per_A->peakCount >= pinkIndexer_private_data->min_peaks);
+
+ }
return indexed;
}
-void *pinkIndexer_prepare(IndexingMethod *indm, UnitCell *cell,
+
+void *pinkIndexer_prepare(IndexingMethod *indm,
+ UnitCell *cell,
struct pinkIndexer_options *pinkIndexer_opts,
- struct detector *det, struct beam_params *beam)
+ double wavelength_estimate)
{
- if ( beam->photon_energy_from != NULL && pinkIndexer_opts->customPhotonEnergy <= 0) {
- ERROR("For pinkIndexer, the photon_energy must be defined as a "
- "constant in the geometry file or as a parameter (see --pinkIndexer-override-photon-energy)\n");
- return NULL;
- }
- if ( (det->panels[0].clen_from != NULL) && pinkIndexer_opts->refinement_type ==
- REFINEMENT_TYPE_firstFixedThenVariableLatticeParametersCenterAdjustmentMultiSeed) {
- ERROR("Using center refinement makes it necessary to have the detector distance fixed in the geometry file!");
+ float beamEenergy_eV;
+
+ if ( isnan(wavelength_estimate) ) {
+ ERROR("PinkIndexer requires a wavelength estimate. "
+ "Try again with --wavelength-estimate=xx\n");
return NULL;
+ } else {
+ beamEenergy_eV = J_to_eV(ph_lambda_to_en(wavelength_estimate));
}
- if(cell == NULL){
- ERROR("Pink indexer needs a unit cell file to be specified!")
+
+ if ( cell == NULL ) {
+ ERROR("Unit cell information is required for "
+ "PinkIndexer.\n");
return NULL;
}
struct pinkIndexer_private_data* pinkIndexer_private_data = malloc(sizeof(struct pinkIndexer_private_data));
- allocReciprocalPeaks(&(pinkIndexer_private_data->reciprocalPeaks_1_per_A));
- pinkIndexer_private_data->intensities = malloc(MAX_PEAK_COUNT_FOR_INDEXER * sizeof(float));
pinkIndexer_private_data->indm = *indm;
pinkIndexer_private_data->cellTemplate = cell;
- pinkIndexer_private_data->threadCount = pinkIndexer_opts->thread_count;
- pinkIndexer_private_data->multi = pinkIndexer_opts->multi;
- pinkIndexer_private_data->min_peaks = pinkIndexer_opts->min_peaks;
- pinkIndexer_private_data->no_check_indexed = pinkIndexer_opts->no_check_indexed;
pinkIndexer_private_data->maxRefinementDisbalance = pinkIndexer_opts->maxRefinementDisbalance;
UnitCell* primitiveCell = uncenter_cell(cell, &pinkIndexer_private_data->centeringTransformation, NULL);
@@ -209,21 +272,7 @@ void *pinkIndexer_prepare(IndexingMethod *indm, UnitCell *cell,
.bx = bsz * 1e-10, .by = bsx * 1e-10, .bz = bsy * 1e-10,
.cx = csz * 1e-10, .cy = csx * 1e-10, .cz = csy * 1e-10 };
- float detectorDistance_m;
- if ( det->panels[0].clen_from != NULL ) {
- detectorDistance_m = 0.25; /* fake value */
- } else {
- detectorDistance_m = det->panels[0].clen + det->panels[0].coffset;
- }
-
- float beamEenergy_eV = beam->photon_energy;
- float nonMonochromaticity = beam->bandwidth*5;
- if(pinkIndexer_opts->customPhotonEnergy > 0){
- beamEenergy_eV = pinkIndexer_opts->customPhotonEnergy;
- }
- if(pinkIndexer_opts->customBandwidth >= 0){
- nonMonochromaticity = pinkIndexer_opts->customBandwidth;
- }
+ float nonMonochromaticity = 0.01;
float reflectionRadius_1_per_A;
if (pinkIndexer_opts->reflectionRadius < 0) {
@@ -235,7 +284,9 @@ void *pinkIndexer_prepare(IndexingMethod *indm, UnitCell *cell,
}
if(beamEenergy_eV > 75000 && nonMonochromaticity < 0.02 && reflectionRadius_1_per_A < 0.0005){
- STATUS("Trying to index electron diffraction? It might be helpful to set a higher reflection radius (see documentation for --pinkIndexer-reflection-radius)")
+ STATUS("Trying to index electron diffraction? It might be "
+ " helpful to set a higher reflection radius "
+ "(see documentation for --pinkIndexer-reflection-radius)");
}
float divergenceAngle_deg = 0.01; //fake
@@ -243,9 +294,14 @@ void *pinkIndexer_prepare(IndexingMethod *indm, UnitCell *cell,
float tolerance = pinkIndexer_opts->tolerance;
Lattice_t sampleReciprocalLattice_1_per_A = lattice;
float detectorRadius_m = 0.03; //fake, only for prediction
- ExperimentSettings* experimentSettings = ExperimentSettings_new(beamEenergy_eV, detectorDistance_m,
- detectorRadius_m, divergenceAngle_deg, nonMonochromaticity, sampleReciprocalLattice_1_per_A, tolerance,
- reflectionRadius_1_per_A);
+ ExperimentSettings *experimentSettings = ExperimentSettings_new(beamEenergy_eV,
+ FAKE_CLEN,
+ detectorRadius_m,
+ divergenceAngle_deg,
+ nonMonochromaticity,
+ sampleReciprocalLattice_1_per_A,
+ tolerance,
+ reflectionRadius_1_per_A);
consideredPeaksCount_t consideredPeaksCount = pinkIndexer_opts->considered_peaks_count;
angleResolution_t angleResolution = pinkIndexer_opts->angle_resolution;
@@ -341,24 +397,10 @@ static void makeRightHanded(UnitCell *cell)
}
}
-//hack for electron crystallography while crystal_set_det_shift is not working approprietly
-static void update_detector(struct detector *det, double xoffs, double yoffs)
-{
- int i;
-
- for (i = 0; i < det->n_panels; i++) {
- struct panel *p = &det->panels[i];
- p->cnx += xoffs * p->res;
- p->cny += yoffs * p->res;
- }
-}
-
void pinkIndexer_cleanup(void *pp)
{
struct pinkIndexer_private_data* pinkIndexer_private_data = (struct pinkIndexer_private_data*) pp;
- freeReciprocalPeaks(pinkIndexer_private_data->reciprocalPeaks_1_per_A);
- free(pinkIndexer_private_data->intensities);
intmat_free(pinkIndexer_private_data->centeringTransformation);
PinkIndexer_delete(pinkIndexer_private_data->pinkIndexer);
}
@@ -370,15 +412,16 @@ const char *pinkIndexer_probe(UnitCell *cell)
#else /* HAVE_PINKINDEXER */
-int run_pinkIndexer(struct image *image, void *ipriv)
+int run_pinkIndexer(struct image *image, void *ipriv, int n_threads)
{
ERROR("This copy of CrystFEL was compiled without PINKINDEXER support.\n");
return 0;
}
-extern void *pinkIndexer_prepare(IndexingMethod *indm, UnitCell *cell,
- struct pinkIndexer_options *pinkIndexer_opts,
- struct detector *det, struct beam_params *beam)
+extern void *pinkIndexer_prepare(IndexingMethod *indm,
+ UnitCell *cell,
+ struct pinkIndexer_options *pinkIndexer_opts,
+ double wavelength_estimate)
{
ERROR("This copy of CrystFEL was compiled without PINKINDEXER support.\n");
ERROR("To use PINKINDEXER indexing, recompile with PINKINDEXER.\n");
@@ -396,7 +439,7 @@ const char *pinkIndexer_probe(UnitCell *cell)
#endif /* HAVE_PINKINDEXER */
-static void show_help()
+static void pinkIndexer_show_help()
{
printf(
"Parameters for the PinkIndexer indexing algorithm:\n"
@@ -417,56 +460,49 @@ static void show_help()
" Specified in 1/A. Default is 2%% of a*.\n"
" --pinkIndexer-max-resolution-for-indexing=n\n"
" Measured in 1/A\n"
-" --pinkIndexer-multi Use pinkIndexers own multi indexing.\n"
-" --pinkIndexer-thread-count=n\n"
-" Thread count for internal parallelization \n"
-" Default: 1\n"
-" --pinkIndexer-no-check-indexed\n"
-" Disable internal check for correct indexing\n"
-" solutions\n"
" --pinkIndexer-max-refinement-disbalance=n\n"
-" Maximum disbalance after refinement:\n"
-" 0 (no disbalance) to 2 (extreme disbalance), default 0.4\n"
-" --pinkIndexer-override-photon-energy=ev\n"
-" Mean energy in eV to use for indexing.\n"
-" --pinkIndexer-override-bandwidth=n\n"
-" Bandwidth in (delta energy)/(mean energy) to use for indexing.\n"
-" --pinkIndexer-override-visible-energy-range=min-max\n"
-" Overrides photon energy and bandwidth according to a range of \n"
-" energies that have high enough intensity to produce \"visible\" \n"
-" Bragg spots on the detector.\n"
-" Min and max range borders are separated by a minus sign (no whitespace).\n"
+" Maximum imbalance after refinement:\n"
+" 0 (no imbalance) to 2 (extreme imbalance), default 0.4\n"
);
}
-static error_t parse_arg(int key, char *arg, struct argp_state *state)
+int pinkIndexer_default_options(PinkIndexerOptions **opts_ptr)
+{
+ PinkIndexerOptions *opts;
+
+ opts = malloc(sizeof(struct pinkIndexer_options));
+ if ( opts == NULL ) return ENOMEM;
+
+ opts->considered_peaks_count = 4;
+ opts->angle_resolution = 2;
+ opts->refinement_type = 1;
+ opts->tolerance = 0.06;
+ opts->maxResolutionForIndexing_1_per_A = +INFINITY;
+ opts->reflectionRadius = -1;
+ opts->maxRefinementDisbalance = 0.4;
+
+ *opts_ptr = opts;
+ return 0;
+}
+
+
+static error_t pinkindexer_parse_arg(int key, char *arg,
+ struct argp_state *state)
{
- float tmp, tmp2;
+ float tmp;
+ int r;
struct pinkIndexer_options **opts_ptr = state->input;
switch ( key ) {
case ARGP_KEY_INIT :
- *opts_ptr = malloc(sizeof(struct pinkIndexer_options));
- if ( *opts_ptr == NULL ) return ENOMEM;
- (*opts_ptr)->considered_peaks_count = 4;
- (*opts_ptr)->angle_resolution = 2;
- (*opts_ptr)->refinement_type = 1;
- (*opts_ptr)->tolerance = 0.06;
- (*opts_ptr)->maxResolutionForIndexing_1_per_A = +INFINITY;
- (*opts_ptr)->thread_count = 1;
- (*opts_ptr)->multi = 0;
- (*opts_ptr)->no_check_indexed = 0;
- (*opts_ptr)->min_peaks = 2;
- (*opts_ptr)->reflectionRadius = -1;
- (*opts_ptr)->customPhotonEnergy = -1;
- (*opts_ptr)->customBandwidth = -1;
- (*opts_ptr)->maxRefinementDisbalance = 0.4;
+ r = pinkIndexer_default_options(opts_ptr);
+ if ( r ) return r;
break;
case 1 :
- show_help();
+ pinkIndexer_show_help();
return EINVAL;
case 2 :
@@ -497,12 +533,9 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
break;
case 5 :
- if (sscanf(arg, "%d", &(*opts_ptr)->thread_count) != 1)
- {
- ERROR("Invalid value for --pinkIndexer-thread-count\n");
- return EINVAL;
- }
- break;
+ ERROR("Please use --max-indexer-threads instead of "
+ "--pinkIndexer-thread-count.\n");
+ return EINVAL;
case 6 :
if (sscanf(arg, "%f", &(*opts_ptr)->maxResolutionForIndexing_1_per_A) != 1)
@@ -522,11 +555,11 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
break;
case 8 :
- (*opts_ptr)->multi = 1;
+ ERROR("WARNING: --pinkIndexer-multi is ignored.\n");
break;
case 9 :
- (*opts_ptr)->no_check_indexed = 1;
+ ERROR("WARNING: --pinkIndexer-no-check-indexed is ignored.\n");
break;
case 10 :
@@ -538,32 +571,20 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
break;
case 11 :
- if (sscanf(arg, "%f", &(*opts_ptr)->customPhotonEnergy) != 1)
- {
- ERROR("Invalid value for --pinkIndexer-override-photon-energy\n");
- return EINVAL;
- }
- break;
+ ERROR("Please use --wavelength-estimate instead of "
+ "--pinkIndexer-override-photon-energy.\n");
+ return EINVAL;
case 12 :
- if (sscanf(arg, "%f", &(*opts_ptr)->customBandwidth) != 1)
- {
- ERROR("Invalid value for --pinkIndexer-override-bandwidth\n");
- return EINVAL;
- }
- break;
+ ERROR("This CrystFEL version does not handle wide bandwidth ");
+ ERROR("(invalid option --pinkIndexer-override-bandwidth)\n");
+ return EINVAL;
+
case 13 :
- if (sscanf(arg, "%f-%f", &tmp, &tmp2) != 2)
- {
- ERROR("Invalid value for --pinkIndexer-override-visible-energy-range\n");
- return EINVAL;
- }
- (*opts_ptr)->customPhotonEnergy = (tmp + tmp2)/2;
- (*opts_ptr)->customBandwidth = (tmp2 - tmp)/(*opts_ptr)->customPhotonEnergy;
- if((*opts_ptr)->customBandwidth < 0){
- (*opts_ptr)->customBandwidth *= -1;
- }
- break;
+ ERROR("This CrystFEL version does not handle wide bandwidth ");
+ ERROR("(invalid option --pinkIndexer-override-visible-energy-range)\n");
+ return EINVAL;
+
case 14 :
if (sscanf(arg, "%f", &(*opts_ptr)->maxRefinementDisbalance) != 1)
{
@@ -576,7 +597,7 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
}
-static struct argp_option options[] = {
+static struct argp_option pinkindexer_options[] = {
{"help-pinkindexer", 1, NULL, OPTION_NO_USAGE,
"Show options for PinkIndexer indexing algorithm", 99},
@@ -617,4 +638,6 @@ static struct argp_option options[] = {
};
-struct argp pinkIndexer_argp = { options, parse_arg, NULL, NULL, NULL, NULL, NULL };
+struct argp pinkIndexer_argp = { pinkindexer_options,
+ pinkindexer_parse_arg,
+ NULL, NULL, NULL, NULL, NULL };
diff --git a/libcrystfel/src/pinkindexer.h b/libcrystfel/src/indexers/pinkindexer.h
index f79f4331..358a8221 100644
--- a/libcrystfel/src/pinkindexer.h
+++ b/libcrystfel/src/indexers/pinkindexer.h
@@ -3,11 +3,12 @@
*
* Interface to PinkIndexer
*
- * Copyright © 2017-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2017-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
* 2017-2019 Yaroslav Gevorkov <yaroslav.gevorkov@desy.de>
+ * 2021 Thomas White <thomas.white@desy.de>
*
* This file is part of CrystFEL.
*
@@ -29,37 +30,19 @@
#ifndef LIBCRYSTFEL_SRC_PINKINDEXER_H_
#define LIBCRYSTFEL_SRC_PINKINDEXER_H_
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-typedef struct pinkIndexer_options PinkIndexerOptions;
-extern struct argp pinkIndexer_argp;
-
-struct pinkIndexer_options {
- unsigned int considered_peaks_count;
- unsigned int angle_resolution;
- unsigned int refinement_type;
- float maxResolutionForIndexing_1_per_A;
- float tolerance;
- int multi;
- int thread_count;
- int min_peaks;
- int no_check_indexed;
- float reflectionRadius; /* In m^-1 */
- float customPhotonEnergy;
- float customBandwidth;
- float maxRefinementDisbalance;
-};
-
#include <stddef.h>
+
#include "index.h"
+#include "datatemplate.h"
+
+extern int pinkIndexer_default_options(PinkIndexerOptions **opts_ptr);
-extern int run_pinkIndexer(struct image *image, void *ipriv);
+extern int run_pinkIndexer(struct image *image, void *ipriv, int n_threads);
-extern void *pinkIndexer_prepare(IndexingMethod *indm, UnitCell *cell,
+extern void *pinkIndexer_prepare(IndexingMethod *indm,
+ UnitCell *cell,
struct pinkIndexer_options *pinkIndexer_opts,
- struct detector *det, struct beam_params *beam);
+ double wavelength_estimate);
extern void pinkIndexer_cleanup(void *pp);
diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/indexers/taketwo.c
index a67d372c..1bccf1e0 100644
--- a/libcrystfel/src/taketwo.c
+++ b/libcrystfel/src/indexers/taketwo.c
@@ -4,12 +4,12 @@
* Rewrite of TakeTwo algorithm (Acta D72 (8) 956-965) for CrystFEL
*
* Copyright © 2016-2017 Helen Ginn
- * Copyright © 2016-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2016-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
* 2016-2017 Helen Ginn <helen@strubi.ox.ac.uk>
- * 2016-2017 Thomas White <taw@physics.org>
+ * 2016-2021 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -86,6 +86,10 @@
* * Clean up the mess (cleanup_taketwo_obs_vecs())
*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_blas.h>
#include <float.h>
@@ -229,7 +233,10 @@ struct TakeTwoCell
/* Maximum observed vectors before TakeTwo gives up and deals with
* what is already there. */
-#define MAX_OBS_VECTORS 100000
+#define MAX_OBS_VECTORS 300
+
+/* Maximum number of seeds to start from in start_seeds() */
+#define MAX_SEEDS 10
/* Tolerance for two angles to be considered the same */
#define ANGLE_TOLERANCE (deg2rad(0.6))
@@ -527,7 +534,7 @@ static double matrix_trace(gsl_matrix *a)
return tr;
}
-static char *add_ua(const char *inp, char ua)
+static char *add_unique_axis(const char *inp, char ua)
{
char *pg = malloc(64);
if ( pg == NULL ) return NULL;
@@ -540,12 +547,13 @@ static char *get_chiral_holohedry(UnitCell *cell)
{
LatticeType lattice = cell_get_lattice_type(cell);
char *pg;
- char *pgout = 0;
+ int add_ua = 1;
switch (lattice)
{
case L_TRICLINIC:
pg = "1";
+ add_ua = 0;
break;
case L_MONOCLINIC:
@@ -554,6 +562,7 @@ static char *get_chiral_holohedry(UnitCell *cell)
case L_ORTHORHOMBIC:
pg = "222";
+ add_ua = 0;
break;
case L_TETRAGONAL:
@@ -562,11 +571,13 @@ static char *get_chiral_holohedry(UnitCell *cell)
case L_RHOMBOHEDRAL:
pg = "3_R";
+ add_ua = 0;
break;
case L_HEXAGONAL:
if ( cell_get_centering(cell) == 'H' ) {
pg = "3_H";
+ add_ua = 0;
} else {
pg = "622";
}
@@ -574,6 +585,7 @@ static char *get_chiral_holohedry(UnitCell *cell)
case L_CUBIC:
pg = "432";
+ add_ua = 0;
break;
default:
@@ -581,26 +593,11 @@ static char *get_chiral_holohedry(UnitCell *cell)
break;
}
- switch (lattice)
- {
- case L_TRICLINIC:
- case L_ORTHORHOMBIC:
- case L_RHOMBOHEDRAL:
- case L_CUBIC:
- pgout = strdup(pg);
- break;
-
- case L_MONOCLINIC:
- case L_TETRAGONAL:
- case L_HEXAGONAL:
- pgout = add_ua(pg, cell_get_unique_axis(cell));
- break;
-
- default:
- break;
+ if ( add_ua ) {
+ return add_unique_axis(pg, cell_get_unique_axis(cell));
+ } else {
+ return strdup(pg);
}
-
- return pgout;
}
@@ -1553,7 +1550,8 @@ static int find_seeds(struct TakeTwoCell *cell, struct taketwo_private *tp)
cell->seeds = tmp;
- for (int i = 0; i < seed_num; i++)
+ int i;
+ for ( i = 0; i < seed_num; i++)
{
if (seeds[i].idx1 < 0 || seeds[i].idx2 < 0)
{
@@ -1582,10 +1580,12 @@ static unsigned int start_seeds(gsl_matrix **rotation, struct TakeTwoCell *cell)
int member_num = 0;
int max_members = 0;
gsl_matrix *rot = NULL;
+ int k;
+
+ if ( seed_num > MAX_SEEDS ) seed_num = MAX_SEEDS;
/* We have seeds! Pass each of them through the seed-starter */
/* If a seed has the highest achieved membership, make note...*/
- int k;
for ( k=0; k<seed_num; k++ ) {
int seed_idx1 = seeds[k].idx1;
int seed_idx2 = seeds[k].idx2;
@@ -2102,7 +2102,8 @@ static void partial_taketwo_cleanup(struct taketwo_private *tp)
{
if (tp->prevSols != NULL)
{
- for (int i = 0; i < tp->numPrevs; i++)
+ int i;
+ for (i = 0; i < tp->numPrevs; i++)
{
gsl_matrix_free(tp->prevSols[i]);
}
@@ -2154,18 +2155,20 @@ int taketwo_index(struct image *image, void *priv)
tp->xtal_num = image->n_crystals;
}
- /*
- STATUS("Indexing %i with %i attempts, %i crystals\n", this_serial, tp->attempts,
- image->n_crystals);
- */
-
rlps = malloc((image_feature_count(image->features)+1)*sizeof(struct rvec));
for ( i=0; i<image_feature_count(image->features); i++ ) {
+
+ double r[3];
struct imagefeature *pk = image_get_feature(image->features, i);
if ( pk == NULL ) continue;
- rlps[n_rlps].u = pk->rx;
- rlps[n_rlps].v = pk->ry;
- rlps[n_rlps].w = pk->rz;
+
+ detgeom_transform_coords(&image->detgeom->panels[pk->pn],
+ pk->fs, pk->ss, image->lambda,
+ 0.0, 0.0, r);
+
+ rlps[n_rlps].u = r[0];
+ rlps[n_rlps].v = r[1];
+ rlps[n_rlps].w = r[2];
n_rlps++;
}
rlps[n_rlps].u = 0.0;
@@ -2235,6 +2238,7 @@ void *taketwo_prepare(IndexingMethod *indm, struct taketwo_options *opts,
if ( tp == NULL ) return NULL;
tp->cell = cell;
+ tp->opts = opts;
tp->indm = *indm;
tp->serial_num = -1;
tp->xtal_num = 0;
@@ -2269,7 +2273,7 @@ const char *taketwo_probe(UnitCell *cell)
}
-static void show_help()
+static void taketwo_show_help()
{
printf("Parameters for the TakeTwo indexing algorithm:\n"
" --taketwo-member-threshold\n"
@@ -2284,24 +2288,38 @@ static void show_help()
}
-static error_t parse_arg(int key, char *arg, struct argp_state *state)
+int taketwo_default_options(TakeTwoOptions **opts_ptr)
+{
+ TakeTwoOptions *opts;
+
+ opts = malloc(sizeof(struct taketwo_options));
+ if ( opts == NULL ) return ENOMEM;
+ opts->member_thresh = -1.0;
+ opts->len_tol = -1.0;
+ opts->angle_tol = -1.0;
+ opts->trace_tol = -1.0;
+
+ *opts_ptr = opts;
+ return 0;
+}
+
+
+static error_t taketwo_parse_arg(int key, char *arg,
+ struct argp_state *state)
{
struct taketwo_options **opts_ptr = state->input;
float tmp;
+ int r;
switch ( key ) {
case ARGP_KEY_INIT :
- *opts_ptr = malloc(sizeof(struct taketwo_options));
- if ( *opts_ptr == NULL ) return ENOMEM;
- (*opts_ptr)->member_thresh = -1.0;
- (*opts_ptr)->len_tol = -1.0;
- (*opts_ptr)->angle_tol = -1.0;
- (*opts_ptr)->trace_tol = -1.0;
+ r = taketwo_default_options(opts_ptr);
+ if ( r ) return r;
break;
case 1 :
- show_help();
+ taketwo_show_help();
return EINVAL;
case 2 :
@@ -2348,7 +2366,7 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
}
-static struct argp_option options[] = {
+static struct argp_option taketwo_options[] = {
{"help-taketwo", 1, NULL, OPTION_NO_USAGE,
"Show options for TakeTwo indexing algorithm", 99},
@@ -2361,4 +2379,5 @@ static struct argp_option options[] = {
};
-struct argp taketwo_argp = { options, parse_arg, NULL, NULL, NULL, NULL, NULL };
+struct argp taketwo_argp = { taketwo_options, taketwo_parse_arg,
+ NULL, NULL, NULL, NULL, NULL };
diff --git a/libcrystfel/src/taketwo.h b/libcrystfel/src/indexers/taketwo.h
index 2239a77a..f3157d72 100644
--- a/libcrystfel/src/taketwo.h
+++ b/libcrystfel/src/indexers/taketwo.h
@@ -4,7 +4,7 @@
* Rewrite of TakeTwo algorithm (Acta D72 (8) 956-965) for CrystFEL
*
* Copyright © 2016-2017 Helen Ginn
- * Copyright © 2016-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2016-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
@@ -38,9 +38,7 @@
/** \file taketwo.h */
-typedef struct taketwo_options TakeTwoOptions;
-extern struct argp taketwo_argp;
-
+extern int taketwo_default_options(TakeTwoOptions **opts_ptr);
extern void *taketwo_prepare(IndexingMethod *indm, struct taketwo_options *opts,
UnitCell *cell);
extern const char *taketwo_probe(UnitCell *cell);
diff --git a/libcrystfel/src/xds.c b/libcrystfel/src/indexers/xds.c
index ab6335db..3b2f2b87 100644
--- a/libcrystfel/src/xds.c
+++ b/libcrystfel/src/indexers/xds.c
@@ -3,13 +3,13 @@
*
* Invoke xds for crystal autoindexing
*
- * Copyright © 2013-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2013-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2013 Cornelius Gati
*
* Authors:
* 2010-2018 Thomas White <taw@physics.org>
- * 2013 Cornelius Gati <cornelius.gati@cfel.de>
+ * 2013 Cornelius Gati <cornelius.gati@cfel.de>
*
* This file is part of CrystFEL.
*
@@ -56,7 +56,6 @@
#include "image.h"
#include "utils.h"
#include "peaks.h"
-#include "detector.h"
#include "cell-utils.h"
/** \file xds.h */
@@ -74,7 +73,7 @@ struct xds_private
};
-/* Essentially the reverse of spacegroup_for_lattice(), below */
+/* Essentially the reverse of xds_spacegroup_for_lattice(), below */
static int convert_spacegroup_number(int spg, LatticeType *lt, char *cen,
char *ua)
{
@@ -214,17 +213,22 @@ static void write_spot(struct image *image)
{
struct imagefeature *f;
double ttx, tty, x, y;
+ double r[3];
f = image_get_feature(image->features, i);
if ( f == NULL ) continue;
if ( f->intensity <= 0 ) continue;
+ detgeom_transform_coords(&image->detgeom->panels[f->pn],
+ f->fs, f->ss, image->lambda,
+ 0.0, 0.0, r);
+
ttx = angle_between_2d(0.0, 1.0,
- f->rx, 1.0/image->lambda + f->rz);
+ r[0], 1.0/image->lambda + r[2]);
tty = angle_between_2d(0.0, 1.0,
- f->ry, 1.0/image->lambda + f->rz);
- if ( f->rx < 0.0 ) ttx *= -1.0;
- if ( f->ry < 0.0 ) tty *= -1.0;
+ r[1], 1.0/image->lambda + r[2]);
+ if ( r[0] < 0.0 ) ttx *= -1.0;
+ if ( r[1] < 0.0 ) tty *= -1.0;
x = tan(ttx)*FAKE_CLEN;
y = tan(tty)*FAKE_CLEN;
@@ -241,7 +245,7 @@ static void write_spot(struct image *image)
/* Turn what we know about the unit cell into something which we can give to
* XDS to make it give us only indexing results compatible with the cell. */
-static const char *spacegroup_for_lattice(UnitCell *cell)
+static const char *xds_spacegroup_for_lattice(UnitCell *cell)
{
LatticeType latt;
char centering;
@@ -336,7 +340,7 @@ static int write_inp(struct image *image, struct xds_private *xp)
if ( xp->indm & INDEXING_USE_LATTICE_TYPE ) {
fprintf(fh, "SPACE_GROUP_NUMBER= %s\n",
- spacegroup_for_lattice(xp->cell));
+ xds_spacegroup_for_lattice(xp->cell));
} else {
fprintf(fh, "SPACE_GROUP_NUMBER= 0\n");
}
@@ -462,7 +466,7 @@ void *xds_prepare(IndexingMethod *indm, UnitCell *cell)
return NULL;
}
- if ( (cell != NULL) && (spacegroup_for_lattice(cell) == NULL) ) {
+ if ( (cell != NULL) && (xds_spacegroup_for_lattice(cell) == NULL) ) {
ERROR("Don't know how to ask XDS for your cell.\n");
return NULL;
}
diff --git a/libcrystfel/src/xds.h b/libcrystfel/src/indexers/xds.h
index bb96feca..49a83ff5 100644
--- a/libcrystfel/src/xds.h
+++ b/libcrystfel/src/indexers/xds.h
@@ -3,13 +3,13 @@
*
* Invoke xds for crystal autoindexing
*
- * Copyright © 2013-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2013-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2013 Cornelius Gati
*
* Authors:
- * 2010-2013,2017 Thomas White <taw@physics.org>
- * 2013 Cornelius Gati <cornelius.gati@cfel.de>
+ * 2010-2017 Thomas White <taw@physics.org>
+ * 2013 Cornelius Gati <cornelius.gati@cfel.de>
*
* This file is part of CrystFEL.
*
@@ -31,10 +31,6 @@
#ifndef XDS_H
#define XDS_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include "cell.h"
#include "index.h"
diff --git a/libcrystfel/src/xgandalf.c b/libcrystfel/src/indexers/xgandalf.c
index 9135c2f3..6b09f65c 100644
--- a/libcrystfel/src/xgandalf.c
+++ b/libcrystfel/src/indexers/xgandalf.c
@@ -3,7 +3,7 @@
*
* Interface to XGANDALF indexer
*
- * Copyright © 2017-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2017-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
@@ -26,6 +26,10 @@
*
*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include "xgandalf.h"
#include <stdlib.h>
@@ -80,21 +84,28 @@ static void makeRightHanded(UnitCell* cell);
int run_xgandalf(struct image *image, void *ipriv)
{
+ int i;
struct xgandalf_private_data *xgandalf_private_data = (struct xgandalf_private_data*) ipriv;
reciprocalPeaks_1_per_A_t *reciprocalPeaks_1_per_A = &(xgandalf_private_data->reciprocalPeaks_1_per_A);
int peakCountMax = image_feature_count(image->features);
reciprocalPeaks_1_per_A->peakCount = 0;
- for (int i = 0; i < peakCountMax && i < MAX_PEAK_COUNT_FOR_INDEXER; i++) {
+ for ( i = 0; i < peakCountMax && i < MAX_PEAK_COUNT_FOR_INDEXER; i++) {
struct imagefeature *f;
+ double r[3];
+
f = image_get_feature(image->features, i);
if (f == NULL) {
continue;
}
- reciprocalPeaks_1_per_A->coordinates_x[reciprocalPeaks_1_per_A->peakCount] = f->rx * 1e-10;
- reciprocalPeaks_1_per_A->coordinates_y[reciprocalPeaks_1_per_A->peakCount] = f->ry * 1e-10;
- reciprocalPeaks_1_per_A->coordinates_z[reciprocalPeaks_1_per_A->peakCount] = f->rz * 1e-10;
+ detgeom_transform_coords(&image->detgeom->panels[f->pn],
+ f->fs, f->ss, image->lambda,
+ 0.0, 0.0, r);
+
+ reciprocalPeaks_1_per_A->coordinates_x[reciprocalPeaks_1_per_A->peakCount] = r[0] * 1e-10;
+ reciprocalPeaks_1_per_A->coordinates_y[reciprocalPeaks_1_per_A->peakCount] = r[1] * 1e-10;
+ reciprocalPeaks_1_per_A->coordinates_z[reciprocalPeaks_1_per_A->peakCount] = r[2] * 1e-10;
reciprocalPeaks_1_per_A->peakCount++;
}
@@ -112,7 +123,7 @@ int run_xgandalf(struct image *image, void *ipriv)
}
int goodLatticesCount = assembledLatticesCount;
- for (int i = 0; i < assembledLatticesCount && i < 1; i++) {
+ for ( i = 0; i < assembledLatticesCount && i < 1; i++) {
reorderLattice(&(xgandalf_private_data->sampleRealLattice_A),
&assembledLattices[i]);
@@ -346,7 +357,7 @@ const char *xgandalf_probe(UnitCell *cell)
#endif // HAVE_XGANDALF
-static void show_help()
+static void xgandalf_show_help()
{
printf("Parameters for the TakeTwo indexing algorithm:\n"
" --xgandalf-sampling-pitch\n"
@@ -378,26 +389,41 @@ static void show_help()
}
-static error_t parse_arg(int key, char *arg, struct argp_state *state)
+int xgandalf_default_options(XGandalfOptions **opts_ptr)
+{
+ XGandalfOptions *opts;
+
+ opts = malloc(sizeof(struct xgandalf_options));
+ if ( opts == NULL ) return ENOMEM;
+
+ opts->sampling_pitch = 6;
+ opts->grad_desc_iterations = 4;
+ opts->tolerance = 0.02;
+ opts->no_deviation_from_provided_cell = 0;
+ opts->minLatticeVectorLength_A = 30;
+ opts->maxLatticeVectorLength_A = 250;
+ opts->maxPeaksForIndexing = 250;
+
+ *opts_ptr = opts;
+ return 0;
+}
+
+
+static error_t xgandalf_parse_arg(int key, char *arg,
+ struct argp_state *state)
{
struct xgandalf_options **opts_ptr = state->input;
+ int r;
switch ( key ) {
case ARGP_KEY_INIT :
- *opts_ptr = malloc(sizeof(struct xgandalf_options));
- if ( *opts_ptr == NULL ) return ENOMEM;
- (*opts_ptr)->sampling_pitch = 6;
- (*opts_ptr)->grad_desc_iterations = 4;
- (*opts_ptr)->tolerance = 0.02;
- (*opts_ptr)->no_deviation_from_provided_cell = 0;
- (*opts_ptr)->minLatticeVectorLength_A = 30;
- (*opts_ptr)->maxLatticeVectorLength_A = 250;
- (*opts_ptr)->maxPeaksForIndexing = 250;
+ r = xgandalf_default_options(opts_ptr);
+ if ( r ) return r;
break;
case 1 :
- show_help();
+ xgandalf_show_help();
return EINVAL;
case 2 :
@@ -457,7 +483,7 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
}
-static struct argp_option options[] = {
+static struct argp_option xgandalf_options[] = {
{"help-xgandalf", 1, NULL, OPTION_NO_USAGE,
"Show options for XGANDALF indexing algorithm", 99},
@@ -488,4 +514,5 @@ static struct argp_option options[] = {
};
-struct argp xgandalf_argp = { options, parse_arg, NULL, NULL, NULL, NULL, NULL };
+struct argp xgandalf_argp = { xgandalf_options, xgandalf_parse_arg,
+ NULL, NULL, NULL, NULL, NULL };
diff --git a/libcrystfel/src/xgandalf.h b/libcrystfel/src/indexers/xgandalf.h
index 07fcba01..79078410 100644
--- a/libcrystfel/src/xgandalf.h
+++ b/libcrystfel/src/indexers/xgandalf.h
@@ -3,7 +3,7 @@
*
* Interface to XGANDALF indexer
*
- * Copyright © 2017-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2017-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
@@ -29,10 +29,6 @@
#ifndef LIBCRYSTFEL_SRC_XGANDALF_H
#define LIBCRYSTFEL_SRC_XGANDALF_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include <stddef.h>
#include <argp.h>
@@ -41,11 +37,10 @@
* XGANDALF indexer interface
*/
-typedef struct xgandalf_options XGandalfOptions;
-extern struct argp xgandalf_argp;
-
#include "index.h"
+extern int xgandalf_default_options(XGandalfOptions **opts_ptr);
+
extern int run_xgandalf(struct image *image, void *ipriv);
extern void *xgandalf_prepare(IndexingMethod *indm, UnitCell *cell,
diff --git a/libcrystfel/src/integer_matrix.c b/libcrystfel/src/integer_matrix.c
index 43f41eeb..7fcd07c4 100644
--- a/libcrystfel/src/integer_matrix.c
+++ b/libcrystfel/src/integer_matrix.c
@@ -3,11 +3,11 @@
*
* A small integer matrix library
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2012 Thomas White <taw@physics.org>
+ * 2012-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -253,8 +253,9 @@ void intmat_zero(IntegerMatrix *m)
}
-static IntegerMatrix *delete_row_and_column(const IntegerMatrix *m,
- unsigned int di, unsigned int dj)
+static IntegerMatrix *intmat_delete_row_and_column(const IntegerMatrix *m,
+ unsigned int di,
+ unsigned int dj)
{
IntegerMatrix *n;
unsigned int i, j;
@@ -280,13 +281,13 @@ static IntegerMatrix *delete_row_and_column(const IntegerMatrix *m,
}
-static signed int cofactor(const IntegerMatrix *m,
- unsigned int i, unsigned int j)
+static signed int intmat_cofactor(const IntegerMatrix *m,
+ unsigned int i, unsigned int j)
{
IntegerMatrix *n;
signed int t, C;
- n = delete_row_and_column(m, i, j);
+ n = intmat_delete_row_and_column(m, i, j);
if ( n == NULL ) {
fprintf(stderr, "Failed to allocate matrix.\n");
return 0;
@@ -324,7 +325,7 @@ signed int intmat_det(const IntegerMatrix *m)
i = 0; /* Fixed */
for ( j=0; j<m->cols; j++ ) {
- det += intmat_get(m, i, j) * cofactor(m, i, j);
+ det += intmat_get(m, i, j) * intmat_cofactor(m, i, j);
}
@@ -343,7 +344,7 @@ static IntegerMatrix *intmat_cofactors(const IntegerMatrix *m)
for ( i=0; i<n->rows; i++ ) {
for ( j=0; j<n->cols; j++ ) {
- intmat_set(n, i, j, cofactor(m, i, j));
+ intmat_set(n, i, j, intmat_cofactor(m, i, j));
}
}
diff --git a/libcrystfel/src/integer_matrix.h b/libcrystfel/src/integer_matrix.h
index 024480c3..2ebef300 100644
--- a/libcrystfel/src/integer_matrix.h
+++ b/libcrystfel/src/integer_matrix.h
@@ -3,11 +3,11 @@
*
* A small integer matrix library
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2012 Thomas White <taw@physics.org>
+ * 2012-2019 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -29,10 +29,6 @@
#ifndef INTEGER_MATRIX_H
#define INTEGER_MATRIX_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
/**
* \file integer_matrix.h
* Matrix type containing only integers
diff --git a/libcrystfel/src/integration.c b/libcrystfel/src/integration.c
index 3d8258c1..4c813a11 100644
--- a/libcrystfel/src/integration.c
+++ b/libcrystfel/src/integration.c
@@ -3,11 +3,11 @@
*
* Integration of intensities
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2016 Thomas White <taw@physics.org>
+ * 2010-2021 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -52,6 +52,7 @@
#include "image.h"
#include "peaks.h"
#include "integration.h"
+#include "detgeom.h"
/** \file integration.h */
@@ -110,7 +111,7 @@ struct peak_box
enum boxmask_val *bm; /* Box mask */
int pn; /* Panel number */
- struct panel *p; /* The panel itself */
+ struct detgeom_panel *p; /* The panel itself */
/* Fitted background parameters */
double a;
@@ -273,9 +274,6 @@ static void show_peak_box(struct intcontext *ic, struct peak_box *bx,
get_indices(bx->refl, &h, &k, &l);
get_detector_pos(bx->refl, &fs, &ss);
- /* Convert coordinates to match arrangement of panels in HDF5 file */
- fs = fs + bx->p->orig_min_fs;
- ss = ss + bx->p->orig_min_ss;
printw("Indices %i %i %i\nPanel %s\nPosition fs = %.1f, ss = %.1f\n\n",
h, k, l, bx->p->name, fs, ss);
@@ -432,33 +430,106 @@ static int alloc_boxes(struct intcontext *ic, int new_max_boxes)
}
-static int init_intcontext(struct intcontext *ic)
+static void setup_ring_masks(struct intcontext *ic,
+ double ir_inn,
+ double ir_mid,
+ double ir_out)
{
- int i;
+ double lim_sq, out_lim_sq, mid_lim_sq;
+ int p, q;
+
+ lim_sq = pow(ir_inn, 2.0);
+ mid_lim_sq = pow(ir_mid, 2.0);
+ out_lim_sq = pow(ir_out, 2.0);
+
+ for ( p=0; p<ic->w; p++ ) {
+ for ( q=0; q<ic->w; q++ ) {
+
+ int rsq;
+
+ rsq = (p-ic->halfw)*(p-ic->halfw) + (q-ic->halfw)*(q-ic->halfw);
+
+ if ( rsq > out_lim_sq ) {
+ /* Outside outer radius */
+ ic->bm[p + ic->w*q] = BM_IG;
+ } else {
+
+ if ( rsq >= mid_lim_sq ) {
+ /* Inside outer radius, outside middle radius */
+ ic->bm[p + ic->w*q] = BM_BG;
+ } else if ( rsq <= lim_sq ) {
+ /* Inside inner radius */
+ ic->bm[p + ic->w*q] = BM_PK;
+ } else {
+ /* Outside inner radius, inside middle radius */
+ ic->bm[p + ic->w*q] = BM_IG;
+ }
+ }
+
+ }
+ }
+
+}
+
+
+void intcontext_set_diag(struct intcontext *ic,
+ IntDiag int_diag,
+ signed int idh,
+ signed int idk,
+ signed int idl)
+{
+ ic->int_diag = int_diag;
+ ic->int_diag_h = idh;
+ ic->int_diag_k = idk;
+ ic->int_diag_l = idl;
+}
+
+
+struct intcontext *intcontext_new(struct image *image,
+ UnitCell *cell,
+ IntegrationMethod meth,
+ int ir_inn, int ir_mid, int ir_out,
+ int **masks)
+{
+ int i;
+ struct intcontext *ic;
+
+ ic = malloc(sizeof(struct intcontext));
+ if ( ic == NULL ) return NULL;
+
+ ic->halfw = ir_out;
+ ic->image = image;
+ ic->k = 1.0/image->lambda;
+ ic->meth = meth;
+ ic->n_saturated = 0;
+ ic->n_implausible = 0;
+ ic->cell = cell;
+ ic->masks = masks;
+ ic->int_diag = INTDIAG_NONE;
ic->w = 2*ic->halfw + 1;
ic->bm = malloc(ic->w * ic->w * sizeof(enum boxmask_val));
if ( ic->bm == NULL ) {
ERROR("Failed to allocate box mask.\n");
- return 1;
+ return NULL;
}
/* How many reference profiles? */
ic->n_reference_profiles = 1;
ic->reference_profiles = calloc(ic->n_reference_profiles,
sizeof(double *));
- if ( ic->reference_profiles == NULL ) return 1;
+ if ( ic->reference_profiles == NULL ) return NULL;
ic->reference_den = calloc(ic->n_reference_profiles, sizeof(double *));
- if ( ic->reference_den == NULL ) return 1;
+ if ( ic->reference_den == NULL ) return NULL;
ic->n_profiles_in_reference = calloc(ic->n_reference_profiles,
sizeof(int));
- if ( ic->n_profiles_in_reference == NULL ) return 1;
+ if ( ic->n_profiles_in_reference == NULL ) return NULL;
for ( i=0; i<ic->n_reference_profiles; i++ ) {
ic->reference_profiles[i] = malloc(ic->w*ic->w*sizeof(double));
- if ( ic->reference_profiles[i] == NULL ) return 1;
+ if ( ic->reference_profiles[i] == NULL ) return NULL;
ic->reference_den[i] = malloc(ic->w*ic->w*sizeof(double));
- if ( ic->reference_den[i] == NULL ) return 1;
+ if ( ic->reference_den[i] == NULL ) return NULL;
}
zero_profiles(ic);
@@ -466,14 +537,16 @@ static int init_intcontext(struct intcontext *ic)
ic->n_boxes = 0;
ic->max_boxes = 0;
if ( alloc_boxes(ic, 32) ) {
- return 1;
+ return NULL;
}
- return 0;
+ setup_ring_masks(ic, ir_inn, ir_mid, ir_out);
+
+ return ic;
}
-static void free_intcontext(struct intcontext *ic)
+void intcontext_free(struct intcontext *ic)
{
int i;
@@ -494,47 +567,6 @@ static void free_intcontext(struct intcontext *ic)
}
-static void setup_ring_masks(struct intcontext *ic,
- double ir_inn, double ir_mid, double ir_out)
-{
- double lim_sq, out_lim_sq, mid_lim_sq;
- int p, q;
-
- lim_sq = pow(ir_inn, 2.0);
- mid_lim_sq = pow(ir_mid, 2.0);
- out_lim_sq = pow(ir_out, 2.0);
-
- for ( p=0; p<ic->w; p++ ) {
- for ( q=0; q<ic->w; q++ ) {
-
- int rsq;
-
- rsq = (p-ic->halfw)*(p-ic->halfw) + (q-ic->halfw)*(q-ic->halfw);
-
- if ( rsq > out_lim_sq ) {
- /* Outside outer radius */
- ic->bm[p + ic->w*q] = BM_IG;
- } else {
-
- if ( rsq >= mid_lim_sq ) {
- /* Inside outer radius, outside middle radius */
- ic->bm[p + ic->w*q] = BM_BG;
- } else if ( rsq <= lim_sq ) {
- /* Inside inner radius */
- ic->bm[p + ic->w*q] = BM_PK;
- } else {
- /* Outside inner radius, inside middle radius */
- ic->bm[p + ic->w*q] = BM_IG;
- }
-
- }
-
- }
- }
-
-}
-
-
static struct peak_box *add_box(struct intcontext *ic)
{
int idx;
@@ -804,9 +836,6 @@ static int check_box(struct intcontext *ic, struct peak_box *bx, int *sat)
for ( q=0; q<ic->w; q++ ) {
int fs, ss;
- double hd, kd, ld;
- signed int h, k, l;
- struct rvec dv;
float lsat;
fs = bx->cfs + p;
@@ -862,22 +891,11 @@ static int check_box(struct intcontext *ic, struct peak_box *bx, int *sat)
if ( sat != NULL ) *sat = 1;
}
- /* Ignore if this pixel is closer to the next reciprocal lattice
- * point */
- dv = get_q_for_panel(bx->p, fs, ss, NULL, ic->k);
- hd = dv.u * adx + dv.v * ady + dv.w * adz;
- kd = dv.u * bdx + dv.v * bdy + dv.w * bdz;
- ld = dv.u * cdx + dv.v * cdy + dv.w * cdz;
- h = lrint(hd);
- k = lrint(kd);
- l = lrint(ld);
- if ( (h != hr) || (k != kr) || (l != lr) ) {
- bx->bm[p+ic->w*q] = BM_BH;
- }
-
+ /* Find brightest pixel */
if ( (bx->bm[p+ic->w*q] != BM_IG)
&& (bx->bm[p+ic->w*q] != BM_BH)
- && (boxi(ic, bx, p, q) > bx->peak) ) {
+ && (boxi(ic, bx, p, q) > bx->peak) )
+ {
bx->peak = boxi(ic, bx, p, q);
}
@@ -1273,7 +1291,6 @@ static void setup_profile_boxes(struct intcontext *ic, RefList *list)
double pfs, pss;
struct peak_box *bx;
int pn;
- struct panel *p;
int fid_fs, fid_ss; /* Center coordinates, rounded,
* in overall data block */
int cfs, css; /* Corner coordinates */
@@ -1283,12 +1300,7 @@ static void setup_profile_boxes(struct intcontext *ic, RefList *list)
set_redundancy(refl, 0);
get_detector_pos(refl, &pfs, &pss);
- p = get_panel(refl);
- pn = panel_number(ic->image->det, p);
- if ( pn == ic->image->det->n_panels ) {
- ERROR("Couldn't find panel %p\n", p);
- continue;
- }
+ pn = get_panel_number(refl);
/* Explicit truncation of digits after the decimal point.
* This is actually the correct thing to do here, not
@@ -1307,7 +1319,7 @@ static void setup_profile_boxes(struct intcontext *ic, RefList *list)
bx->refl = refl;
bx->cfs = cfs;
bx->css = css;
- bx->p = p;
+ bx->p = &ic->image->detgeom->panels[pn];
bx->pn = pn;
/* Which reference profile? */
@@ -1345,68 +1357,58 @@ static void setup_profile_boxes(struct intcontext *ic, RefList *list)
}
-static void integrate_prof2d(IntegrationMethod meth,
- Crystal *cr, struct image *image, IntDiag int_diag,
- signed int idh, signed int idk, signed int idl,
- double ir_inn, double ir_mid, double ir_out,
- pthread_mutex_t *term_lock, int **masks)
+void integrate_prof2d(IntegrationMethod meth,
+ Crystal *cr, struct image *image, IntDiag int_diag,
+ signed int idh, signed int idk, signed int idl,
+ double ir_inn, double ir_mid, double ir_out,
+ pthread_mutex_t *term_lock, int **masks)
{
RefList *list;
UnitCell *cell;
- struct intcontext ic;
+ struct intcontext *ic;
int i;
list = crystal_get_reflections(cr);
cell = crystal_get_cell(cr);
- ic.halfw = ir_out;
- ic.image = image;
- ic.k = 1.0/image->lambda;
- ic.meth = meth;
- ic.n_saturated = 0;
- ic.n_implausible = 0;
- ic.cell = cell;
- ic.int_diag = int_diag;
- ic.int_diag_h = idh;
- ic.int_diag_k = idk;
- ic.int_diag_l = idl;
- ic.masks = masks;
- if ( init_intcontext(&ic) ) {
+ ic = intcontext_new(image, cell, meth,
+ ir_inn, ir_mid, ir_out,
+ masks);
+ if ( ic == NULL ) {
ERROR("Failed to initialise integration.\n");
return;
}
- setup_ring_masks(&ic, ir_inn, ir_mid, ir_out);
- setup_profile_boxes(&ic, list);
- calculate_reference_profiles(&ic);
+ intcontext_set_diag(ic, int_diag, idh, idk, idl);
+ setup_profile_boxes(ic, list);
+ calculate_reference_profiles(ic);
- for ( i=0; i<ic.n_reference_profiles; i++ ) {
- if ( ic.n_profiles_in_reference[i] == 0 ) {
+ for ( i=0; i<ic->n_reference_profiles; i++ ) {
+ if ( ic->n_profiles_in_reference[i] == 0 ) {
ERROR("Reference profile %i has no contributions.\n",
i);
- free_intcontext(&ic);
+ intcontext_free(ic);
return;
}
}
- for ( i=0; i<ic.n_boxes; i++ ) {
+ for ( i=0; i<ic->n_boxes; i++ ) {
struct peak_box *bx;
- bx = &ic.boxes[i];
- integrate_prof2d_once(&ic, bx, term_lock);
+ bx = &ic->boxes[i];
+ integrate_prof2d_once(ic, bx, term_lock);
}
- free_intcontext(&ic);
+ intcontext_free(ic);
}
-static int integrate_rings_once(Reflection *refl, struct image *image,
- struct intcontext *ic, UnitCell *cell,
- pthread_mutex_t *term_lock)
+int integrate_rings_once(Reflection *refl,
+ struct intcontext *ic,
+ pthread_mutex_t *term_lock)
{
double pfs, pss;
struct peak_box *bx;
int pn;
- struct panel *p;
int fid_fs, fid_ss; /* Center coordinates, rounded,
* in overall data block */
int cfs, css; /* Corner coordinates */
@@ -1419,12 +1421,7 @@ static int integrate_rings_once(Reflection *refl, struct image *image,
set_redundancy(refl, 0);
get_detector_pos(refl, &pfs, &pss);
- p = get_panel(refl);
- pn = panel_number(image->det, p);
- if ( pn == image->det->n_panels ) {
- ERROR("Couldn't find panel %p\n", p);
- return 1;
- }
+ pn = get_panel_number(refl);
/* Explicit truncation of digits after the decimal point.
* This is actually the correct thing to do here, not
@@ -1442,7 +1439,7 @@ static int integrate_rings_once(Reflection *refl, struct image *image,
bx->refl = refl;
bx->cfs = cfs;
bx->css = css;
- bx->p = p;
+ bx->p = &ic->image->detgeom->panels[pn];
bx->pn = pn;
if ( ic->meth & INTEGRATION_CENTER ) {
@@ -1521,17 +1518,7 @@ static int integrate_rings_once(Reflection *refl, struct image *image,
}
-static int compare_double(const void *av, const void *bv)
-{
- double a = *(double *)av;
- double b = *(double *)bv;
- if ( a > b ) return 1;
- if ( a < b ) return -1;
- return 0;
-}
-
-
-static double estimate_resolution(UnitCell *cell, ImageFeatureList *flist)
+static double estimate_resolution(Crystal *cr, struct image *image)
{
int i;
const double min_dist = 0.25;
@@ -1540,6 +1527,9 @@ static double estimate_resolution(UnitCell *cell, ImageFeatureList *flist)
int n_acc = 0;
int max_acc = 1024;
int n;
+ double dx, dy;
+ UnitCell *cell;
+
acc = malloc(max_acc*sizeof(double));
if ( acc == NULL ) {
@@ -1547,27 +1537,36 @@ static double estimate_resolution(UnitCell *cell, ImageFeatureList *flist)
return INFINITY;
}
- for ( i=0; i<image_feature_count(flist); i++ ) {
+ cell = crystal_get_cell(cr);
+ crystal_get_det_shift(cr, &dx, &dy);
+
+ for ( i=0; i<image_feature_count(image->features); i++ ) {
struct imagefeature *f;
double h, k, l, hd, kd, ld;
-
- /* Assume all image "features" are genuine peaks */
- f = image_get_feature(flist, i);
- if ( f == NULL ) continue;
-
double ax, ay, az;
double bx, by, bz;
double cx, cy, cz;
+ double r[3];
+
+ /* Assume all image "features" are genuine peaks */
+ f = image_get_feature(image->features, i);
+ if ( f == NULL ) continue;
cell_get_cartesian(cell,
- &ax, &ay, &az, &bx, &by, &bz, &cx, &cy, &cz);
+ &ax, &ay, &az,
+ &bx, &by, &bz,
+ &cx, &cy, &cz);
+
+ detgeom_transform_coords(&image->detgeom->panels[f->pn],
+ f->fs, f->ss, image->lambda,
+ dx, dy, r);
/* Decimal and fractional Miller indices of nearest
* reciprocal lattice point */
- hd = f->rx * ax + f->ry * ay + f->rz * az;
- kd = f->rx * bx + f->ry * by + f->rz * bz;
- ld = f->rx * cx + f->ry * cy + f->rz * cz;
+ hd = r[0] * ax + r[1] * ay + r[2] * az;
+ kd = r[0] * bx + r[1] * by + r[2] * bz;
+ ld = r[0] * cx + r[1] * cy + r[2] * cz;
h = lrint(hd);
k = lrint(kd);
l = lrint(ld);
@@ -1619,49 +1618,39 @@ static void integrate_rings(IntegrationMethod meth,
Reflection *refl;
RefListIterator *iter;
UnitCell *cell;
- struct intcontext ic;
+ struct intcontext *ic;
int n_rej = 0;
list = crystal_get_reflections(cr);
cell = crystal_get_cell(cr);
- ic.halfw = ir_out;
- ic.image = image;
- ic.k = 1.0/image->lambda;
- ic.n_saturated = 0;
- ic.n_implausible = 0;
- ic.cell = cell;
- ic.ir_inn = ir_inn;
- ic.ir_mid = ir_mid;
- ic.ir_out = ir_out;
- ic.int_diag = int_diag;
- ic.int_diag_h = idh;
- ic.int_diag_k = idk;
- ic.int_diag_l = idl;
- ic.meth = meth;
- ic.masks = masks;
- if ( init_intcontext(&ic) ) {
+ ic = intcontext_new(image, cell, meth,
+ ir_inn, ir_mid, ir_out,
+ masks);
+ if ( ic == NULL ) {
ERROR("Failed to initialise integration.\n");
return;
}
- setup_ring_masks(&ic, ir_inn, ir_mid, ir_out);
+
+ intcontext_set_diag(ic, int_diag, idh, idk, idl);
for ( refl = first_refl(list, &iter);
refl != NULL;
refl = next_refl(refl, iter) )
{
- n_rej += integrate_rings_once(refl, image, &ic, cell, term_lock);
+ n_rej += integrate_rings_once(refl, ic,
+ term_lock);
}
- free_intcontext(&ic);
+ intcontext_free(ic);
if ( n_rej > 0 ) {
ERROR("WARNING: %i reflections could not be integrated\n",
n_rej);
}
- crystal_set_num_saturated_reflections(cr, ic.n_saturated);
- crystal_set_num_implausible_reflections(cr, ic.n_implausible);
+ crystal_set_num_saturated_reflections(cr, ic->n_saturated);
+ crystal_set_num_implausible_reflections(cr, ic->n_implausible);
}
@@ -1673,7 +1662,7 @@ void integrate_all_5(struct image *image, IntegrationMethod meth,
pthread_mutex_t *term_lock, int overpredict)
{
int i;
- int *masks[image->det->n_panels];
+ int *masks[image->detgeom->n_panels];
/* Predict all reflections */
for ( i=0; i<image->n_crystals; i++ ) {
@@ -1687,8 +1676,7 @@ void integrate_all_5(struct image *image, IntegrationMethod meth,
saved_R * 5);
}
- res = estimate_resolution(crystal_get_cell(image->crystals[i]),
- image->features);
+ res = estimate_resolution(image->crystals[i], image);
crystal_set_resolution_limit(image->crystals[i], res);
list = predict_to_res(image->crystals[i], res+push_res);
@@ -1700,8 +1688,9 @@ void integrate_all_5(struct image *image, IntegrationMethod meth,
}
- for ( i=0; i<image->det->n_panels; i++ ) {
- masks[i] = make_BgMask(image, &image->det->panels[i], ir_inn);
+ for ( i=0; i<image->detgeom->n_panels; i++ ) {
+ masks[i] = make_BgMask(image, &image->detgeom->panels[i],
+ i, ir_inn);
}
for ( i=0; i<image->n_crystals; i++ ) {
@@ -1737,7 +1726,7 @@ void integrate_all_5(struct image *image, IntegrationMethod meth,
}
- for ( i=0; i<image->det->n_panels; i++ ) {
+ for ( i=0; i<image->detgeom->n_panels; i++ ) {
free(masks[i]);
}
}
@@ -1852,4 +1841,3 @@ IntegrationMethod integration_method(const char *str, int *err)
return meth;
}
-
diff --git a/libcrystfel/src/integration.h b/libcrystfel/src/integration.h
index 11e67dbe..f230201d 100644
--- a/libcrystfel/src/integration.h
+++ b/libcrystfel/src/integration.h
@@ -3,11 +3,11 @@
*
* Integration of intensities
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2015 Thomas White <taw@physics.org>
+ * 2010-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -29,10 +29,6 @@
#ifndef INTEGRATION_H
#define INTEGRATION_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include "geometry.h"
/**
@@ -113,8 +109,22 @@ typedef enum {
extern "C" {
#endif
+struct intcontext;
+
extern IntegrationMethod integration_method(const char *t, int *err);
+extern struct intcontext *intcontext_new(struct image *image,
+ UnitCell *cell,
+ IntegrationMethod meth,
+ int ir_inn, int ir_mid, int ir_out,
+ int **masks);
+
+extern int integrate_rings_once(Reflection *refl,
+ struct intcontext *ic,
+ pthread_mutex_t *term_lock);
+
+extern void intcontext_free(struct intcontext *ic);
+
extern void integrate_all(struct image *image, IntegrationMethod meth,
double ir_inn, double ir_mid, double ir_out,
IntDiag int_diag,
diff --git a/libcrystfel/src/libcrystfel-version.c.cmake.in b/libcrystfel/src/libcrystfel-version.c.cmake.in
new file mode 100644
index 00000000..513d7871
--- /dev/null
+++ b/libcrystfel/src/libcrystfel-version.c.cmake.in
@@ -0,0 +1,4 @@
+const char *libcrystfel_version_string()
+{
+ return "${CRYSTFEL_VERSION}";
+}
diff --git a/libcrystfel/src/libcrystfel-version.c.in b/libcrystfel/src/libcrystfel-version.c.in
new file mode 100644
index 00000000..1cde75f7
--- /dev/null
+++ b/libcrystfel/src/libcrystfel-version.c.in
@@ -0,0 +1,6 @@
+#define LIBCRYSTFEL_VERSION_H
+
+const char *libcrystfel_version_string()
+{
+ return "@VCS_TAG@";
+}
diff --git a/libcrystfel/src/libcrystfel-version.h b/libcrystfel/src/libcrystfel-version.h
new file mode 100644
index 00000000..837b8299
--- /dev/null
+++ b/libcrystfel/src/libcrystfel-version.h
@@ -0,0 +1,5 @@
+#ifndef LIBCRYSTFEL_VERSION_H
+#define LIBCRYSTFEL_VERSION_H
+extern const char *libcrystfel_version_string(void);
+extern const char *libcrystfel_licence_string(void);
+#endif
diff --git a/libcrystfel/src/peakfinder8.c b/libcrystfel/src/peakfinder8.c
index c3f7c391..641a154b 100644
--- a/libcrystfel/src/peakfinder8.c
+++ b/libcrystfel/src/peakfinder8.c
@@ -3,13 +3,14 @@
*
* The peakfinder8 algorithm
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2017 Valerio Mariani <valerio.mariani@desy.de>
- * 2017 Anton Barty <anton.barty@desy.de>
- * 2017 Oleksandr Yefanov <oleksandr.yefanov@desy.de>
+ * 2017-2021 Thomas White <taw@physics.org>
+ * 2017 Valerio Mariani <valerio.mariani@desy.de>
+ * 2017 Anton Barty <anton.barty@desy.de>
+ * 2017 Oleksandr Yefanov <oleksandr.yefanov@desy.de>
*
* This file is part of CrystFEL.
*
@@ -37,6 +38,8 @@
#include <stdlib.h>
#include "peakfinder8.h"
+#include "detgeom.h"
+#include "image.h"
/** \file peakfinder8.h */
@@ -101,10 +104,10 @@ struct peakfinder_peak_data
// CrystFEL-only block 2
-static struct radius_maps *compute_radius_maps(struct detector *det)
+static struct radius_maps *compute_radius_maps(struct detgeom *det)
{
int i, u, iss, ifs;
- struct panel p;
+ struct detgeom_panel p;
struct radius_maps *rm = NULL;
rm = (struct radius_maps *)malloc(sizeof(struct radius_maps));
@@ -173,14 +176,14 @@ static struct peakfinder_mask *create_peakfinder_mask(struct image *img,
struct peakfinder_mask *msk;
msk = (struct peakfinder_mask *)malloc(sizeof(struct peakfinder_mask));
- msk->masks =(char **) malloc(img->det->n_panels*sizeof(char*));
- msk->n_masks = img->det->n_panels;
- for ( i=0; i<img->det->n_panels; i++) {
+ msk->masks =(char **) malloc(img->detgeom->n_panels*sizeof(char*));
+ msk->n_masks = img->detgeom->n_panels;
+ for ( i=0; i<img->detgeom->n_panels; i++) {
- struct panel p;
+ struct detgeom_panel p;
int iss, ifs;
- p = img->det->panels[i];
+ p = img->detgeom->panels[i];
msk->masks[i] = (char *)calloc(p.w*p.h,sizeof(char));
@@ -1040,14 +1043,10 @@ int peakfinder8(struct image *img, int max_n_peaks,
iterations = 5;
- if ( img-> det == NULL) {
- return 1;
- }
+ if ( img->detgeom == NULL) return 1;
- rmaps = compute_radius_maps(img->det);
- if ( rmaps == NULL ) {
- return 1;
- }
+ rmaps = compute_radius_maps(img->detgeom);
+ if ( rmaps == NULL ) return 1;
pfmask = create_peakfinder_mask(img, rmaps, min_res, max_res);
if ( pfmask == NULL ) {
@@ -1055,18 +1054,18 @@ int peakfinder8(struct image *img, int max_n_peaks,
return 1;
}
- pfdata = allocate_panel_data(img->det->n_panels);
+ pfdata = allocate_panel_data(img->detgeom->n_panels);
if ( pfdata == NULL) {
free_radius_maps(rmaps);
free_peakfinder_mask(pfmask);
return 1;
}
- for ( pi=0 ; pi<img->det->n_panels ; pi++ ) {
- pfdata->panel_h[pi] = img->det->panels[pi].h;
- pfdata->panel_w[pi] = img->det->panels[pi].w;
+ for ( pi=0 ; pi<img->detgeom->n_panels ; pi++ ) {
+ pfdata->panel_h[pi] = img->detgeom->panels[pi].h;
+ pfdata->panel_w[pi] = img->detgeom->panels[pi].w;
pfdata->panel_data[pi] = img->dp[pi];
- pfdata->num_panels = img->det->n_panels;
+ pfdata->num_panels = img->detgeom->n_panels;
}
max_r = -1e9;
@@ -1139,7 +1138,7 @@ int peakfinder8(struct image *img, int max_n_peaks,
remaining_max_num_peaks = max_n_peaks;
- for ( pi=0 ; pi<img->det->n_panels ; pi++) {
+ for ( pi=0 ; pi<img->detgeom->n_panels ; pi++) {
int peaks_to_add;
int pki;
@@ -1147,10 +1146,6 @@ int peakfinder8(struct image *img, int max_n_peaks,
num_found_peaks = 0;
- if ( img->det->panels[pi].no_index ) {
- continue;
- }
-
ret = peakfinder8_base(rstats->roffset,
rstats->rthreshold,
pfdata->panel_data[pi],
@@ -1192,9 +1187,9 @@ int peakfinder8(struct image *img, int max_n_peaks,
for ( pki=0 ; pki<peaks_to_add ; pki++ ) {
- struct panel *p;
+ struct detgeom_panel *p;
- p = &img->det->panels[pi];
+ p = &img->detgeom->panels[pi];
if ( pkdata->max_i[pki] > p->max_adu ) {
if ( !use_saturated ) {
@@ -1205,9 +1200,7 @@ int peakfinder8(struct image *img, int max_n_peaks,
image_add_feature(img->features,
pkdata->com_fs[pki]+0.5,
pkdata->com_ss[pki]+0.5,
- p,
- img,
- pkdata->tot_i[pki],
+ pi, img, pkdata->tot_i[pki],
NULL);
}
}
diff --git a/libcrystfel/src/peakfinder8.h b/libcrystfel/src/peakfinder8.h
index b4d54fd1..28212e49 100644
--- a/libcrystfel/src/peakfinder8.h
+++ b/libcrystfel/src/peakfinder8.h
@@ -3,13 +3,14 @@
*
* The peakfinder8 algorithm
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2017 Valerio Mariani <valerio.mariani@desy.de>
- * 2017 Anton Barty <anton.barty@desy.de>
- * 2017 Oleksandr Yefanov <oleksandr.yefanov@desy.de>
+ * 2019 Thomas White <taw@physics.org>
+ * 2017 Valerio Mariani <valerio.mariani@desy.de>
+ * 2017 Anton Barty <anton.barty@desy.de>
+ * 2017 Oleksandr Yefanov <oleksandr.yefanov@desy.de>
*
* This file is part of CrystFEL.
*
diff --git a/libcrystfel/src/peaks.c b/libcrystfel/src/peaks.c
index 7f2526bc..d55ddd03 100644
--- a/libcrystfel/src/peaks.c
+++ b/libcrystfel/src/peaks.c
@@ -3,12 +3,12 @@
*
* Peak search and other image analysis
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2012 Richard Kirian
*
* Authors:
- * 2010-2016 Thomas White <taw@physics.org>
+ * 2010-2020 Thomas White <taw@physics.org>
* 2012 Kenneth Beyerlein <kenneth.beyerlein@desy.de>
* 2011 Andrew Martin <andrew.martin@desy.de>
* 2011 Richard Kirian
@@ -55,7 +55,7 @@
#include "image.h"
#include "utils.h"
#include "peaks.h"
-#include "detector.h"
+#include "detgeom.h"
#include "filters.h"
#include "reflist-utils.h"
#include "cell-utils.h"
@@ -64,94 +64,8 @@
/** \file peaks.h */
-static int cull_peaks_in_panel(struct image *image, struct panel *p)
-{
- int i, n;
- int nelim = 0;
-
- n = image_feature_count(image->features);
-
- for ( i=0; i<n; i++ ) {
-
- struct imagefeature *f;
- int j, ncol;
-
- f = image_get_feature(image->features, i);
- if ( f == NULL ) continue;
-
- if ( f->p != p ) continue;
-
- /* How many peaks are in the same column? */
- ncol = 0;
- for ( j=0; j<n; j++ ) {
-
- struct imagefeature *g;
-
- if ( i==j ) continue;
-
- g = image_get_feature(image->features, j);
- if ( g == NULL ) continue;
-
- if ( p->badrow == 'f' ) {
- if ( fabs(f->ss - g->ss) < 2.0 ) ncol++;
- } else if ( p->badrow == 's' ) {
- if ( fabs(f->fs - g->fs) < 2.0 ) ncol++;
- } /* else do nothing */
-
- }
-
- /* More than three? */
- if ( ncol <= 3 ) continue;
-
- /* Yes? Delete them all... */
- for ( j=0; j<n; j++ ) {
- struct imagefeature *g;
- g = image_get_feature(image->features, j);
- if ( g == NULL ) continue;
- if ( p->badrow == 'f' ) {
- if ( fabs(f->ss - g->ss) < 2.0 ) {
- image_remove_feature(image->features,
- j);
- nelim++;
- }
- } else if ( p->badrow == 's' ) {
- if ( fabs(f->fs - g->ss) < 2.0 ) {
- image_remove_feature(image->features,
- j);
- nelim++;
- }
- } else {
- ERROR("Invalid badrow direction.\n");
- abort();
- }
-
- }
-
- }
-
- return nelim;
-}
-
-
-/* Post-processing of the peak list to remove noise */
-static int cull_peaks(struct image *image)
-{
- int nelim = 0;
- struct panel *p;
- int i;
-
- for ( i=0; i<image->det->n_panels; i++ ) {
- p = &image->det->panels[i];
- if ( p->badrow != '-' ) {
- nelim += cull_peaks_in_panel(image, p);
- }
- }
-
- return nelim;
-}
-
-
-static void add_crystal_to_mask(struct image *image, struct panel *p,
+static void add_crystal_to_mask(struct image *image,
+ struct detgeom_panel *p, int pn,
double ir_inn, int *mask, Crystal *cr)
{
Reflection *refl;
@@ -168,7 +82,7 @@ static void add_crystal_to_mask(struct image *image, struct panel *p,
get_detector_pos(refl, &pk2_fs, &pk2_ss);
/* Determine if reflection is in the same panel */
- if ( get_panel(refl) != p ) continue;
+ if ( get_panel_number(refl) != pn ) continue;
for ( dfs=-ir_inn; dfs<=ir_inn; dfs++ ) {
for ( dss=-ir_inn; dss<=ir_inn; dss++ ) {
@@ -197,7 +111,8 @@ static void add_crystal_to_mask(struct image *image, struct panel *p,
/* cfs, css relative to panel origin */
-int *make_BgMask(struct image *image, struct panel *p, double ir_inn)
+int *make_BgMask(struct image *image, struct detgeom_panel *p,
+ int pn, double ir_inn)
{
int *mask;
int i;
@@ -208,7 +123,7 @@ int *make_BgMask(struct image *image, struct panel *p, double ir_inn)
if ( image->crystals == NULL ) return mask;
for ( i=0; i<image->n_crystals; i++ ) {
- add_crystal_to_mask(image, p, ir_inn,
+ add_crystal_to_mask(image, p, pn, ir_inn,
mask, image->crystals[i]);
}
@@ -218,12 +133,12 @@ int *make_BgMask(struct image *image, struct panel *p, double ir_inn)
/* Returns non-zero if peak has been vetoed.
* i.e. don't use result if return value is not zero. */
-static int integrate_peak(struct image *image,
- int p_cfs, int p_css, struct panel *p,
- double *pfs, double *pss,
- double *intensity, double *sigma,
- double ir_inn, double ir_mid, double ir_out,
- int *saturated)
+int integrate_peak(struct image *image,
+ int p_cfs, int p_css, int pn,
+ double *pfs, double *pss,
+ double *intensity, double *sigma,
+ double ir_inn, double ir_mid, double ir_out,
+ int *saturated)
{
signed int dfs, dss;
double lim_sq, out_lim_sq, mid_lim_sq;
@@ -236,22 +151,18 @@ static int integrate_peak(struct image *image,
double bg_tot_sq = 0.0;
double var;
double aduph;
- int pn;
+ struct detgeom_panel *p;
if ( saturated != NULL ) *saturated = 0;
+ p = &image->detgeom->panels[pn];
+
aduph = p->adu_per_photon;
lim_sq = pow(ir_inn, 2.0);
mid_lim_sq = pow(ir_mid, 2.0);
out_lim_sq = pow(ir_out, 2.0);
- pn = panel_number(image->det, p);
- if ( pn == image->det->n_panels ) {
- ERROR("Couldn't find panel %p\n", p);
- return 20;
- }
-
/* Estimate the background */
for ( dss=-ir_out; dss<=+ir_out; dss++ ) {
for ( dfs=-ir_out; dfs<=+ir_out; dfs++ ) {
@@ -352,7 +263,7 @@ static void search_peaks_in_panel(struct image *image, float threshold,
{
int fs, ss, stride;
float *data;
- struct panel *p;
+ struct detgeom_panel *p;
double d;
int idx;
double f_fs = 0.0;
@@ -366,9 +277,8 @@ static void search_peaks_in_panel(struct image *image, float threshold,
int nrej_snr = 0;
int nrej_sat = 0;
int nacc = 0;
- int ncull;
- p = &image->det->panels[pn];
+ p = &image->detgeom->panels[pn];
data = image->dp[pn];
stride = p->w;
@@ -456,7 +366,7 @@ static void search_peaks_in_panel(struct image *image, float threshold,
assert(mask_ss >= 0);
/* Centroid peak and get better coordinates. */
- r = integrate_peak(image, mask_fs, mask_ss, p,
+ r = integrate_peak(image, mask_fs, mask_ss, pn,
&f_fs, &f_ss, &intensity, &sigma,
ir_inn, ir_mid, ir_out, &saturated);
@@ -479,7 +389,8 @@ static void search_peaks_in_panel(struct image *image, float threshold,
}
/* Check for a nearby feature */
- image_feature_closest(image->features, f_fs, f_ss, p, &d, &idx);
+ image_feature_closest(image->features, f_fs, f_ss, pn,
+ &d, &idx);
if ( d < 2.0*ir_inn ) {
nrej_pro++;
continue;
@@ -491,33 +402,19 @@ static void search_peaks_in_panel(struct image *image, float threshold,
}
/* Add using "better" coordinates */
- image_add_feature(image->features, f_fs, f_ss, p,
+ image_add_feature(image->features, f_fs, f_ss, pn,
image, intensity, NULL);
nacc++;
}
}
- if ( image->det != NULL ) {
- ncull = cull_peaks(image);
- nacc -= ncull;
- } else {
- STATUS("Not culling peaks because I don't have a "
- "detector geometry file.\n");
- ncull = 0;
- }
-
//STATUS("%i accepted, %i box, %i proximity, %i outside panel, "
// "%i failed integration, %i with SNR < %g, %i badrow culled, "
// "%i saturated.\n",
// nacc, nrej_dis, nrej_pro, nrej_fra, nrej_fail,
- // nrej_snr, min_snr, ncull, nrej_sat);
+ // nrej_snr, min_snr, nrej_sat);
- if ( ncull != 0 ) {
- STATUS("WARNING: %i peaks were badrow culled. This feature"
- " should not usually be used.\nConsider setting"
- " badrow=- in the geometry file.\n", ncull);
- }
}
@@ -532,9 +429,7 @@ void search_peaks(struct image *image, float threshold, float min_sq_gradient,
}
image->features = image_feature_list_new();
- for ( i=0; i<image->det->n_panels; i++ ) {
-
- if ( image->det->panels[i].no_index ) continue;
+ for ( i=0; i<image->detgeom->n_panels; i++ ) {
search_peaks_in_panel(image, threshold, min_sq_gradient,
min_snr, i, ir_inn, ir_mid, ir_out,
@@ -606,16 +501,14 @@ int search_peaks_peakfinder9(struct image *image, float min_snr_biggest_pix,
if ( allocatePeakList(&peakList, NpeaksMax) ) return 1;
- for ( panel_number=0; panel_number<image->det->n_panels; panel_number++ ) {
+ for ( panel_number=0; panel_number<image->detgeom->n_panels; panel_number++ ) {
int w, h;
int peak_number;
detectorRawFormat_t det_size_one_panel;
- if ( image->det->panels[panel_number].no_index ) continue;
-
- w = image->det->panels[panel_number].w;
- h = image->det->panels[panel_number].h;
+ w = image->detgeom->panels[panel_number].w;
+ h = image->detgeom->panels[panel_number].h;
det_size_one_panel.asic_nx = w;
det_size_one_panel.asic_ny = h;
@@ -648,8 +541,7 @@ int search_peaks_peakfinder9(struct image *image, float min_snr_biggest_pix,
image_add_feature(image->features,
peakList.centerOfMass_rawX[peak_number],
peakList.centerOfMass_rawY[peak_number],
- &image->det->panels[panel_number],
- image,
+ panel_number, image,
peakList.totalIntensity[peak_number],
NULL);
}
@@ -698,7 +590,7 @@ int indexing_peak_check(struct image *image, Crystal **crystals, int n_cryst,
for ( i=0; i<image_feature_count(image->features); i++ ) {
struct imagefeature *f;
- struct rvec q;
+ double q[3];
double h,k,l,hd,kd,ld;
int j;
int ok = 0;
@@ -708,15 +600,22 @@ int indexing_peak_check(struct image *image, Crystal **crystals, int n_cryst,
if ( f == NULL ) continue;
n_feat++;
- /* Reciprocal space position of found peak */
- q = get_q_for_panel(f->p, f->fs, f->ss,
- NULL, 1.0/image->lambda);
-
for ( j=0; j<n_cryst; j++ ) {
double ax, ay, az;
double bx, by, bz;
double cx, cy, cz;
+ double dx, dy;
+
+ crystal_get_det_shift(crystals[j], &dx, &dy);
+
+ /* Reciprocal space position of found peak,
+ * based on a calculation including any updates to the
+ * detector position from the refinement of the
+ * current crystal. */
+ detgeom_transform_coords(&image->detgeom->panels[f->pn],
+ f->fs, f->ss, image->lambda,
+ dx, dy, q);
cell_get_cartesian(crystal_get_cell(crystals[j]),
&ax, &ay, &az,
@@ -725,9 +624,9 @@ int indexing_peak_check(struct image *image, Crystal **crystals, int n_cryst,
/* Decimal and fractional Miller indices of nearest
* reciprocal lattice point */
- hd = q.u * ax + q.v * ay + q.w * az;
- kd = q.u * bx + q.v * by + q.w * bz;
- ld = q.u * cx + q.v * cy + q.w * cz;
+ hd = q[0] * ax + q[1] * ay + q[2] * az;
+ kd = q[0] * bx + q[1] * by + q[2] * bz;
+ ld = q[0] * cx + q[1] * cy + q[2] * cz;
h = lrint(hd);
k = lrint(kd);
l = lrint(ld);
@@ -797,7 +696,7 @@ void validate_peaks(struct image *image, double min_snr,
continue;
}
- r = integrate_peak(image, f->fs, f->ss, f->p,
+ r = integrate_peak(image, f->fs, f->ss, f->pn,
&f_fs, &f_ss, &intensity, &sigma,
ir_inn, ir_mid, ir_out, &saturated);
if ( r ) {
@@ -818,8 +717,8 @@ void validate_peaks(struct image *image, double min_snr,
}
/* Add using "better" coordinates */
- image_add_feature(flist, f->fs, f->ss, f->p, image, intensity,
- NULL);
+ image_add_feature(flist, f->fs, f->ss, f->pn, image,
+ intensity, NULL);
}
@@ -831,17 +730,8 @@ void validate_peaks(struct image *image, double min_snr,
}
-static int compare_double(const void *av, const void *bv)
-{
- double a = *(double *)av;
- double b = *(double *)bv;
- if ( a > b ) return 1;
- if ( a < b ) return -1;
- return 0;
-}
-
-
-double estimate_peak_resolution(ImageFeatureList *peaks, double lambda)
+double estimate_peak_resolution(ImageFeatureList *peaks, double lambda,
+ struct detgeom *det)
{
int i, npk, ncut;
double *rns;
@@ -859,12 +749,14 @@ double estimate_peak_resolution(ImageFeatureList *peaks, double lambda)
for ( i=0; i<npk; i++ ) {
struct imagefeature *f;
- struct rvec r;
+ double r[3];
f = image_get_feature(peaks, i);
- r = get_q_for_panel(f->p, f->fs, f->ss, NULL, 1.0/lambda);
- rns[i] = modulus(r.u, r.v, r.w);
+ detgeom_transform_coords(&det->panels[f->pn],
+ f->fs, f->ss,
+ lambda, 0.0, 0.0, r);
+ rns[i] = modulus(r[0], r[1], r[2]);
}
@@ -877,3 +769,38 @@ double estimate_peak_resolution(ImageFeatureList *peaks, double lambda)
free(rns);
return max_res;
}
+
+const char *str_peaksearch(enum peak_search_method meth)
+{
+ switch ( meth ) {
+ case PEAK_PEAKFINDER9: return "peakfinder9";
+ case PEAK_PEAKFINDER8: return "peakfinder8";
+ case PEAK_ZAEF: return "zaef";
+ case PEAK_HDF5: return "hdf5";
+ case PEAK_CXI: return "cxi";
+ case PEAK_MSGPACK: return "msgpack";
+ case PEAK_NONE: return "none";
+ default: return "???";
+ }
+}
+
+enum peak_search_method parse_peaksearch(const char *arg)
+{
+ if ( strcmp(arg, "zaef") == 0 ) {
+ return PEAK_ZAEF;
+ } else if ( strcmp(arg, "peakfinder8") == 0 ) {
+ return PEAK_PEAKFINDER8;
+ } else if ( strcmp(arg, "hdf5") == 0 ) {
+ return PEAK_HDF5;
+ } else if ( strcmp(arg, "cxi") == 0 ) {
+ return PEAK_CXI;
+ } else if ( strcmp(arg, "peakfinder9") == 0 ) {
+ return PEAK_PEAKFINDER9;
+ } else if ( strcmp(arg, "msgpack") == 0 ) {
+ return PEAK_MSGPACK;
+ } else if ( strcmp(arg, "none") == 0 ) {
+ return PEAK_NONE;
+ }
+
+ return PEAK_ERROR;
+}
diff --git a/libcrystfel/src/peaks.h b/libcrystfel/src/peaks.h
index 6e61758c..2f100db2 100644
--- a/libcrystfel/src/peaks.h
+++ b/libcrystfel/src/peaks.h
@@ -3,11 +3,11 @@
*
* Peak search and other image analysis
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2018 Thomas White <taw@physics.org>
+ * 2010-2020 Thomas White <taw@physics.org>
* 2017 Valerio Mariani <valerio.mariani@desy.de>
* 2017-2018 Yaroslav Gevorkov <yaroslav.gevorkov@desy.de>
*
@@ -31,14 +31,12 @@
#ifndef PEAKS_H
#define PEAKS_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include <pthread.h>
#include "reflist.h"
#include "crystal.h"
+#include "image.h"
+#include "detgeom.h"
#ifdef __cplusplus
extern "C" {
@@ -49,7 +47,23 @@ extern "C" {
* Peak search functions
*/
-extern int *make_BgMask(struct image *image, struct panel *p, double ir_inn);
+enum peak_search_method {
+ PEAK_PEAKFINDER9,
+ PEAK_PEAKFINDER8,
+ PEAK_ZAEF,
+ PEAK_HDF5,
+ PEAK_CXI,
+ PEAK_MSGPACK,
+ PEAK_NONE,
+ PEAK_ERROR
+};
+
+extern const char *str_peaksearch(enum peak_search_method meth);
+
+extern enum peak_search_method parse_peaksearch(const char *arg);
+
+extern int *make_BgMask(struct image *image, struct detgeom_panel *p,
+ int pn, double ir_inn);
extern void search_peaks(struct image *image, float threshold,
float min_gradient, float min_snr, double ir_inn,
@@ -78,7 +92,9 @@ extern void validate_peaks(struct image *image, double min_snr,
int ir_inn, int ir_mid, int ir_out,
int use_saturated, int check_snr);
-extern double estimate_peak_resolution(ImageFeatureList *peaks, double lambda);
+extern double estimate_peak_resolution(ImageFeatureList *peaks,
+ double lambda,
+ struct detgeom *det);
#ifdef __cplusplus
}
diff --git a/libcrystfel/src/predict-refine.c b/libcrystfel/src/predict-refine.c
index aff5fc22..2432055f 100644
--- a/libcrystfel/src/predict-refine.c
+++ b/libcrystfel/src/predict-refine.c
@@ -3,11 +3,11 @@
*
* Prediction refinement
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2016 Thomas White <taw@physics.org>
+ * 2010-2020 Thomas White <taw@physics.org>
* 2016 Valerio Mariani
*
* This file is part of CrystFEL.
@@ -73,21 +73,21 @@ struct reflpeak {
Reflection *refl;
struct imagefeature *peak;
double Ih; /* normalised */
- struct panel *panel; /* panel the reflection appears on
- * (we assume this never changes) */
+ struct detgeom_panel *panel; /* panel the reflection appears on
+ * (we assume this never changes) */
};
static void twod_mapping(double fs, double ss, double *px, double *py,
- struct panel *p)
+ struct detgeom_panel *p)
{
double xs, ys;
- xs = fs*p->fsx + ss*p->ssx;
- ys = fs*p->fsy + ss*p->ssy;
+ xs = fs*p->fsx + ss*p->ssx; /* pixels */
+ ys = fs*p->fsy + ss*p->ssy; /* pixels */
- *px = (xs + p->cnx) / p->res;
- *py = (ys + p->cny) / p->res;
+ *px = (xs + p->cnx) * p->pixel_pitch; /* metres */
+ *py = (ys + p->cny) * p->pixel_pitch; /* metres */
}
@@ -98,7 +98,7 @@ static double r_dev(struct reflpeak *rp)
}
-static double x_dev(struct reflpeak *rp, struct detector *det)
+static double x_dev(struct reflpeak *rp, struct detgeom *det)
{
/* Peak position term */
double xpk, ypk, xh, yh;
@@ -110,7 +110,7 @@ static double x_dev(struct reflpeak *rp, struct detector *det)
}
-static double y_dev(struct reflpeak *rp, struct detector *det)
+static double y_dev(struct reflpeak *rp, struct detgeom *det)
{
/* Peak position term */
double xpk, ypk, xh, yh;
@@ -122,50 +122,6 @@ static double y_dev(struct reflpeak *rp, struct detector *det)
}
-static void UNUSED write_pairs(const char *filename, struct reflpeak *rps,
- int n, struct detector *det)
-{
- int i;
- FILE *fh;
-
- fh = fopen(filename, "w");
- if ( fh == NULL ) {
- ERROR("Failed to open '%s'\n", filename);
- return;
- }
-
- for ( i=0; i<n; i++ ) {
-
- double write_fs, write_ss;
- double fs, ss;
- struct panel *p;
- signed int h, k, l;
-
- fs = rps[i].peak->fs;
- ss = rps[i].peak->ss;
- p = rps[i].panel;
- get_indices(rps[i].refl, &h, &k, &l);
-
- write_fs = fs + p->orig_min_fs;
- write_ss = ss + p->orig_min_ss;
-
- fprintf(fh, "%7.2f %7.2f dev r,x,y: %9f %9f %9f %9f\n",
- write_fs, write_ss,
- r_dev(&rps[i])/1e9, fabs(r_dev(&rps[i])/1e9),
- x_dev(&rps[i], det),
- y_dev(&rps[i], det));
-
- //fprintf(fh, "%4i %4i %4i 0.0 - 0.0 1 %7.2f %7.2f %s\n",
- // h, k, l, write_fs, write_ss, p->name);
-
- }
-
- fclose(fh);
-
- STATUS("Wrote %i pairs to %s\n", n, filename);
-}
-
-
static int cmpd2(const void *av, const void *bv)
{
struct reflpeak *a, *b;
@@ -179,14 +135,13 @@ static int cmpd2(const void *av, const void *bv)
static int check_outlier_transition(struct reflpeak *rps, int n,
- struct detector *det)
+ struct detgeom *det)
{
int i;
if ( n < 3 ) return n;
qsort(rps, n, sizeof(struct reflpeak), cmpd2);
- //write_pairs("pairs-before-outlier.lst", rps, n, det);
for ( i=1; i<n-1; i++ ) {
@@ -223,12 +178,15 @@ static int pair_peaks(struct image *image, Crystal *cr,
double ax, ay, az;
double bx, by, bz;
double cx, cy, cz;
+ double dx, dy;
RefList *all_reflist;
all_reflist = reflist_new();
cell_get_cartesian(crystal_get_cell(cr),
&ax, &ay, &az, &bx, &by, &bz, &cx, &cy, &cz);
+ crystal_get_det_shift(cr, &dx, &dy);
+
/* First, create a RefList containing the most likely indices for each
* peak, with no exclusion criteria */
for ( i=0; i<image_feature_count(image->features); i++ ) {
@@ -236,16 +194,21 @@ static int pair_peaks(struct image *image, Crystal *cr,
struct imagefeature *f;
double h, k, l, hd, kd, ld;
Reflection *refl;
+ double r[3];
/* Assume all image "features" are genuine peaks */
f = image_get_feature(image->features, i);
if ( f == NULL ) continue;
+ detgeom_transform_coords(&image->detgeom->panels[f->pn],
+ f->fs, f->ss, image->lambda,
+ dx, dy, r);
+
/* Decimal and fractional Miller indices of nearest reciprocal
* lattice point */
- hd = f->rx * ax + f->ry * ay + f->rz * az;
- kd = f->rx * bx + f->ry * by + f->rz * bz;
- ld = f->rx * cx + f->ry * cy + f->rz * cz;
+ hd = r[0] * ax + r[1] * ay + r[2] * az;
+ kd = r[0] * bx + r[1] * by + r[2] * bz;
+ ld = r[0] * cx + r[1] * cy + r[2] * cz;
h = lrint(hd);
k = lrint(kd);
l = lrint(ld);
@@ -267,11 +230,11 @@ static int pair_peaks(struct image *image, Crystal *cr,
* in how far away it is from the peak location.
* The predicted position and excitation errors will be
* filled in by update_predictions(). */
- set_panel(refl, f->p);
+ set_panel_number(refl, f->pn);
rps[n].refl = refl;
rps[n].peak = f;
- rps[n].panel = f->p;
+ rps[n].panel = &image->detgeom->panels[f->pn];
n++;
}
@@ -307,7 +270,7 @@ static int pair_peaks(struct image *image, Crystal *cr,
/* Sort the pairings by excitation error and look for a transition
* between good pairings and outliers */
- n_final = check_outlier_transition(rps, n_acc, image->det);
+ n_final = check_outlier_transition(rps, n_acc, image->detgeom);
/* Add the final accepted reflections to the caller's list */
if ( reflist != NULL ) {
@@ -359,16 +322,18 @@ int refine_radius(Crystal *cr, struct image *image)
}
-static void update_detector(struct detector *det, double xoffs, double yoffs,
- double coffs)
+static void update_detector(struct detgeom *det,
+ double xoffs, double yoffs, double coffs)
{
int i;
for ( i=0; i<det->n_panels; i++ ) {
- struct panel *p = &det->panels[i];
- p->cnx += xoffs * p->res;
- p->cny += yoffs * p->res;
- p->clen += coffs;
+ struct detgeom_panel *p = &det->panels[i];
+
+ /* Convert to pixels */
+ p->cnx += xoffs / p->pixel_pitch;
+ p->cny += yoffs / p->pixel_pitch;
+ p->cnz += coffs / p->pixel_pitch;
}
}
@@ -454,7 +419,7 @@ static int iterate(struct reflpeak *rps, int n, UnitCell *cell,
}
- v_c = x_dev(&rps[i], image->det);
+ v_c = x_dev(&rps[i], image->detgeom);
v_c *= -gradients[k];
v_curr = gsl_vector_get(v, k);
gsl_vector_set(v, k, v_curr + v_c);
@@ -486,7 +451,7 @@ static int iterate(struct reflpeak *rps, int n, UnitCell *cell,
}
- v_c = y_dev(&rps[i], image->det);
+ v_c = y_dev(&rps[i], image->detgeom);
v_c *= -gradients[k];
v_curr = gsl_vector_get(v, k);
gsl_vector_set(v, k, v_curr + v_c);
@@ -538,12 +503,13 @@ static int iterate(struct reflpeak *rps, int n, UnitCell *cell,
csx += gsl_vector_get(shifts, 6);
csy += gsl_vector_get(shifts, 7);
csz += gsl_vector_get(shifts, 8);
- update_detector(image->det, gsl_vector_get(shifts, 9),
- gsl_vector_get(shifts, 10),
- gsl_vector_get(shifts, 11));
+ update_detector(image->detgeom,
+ gsl_vector_get(shifts, 9),
+ gsl_vector_get(shifts, 10),
+ 0.0);
*total_x += gsl_vector_get(shifts, 9);
*total_y += gsl_vector_get(shifts, 10);
- *total_z += gsl_vector_get(shifts, 11);
+ *total_z += 0.0;
cell_set_reciprocal(cell, asx, asy, asz, bsx, bsy, bsz, csx, csy, csz);
@@ -555,7 +521,7 @@ static int iterate(struct reflpeak *rps, int n, UnitCell *cell,
}
-static double pred_residual(struct reflpeak *rps, int n, struct detector *det)
+static double pred_residual(struct reflpeak *rps, int n, struct detgeom *det)
{
int i;
double res = 0.0;
@@ -621,6 +587,8 @@ int refine_prediction(struct image *image, Crystal *cr)
}
crystal_set_reflections(cr, reflist);
+ crystal_get_det_shift(cr, &total_x, &total_y);
+
/* Normalise the intensities to max 1 */
max_I = -INFINITY;
for ( i=0; i<n; i++ ) {
@@ -636,7 +604,7 @@ int refine_prediction(struct image *image, Crystal *cr)
rps[i].Ih = rps[i].peak->intensity / max_I;
}
- //STATUS("Initial residual = %e\n", pred_residual(rps, n, image->det));
+ //STATUS("Initial residual = %e\n", pred_residual(rps, n, image->detgeom));
/* Refine */
for ( i=0; i<MAX_CYCLES; i++ ) {
@@ -644,12 +612,12 @@ int refine_prediction(struct image *image, Crystal *cr)
if ( iterate(rps, n, crystal_get_cell(cr), image,
&total_x, &total_y, &total_z) ) return 1;
//STATUS("Residual after %i = %e\n", i,
- // pred_residual(rps, n, image->det));
+ // pred_residual(rps, n, image->detgeom));
}
- //STATUS("Final residual = %e\n", pred_residual(rps, n, image->det));
+ //STATUS("Final residual = %e\n", pred_residual(rps, n, image->detgeom));
snprintf(tmp, 255, "predict_refine/final_residual = %e",
- pred_residual(rps, n, image->det));
+ pred_residual(rps, n, image->detgeom));
crystal_add_notes(cr, tmp);
crystal_set_det_shift(cr, total_x, total_y);
diff --git a/libcrystfel/src/predict-refine.h b/libcrystfel/src/predict-refine.h
index 6396df8a..5607e356 100644
--- a/libcrystfel/src/predict-refine.h
+++ b/libcrystfel/src/predict-refine.h
@@ -3,11 +3,11 @@
*
* Prediction refinement
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2015 Thomas White <taw@physics.org>
+ * 2010-2019 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -29,11 +29,6 @@
#ifndef PREDICT_REFINE_H
#define PREDICT_REFINE_H
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include "crystal.h"
struct image;
diff --git a/libcrystfel/src/rational.c b/libcrystfel/src/rational.c
index 05bca429..afffcf47 100644
--- a/libcrystfel/src/rational.c
+++ b/libcrystfel/src/rational.c
@@ -3,11 +3,11 @@
*
* A small rational number library
*
- * Copyright © 2019-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2019-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2019 Thomas White <taw@physics.org>
+ * 2019-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -640,8 +640,9 @@ void transform_fractional_coords_rtnl_inverse(const RationalMatrix *P,
}
-static RationalMatrix *delete_row_and_column(const RationalMatrix *m,
- unsigned int di, unsigned int dj)
+static RationalMatrix *rational_delete_row_and_column(const RationalMatrix *m,
+ unsigned int di,
+ unsigned int dj)
{
RationalMatrix *n;
unsigned int i, j;
@@ -667,13 +668,13 @@ static RationalMatrix *delete_row_and_column(const RationalMatrix *m,
}
-static Rational cofactor(const RationalMatrix *m,
- unsigned int i, unsigned int j)
+static Rational rational_cofactor(const RationalMatrix *m,
+ unsigned int i, unsigned int j)
{
RationalMatrix *n;
Rational t, C;
- n = delete_row_and_column(m, i, j);
+ n = rational_delete_row_and_column(m, i, j);
if ( n == NULL ) {
fprintf(stderr, "Failed to allocate matrix.\n");
return rtnl_zero();
@@ -708,7 +709,8 @@ Rational rtnl_mtx_det(const RationalMatrix *m)
det = rtnl_zero();
for ( j=0; j<m->cols; j++ ) {
Rational a;
- a = rtnl_mul(rtnl_mtx_get(m, i, j), cofactor(m, i, j));
+ a = rtnl_mul(rtnl_mtx_get(m, i, j),
+ rational_cofactor(m, i, j));
det = rtnl_add(det, a);
}
diff --git a/libcrystfel/src/rational.h b/libcrystfel/src/rational.h
index f8aaa537..a083f861 100644
--- a/libcrystfel/src/rational.h
+++ b/libcrystfel/src/rational.h
@@ -3,7 +3,7 @@
*
* A small rational number library
*
- * Copyright © 2019-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2019-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
@@ -29,10 +29,6 @@
#ifndef RATIONAL_H
#define RATIONAL_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
/**
* \file rational.h
* %Rational numbers (including rational matrices)
diff --git a/libcrystfel/src/reflist-utils.c b/libcrystfel/src/reflist-utils.c
index 7a41f335..42c3f06d 100644
--- a/libcrystfel/src/reflist-utils.c
+++ b/libcrystfel/src/reflist-utils.c
@@ -3,11 +3,11 @@
*
* Utilities to complement the core reflist.c
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2011-2018 Thomas White <taw@physics.org>
+ * 2011-2020 Thomas White <taw@physics.org>
* 2014 Valerio Mariani
*
* This file is part of CrystFEL.
@@ -41,6 +41,7 @@
#include "utils.h"
#include "reflist-utils.h"
#include "symmetry.h"
+#include "libcrystfel-version.h"
/** \file reflist-utils.h
@@ -672,7 +673,7 @@ void free_contribs(RefList *list)
static char *full_command_line(int argc, char *argv[])
{
int i;
- size_t len = 0;
+ size_t len = 1;
char *cl;
if ( argc == 0 ) return strdup("");
@@ -698,9 +699,8 @@ void reflist_add_command_and_version(RefList *list, int argc, char *argv[])
char *tmp;
char vers[128];
- vers[0] = '\0';
- strcat(vers, "Generated by CrystFEL ");
- strncat(vers, CRYSTFEL_VERSIONSTRING, 100);
+ snprintf(vers, 128, "Generated by CrystFEL %s",
+ libcrystfel_version_string());
reflist_add_notes(list, vers);
tmp = full_command_line(argc, argv);
diff --git a/libcrystfel/src/reflist-utils.h b/libcrystfel/src/reflist-utils.h
index 9eb21ecb..f5177cee 100644
--- a/libcrystfel/src/reflist-utils.h
+++ b/libcrystfel/src/reflist-utils.h
@@ -3,11 +3,11 @@
*
* Utilities to complement the core reflist.c
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2011-2018 Thomas White <taw@physics.org>
+ * 2011-2019 Thomas White <taw@physics.org>
* 2014 Valerio Mariani
*
* This file is part of CrystFEL.
@@ -27,10 +27,6 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
/** @cond */
#ifndef REFLIST_UTILS_H
#define REFLIST_UTILS_H
diff --git a/libcrystfel/src/reflist.c b/libcrystfel/src/reflist.c
index 9cedfc86..90c50e1f 100644
--- a/libcrystfel/src/reflist.c
+++ b/libcrystfel/src/reflist.c
@@ -3,11 +3,11 @@
*
* Fast reflection/peak list
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2011-2018 Thomas White <taw@physics.org>
+ * 2011-2021 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -26,6 +26,10 @@
*
*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
@@ -53,7 +57,7 @@ struct _refldata {
/* Location in image */
double fs;
double ss;
- struct panel *panel;
+ int panel_number;
/* Non-zero if this reflection can be used for scaling */
int scalable;
@@ -111,7 +115,6 @@ struct _reflection {
struct _reflist {
struct _reflection *head;
- struct _reflection *tail;
char *notes;
};
@@ -124,6 +127,7 @@ static Reflection *new_node(unsigned int serial)
Reflection *new;
new = calloc(1, sizeof(struct _reflection));
+ if ( new == NULL ) return NULL;
new->serial = serial;
new->next = NULL;
new->prev = NULL;
@@ -308,12 +312,13 @@ void get_detector_pos(const Reflection *refl, double *fs, double *ss)
/**
* \param refl: Reflection
*
- * \returns the panel which the reflection appears on
+ * \returns panel number (index in detgeom/DataTemplate structure)
+ * which the reflection appears on
*
**/
-struct panel *get_panel(const Reflection *refl)
+int get_panel_number(const Reflection *refl)
{
- return refl->data.panel;
+ return refl->data.panel_number;
}
@@ -589,14 +594,13 @@ void set_detector_pos(Reflection *refl, double fs, double ss)
/**
* \param refl: Reflection
- * \param p: Pointer to the panel structure on which the reflection appears
- *
- * Note that the pointer will be stored, not the contents of the structure.
+ * \param pn: Panel number (index in detgeom/DataTemplate structure) of
+ * the panel on which the reflection appears.
*
**/
-void set_panel(Reflection *refl, struct panel *p)
+void set_panel_number(Reflection *refl, int pn)
{
- refl->data.panel = p;
+ refl->data.panel_number = pn;
}
@@ -882,8 +886,11 @@ static Reflection *insert_node(Reflection *refl, Reflection *new)
}
-static void add_to_list(RefList *list, Reflection *new,
- signed int h, signed int k, signed int l)
+static void add_refl_to_list_real(RefList *list,
+ Reflection *new,
+ signed int h,
+ signed int k,
+ signed int l)
{
Reflection *f;
@@ -929,7 +936,7 @@ Reflection *add_refl(RefList *list, signed int h, signed int k, signed int l)
new = new_node(SERIAL(h, k, l));
if ( new == NULL ) return NULL;
- add_to_list(list, new, h, k, l);
+ add_refl_to_list_real(list, new, h, k, l);
return new;
}
@@ -948,7 +955,7 @@ void add_refl_to_list(Reflection *refl, RefList *list)
get_indices(refl, &h, &k, &l);
- add_to_list(list, refl, h, k, l);
+ add_refl_to_list_real(list, refl, h, k, l);
}
diff --git a/libcrystfel/src/reflist.h b/libcrystfel/src/reflist.h
index 3085a2aa..864e871d 100644
--- a/libcrystfel/src/reflist.h
+++ b/libcrystfel/src/reflist.h
@@ -3,11 +3,11 @@
*
* Fast reflection/peak list
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2011-2018 Thomas White <taw@physics.org>
+ * 2011-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -29,10 +29,6 @@
#ifndef REFLIST_H
#define REFLIST_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#define SERIAL(h, k, l) ((((h)+512)<<20) + (((k)+512)<<10) + ((l)+512))
#define GET_H(serial) ((((serial) & 0x3ff00000)>>20)-512)
#define GET_K(serial) ((((serial) & 0x000ffc00)>>10)-512)
@@ -109,7 +105,7 @@ extern Reflection *next_found_refl(Reflection *refl);
/* Get */
extern void get_detector_pos(const Reflection *refl, double *fs, double *ss);
-extern struct panel *get_panel(const Reflection *refl);
+extern int get_panel_number(const Reflection *refl);
extern double get_partiality(const Reflection *refl);
extern double get_khalf(const Reflection *refl);
extern double get_kpred(const Reflection *refl);
@@ -134,7 +130,7 @@ extern struct reflection_contributions *get_contributions(const Reflection *refl
/* Set */
extern void copy_data(Reflection *to, const Reflection *from);
extern void set_detector_pos(Reflection *refl, double fs, double ss);
-extern void set_panel(Reflection *refl, struct panel *p);
+extern void set_panel_number(Reflection *refl, int pn);
extern void set_kpred(Reflection *refl, double kpred);
extern void set_khalf(Reflection *refl, double khalf);
extern void set_exerr(Reflection *refl, double exerr);
diff --git a/libcrystfel/src/spectrum.c b/libcrystfel/src/spectrum.c
index e00b697f..bca293e9 100644
--- a/libcrystfel/src/spectrum.c
+++ b/libcrystfel/src/spectrum.c
@@ -3,7 +3,7 @@
*
* A class representing a radiation spectrum
*
- * Copyright © 2019-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2019-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
diff --git a/libcrystfel/src/spectrum.h b/libcrystfel/src/spectrum.h
index 55578974..d0fcc9c1 100644
--- a/libcrystfel/src/spectrum.h
+++ b/libcrystfel/src/spectrum.h
@@ -3,7 +3,7 @@
*
* A class representing a radiation spectrum
*
- * Copyright © 2019-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2019-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
@@ -29,10 +29,6 @@
#ifndef SPECTRUM_H
#define SPECTRUM_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include <gsl/gsl_rng.h>
/**
diff --git a/libcrystfel/src/stream.c b/libcrystfel/src/stream.c
index bfe4a50a..83756c7a 100644
--- a/libcrystfel/src/stream.c
+++ b/libcrystfel/src/stream.c
@@ -3,12 +3,12 @@
*
* Stream tools
*
- * Copyright © 2013-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2013-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2012 Richard Kirian
*
* Authors:
- * 2010-2019 Thomas White <taw@physics.org>
+ * 2010-2021 Thomas White <taw@physics.org>
* 2014-2016 Valerio Mariani
* 2011 Richard Kirian
* 2011 Andrew Aquila
@@ -51,6 +51,10 @@
#include "stream.h"
#include "reflist.h"
#include "reflist-utils.h"
+#include "datatemplate.h"
+#include "detgeom.h"
+#include "libcrystfel-version.h"
+
/** \file stream.h */
@@ -69,15 +73,21 @@ struct _stream
char *audit_info;
char *geometry_file;
+ /* The DataTemplate provided to us for writing things.
+ * We don't own this. */
+ const DataTemplate *dtempl_write;
+
+ /* The DataTemplate we got from the stream itself, used for
+ * reading things. We own this. */
+ DataTemplate *dtempl_read;
+
long long int ln;
int old_indexers; /* True if the stream reader encountered a deprecated
* indexing method */
- int in_chunk; /* True if a chunk start marker has been "accidentally"
- * encountered, so read_chunk() should assume a chunk is
- * already in progress instead of looking for another
- * marker */
+ long *chunk_offsets;
+ int n_chunks;
};
@@ -87,211 +97,136 @@ int stream_has_old_indexers(Stream *st)
}
-static int read_peaks(Stream *st, struct image *image)
+static ImageFeatureList *read_peaks(Stream *st,
+ struct image *image)
{
char *rval = NULL;
int first = 1;
+ ImageFeatureList *features;
- image->features = image_feature_list_new();
+ features = image_feature_list_new();
do {
char line[1024];
float x, y, d, intensity;
- int r;
- struct panel *p = NULL;
- float add_x, add_y;
+ int r, exp_n;
+ char panel_name[1024];
rval = fgets(line, 1023, st->fh);
st->ln++;
- if ( rval == NULL ) continue;
+ if ( rval == NULL ) {
+ image_feature_list_free(features);
+ return NULL;
+ }
chomp(line);
- if ( strcmp(line, PEAK_LIST_END_MARKER) == 0 ) return 0;
-
- r = sscanf(line, "%f %f %f %f", &x, &y, &d, &intensity);
- if ( (r != 4) && (!first) ) {
- ERROR("Failed to parse peak list line.\n");
- ERROR("The failed line was: '%s'\n", line);
- return 1;
+ if ( strcmp(line, STREAM_PEAK_LIST_END_MARKER) == 0 ) {
+ return features;
}
- first = 0;
- if ( r == 4 ) {
-
- if ( image->det != NULL ) {
-
- p = find_orig_panel(image->det, x, y);
- if ( p == NULL ) {
- ERROR("Panel not found\n");
- return 1;
- }
-
- add_x = x-p->orig_min_fs;
- add_y = y-p->orig_min_ss;
-
- image_add_feature(image->features, add_x, add_y,
- p, image, intensity, NULL);
-
- } else {
-
- image_add_feature(image->features, x, y,
- p, image, intensity, NULL);
- }
+ if ( first ) {
+ first = 0;
+ continue;
}
- } while ( rval != NULL );
-
- /* Got read error of some kind before finding PEAK_LIST_END_MARKER */
- return 1;
-}
-
-
-static int read_peaks_2_3(Stream *st, struct image *image)
-{
- char *rval = NULL;
- int first = 1;
-
- image->features = image_feature_list_new();
-
- do {
-
- char line[1024];
- char pn[32];
- float x, y, d, intensity;
- int r;
- struct panel *p = NULL;
- float add_x, add_y;
-
- rval = fgets(line, 1023, st->fh);
- st->ln++;
- if ( rval == NULL ) continue;
- chomp(line);
-
- if ( strcmp(line, PEAK_LIST_END_MARKER) == 0 ) return 0;
+ if ( AT_LEAST_VERSION(st, 2, 3) ) {
+ r = sscanf(line, "%f %f %f %f %s",
+ &x, &y, &d, &intensity, panel_name);
+ exp_n = 5;
+ } else {
+ r = sscanf(line, "%f %f %f %f",
+ &x, &y, &d, &intensity);
+ exp_n = 4;
+ }
- r = sscanf(line, "%f %f %f %f %s", &x, &y, &d, &intensity, pn);
- if ( (r != 5) && (!first) ) {
+ if ( r != exp_n ) {
ERROR("Failed to parse peak list line.\n");
ERROR("The failed line was: '%s'\n", line);
- return 1;
- }
-
- first = 0;
-
- if ( r == 5 ) {
-
- p = find_panel_by_name(image->det, pn);
- if ( p == NULL ) {
- ERROR("Panel not found: %s\n", pn);
- return 1;
- }
-
- add_x = x-p->orig_min_fs;
- add_y = y-p->orig_min_ss;
-
- image_add_feature(image->features, add_x, add_y, p,
- image, intensity, NULL);
-
+ image_feature_list_free(features);
+ return NULL;
}
- } while ( rval != NULL );
-
- /* Got read error of some kind before finding PEAK_LIST_END_MARKER */
- return 1;
-}
-
-
-static int write_peaks(struct image *image, FILE *ofh)
-{
- int i;
-
- fprintf(ofh, PEAK_LIST_START_MARKER"\n");
- fprintf(ofh, " fs/px ss/px (1/d)/nm^-1 Intensity\n");
-
- for ( i=0; i<image_feature_count(image->features); i++ ) {
-
- struct imagefeature *f;
- struct rvec r;
- double q;
+ if ( (panel_name[0] != '\0') && (st->dtempl_read != NULL) ) {
- f = image_get_feature(image->features, i);
- if ( f == NULL ) continue;
+ int pn;
- r = get_q_for_panel(f->p, f->fs, f->ss,
- NULL, 1.0/image->lambda);
- q = modulus(r.u, r.v, r.w);
+ if ( data_template_panel_name_to_number(st->dtempl_read,
+ panel_name,
+ &pn) )
+ {
+ ERROR("No such panel '%s'\n",
+ panel_name);
+ } else {
- if ( image->det != NULL ) {
+ data_template_file_to_panel_coords(st->dtempl_read,
+ &x, &y, &pn);
- struct panel *p;
- double write_fs, write_ss;
+ image_add_feature(features, x, y,
+ pn, image, intensity,
+ NULL);
- p = find_orig_panel(image->det, f->fs, f->ss);
- if ( p == NULL ) {
- ERROR("Panel not found\n");
- return 1;
}
- /* Convert coordinates to match arrangement of panels in
- * HDF5 file */
- write_fs = f->fs + p->orig_min_fs;
- write_ss = f->ss + p->orig_min_ss;
-
- fprintf(ofh, "%7.2f %7.2f %10.2f %10.2f\n",
- write_fs, write_ss, q/1.0e9, f->intensity);
-
} else {
- fprintf(ofh, "%7.2f %7.2f %10.2f %10.2f\n",
- f->fs, f->ss, q/1.0e9, f->intensity);
+ /* Either it's an old format stream (in which
+ * case the data is probably "slabby", so no
+ * coordinate conversion is needed), or
+ * the caller isn't interested in panel
+ * locations */
+ image_add_feature(features, x, y, 0,
+ image, intensity, NULL);
}
- }
+ } while ( rval != NULL );
- fprintf(ofh, PEAK_LIST_END_MARKER"\n");
- return 0;
+ return features;
}
-static int write_peaks_2_3(struct image *image, FILE *ofh)
+static int write_peaks(const struct image *image,
+ const DataTemplate *dtempl, FILE *ofh)
{
int i;
- fprintf(ofh, PEAK_LIST_START_MARKER"\n");
+ fprintf(ofh, STREAM_PEAK_LIST_START_MARKER"\n");
fprintf(ofh, " fs/px ss/px (1/d)/nm^-1 Intensity Panel\n");
for ( i=0; i<image_feature_count(image->features); i++ ) {
struct imagefeature *f;
- struct rvec r;
+ double r[3];
double q;
- double write_fs, write_ss;
+ float write_fs, write_ss;
+ struct detgeom_panel *p;
f = image_get_feature(image->features, i);
if ( f == NULL ) continue;
- r = get_q_for_panel(f->p, f->fs, f->ss,
- NULL, 1.0/image->lambda);
- q = modulus(r.u, r.v, r.w);
+ p = &image->detgeom->panels[f->pn];
+ detgeom_transform_coords(p, f->fs, f->ss,
+ image->lambda, 0.0, 0.0, r);
+ q = modulus(r[0], r[1], r[2]);
- /* Convert coordinates to match arrangement of panels in HDF5
- * file */
- write_fs = f->fs + f->p->orig_min_fs;
- write_ss = f->ss + f->p->orig_min_ss;
+ write_fs = f->fs;
+ write_ss = f->ss;
+ data_template_panel_to_file_coords(dtempl, f->pn,
+ &write_fs, &write_ss);
fprintf(ofh, "%7.2f %7.2f %10.2f %10.2f %s\n",
- write_fs, write_ss, q/1.0e9, f->intensity, f->p->name);
+ write_fs, write_ss, q/1.0e9, f->intensity,
+ data_template_panel_number_to_name(dtempl, f->pn));
}
- fprintf(ofh, PEAK_LIST_END_MARKER"\n");
+ fprintf(ofh, STREAM_PEAK_LIST_END_MARKER"\n");
return 0;
}
-static RefList *read_stream_reflections_2_3(Stream *st, struct detector *det)
+static RefList *read_stream_reflections_2_3(Stream *st)
{
char *rval = NULL;
int first = 1;
@@ -317,7 +252,7 @@ static RefList *read_stream_reflections_2_3(Stream *st, struct detector *det)
if ( rval == NULL ) continue;
chomp(line);
- if ( strcmp(line, REFLECTION_END_MARKER) == 0 ) return out;
+ if ( strcmp(line, STREAM_REFLECTION_END_MARKER) == 0 ) return out;
r = sscanf(line, "%i %i %i %f %f %f %f %f %f %s",
&h, &k, &l, &intensity, &sigma, &pk, &bg,
@@ -332,24 +267,19 @@ static RefList *read_stream_reflections_2_3(Stream *st, struct detector *det)
if ( r == 10 ) {
- struct panel *p;
-
refl = add_refl(out, h, k, l);
if ( refl == NULL ) {
ERROR("Failed to add reflection\n");
return NULL;
}
set_intensity(refl, intensity);
- if ( det != NULL ) {
- double write_fs, write_ss;
- p = find_panel_by_name(det,pn);
- if ( p == NULL ) {
- ERROR("Couldn't find panel '%s'\n", pn);
+ if ( st->dtempl_read != NULL ) {
+ int pn;
+ if ( data_template_file_to_panel_coords(st->dtempl_read, &fs, &ss, &pn) ) {
+ ERROR("Failed to convert\n");
} else {
- write_fs = fs - p->orig_min_fs;
- write_ss = ss - p->orig_min_ss;
- set_detector_pos(refl, write_fs, write_ss);
- set_panel(refl, p);
+ set_detector_pos(refl, fs, ss);
+ set_panel_number(refl, pn);
}
}
set_esd_intensity(refl, sigma);
@@ -361,12 +291,12 @@ static RefList *read_stream_reflections_2_3(Stream *st, struct detector *det)
} while ( rval != NULL );
- /* Got read error of some kind before finding PEAK_LIST_END_MARKER */
+ /* Got read error of some kind before finding STREAM_PEAK_LIST_END_MARKER */
return NULL;
}
-static RefList *read_stream_reflections_2_1(Stream *st, struct detector *det)
+static RefList *read_stream_reflections_2_1(Stream *st)
{
char *rval = NULL;
int first = 1;
@@ -393,7 +323,7 @@ static RefList *read_stream_reflections_2_1(Stream *st, struct detector *det)
if ( rval == NULL ) continue;
chomp(line);
- if ( strcmp(line, REFLECTION_END_MARKER) == 0 ) return out;
+ if ( strcmp(line, STREAM_REFLECTION_END_MARKER) == 0 ) return out;
r = sscanf(line, "%i %i %i %f %s %f %i %f %f",
&h, &k, &l, &intensity, phs, &sigma, &cts,
@@ -416,19 +346,14 @@ static RefList *read_stream_reflections_2_1(Stream *st, struct detector *det)
}
set_intensity(refl, intensity);
- if ( det != NULL ) {
-
- double write_fs, write_ss;
- struct panel *p;
+ if ( st->dtempl_read != NULL ) {
- p = find_orig_panel(det, fs, ss);
- if ( p == NULL ) {
- ERROR("No panel at %.2f,%.2f\n",
- fs, ss);
+ int pn;
+ if ( data_template_file_to_panel_coords(st->dtempl_read, &fs, &ss, &pn) ) {
+ ERROR("Failed to convert\n");
} else {
- write_fs = fs - p->orig_min_fs;
- write_ss = ss - p->orig_min_ss;
- set_detector_pos(refl, write_fs, write_ss);
+ set_detector_pos(refl, fs, ss);
+ set_panel_number(refl, pn);
}
} else {
@@ -447,12 +372,12 @@ static RefList *read_stream_reflections_2_1(Stream *st, struct detector *det)
} while ( rval != NULL );
- /* Got read error of some kind before finding PEAK_LIST_END_MARKER */
+ /* Got read error of some kind before finding STREAM_PEAK_LIST_END_MARKER */
return NULL;
}
-static RefList *read_stream_reflections_2_2(Stream *st, struct detector *det)
+static RefList *read_stream_reflections_2_2(Stream *st)
{
char *rval = NULL;
int first = 1;
@@ -473,7 +398,7 @@ static RefList *read_stream_reflections_2_2(Stream *st, struct detector *det)
if ( rval == NULL ) continue;
chomp(line);
- if ( strcmp(line, REFLECTION_END_MARKER) == 0 ) return out;
+ if ( strcmp(line, STREAM_REFLECTION_END_MARKER) == 0 ) return out;
r = sscanf(line, "%i %i %i %f %f %f %f %f %f",
&h, &k, &l, &intensity, &sigma, &pk, &bg, &fs, &ss);
@@ -492,19 +417,17 @@ static RefList *read_stream_reflections_2_2(Stream *st, struct detector *det)
}
set_intensity(refl, intensity);
- if ( det != NULL ) {
+ if ( st->dtempl_read != NULL ) {
- double write_fs, write_ss;
- struct panel *p;
+ int pn;
- p = find_orig_panel(det, fs, ss);
- if ( p == NULL ) {
- ERROR("No panel at %.2f,%.2f\n",
- fs, ss);
+ if ( data_template_file_to_panel_coords(st->dtempl_read, &fs, &ss, &pn) ) {
+ ERROR("Failed to convert to "
+ "panel-relative coordinates: "
+ "%i,%i\n", fs, ss);
} else {
- write_fs = fs - p->orig_min_fs;
- write_ss = ss - p->orig_min_ss;
- set_detector_pos(refl, write_fs, write_ss);
+ set_detector_pos(refl, fs, ss);
+ set_panel_number(refl, pn);
}
} else {
@@ -523,144 +446,13 @@ static RefList *read_stream_reflections_2_2(Stream *st, struct detector *det)
} while ( rval != NULL );
- /* Got read error of some kind before finding REFLECTION_END_MARKER */
+ /* Got read error of some kind before finding STREAM_REFLECTION_END_MARKER */
return NULL;
}
-static int write_stream_reflections_2_1(FILE *fh, RefList *list,
- struct image *image)
-{
- Reflection *refl;
- RefListIterator *iter;
-
- fprintf(fh, " h k l I phase sigma(I) "
- " counts fs/px ss/px\n");
-
- for ( refl = first_refl(list, &iter);
- refl != NULL;
- refl = next_refl(refl, iter) )
- {
-
- signed int h, k, l;
- double intensity, esd_i, ph;
- int red;
- double fs, ss;
- char phs[16];
- int have_phase;
-
- get_indices(refl, &h, &k, &l);
- get_detector_pos(refl, &fs, &ss);
- intensity = get_intensity(refl);
- esd_i = get_esd_intensity(refl);
- red = get_redundancy(refl);
- ph = get_phase(refl, &have_phase);
-
- /* Reflections with redundancy = 0 are not written */
- if ( red == 0 ) continue;
-
- if ( have_phase ) {
- snprintf(phs, 16, "%8.2f", rad2deg(ph));
- } else {
- strncpy(phs, " -", 15);
- }
-
- if ( image->det != NULL ) {
-
- struct panel *p;
- double write_fs, write_ss;
-
- p = find_orig_panel(image->det, fs, ss);
- if ( p == NULL ) {
- ERROR("Panel not found\n");
- return 1;
- }
-
- /* Convert coordinates to match arrangement of panels
- * in HDF5 file */
- write_fs = fs + p->orig_min_fs;
- write_ss = ss + p->orig_min_ss;
-
- fprintf(fh, "%3i %3i %3i %10.2f %s %10.2f %7i "
- "%6.1f %6.1f\n",
- h, k, l, intensity, phs, esd_i, red,
- write_fs, write_ss);
-
- } else {
-
- fprintf(fh, "%3i %3i %3i %10.2f %s %10.2f %7i "
- "%6.1f %6.1f\n",
- h, k, l, intensity, phs, esd_i, red,
- fs, ss);
-
- }
- }
- return 0;
-}
-
-
-static int write_stream_reflections_2_2(FILE *fh, RefList *list,
- struct image *image)
-{
- Reflection *refl;
- RefListIterator *iter;
-
- fprintf(fh, " h k l I sigma(I) "
- "peak background fs/px ss/px\n");
-
- for ( refl = first_refl(list, &iter);
- refl != NULL;
- refl = next_refl(refl, iter) )
- {
-
- signed int h, k, l;
- double intensity, esd_i, bg, pk;
- double fs, ss;
-
- get_indices(refl, &h, &k, &l);
- get_detector_pos(refl, &fs, &ss);
- intensity = get_intensity(refl);
- esd_i = get_esd_intensity(refl);
- pk = get_peak(refl);
- bg = get_mean_bg(refl);
-
- /* Reflections with redundancy = 0 are not written */
- if ( get_redundancy(refl) == 0 ) continue;
-
- if ( image->det != NULL ) {
-
- struct panel *p;
- double write_fs, write_ss;
-
- p = find_orig_panel(image->det, fs, ss);
- if ( p == NULL ) {
- ERROR("Panel not found\n");
- return 1;
- }
-
- /* Convert coordinates to match arrangement of panels in HDF5
- * file */
- write_fs = fs + p->orig_min_fs;
- write_ss = ss + p->orig_min_ss;
-
- fprintf(fh, "%4i %4i %4i %10.2f %10.2f %10.2f %10.2f"
- " %6.1f %6.1f\n",
- h, k, l, intensity, esd_i, pk, bg, write_fs,
- write_ss);
-
- } else {
-
- fprintf(fh, "%4i %4i %4i %10.2f %10.2f %10.2f %10.2f"
- " %6.1f %6.1f\n",
- h, k, l, intensity, esd_i, pk, bg, fs, ss);
- }
- }
- return 0;
-}
-
-
-static int write_stream_reflections_2_3(FILE *fh, RefList *list,
- struct image *image)
+static int write_stream_reflections(FILE *fh, RefList *list,
+ const DataTemplate *dtempl)
{
Reflection *refl;
RefListIterator *iter;
@@ -675,13 +467,14 @@ static int write_stream_reflections_2_3(FILE *fh, RefList *list,
signed int h, k, l;
double intensity, esd_i, pk, bg;
- double fs, ss;
- double write_fs, write_ss;
- struct panel *p;
+ double dfs, dss;
+ float fs, ss;
+ int pn;
get_indices(refl, &h, &k, &l);
- get_detector_pos(refl, &fs, &ss);
- p = get_panel(refl);
+ get_detector_pos(refl, &dfs, &dss);
+ fs = dfs; ss = dss;
+ pn = get_panel_number(refl);
intensity = get_intensity(refl);
esd_i = get_esd_intensity(refl);
pk = get_peak(refl);
@@ -690,14 +483,13 @@ static int write_stream_reflections_2_3(FILE *fh, RefList *list,
/* Reflections with redundancy = 0 are not written */
if ( get_redundancy(refl) == 0 ) continue;
- write_fs = fs+p->orig_min_fs;
- write_ss = ss+p->orig_min_ss;
+ data_template_panel_to_file_coords(dtempl, pn,
+ &fs, &ss);
- fprintf(fh,
- "%4i %4i %4i %10.2f %10.2f %10.2f %10.2f "
- "%6.1f %6.1f %s\n",
- h, k, l, intensity, esd_i, pk, bg,
- write_fs, write_ss, p->name);
+ fprintf(fh, "%4i %4i %4i %10.2f %10.2f %10.2f %10.2f "
+ "%6.1f %6.1f %s\n",
+ h, k, l, intensity, esd_i, pk, bg,
+ fs, ss, data_template_panel_number_to_name(dtempl, pn));
}
return 0;
@@ -721,7 +513,8 @@ static int num_integrated_reflections(RefList *list)
}
-static int write_crystal(Stream *st, Crystal *cr, int include_reflections)
+static int write_crystal(Stream *st, Crystal *cr,
+ int include_reflections)
{
UnitCell *cell;
RefList *reflist;
@@ -733,7 +526,7 @@ static int write_crystal(Stream *st, Crystal *cr, int include_reflections)
double det_shift_x, det_shift_y;
int ret = 0;
- fprintf(st->fh, CRYSTAL_START_MARKER"\n");
+ fprintf(st->fh, STREAM_CRYSTAL_START_MARKER"\n");
cell = crystal_get_cell(cr);
assert(cell != NULL);
@@ -792,27 +585,10 @@ static int write_crystal(Stream *st, Crystal *cr, int include_reflections)
if ( reflist != NULL ) {
- struct image *image;
-
- image = crystal_get_image(cr);
-
- fprintf(st->fh, REFLECTION_START_MARKER"\n");
- if ( AT_LEAST_VERSION(st, 2, 3) ) {
- ret = write_stream_reflections_2_3(st->fh,
- reflist,
- image);
- } else if ( AT_LEAST_VERSION(st, 2, 2) ) {
- ret = write_stream_reflections_2_2(st->fh,
- reflist,
- image);
- } else {
- /* This function writes like a normal reflection
- * list was written in stream 2.1 */
- ret = write_stream_reflections_2_1(st->fh,
- reflist,
- image);
- }
- fprintf(st->fh, REFLECTION_END_MARKER"\n");
+ fprintf(st->fh, STREAM_REFLECTION_START_MARKER"\n");
+ ret = write_stream_reflections(st->fh, reflist,
+ st->dtempl_write);
+ fprintf(st->fh, STREAM_REFLECTION_END_MARKER"\n");
} else {
@@ -821,7 +597,7 @@ static int write_crystal(Stream *st, Crystal *cr, int include_reflections)
}
}
- fprintf(st->fh, CRYSTAL_END_MARKER"\n");
+ fprintf(st->fh, STREAM_CRYSTAL_END_MARKER"\n");
return ret;
}
@@ -830,29 +606,23 @@ static int write_crystal(Stream *st, Crystal *cr, int include_reflections)
/**
* \param st A \ref Stream
* \param i An \ref image structure
- * \param imfile A \ref imagefile structure
- * \param include_peaks Whether to include peak search results in stream
- * \param include_reflections Whether to include integration results in stream
- * \param ev A \ref event strucutre
+ * \param srf A \ref StreamFlags enum saying what to write
*
* Writes a new chunk to \p st.
*
* \returns non-zero on error.
*/
-int write_chunk(Stream *st, struct image *i, struct imagefile *imfile,
- int include_peaks, int include_reflections, struct event *ev)
+int stream_write_chunk(Stream *st, const struct image *i,
+ StreamFlags srf)
{
int j;
char *indexer;
int ret = 0;
- fprintf(st->fh, CHUNK_START_MARKER"\n");
+ fprintf(st->fh, STREAM_CHUNK_START_MARKER"\n");
fprintf(st->fh, "Image filename: %s\n", i->filename);
- if ( i->event != NULL ) {
- fprintf(st->fh, "Event: %s\n", get_event_string(i->event));
- }
-
+ fprintf(st->fh, "Event: %s\n", i->ev);
fprintf(st->fh, "Image serial number: %i\n", i->serial);
fprintf(st->fh, "hit = %i\n", i->hit);
@@ -869,40 +639,39 @@ int write_chunk(Stream *st, struct image *i, struct imagefile *imfile,
fprintf(st->fh, "beam_divergence = %.2e rad\n", i->div);
fprintf(st->fh, "beam_bandwidth = %.2e (fraction)\n", i->bw);
- imagefile_copy_fields(imfile, i->copyme, st->fh, ev);
+ /* FIXME: Better way of doing this */
+ //imagefile_copy_fields(imfile, i->copyme, st->fh, ev);
- if ( i->det != NULL ) {
+ if ( i->detgeom != NULL ) {
int j;
double tclen = 0.0;
- for ( j=0; j<i->det->n_panels; j++ ) {
- tclen += i->det->panels[j].clen;
+ for ( j=0; j<i->detgeom->n_panels; j++ ) {
+ tclen += i->detgeom->panels[j].cnz
+ * i->detgeom->panels[j].pixel_pitch;
}
fprintf(st->fh, "average_camera_length = %f m\n",
- tclen / i->det->n_panels);
+ tclen / i->detgeom->n_panels);
}
fprintf(st->fh, "num_peaks = %i\n", image_feature_count(i->features));
fprintf(st->fh, "peak_resolution = %f nm^-1 or %f A\n",
i->peak_resolution/1e9, 1e10/i->peak_resolution);
- if ( include_peaks ) {
- if ( AT_LEAST_VERSION(st, 2, 3) ) {
- ret = write_peaks_2_3(i, st->fh);
- } else {
- ret = write_peaks(i, st->fh);
- }
+ if ( srf & STREAM_PEAKS ) {
+ ret = write_peaks(i, st->dtempl_write, st->fh);
}
for ( j=0; j<i->n_crystals; j++ ) {
- if ( crystal_get_user_flag(i->crystals[j]) == 0 ) {
- ret = write_crystal(st, i->crystals[j],
- include_reflections);
+ if ( crystal_get_user_flag(i->crystals[j]) ) {
+ continue;
}
+ ret = write_crystal(st, i->crystals[j],
+ srf & STREAM_REFLECTIONS);
}
- fprintf(st->fh, CHUNK_END_MARKER"\n");
+ fprintf(st->fh, STREAM_CHUNK_END_MARKER"\n");
fflush(st->fh);
@@ -915,14 +684,6 @@ static int find_start_of_chunk(Stream *st)
char *rval = NULL;
char line[1024];
- /* Perhaps read_geometry() encountered a chunk start marker instead of a
- * geometry file. In that case, we're already in a chunk, so this is
- * easy. */
- if ( st->in_chunk ) {
- st->in_chunk = 0;
- return 0;
- }
-
do {
rval = fgets(line, 1023, st->fh);
@@ -933,13 +694,14 @@ static int find_start_of_chunk(Stream *st)
chomp(line);
- } while ( strcmp(line, CHUNK_START_MARKER) != 0 );
+ } while ( strcmp(line, STREAM_CHUNK_START_MARKER) != 0 );
return 0;
}
-static void read_crystal(Stream *st, struct image *image, StreamReadFlags srf)
+static void read_crystal(Stream *st, struct image *image,
+ StreamFlags srf)
{
char line[1024];
char *rval = NULL;
@@ -980,29 +742,25 @@ static void read_crystal(Stream *st, struct image *image, StreamReadFlags srf)
if ( rval == NULL ) break;
chomp(line);
- if ( (srf & STREAM_READ_UNITCELL)
- && (sscanf(line, "astar = %f %f %f", &u, &v, &w) == 3) )
+ if ( sscanf(line, "astar = %f %f %f", &u, &v, &w) == 3 )
{
as.u = u*1e9; as.v = v*1e9; as.w = w*1e9;
have_as = 1;
}
- if ( (srf & STREAM_READ_UNITCELL)
- && (sscanf(line, "bstar = %f %f %f", &u, &v, &w) == 3) )
+ if ( sscanf(line, "bstar = %f %f %f", &u, &v, &w) == 3 )
{
bs.u = u*1e9; bs.v = v*1e9; bs.w = w*1e9;
have_bs = 1;
}
- if ( (srf & STREAM_READ_UNITCELL)
- && (sscanf(line, "cstar = %f %f %f", &u, &v, &w) == 3) )
+ if ( sscanf(line, "cstar = %f %f %f", &u, &v, &w) == 3 )
{
cs.u = u*1e9; cs.v = v*1e9; cs.w = w*1e9;
have_cs = 1;
}
- if ( (srf & STREAM_READ_UNITCELL)
- && (sscanf(line, "centering = %c", &c) == 1) )
+ if ( sscanf(line, "centering = %c", &c) == 1 )
{
if ( !have_cen ) {
centering = c;
@@ -1013,8 +771,7 @@ static void read_crystal(Stream *st, struct image *image, StreamReadFlags srf)
}
}
- if ( (srf & STREAM_READ_UNITCELL)
- && (sscanf(line, "unique_axis = %c", &c) == 1) )
+ if ( sscanf(line, "unique_axis = %c", &c) == 1 )
{
if ( !have_ua ) {
unique_axis = c;
@@ -1025,8 +782,7 @@ static void read_crystal(Stream *st, struct image *image, StreamReadFlags srf)
}
}
- if ( (srf & STREAM_READ_UNITCELL)
- && (strncmp(line, "lattice_type = ", 15) == 0) )
+ if ( strncmp(line, "lattice_type = ", 15) == 0 )
{
if ( !have_latt ) {
lattice_type = lattice_from_str(line+15);
@@ -1057,8 +813,8 @@ static void read_crystal(Stream *st, struct image *image, StreamReadFlags srf)
}
- if ( (strcmp(line, REFLECTION_START_MARKER) == 0)
- && (srf & STREAM_READ_REFLECTIONS) )
+ if ( (strcmp(line, STREAM_REFLECTION_START_MARKER) == 0)
+ && (srf & STREAM_REFLECTIONS) )
{
RefList *reflist;
@@ -1066,20 +822,16 @@ static void read_crystal(Stream *st, struct image *image, StreamReadFlags srf)
/* The reflection list format in the stream diverges
* after 2.2 */
if ( AT_LEAST_VERSION(st, 2, 3) ) {
- reflist = read_stream_reflections_2_3(st,
- image->det);
+ reflist = read_stream_reflections_2_3(st);
} else if ( AT_LEAST_VERSION(st, 2, 2) ) {
- reflist = read_stream_reflections_2_2(st,
- image->det);
+ reflist = read_stream_reflections_2_2(st);
} else {
- reflist = read_stream_reflections_2_1(st,
- image->det);
+ reflist = read_stream_reflections_2_1(st);
}
if ( reflist == NULL ) {
ERROR("Failed while reading reflections\n");
ERROR("Filename = %s\n", image->filename);
- ERROR("Event = %s\n",
- get_event_string(image->event));
+ ERROR("Event = %s\n", image->ev);
break;
}
@@ -1087,7 +839,7 @@ static void read_crystal(Stream *st, struct image *image, StreamReadFlags srf)
}
- if ( strcmp(line, CRYSTAL_END_MARKER) == 0 ) break;
+ if ( strcmp(line, STREAM_CRYSTAL_END_MARKER) == 0 ) break;
} while ( 1 );
@@ -1139,77 +891,21 @@ static void read_crystal(Stream *st, struct image *image, StreamReadFlags srf)
}
-void free_stuff_from_stream(struct stuff_from_stream *sfs)
-{
- int i;
- if ( sfs == NULL ) return;
- for ( i=0; i<sfs->n_fields; i++ ) {
- free(sfs->fields[i]);
- }
- free(sfs->fields);
- free(sfs);
-}
-
-
-static int read_and_store_field(struct image *image, const char *line)
-{
- char **new_fields;
- char *nf;
-
- if ( image->stuff_from_stream == NULL ) {
- image->stuff_from_stream =
- malloc(sizeof(struct stuff_from_stream));
- if ( image->stuff_from_stream == NULL) {
- ERROR("Failed reading entries from stream\n");
- return 1;
- }
- image->stuff_from_stream->fields = NULL;
- image->stuff_from_stream->n_fields = 0;
- }
-
- new_fields = realloc(image->stuff_from_stream->fields,
- (1+image->stuff_from_stream->n_fields)*
- sizeof(char *));
- if ( new_fields == NULL ) {
- ERROR("Failed reading entries from stream\n");
- return 1;
- }
- image->stuff_from_stream->fields = new_fields;
-
- nf = strdup(line);
- if ( nf == NULL ) {
- ERROR("Failed to allocate field from stream\n");
- return 1;
- }
- image->stuff_from_stream->fields[image->stuff_from_stream->n_fields] = nf;
- image->stuff_from_stream->n_fields++;
-
- return 0;
-}
-
-
/**
- * Read the next chunk from a stream and fill in 'image'
+ * Read the next chunk from a stream and return an image structure
*/
-int read_chunk_2(Stream *st, struct image *image, StreamReadFlags srf)
+struct image *stream_read_chunk(Stream *st, StreamFlags srf)
{
char line[1024];
char *rval = NULL;
int have_filename = 0;
int have_ev = 0;
+ struct image *image;
- if ( find_start_of_chunk(st) ) return 1;
+ if ( find_start_of_chunk(st) ) return NULL;
- image->lambda = -1.0;
- image->features = NULL;
- image->crystals = NULL;
- image->n_crystals = 0;
- image->event = NULL;
- image->stuff_from_stream = NULL;
-
- if ( (srf & STREAM_READ_REFLECTIONS) || (srf & STREAM_READ_UNITCELL) ) {
- srf |= STREAM_READ_CRYSTALS;
- }
+ image = image_new();
+ if ( image == NULL ) return NULL;
do {
int ser;
@@ -1229,7 +925,7 @@ int read_chunk_2(Stream *st, struct image *image, StreamReadFlags srf)
}
if ( strncmp(line, "Event: ", 7) == 0 ) {
- image->event = get_event_from_event_string(line+7);
+ image->ev = strdup(line+7);
}
if ( strncmp(line, "indexed_by = ", 13) == 0 ) {
@@ -1260,70 +956,46 @@ int read_chunk_2(Stream *st, struct image *image, StreamReadFlags srf)
image->serial = ser;
}
- if ( strncmp(line, "camera_length_", 14) == 0 ) {
- if ( image->det != NULL ) {
-
- int k;
- char name[1024];
- struct panel *p;
-
- for ( k=0; k<strlen(line)-14; k++ ) {
- char ch = line[k+14];
- name[k] = ch;
- if ( (ch == ' ') || (ch == '=') ) {
- name[k] = '\0';
- break;
- }
- }
-
- p = find_panel_by_name(image->det, name);
- if ( p == NULL ) {
- ERROR("No panel '%s'\n", name);
- } else {
- p->clen = atof(line+14+k+3);
- }
-
- }
- }
- if ( strstr(line, " = ") != NULL ) {
+ if ( (srf & STREAM_PEAKS)
+ && strcmp(line, STREAM_PEAK_LIST_START_MARKER) == 0 ) {
- int fail;
+ ImageFeatureList *peaks;
+ peaks = read_peaks(st, image);
- fail = read_and_store_field(image, line);
- if ( fail ) {
- ERROR("Failed to read fields from stream.\n");
- return 1;
+ if ( peaks == NULL ) {
+ ERROR("Failed while reading peaks\n");
+ image_free(image);
+ return NULL;
}
- }
- if ( (srf & STREAM_READ_PEAKS)
- && strcmp(line, PEAK_LIST_START_MARKER) == 0 ) {
+ image->features = peaks;
- int fail;
- if ( AT_LEAST_VERSION(st, 2, 3) ) {
- fail = read_peaks_2_3(st, image);
- } else {
- fail = read_peaks(st, image);
- }
- if ( fail ) {
- ERROR("Failed while reading peaks\n");
- return 1;
- }
}
- if ( (srf & STREAM_READ_CRYSTALS)
- && (strcmp(line, CRYSTAL_START_MARKER) == 0) ) {
+ if ( strcmp(line, STREAM_CRYSTAL_START_MARKER) == 0 ) {
read_crystal(st, image, srf);
}
/* A chunk must have at least a filename and a wavelength,
* otherwise it's incomplete */
- if ( strcmp(line, CHUNK_END_MARKER) == 0 ) {
- if ( have_filename && have_ev ) return 0;
+ if ( strcmp(line, STREAM_CHUNK_END_MARKER) == 0 ) {
+ if ( have_filename && have_ev ) {
+ /* Success */
+ if ( srf & STREAM_DATA_DETGEOM ) {
+ create_detgeom(image, st->dtempl_read);
+ image_set_zero_data(image, st->dtempl_read);
+ image_set_zero_mask(image, st->dtempl_read);
+ }
+ /* FIXME: Maybe arbitrary spectrum from file (?) */
+ image->spectrum = spectrum_generate_gaussian(image->lambda,
+ image->bw);
+ return image;
+ }
ERROR("Incomplete chunk found in input file.\n");
- return 1;
+ image_free(image);
+ return NULL;
}
} while ( 1 );
@@ -1332,38 +1004,9 @@ int read_chunk_2(Stream *st, struct image *image, StreamReadFlags srf)
ERROR("Error reading stream.\n");
}
- return 1; /* Either error or EOF, don't care because we will complain
- * on the terminal if it was an error. */
-}
-
-
-
-/**
- * \param st A \ref Stream
- * \param image An \ref image structure to be filled
- *
- * Reads a chunk from \p st, placing the information in \p image.
- *
- * \returns non-zero on error.
- */
-int read_chunk(Stream *st, struct image *image)
-{
- return read_chunk_2(st, image, STREAM_READ_UNITCELL
- | STREAM_READ_REFLECTIONS
- | STREAM_READ_PEAKS);
-}
-
-
-void write_stream_header(FILE *ofh, int argc, char *argv[])
-{
- int i;
-
- fprintf(ofh, "Command line:");
- for ( i=0; i<argc; i++ ) {
- fprintf(ofh, " %s", argv[i]);
- }
- fprintf(ofh, "\n");
- fflush(ofh);
+ image_free(image);
+ return NULL; /* Either error or EOF, don't care because we will complain
+ * on the terminal if it was an error. */
}
@@ -1380,120 +1023,101 @@ char *stream_geometry_file(Stream *st)
}
-static void read_audit_lines(Stream *st)
+static void read_geometry_file(Stream *st)
{
int done = 0;
size_t len = 0;
- int first = 1;
+ const size_t max_geom_len = 64*1024;
+ char *geom;
- st->audit_info = malloc(4096);
- if ( st->audit_info == NULL ) {
- ERROR("Failed to allocate memory for audit information\n");
+ geom = malloc(max_geom_len);
+ if ( geom == NULL ) {
+ ERROR("Failed to allocate memory for geometry file\n");
return;
}
- st->audit_info[0] = '\0';
+ geom[0] = '\0';
- /* Read lines from stream until one of them starts with "-----",
- * then rewind to the start of that line */
do {
char line[1024];
char *rval;
- long pos;
-
- pos = ftell(st->fh);
rval = fgets(line, 1023, st->fh);
+ st->ln++;
if ( rval == NULL ) {
- ERROR("Failed to read stream audit info.\n");
- close_stream(st);
+ ERROR("Failed to read stream geometry file.\n");
+ stream_close(st);
+ free(geom);
return;
}
- if ( strncmp(line, "-----", 5) == 0 ) {
- fseek(st->fh, pos, SEEK_SET);
+ if ( strcmp(line, STREAM_GEOM_END_MARKER"\n") == 0 ) {
done = 1;
+ continue;
+ }
+
+ len += strlen(line);
+ if ( len > max_geom_len-1 ) {
+ ERROR("Stream's geometry file is too long (%li > %i).\n",
+ (long)len, (int)max_geom_len);
+ free(geom);
+ return;
} else {
- chomp(line);
- len += strlen(line);
- if ( len > 4090 ) {
- ERROR("Too much audit information.\n");
- return;
- } else {
- if ( !first ) {
- strcat(st->audit_info, "\n");
- }
- first = 0;
- strcat(st->audit_info, line);
- }
+ strcat(geom, line);
}
} while ( !done );
+
+ st->geometry_file = geom;
+ st->dtempl_read = data_template_new_from_string(geom);
}
-static void read_geometry_file(Stream *st)
+static void read_headers(Stream *st)
{
int done = 0;
size_t len = 0;
- int started = 0;
- const size_t max_geom_len = 64*1024;
- st->geometry_file = malloc(max_geom_len);
- if ( st->geometry_file == NULL ) {
+ st->audit_info = malloc(4096);
+ if ( st->audit_info == NULL ) {
ERROR("Failed to allocate memory for audit information\n");
return;
}
- st->geometry_file[0] = '\0';
+ st->audit_info[0] = '\0';
+ /* Read lines from stream until one of them starts with "-----",
+ * then rewind to the start of that line */
do {
char line[1024];
char *rval;
rval = fgets(line, 1023, st->fh);
+ st->ln++;
if ( rval == NULL ) {
- ERROR("Failed to read stream geometry file.\n");
- close_stream(st);
- free(st->geometry_file);
- st->geometry_file = NULL;
+ ERROR("Failed to read stream audit info.\n");
+ stream_close(st);
return;
}
- if ( strcmp(line, GEOM_START_MARKER"\n") == 0 ) {
- started = 1;
- continue;
- }
-
- if ( strcmp(line, GEOM_END_MARKER"\n") == 0 ) {
- done = 1;
- continue;
- }
-
- if ( strcmp(line, CHUNK_START_MARKER"\n") == 0 ) {
+ if ( strcmp(line, STREAM_GEOM_START_MARKER"\n") == 0 ) {
+ read_geometry_file(st);
done = 1;
- st->in_chunk = 1;
- continue;
- }
-
- if ( !started ) continue;
-
- len += strlen(line);
- if ( len > max_geom_len-1 ) {
- ERROR("Stream's geometry file is too long (%li > %i).\n",
- (long)len, (int)max_geom_len);
- free(st->geometry_file);
- st->geometry_file = NULL;
- return;
} else {
- strcat(st->geometry_file, line);
+ len += strlen(line);
+ if ( len > 4090 ) {
+ ERROR("Too much audit information.\n");
+ return;
+ } else {
+ strcat(st->audit_info, line);
+ }
}
} while ( !done );
}
-Stream *open_stream_for_read(const char *filename)
+Stream *stream_open_for_read(const char *filename)
{
Stream *st;
@@ -1502,7 +1126,10 @@ Stream *open_stream_for_read(const char *filename)
st->old_indexers = 0;
st->audit_info = NULL;
st->geometry_file = NULL;
- st->in_chunk = 0;
+ st->n_chunks = 0;
+ st->chunk_offsets = NULL;
+ st->dtempl_read = NULL;
+ st->dtempl_write = NULL;
if ( strcmp(filename, "-") == 0 ) {
st->fh = stdin;
@@ -1521,7 +1148,7 @@ Stream *open_stream_for_read(const char *filename)
rval = fgets(line, 1023, st->fh);
if ( rval == NULL ) {
ERROR("Failed to read stream version.\n");
- close_stream(st);
+ stream_close(st);
return NULL;
}
@@ -1539,14 +1166,13 @@ Stream *open_stream_for_read(const char *filename)
st->minor_version = 3;
} else {
ERROR("Invalid stream, or stream format is too new.\n");
- close_stream(st);
+ stream_close(st);
return NULL;
}
st->ln = 1;
- read_audit_lines(st);
- read_geometry_file(st);
+ read_headers(st);
return st;
}
@@ -1556,16 +1182,16 @@ Stream *open_stream_for_read(const char *filename)
* \param fd File descriptor (e.g. from open()) to use for stream data.
*
* Creates a new \ref Stream from \p fd, so that stream data can be written to \p fd
- * using \ref write_chunk.
+ * using \ref stream_write_chunk.
*
- * In contrast to \ref open_stream_for_write, this function does not write any of
+ * In contrast to \ref stream_open_for_write, this function does not write any of
* the usual headers. This function is mostly for use when multiple substreams
* need to be multiplexed into a single master stream. The master would be
- * opened using \ref open_stream_for_write, and the substreams using this function.
+ * opened using \ref stream_open_for_write, and the substreams using this function.
*
* \returns A \ref Stream, or NULL on failure.
*/
-Stream *open_stream_fd_for_write(int fd)
+Stream *stream_open_fd_for_write(int fd, const DataTemplate *dtempl)
{
Stream *st;
@@ -1574,7 +1200,10 @@ Stream *open_stream_fd_for_write(int fd)
st->old_indexers = 0;
st->audit_info = NULL;
st->geometry_file = NULL;
- st->in_chunk = 0;
+ st->n_chunks = 0;
+ st->chunk_offsets = NULL;
+ st->dtempl_read = NULL;
+ st->dtempl_write = NULL;
st->fh = fdopen(fd, "w");
if ( st->fh == NULL ) {
@@ -1582,6 +1211,7 @@ Stream *open_stream_fd_for_write(int fd)
return NULL;
}
+ st->dtempl_write = dtempl;
st->major_version = LATEST_MAJOR_VERSION;
st->minor_version = LATEST_MINOR_VERSION;
@@ -1589,102 +1219,32 @@ Stream *open_stream_fd_for_write(int fd)
}
-static void write_cell_to_stream(Stream *st, UnitCell *cell)
+void stream_write_target_cell(Stream *st, UnitCell *cell)
{
- fprintf(st->fh, CELL_START_MARKER"\n");
+ if ( cell == NULL ) return;
+ fprintf(st->fh, STREAM_CELL_START_MARKER"\n");
write_cell(cell, st->fh);
fprintf(st->fh, "; Please note: this is the target unit cell.\n");
fprintf(st->fh, "; The actual unit cells produced by indexing "
"depend on many other factors.\n");
- fprintf(st->fh, CELL_END_MARKER"\n");
+ fprintf(st->fh, STREAM_CELL_END_MARKER"\n");
fflush(st->fh);
}
/**
* \param filename Filename of new stream
- * \param geom_filename The geometry filename to copy
- * \param cell A \ref UnitCell to write into the stream
- * \param argc The number of arguments to the program
- * \param argv The arguments to the program
- * \param indm_str The list of indexing methods
+ * \param dtempl A DataTemplate
*
- * Creates a new stream with name \p filename, and adds the stream format
- * and version header, plus a verbatim copy of the geometry file and the unit
- * cell in CrystFEL format.
- *
- * \returns A \ref Stream, or NULL on failure.
- */
-Stream *open_stream_for_write_4(const char *filename,
- const char *geom_filename, UnitCell *cell,
- int argc, char *argv[], const char *indm_str)
-
-{
- Stream *st;
-
- st = malloc(sizeof(struct _stream));
- if ( st == NULL ) return NULL;
- st->old_indexers = 0;
- st->audit_info = NULL;
- st->geometry_file = NULL;
- st->in_chunk = 0;
-
- st->fh = fopen(filename, "w");
- if ( st->fh == NULL ) {
- ERROR("Failed to open stream.\n");
- free(st);
- return NULL;
- }
-
- st->major_version = LATEST_MAJOR_VERSION;
- st->minor_version = LATEST_MINOR_VERSION;
-
- fprintf(st->fh, "CrystFEL stream format %i.%i\n",
- st->major_version, st->minor_version);
- fprintf(st->fh, "Generated by CrystFEL "CRYSTFEL_VERSIONSTRING"\n");
- fflush(st->fh);
-
- if ( (argc > 0) && (argv != NULL) ) {
- write_command(st, argc, argv);
- }
-
- if ( indm_str != NULL ) {
- fprintf(st->fh, "Indexing methods selected: %s\n", indm_str);
- }
- if ( geom_filename != NULL ) {
- write_geometry_file(st, geom_filename);
- }
- if ( cell != NULL ) {
- write_cell_to_stream(st, cell);
- }
-
- return st;
-}
-
-
-Stream *open_stream_for_write_3(const char *filename,
- const char *geom_filename, UnitCell *cell,
- int argc, char *argv[])
-{
- return open_stream_for_write_4(filename, geom_filename, cell,
- argc, argv, NULL);
-}
-
-
-/**
- * \param filename Filename of new stream
- * \param geom_filename The geometry filename to copy
- * \param argc The number of arguments to the program
- * \param argv The arguments to the program
+ * Creates a new stream with name \p filename. If \p filename already
+ * exists, it will be overwritten.
*
- * Creates a new stream with name \p filename, and adds the stream format
- * and version header, plus a verbatim copy of the geometry file
+ * Audit information (e.g. CrystFEL version number) will be written.
*
* \returns A \ref Stream, or NULL on failure.
*/
-Stream *open_stream_for_write_2(const char *filename,
- const char *geom_filename, int argc,
- char *argv[])
+Stream *stream_open_for_write(const char *filename,
+ const DataTemplate *dtempl)
{
Stream *st;
@@ -1694,7 +1254,10 @@ Stream *open_stream_for_write_2(const char *filename,
st->old_indexers = 0;
st->audit_info = NULL;
st->geometry_file = NULL;
- st->in_chunk = 0;
+ st->n_chunks = 0;
+ st->chunk_offsets = NULL;
+ st->dtempl_write = dtempl;
+ st->dtempl_read = NULL;
st->fh = fopen(filename, "w");
if ( st->fh == NULL ) {
@@ -1708,50 +1271,15 @@ Stream *open_stream_for_write_2(const char *filename,
fprintf(st->fh, "CrystFEL stream format %i.%i\n",
st->major_version, st->minor_version);
- fprintf(st->fh, "Generated by CrystFEL "CRYSTFEL_VERSIONSTRING"\n");
+ fprintf(st->fh, "Generated by CrystFEL %s\n",
+ libcrystfel_version_string());
fflush(st->fh);
- if ( (argc > 0) && (argv != NULL) ) {
- write_command(st, argc, argv);
- }
- if ( geom_filename != NULL ) {
- write_geometry_file(st, geom_filename);
- }
-
return st;
}
-/**
- * \param filename Filename of new stream
- *
- * Creates a new stream with name \p filename, and adds the stream format
- * and version headers.
- *
- * You may want to follow this with a call to \ref write_command to record the
- * command line.
- *
- * \returns A \ref Stream, or NULL on failure.
- */
-Stream *open_stream_for_write(const char *filename)
-{
- return open_stream_for_write_2(filename, NULL, 0, NULL);
-}
-
-
-/**
- * \param st A \ref Stream
- *
- * This function gets the integer file descriptor for \p st, a bit like fileno().
- *
- * This is useful in conjunction with \ref open_stream_fd_for_write, to get the
- * underlying file descriptor to which the multiplexed stream data should be
- * written. In this case, the only other operations you should ever do (or have
- * done) on \p st are \ref open_stream_for_write and \ref close_stream.
- *
- * \returns An integer file descriptor
- */
-int get_stream_fd(Stream *st)
+int stream_get_fd(Stream *st)
{
return fileno(st->fh);
}
@@ -1762,46 +1290,27 @@ int get_stream_fd(Stream *st)
*
* Closes the stream
*/
-void close_stream(Stream *st)
+void stream_close(Stream *st)
{
+ if ( st == NULL ) return;
free(st->audit_info);
free(st->geometry_file);
+ data_template_free(st->dtempl_read);
fclose(st->fh);
free(st);
}
-int is_stream(const char *filename)
-{
- FILE *fh;
- char line[1024];
- char *rval;
-
- fh = fopen(filename, "r");
- if ( fh == NULL ) return 0;
-
- rval = fgets(line, 1023, fh);
- fclose(fh);
- if ( rval == NULL ) return 0;
-
- if ( strncmp(line, "CrystFEL stream format 2.0", 26) == 0 ) return 1;
- if ( strncmp(line, "CrystFEL stream format 2.1", 26) == 0 ) return 1;
- if ( strncmp(line, "CrystFEL stream format 2.2", 26) == 0 ) return 1;
-
- return 0;
-}
-
-
/**
* \param st A \ref Stream
* \param argc number of arguments
* \param argv command-line arguments
*
- * Writes the command line to \p st. \p argc and \p argv should be exactly as were
- * given to main(). This should usually be called immediately after
- * ref open_stream_for_write.
+ * Writes the command line to \p st. \p argc and \p argv should be
+ * exactly as were given to main(). This should usually be called
+ * immediately after \ref stream_open_for_write.
*/
-void write_command(Stream *st, int argc, char *argv[])
+void stream_write_commandline_args(Stream *st, int argc, char *argv[])
{
int i;
@@ -1816,6 +1325,13 @@ void write_command(Stream *st, int argc, char *argv[])
}
+void stream_write_indexing_methods(Stream *st, const char *indm_str)
+{
+ fprintf(st->fh, "Indexing methods selected: %s\n", indm_str);
+ fflush(st->fh);
+}
+
+
/**
* \param st A \ref Stream
* \param geom_filename geomtry file name
@@ -1823,8 +1339,8 @@ void write_command(Stream *st, int argc, char *argv[])
* Writes the content of the geometry file to \p st. This should usually be
* called immediately after \ref write_command.
*/
-void write_geometry_file(Stream *st, const char *geom_filename) {
-
+void stream_write_geometry_file(Stream *st, const char *geom_filename)
+{
char line[2014];
FILE *geom_fh;
char *rval;
@@ -1838,7 +1354,7 @@ void write_geometry_file(Stream *st, const char *geom_filename) {
"'%s'\n", geom_filename);
return;
}
- fprintf(st->fh, GEOM_START_MARKER"\n");
+ fprintf(st->fh, STREAM_GEOM_START_MARKER"\n");
do {
rval = fgets(line, 1023, geom_fh);
@@ -1853,7 +1369,7 @@ void write_geometry_file(Stream *st, const char *geom_filename) {
fclose(geom_fh);
- fprintf(st->fh, GEOM_END_MARKER"\n");
+ fprintf(st->fh, STREAM_GEOM_END_MARKER"\n");
fflush(st->fh);
}
@@ -1862,16 +1378,186 @@ void write_geometry_file(Stream *st, const char *geom_filename) {
* \param st A \ref Stream
*
* Attempts to set the file pointer for \p st to the start of the stream, so that
- * later calls to \ref read_chunk will repeat the sequence of chunks from the
+ * later calls to \ref stream_read_chunk will repeat the sequence of chunks from the
* start.
*
* Programs must not assume that this operation always succeeds!
*
* \returns Non-zero if the stream could not be rewound.
*/
-int rewind_stream(Stream *st)
+int stream_rewind(Stream *st)
{
st->ln = 0;
return fseek(st->fh, 0, SEEK_SET);
}
+
+struct _streamindex
+{
+ char **keys;
+ long int *ptrs;
+ int n_keys;
+ int max_keys;
+};
+
+
+void stream_index_free(StreamIndex *index)
+{
+ if ( index == NULL ) return;
+ free(index->keys);
+ free(index->ptrs);
+ free(index);
+}
+
+
+static char *make_key(const char *filename,
+ const char *ev)
+{
+ char *key;
+
+ if ( ev == NULL ) ev = "//";
+
+ key = malloc(strlen(filename)+strlen(ev)+2);
+ if ( key == NULL ) return NULL;
+
+ strcpy(key, filename);
+ strcat(key, " ");
+ strcat(key, ev);
+
+ return key;
+}
+
+
+int stream_select_chunk(Stream *st,
+ StreamIndex *index,
+ const char *filename,
+ const char *ev)
+{
+ int i;
+ char *key;
+
+ if ( index == NULL ) return 1;
+
+ key = make_key(filename, ev);
+ for ( i=0; i<index->n_keys; i++ ) {
+ if ( strcmp(index->keys[i], key) == 0 ) {
+ if ( st != NULL ) {
+ fseek(st->fh, index->ptrs[i], SEEK_SET);
+ }
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+static void add_index_record(StreamIndex *index,
+ long int ptr,
+ const char *filename,
+ const char *ev)
+{
+ char *key;
+
+ if ( index->n_keys == index->max_keys ) {
+
+ int new_max_keys = index->max_keys + 256;
+ char **new_keys;
+ long int *new_ptrs;
+
+ new_keys = realloc(index->keys,
+ new_max_keys*sizeof(char *));
+ if ( new_keys == NULL ) return;
+
+ new_ptrs = realloc(index->ptrs,
+ new_max_keys*sizeof(long int));
+ if ( new_ptrs == NULL ) return;
+
+ index->keys = new_keys;
+ index->ptrs = new_ptrs;
+ index->max_keys = new_max_keys;
+
+ }
+
+ key = make_key(filename, ev);
+ if ( key == NULL ) return;
+
+ index->keys[index->n_keys] = key;
+ index->ptrs[index->n_keys] = ptr;
+ index->n_keys++;
+}
+
+
+StreamIndex *stream_make_index(const char *filename)
+{
+ FILE *fh;
+ StreamIndex *index;
+ long int last_start_pos = 0;
+ char *last_filename = NULL;
+ char *last_ev = NULL;
+ int done = 0;
+
+ fh = fopen(filename, "r");
+ if ( fh == NULL ) return NULL;
+
+ index = malloc(sizeof(StreamIndex));
+ if ( index == NULL ) {
+ fclose(fh);
+ return NULL;
+ }
+
+ index->keys = NULL;
+ index->ptrs = NULL;
+ index->n_keys = 0;
+ index->max_keys = 0;
+
+ STATUS("Scanning %s\n", filename);
+
+ do {
+
+ char *rval;
+ char line[1024];
+ long int pos;
+
+ pos = ftell(fh);
+ rval = fgets(line, 1024, fh);
+ if ( rval == NULL ) {
+ done = 1;
+ break;
+ }
+ chomp(line);
+
+ if ( strcmp(line, STREAM_CHUNK_START_MARKER) == 0 ) {
+ last_start_pos = pos;
+ last_filename = NULL;
+ last_ev = NULL;
+ }
+
+ if ( strncmp(line, "Image filename: ", 16) == 0 ) {
+ last_filename = strdup(line+16);
+ }
+
+ if ( strncmp(line, "Event: ", 7) == 0 ) {
+ last_ev = strdup(line+7);
+ }
+
+ if ( strcmp(line, STREAM_CHUNK_END_MARKER) == 0 ) {
+ if ( (last_start_pos != 0)
+ && (last_filename != NULL) )
+ {
+ add_index_record(index,
+ last_start_pos,
+ last_filename,
+ last_ev);
+ }
+ free(last_filename);
+ free(last_ev);
+ last_start_pos = 0;
+ last_filename = NULL;
+ last_ev = NULL;
+ }
+
+ } while ( !done );
+
+ fclose(fh);
+ return index;
+}
diff --git a/libcrystfel/src/stream.h b/libcrystfel/src/stream.h
index f3e4d7e8..115d9918 100644
--- a/libcrystfel/src/stream.h
+++ b/libcrystfel/src/stream.h
@@ -3,11 +3,11 @@
*
* Stream tools
*
- * Copyright © 2013-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2013-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2019 Thomas White <taw@physics.org>
+ * 2010-2021 Thomas White <taw@physics.org>
* 2014 Valerio Mariani
* 2011 Andrew Aquila
*
@@ -31,34 +31,28 @@
#ifndef STREAM_H
#define STREAM_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
/**
* \file stream.h
* Stream functions (for indexing results)
*/
struct image;
-struct hdfile;
-struct event;
-struct imagefile;
+
+#include "datatemplate.h"
#include "cell.h"
-#define GEOM_START_MARKER "----- Begin geometry file -----"
-#define GEOM_END_MARKER "----- End geometry file -----"
-#define CELL_START_MARKER "----- Begin unit cell -----"
-#define CELL_END_MARKER "----- End unit cell -----"
-#define CHUNK_START_MARKER "----- Begin chunk -----"
-#define CHUNK_END_MARKER "----- End chunk -----"
-#define PEAK_LIST_START_MARKER "Peaks from peak search"
-#define PEAK_LIST_END_MARKER "End of peak list"
-#define CRYSTAL_START_MARKER "--- Begin crystal"
-#define CRYSTAL_END_MARKER "--- End crystal"
-#define REFLECTION_START_MARKER "Reflections measured after indexing"
-/* REFLECTION_END_MARKER is over in reflist-utils.h because it is also
- * used to terminate a standalone list of reflections */
+#define STREAM_GEOM_START_MARKER "----- Begin geometry file -----"
+#define STREAM_GEOM_END_MARKER "----- End geometry file -----"
+#define STREAM_CELL_START_MARKER "----- Begin unit cell -----"
+#define STREAM_CELL_END_MARKER "----- End unit cell -----"
+#define STREAM_CHUNK_START_MARKER "----- Begin chunk -----"
+#define STREAM_CHUNK_END_MARKER "----- End chunk -----"
+#define STREAM_PEAK_LIST_START_MARKER "Peaks from peak search"
+#define STREAM_PEAK_LIST_END_MARKER "End of peak list"
+#define STREAM_CRYSTAL_START_MARKER "--- Begin crystal"
+#define STREAM_CRYSTAL_END_MARKER "--- End crystal"
+#define STREAM_REFLECTION_START_MARKER "Reflections measured after indexing"
+#define STREAM_REFLECTION_END_MARKER "End of reflections"
/**
* An opaque structure representing a stream being read or written
@@ -66,77 +60,72 @@ struct imagefile;
typedef struct _stream Stream;
/**
- * A bitfield of things that can be read from a stream. Use this (and
- * \ref read_chunk_2) to read the stream faster if you don't need the entire
- * contents of the stream.
+ * A bitfield of things that can be read from or written to a stream.
+ * Use this together with stream_{read,write}_chunk to read/write the
+ * stream faster if you don't need all the information.
*
- * Using either or both of \p STREAM_READ_REFLECTIONS and \p STREAM_READ_UNITCELL
- * implies \p STREAM_READ_CRYSTALS.
+ * General information about crystals (including unit cell parameters)
+ * is always read and written.
**/
typedef enum {
- /** Read the unit cell */
- STREAM_READ_UNITCELL = 1,
-
/** Read the integrated reflections */
- STREAM_READ_REFLECTIONS = 2,
+ STREAM_REFLECTIONS = 2,
/** Read the peak search results */
- STREAM_READ_PEAKS = 4,
-
- /** Read the general information about crystals */
- STREAM_READ_CRYSTALS = 8,
+ STREAM_PEAKS = 4,
-} StreamReadFlags;
+ /** Reconstruct the detgeom structure,
+ * and create (blank) data/mask arrays.
+ * (NB this is (currently) a slow operation) */
+ STREAM_DATA_DETGEOM = 8,
-struct stuff_from_stream
-{
- char **fields;
- int n_fields;
-};
+} StreamFlags;
#ifdef __cplusplus
extern "C" {
#endif
-extern Stream *open_stream_for_read(const char *filename);
-extern Stream *open_stream_for_write(const char *filename);
-extern Stream *open_stream_for_write_2(const char *filename,
- const char* geom_filename, int argc,
- char *argv[]);
-extern Stream *open_stream_for_write_3(const char *filename,
- const char* geom_filename, UnitCell *cell,
- int argc, char *argv[]);
-extern Stream *open_stream_for_write_4(const char *filename,
- const char *geom_filename, UnitCell *cell,
- int argc, char *argv[], const char *indm_str);
-extern Stream *open_stream_fd_for_write(int fd);
-extern int get_stream_fd(Stream *st);
-extern void close_stream(Stream *st);
-
-extern void free_stuff_from_stream(struct stuff_from_stream *sfs);
-
-extern int read_chunk(Stream *st, struct image *image);
-extern int read_chunk_2(Stream *st, struct image *image,
- StreamReadFlags srf);
+/* Opening/closing streams */
+extern Stream *stream_open_for_read(const char *filename);
+extern Stream *stream_open_for_write(const char *filename,
+ const DataTemplate *dtempl);
+extern Stream *stream_open_fd_for_write(int fd,
+ const DataTemplate *dtempl);
+extern void stream_close(Stream *st);
+
+/* Writing things to stream header */
+extern void stream_write_geometry_file(Stream *st,
+ const char *geom_filename);
+extern void stream_write_target_cell(Stream *st,
+ UnitCell *cell);
+extern void stream_write_commandline_args(Stream *st,
+ int argc, char *argv[]);
+extern void stream_write_indexing_methods(Stream *st,
+ const char *indm_str);
+
+/* Metadata */
extern int stream_has_old_indexers(Stream *st);
-
-extern int write_chunk(Stream *st, struct image *image, struct imagefile *imfile,
- int include_peaks, int include_reflections,
- struct event *ev);
-
-extern int write_chunk_2(Stream *st, struct image *image,
- struct imagefile *imfile,
- int include_peaks, int include_reflections,
- struct event *ev);
-
-extern void write_command(Stream *st, int argc, char *argv[]);
-extern void write_geometry_file(Stream *st, const char *geom_filename);
-extern int rewind_stream(Stream *st);
-extern int is_stream(const char *filename);
extern char *stream_audit_info(Stream *st);
extern char *stream_geometry_file(Stream *st);
+/* Low-level stuff used for indexamajig sandbox */
+extern int stream_get_fd(Stream *st);
+extern int stream_rewind(Stream *st);
+
+/* Random access */
+typedef struct _streamindex StreamIndex;
+extern StreamIndex *stream_make_index(const char *filename);
+extern int stream_select_chunk(Stream *st, StreamIndex *index,
+ const char *filename,
+ const char *ev);
+extern void stream_index_free(StreamIndex *index);
+
+/* Read/write chunks */
+extern struct image *stream_read_chunk(Stream *st, StreamFlags srf);
+extern int stream_write_chunk(Stream *st, const struct image *image,
+ StreamFlags srf);
+
#ifdef __cplusplus
}
#endif
diff --git a/libcrystfel/src/symmetry.c b/libcrystfel/src/symmetry.c
index 32c5f6c3..bd6d2e8f 100644
--- a/libcrystfel/src/symmetry.c
+++ b/libcrystfel/src/symmetry.c
@@ -3,11 +3,11 @@
*
* Symmetry
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2019 Thomas White <taw@physics.org>
+ * 2010-2020 Thomas White <taw@physics.org>
* 2014 Kenneth Beyerlein <kenneth.beyerlein@desy.de>
*
* This file is part of CrystFEL.
@@ -1684,21 +1684,24 @@ SymOpList *parse_symmetry_operations(const char *s)
}
-static void add_chars(char *t, const char *s, int max_len)
+static void add_chars(char *t, const char *s, size_t max_len)
{
- char *tmp;
+ size_t len;
- tmp = strdup(t);
+ len = strlen(t) + strlen(s);
+ if ( len > max_len ) {
+ ERROR("get_matrix_name: String too long!\n");
+ return;
+ }
- snprintf(t, max_len, "%s%s", tmp, s);
- free(tmp);
+ strcat(t, s);
}
char *get_matrix_name(const IntegerMatrix *m, int col)
{
char *text;
- const int max_len = 9;
+ const size_t max_len = 31;
int i;
int printed = 0;
diff --git a/libcrystfel/src/symmetry.h b/libcrystfel/src/symmetry.h
index f71cadb9..b8780735 100644
--- a/libcrystfel/src/symmetry.h
+++ b/libcrystfel/src/symmetry.h
@@ -3,7 +3,7 @@
*
* Symmetry
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
@@ -30,11 +30,6 @@
#ifndef SYMMETRY_H
#define SYMMETRY_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include "integer_matrix.h"
#include "rational.h"
diff --git a/libcrystfel/src/thread-pool.c b/libcrystfel/src/thread-pool.c
index 67645b1e..61849270 100644
--- a/libcrystfel/src/thread-pool.c
+++ b/libcrystfel/src/thread-pool.c
@@ -3,11 +3,11 @@
*
* A thread pool implementation
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2012 Thomas White <taw@physics.org>
+ * 2010-2019 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -47,7 +47,6 @@
static int use_status_labels = 0;
static pthread_key_t status_label_key;
-pthread_mutex_t stderr_lock = PTHREAD_MUTEX_INITIALIZER;
struct worker_args
{
diff --git a/libcrystfel/src/thread-pool.h b/libcrystfel/src/thread-pool.h
index 16fb38bf..6bd7139c 100644
--- a/libcrystfel/src/thread-pool.h
+++ b/libcrystfel/src/thread-pool.h
@@ -3,11 +3,11 @@
*
* A thread pool implementation
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2012 Thomas White <taw@physics.org>
+ * 2010-2019 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -29,18 +29,12 @@
#ifndef THREAD_POOL_H
#define THREAD_POOL_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include <pthread.h>
#ifdef __cplusplus
extern "C" {
#endif
-extern pthread_mutex_t stderr_lock;
extern signed int get_status_label(void);
/**
diff --git a/libcrystfel/src/utils.c b/libcrystfel/src/utils.c
index 4873b050..053e952b 100644
--- a/libcrystfel/src/utils.c
+++ b/libcrystfel/src/utils.c
@@ -3,11 +3,11 @@
*
* Utility stuff
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2009-2014 Thomas White <taw@physics.org>
+ * 2009-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -34,6 +34,7 @@
#include <math.h>
#include <string.h>
#include <stdio.h>
+#include <stdarg.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -251,6 +252,76 @@ gsl_vector *solve_svd(gsl_vector *v, gsl_matrix *M, int *pn_filt, int verbose)
}
+/* ------------------------------ Message logging ---------------------------- */
+
+/* Lock to keep lines serialised on the terminal */
+pthread_mutex_t stderr_lock = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void log_to_stderr(enum log_msg_type type, const char *msg,
+ void *vp)
+{
+ int error_print_val = get_status_label();
+ pthread_mutex_lock(&stderr_lock);
+ if ( error_print_val >= 0 ) {
+ fprintf(stderr, "%3i: ", error_print_val);
+ }
+ fprintf(stderr, "%s", msg);
+ pthread_mutex_unlock(&stderr_lock);
+}
+
+
+/* Function to call with ERROR/STATUS messages */
+LogMsgFunc log_msg_func = log_to_stderr;
+void *log_msg_vp = NULL;
+
+
+void set_log_message_func(LogMsgFunc new_log_msg_func, void *vp)
+{
+ log_msg_func = new_log_msg_func;
+ log_msg_vp = vp;
+}
+
+
+void STATUS(const char *format, ...)
+{
+ va_list args;
+ char tmp[1024];
+ va_start(args, format);
+ vsnprintf(tmp, 1024, format, args);
+ va_end(args);
+ log_msg_func(LOG_MSG_STATUS, tmp, log_msg_vp);
+}
+
+
+void ERROR(const char *format, ...)
+{
+ va_list args;
+ char tmp[1024];
+ va_start(args, format);
+ vsnprintf(tmp, 1024, format, args);
+ va_end(args);
+ log_msg_func(LOG_MSG_ERROR, tmp, log_msg_vp);
+}
+
+
+/* ------------------------------ Useful functions ---------------------------- */
+
+int convert_int(const char *str, int *pval)
+{
+ int val;
+ char *rval;
+
+ val = strtod(str, &rval);
+ if ( *rval != '\0' ) {
+ return 1;
+ } else {
+ *pval = val;
+ return 0;
+ }
+}
+
+
size_t notrail(char *s)
{
ssize_t i;
@@ -272,10 +343,12 @@ size_t notrail(char *s)
void chomp(char *s)
{
size_t i;
+ size_t len;
if ( s == NULL ) return;
+ len = strlen(s);
- for ( i=0; i<strlen(s); i++ ) {
+ for ( i=0; i<len; i++ ) {
if ( (s[i] == '\n') || (s[i] == '\r') ) {
s[i] = '\0';
return;
@@ -503,6 +576,13 @@ char *check_prefix(char *prefix)
}
+char *safe_strdup(const char *in)
+{
+ if ( in == NULL ) return NULL;
+ return strdup(in);
+}
+
+
char *safe_basename(const char *in)
{
int i;
@@ -550,6 +630,29 @@ void strip_extension(char *bfn)
}
+const char *filename_extension(const char *fn, const char **pext2)
+{
+ const char *ext = NULL;
+ const char *ext2 = NULL;
+ size_t r = strlen(fn)-1;
+
+ while ( r > 0 ) {
+ if ( fn[r] == '.' ) {
+ if ( ext != NULL ) {
+ ext2 = fn+r;
+ break;
+ } else {
+ ext = fn+r;
+ }
+ }
+ r--;
+ }
+
+ if ( pext2 != NULL ) *pext2 = ext2;
+ return ext;
+}
+
+
/* Force the linker to bring in CBLAS to make GSL happy */
void utils_fudge_gslcblas()
{
@@ -674,3 +777,64 @@ struct rvec quat_rot(struct rvec q, struct quaternion z)
return res;
}
+
+
+char *load_entire_file(const char *filename)
+{
+ struct stat statbuf;
+ int r;
+ char *contents;
+ FILE *fh;
+
+ r = stat(filename, &statbuf);
+ if ( r != 0 ) {
+ ERROR("File '%s' not found\n", filename);
+ return NULL;
+ }
+
+ contents = malloc(statbuf.st_size+1);
+ if ( contents == NULL ) {
+ ERROR("Failed to allocate memory for file\n");
+ return NULL;
+ }
+
+ fh = fopen(filename, "r");
+ if ( fh == NULL ) {
+ ERROR("Failed to open file '%s'\n", filename);
+ free(contents);
+ return NULL;
+ }
+
+ if ( fread(contents, 1, statbuf.st_size, fh) != statbuf.st_size ) {
+ ERROR("Failed to read file '%s'\n", filename);
+ free(contents);
+ return NULL;
+ }
+ contents[statbuf.st_size] = '\0';
+
+ fclose(fh);
+
+ return contents;
+}
+
+
+int compare_double(const void *av, const void *bv)
+{
+ double a = *(double *)av;
+ double b = *(double *)bv;
+ if ( a > b ) return 1;
+ if ( a < b ) return -1;
+ return 0;
+}
+
+
+/* -------------------------- libcrystfel features ------------------------ */
+
+int crystfel_has_peakfinder9()
+{
+#ifdef HAVE_FDIP
+ return 1;
+#else
+ return 0;
+#endif
+}
diff --git a/libcrystfel/src/utils.h b/libcrystfel/src/utils.h
index beb05ee0..8bcb51ff 100644
--- a/libcrystfel/src/utils.h
+++ b/libcrystfel/src/utils.h
@@ -3,11 +3,11 @@
*
* Utility stuff
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2009-2014 Thomas White <taw@physics.org>
+ * 2009-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -29,10 +29,6 @@
#ifndef UTILS_H
#define UTILS_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include <math.h>
#include <complex.h>
#include <float.h>
@@ -54,9 +50,12 @@
/* -------------------------- Fundamental constants ------------------------ */
-/* Electron charge in C */
+/* Electron charge (Coulombs) */
#define ELECTRON_CHARGE (1.6021773e-19)
+/* Electron rest mass (kg) */
+#define ELECTRON_MASS (9.1093837015e-31)
+
/* Planck's constant (Js) */
#define PLANCK (6.62606896e-34)
@@ -77,9 +76,13 @@ extern void show_matrix_eqn(gsl_matrix *M, gsl_vector *v);
extern void show_matrix(gsl_matrix *M);
extern gsl_vector *solve_svd(gsl_vector *v, gsl_matrix *M, int *n_filt,
int verbose);
+
extern size_t notrail(char *s);
+extern int convert_int(const char *str, int *pval);
extern void chomp(char *s);
+#define CLEAR_BIT(val, bit) (((val) | (bit)) ^ (bit))
+
/**
* Controls the behaviour of \ref assplode.
**/
@@ -192,37 +195,45 @@ static inline int within_tolerance(double a, double b, double percent)
/* Photon energy (eV) to k (1/m) */
#define ph_eV_to_k(a) ((a)*ELECTRON_CHARGE/PLANCK/C_VACUO)
+/* Electron accelerating voltage (V) to wavelength (m) */
+static inline double el_V_to_lambda(double E)
+{
+ double Estar;
+
+ /* Relativistically corrected accelerating voltage */
+ Estar = E * (1.0 + E * ELECTRON_CHARGE/(2.0*ELECTRON_MASS*C_VACUO*C_VACUO));
+
+ return PLANCK / sqrt(2.0*ELECTRON_MASS*ELECTRON_CHARGE*Estar);
+}
+
-/* ------------------------------ Message macros ---------------------------- */
+/* ------------------------------ Message logging ---------------------------- */
extern pthread_mutex_t stderr_lock;
-#define ERROR(...) { \
- int error_print_val = get_status_label(); \
- pthread_mutex_lock(&stderr_lock); \
- if ( error_print_val >= 0 ) { \
- fprintf(stderr, "%3i: ", error_print_val); \
- } \
- fprintf(stderr, __VA_ARGS__); \
- pthread_mutex_unlock(&stderr_lock); \
- }
-
-#define STATUS(...) { \
- int status_print_val = get_status_label(); \
- pthread_mutex_lock(&stderr_lock); \
- if ( status_print_val >= 0 ) { \
- fprintf(stderr, "%3i: ", status_print_val); \
- } \
- fprintf(stderr, __VA_ARGS__); \
- pthread_mutex_unlock(&stderr_lock); \
- }
+enum log_msg_type {
+ LOG_MSG_STATUS,
+ LOG_MSG_ERROR
+};
+
+
+extern void STATUS(const char *format, ...);
+extern void ERROR(const char *format, ...);
+
+typedef void (*LogMsgFunc)(enum log_msg_type type, const char *msg, void *vp);
+
+extern void set_log_message_func(LogMsgFunc new_log_msg_func,
+ void *vp);
/* ------------------------------ File handling ----------------------------- */
extern char *check_prefix(char *prefix);
extern char *safe_basename(const char *in);
+extern char *safe_strdup(const char *in);
extern void strip_extension(char *bfn);
+extern char *load_entire_file(const char *filename);
+extern const char *filename_extension(const char *fn, const char **ext2);
/* ------------------------------ Useful stuff ------------------------------ */
@@ -258,6 +269,8 @@ extern struct quaternion random_quaternion(gsl_rng *rng);
extern int quaternion_valid(struct quaternion q);
extern struct rvec quat_rot(struct rvec q, struct quaternion z);
+extern int compare_double(const void *av, const void *bv);
+
/* Keep these ones inline, to avoid function call overhead */
static inline struct quaternion invalid_quaternion(void)
{
@@ -293,6 +306,12 @@ static inline void mean_variance(const double x, const double w,
*sumw = temp;
}
+
+/* -------------------------- libcrystfel features ------------------------ */
+
+extern int crystfel_has_peakfinder9(void);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/meson.build b/meson.build
new file mode 100644
index 00000000..da524d0c
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,309 @@
+# Meson file for CrystFEL
+project('crystfel', 'c',
+ version : '0.9.1',
+ license : 'GPL3+',
+ default_options : ['buildtype=debugoptimized'])
+
+add_project_arguments('-DHAVE_CONFIG_H', language : 'c')
+
+versionc = vcs_tag(input: 'src/version.c.in',
+ output: 'version.c')
+
+
+conf_data = configuration_data()
+
+# Mandatory dependencies
+cc = meson.get_compiler('c')
+mdep = cc.find_library('m', required : true)
+gsldep = dependency('gsl', required : true)
+zlibdep = dependency('zlib', required : true)
+pthreaddep = dependency('threads', required : true)
+
+# Try via pkg-config first:
+slurmdep = dependency('slurm', required : false)
+if not slurmdep.found()
+ slurmdep = cc.find_library('slurm', required : false)
+endif
+
+if slurmdep.found()
+ conf_data.set10('HAVE_SLURM', 1)
+endif
+
+# HDF5 >= 1.8.21 and >= 1.10.2 has a pkg-config file:
+hdf5dep = dependency('hdf5', language : 'c', required : false)
+
+# Otherwise, try finding it ourselves:
+if not hdf5dep.found()
+ hdf5dep = cc.find_library('hdf5', required : false)
+endif
+
+if not hdf5dep.found()
+ error('Couldn\'t find HDF5')
+endif
+
+# 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')
+
+# "Optional" dependencies
+fftwdep = dependency('fftw3', required : false)
+if fftwdep.found()
+ conf_data.set10('HAVE_FFTW', 1)
+endif
+
+gtkdep = dependency('gtk+-3.0', required : false)
+if gtkdep.found()
+ add_project_arguments('-Wno-deprecated-declarations', language : 'c')
+ conf_data.set10('HAVE_GTK', 1)
+endif
+
+gdkdep = dependency('gdk-3.0', required : false)
+if gdkdep.found()
+ conf_data.set10('HAVE_GDK', 1)
+endif
+
+gdkpixbufdep = dependency('gdk-pixbuf-2.0', required : false)
+if gdkpixbufdep.found()
+ conf_data.set10('HAVE_GDKPIXBUF', 1)
+endif
+
+cairodep = dependency('cairo', required : false)
+if cairodep.found()
+ conf_data.set10('HAVE_CAIRO', 1)
+endif
+
+opencldep = dependency('OpenCL', required : false)
+if opencldep.found()
+ conf_data.set10('HAVE_OPENCL', 1)
+endif
+if cc.has_header('CL/cl.h')
+ conf_data.set10('HAVE_CL_CL_H', 1)
+endif
+
+zmqdep = dependency('libzmq', required : false)
+if zmqdep.found()
+ conf_data.set10('HAVE_ZMQ', 1)
+endif
+
+msgpackdep = dependency('msgpack', required : false)
+if msgpackdep.found()
+ conf_data.set10('HAVE_MSGPACK', 1)
+endif
+
+if cc.has_function('clock_gettime', prefix : '#include <time.h>')
+ conf_data.set10('HAVE_CLOCK_GETTIME', 1)
+endif
+
+ccp4dep = dependency('libccp4c', required: false)
+if ccp4dep.found()
+ conf_data.set10('HAVE_LIBCCP4', 1)
+endif
+
+# ************************ libcrystfel (subdir) ************************
+
+subdir('libcrystfel')
+
+# ************************ The programs ************************
+
+configure_file(input : 'config.h.in',
+ output : 'config.h',
+ configuration : conf_data)
+conf_inc = include_directories('.')
+
+# cell_tool
+executable('cell_tool',
+ ['src/cell_tool.c', versionc],
+ dependencies : [mdep, libcrystfeldep],
+ install : true,
+ install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib')
+
+# partial_sim
+executable('partial_sim',
+ ['src/partial_sim.c', versionc],
+ dependencies : [mdep, libcrystfeldep, gsldep, pthreaddep],
+ install : true,
+ install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib')
+
+# process_hkl
+process_hkl = executable('process_hkl',
+ ['src/process_hkl.c', versionc],
+ dependencies : [mdep, libcrystfeldep],
+ install : true,
+ install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib')
+
+# list_events
+executable('list_events',
+ ['src/list_events.c', versionc],
+ dependencies : [mdep, libcrystfeldep],
+ install : true,
+ install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib')
+
+# get_hkl
+executable('get_hkl',
+ ['src/get_hkl.c', versionc],
+ dependencies : [mdep, libcrystfeldep, gsldep],
+ install : true,
+ install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib')
+
+# compare_hkl
+executable('compare_hkl',
+ ['src/compare_hkl.c', versionc],
+ dependencies : [mdep, libcrystfeldep, gsldep],
+ install : true,
+ install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib')
+
+# check_hkl
+executable('check_hkl',
+ ['src/check_hkl.c', versionc],
+ dependencies : [mdep, libcrystfeldep, gsldep],
+ install : true,
+ install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib')
+
+# partialator
+partialator = executable('partialator',
+ ['src/partialator.c',
+ 'src/post-refinement.c',
+ 'src/merge.c',
+ 'src/rejection.c',
+ 'src/scaling.c',
+ versionc],
+ dependencies : [mdep, libcrystfeldep, gsldep, pthreaddep],
+ install : true,
+ install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib')
+
+# ambigator
+executable('ambigator',
+ ['src/ambigator.c', versionc],
+ dependencies : [mdep, libcrystfeldep, gsldep, hdf5dep],
+ install : true,
+ install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib')
+
+# whirligig
+executable('whirligig',
+ ['src/whirligig.c', versionc],
+ dependencies : [mdep, libcrystfeldep],
+ install : true,
+ install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib')
+
+# indexamajig
+indexamajig_sources = ['src/indexamajig.c', 'src/im-sandbox.c',
+ 'src/process_image.c', 'src/time-accounts.c',
+ versionc]
+if zmqdep.found() and msgpackdep.found()
+ indexamajig_sources += ['src/im-zmq.c']
+endif
+
+executable('indexamajig', indexamajig_sources,
+ dependencies : [mdep, libcrystfeldep, gsldep, pthreaddep, zmqdep,
+ msgpackdep],
+ install : true,
+ 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')
+
+# geoptimiser
+# FIXME: restore
+#executable('geoptimiser',
+# ['src/geoptimiser.c', 'src/hdfsee-render.c', versionc],
+# dependencies : [mdep, libcrystfeldep, gsldep, gdkpixbufdep, gdkdep],
+# install : true,
+# install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib')
+
+# CrystFEL GUI
+if gtkdep.found()
+
+ gui_sources = ['src/crystfel_gui.c',
+ 'src/crystfelimageview.c',
+ 'src/crystfelindexingopts.c',
+ 'src/crystfelmergeopts.c',
+ 'src/crystfelsymmetryselector.c',
+ 'src/gtk-util-routines.c',
+ 'src/gui_import.c',
+ 'src/gui_peaksearch.c',
+ 'src/gui_index.c',
+ 'src/gui_merge.c',
+ 'src/gui_fom.c',
+ 'src/gui_export.c',
+ 'src/gui_ambi.c',
+ 'src/gui_backend_local.c',
+ 'src/gui_project.c',
+ versionc]
+
+ if slurmdep.found()
+ gui_sources += 'src/gui_backend_slurm.c'
+ endif
+
+
+ executable('crystfel', gui_sources,
+ dependencies : [mdep, libcrystfeldep, gtkdep, gsldep, slurmdep,
+ ccp4dep],
+ install : true,
+ install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib')
+
+endif
+
+# render_hkl
+executable('render_hkl',
+ ['src/render_hkl.c', versionc],
+ dependencies : [mdep, libcrystfeldep, cairodep, gsldep],
+ install : true,
+ install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib')
+
+# cell_explorer
+if gtkdep.found()
+ executable('cell_explorer',
+ ['src/cell_explorer.c', 'src/multihistogram.c', versionc],
+ dependencies : [mdep, libcrystfeldep, gtkdep, gsldep],
+ install : true,
+ install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib')
+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']
+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'],
+ install_dir : get_option('datadir')+'/icons/hicolor/scalable/apps')
+
+
+# ************************ Testing ************************
+
+subdir('tests')
+
+
+# ************************ Manual pages ************************
+install_man(['doc/man/ambigator.1',
+ 'doc/man/cell_explorer.1',
+ 'doc/man/cell_tool.1',
+ 'doc/man/check_hkl.1',
+ 'doc/man/compare_hkl.1',
+ 'doc/man/crystfel.7',
+ 'doc/man/crystfel_geometry.5',
+ 'doc/man/geoptimiser.1',
+ 'doc/man/get_hkl.1',
+ 'doc/man/indexamajig.1',
+ 'doc/man/list_events.1',
+ 'doc/man/list_events.1',
+ 'doc/man/make_pixelmap.1',
+ 'doc/man/partialator.1',
+ 'doc/man/partial_sim.1',
+ 'doc/man/pattern_sim.1',
+ 'doc/man/process_hkl.1',
+ 'doc/man/render_hkl.1',
+ 'doc/man/whirligig.1'])
diff --git a/scripts/check-near-bragg b/scripts/check-near-bragg
deleted file mode 100755
index 2130378b..00000000
--- a/scripts/check-near-bragg
+++ /dev/null
@@ -1,107 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-use File::Basename;
-use File::stat;
-
-my $skip = 0;
-
-my $args = join(" ", splice(@ARGV, 1, scalar(@ARGV)-1));
-if ( !($args eq "") ) {
- printf("Extra arguments for hdfsee: %s\n", $args);
-} else {
- # Default arguments - feel free to override!
- $args = "--binning=2 --int-boost=10";
- printf("Using default arguments for hdfsee: %s\n", $args);
-}
-
-my $file = $ARGV[0];
-
-open(FH, $file);
-open(TMP, "> list.tmp");
-
-my $statbuf = stat($file);
-if ( not $statbuf ) {
- printf("Couldn't stat stream. Check the filename.\n");
- exit;
-}
-my $stream_mtime = $statbuf->mtime;
-
-my $in_image = 0;
-my $line;
-my $filename;
-my $event = "";
-my $n_seen = 0;
-
-while ( $line = <FH> ) {
-
- chomp $line;
- my $handled = 0;
-
- if ( $in_image ) {
- printf(TMP "%s\n", $line);
- $handled = 1;
- }
-
- if ( $line =~ /^Reflections\ measured\ after\ indexing$/ ) {
- $in_image = 1;
- $handled = 1;
- }
-
- if ( $line =~ /^Image\ filename:\ (.+)$/ ) {
- $filename = $1;
- $handled = 1;
- }
-
- if ( $line =~ /^Event:\ (.+)$/ ) {
- $event = $1;
- }
-
- if ( $line =~ /^End\ of\ reflections$/ ) {
-
- close(TMP);
-
- # Example of how to do "basename" and "prefix":
- # $filename = "images-old/".basename($filename);
-
- my $ev;
- my $evr;
- if ( $event eq "" ) {
- $ev = "";
- $evr = "";
- } else {
- $ev = " --event=".$event;
- $evr = ", event ".$event;
- }
-
- $n_seen++;
- if ( $n_seen > $skip ) {
-
- my $statbuf = stat($filename);
- if ( not $statbuf ) {
- printf("Couldn't stat image file '%s' - does it exist?\n",
- $filename);
- exit;
- }
- my $image_mtime = $statbuf->mtime;
- if ( $image_mtime > $stream_mtime ) {
- printf(STDERR "WARNING: Image file is newer than stream\n");
- }
-
- printf(STDERR "Viewing %s%s\n", $filename, $evr);
- system("hdfsee ".$filename.$ev.
- " --peak-overlay=list.tmp ".$args);
- if ( $? != 0 ) { exit; }
- } else {
- printf(STDERR "Skipping %s%s\n", $filename, $evr);
- }
-
- unlink("list.tmp");
- open(TMP, "> list.tmp");
- $handled = 1;
- $in_image = 0;
- $event = "";
-
- }
-
-}
diff --git a/scripts/check-peak-detection b/scripts/check-peak-detection
deleted file mode 100755
index 91d21f63..00000000
--- a/scripts/check-peak-detection
+++ /dev/null
@@ -1,153 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-use File::Basename;
-use File::stat;
-
-my $skip = 0;
-
-my $only;
-my $file;
-my $start;
-
-# Horrible option processing
-if ( $ARGV[0] eq "--indexed" ) {
- $only = "indexed";
- $file = $ARGV[1];
- $start = 2;
-} elsif ( $ARGV[0] eq "--not-indexed" ) {
- $only = "notindexed";
- $file = $ARGV[1];
- $start = 2;
-} else {
- $only = "";
- $file = $ARGV[0];
- $start = 1;
-}
-my $args = join(" ", splice(@ARGV, $start, scalar(@ARGV)-1));
-if ( !($args eq "") ) {
- printf("Extra arguments for hdfsee: %s\n", $args);
-} else {
- # Default arguments - feel free to override!
- $args = "--binning=2 --int-boost=10";
- printf("Using default arguments for hdfsee: %s\n", $args);
-}
-
-open(FH, $file);
-open(TMP, "> list.tmp");
-
-my $statbuf = stat($file);
-if ( not $statbuf ) {
- printf("Couldn't stat stream. Check the filename.\n");
- exit;
-}
-my $stream_mtime = $statbuf->mtime;
-
-my $in_image = 0;
-my $line;
-my $filename;
-my $event = "";
-my $indexed;
-my $n_seen = 0;
-
-while ( $line = <FH> ) {
-
- chomp $line;
-
- if ( $in_image ) {
- printf(TMP "%s\n", $line);
- }
-
- if ( $line =~ /^Peaks\ from\ peak\ search$/ ) {
- $in_image = 1;
- }
-
- if ( $line =~ /^Image\ filename:\ (.+)$/ ) {
- $filename = $1;
- }
-
- if ( $line =~ /^Event:\ (.+)$/ ) {
- $event = $1;
- }
-
- if ( $line =~ /^indexed_by\ =\ (.*)$/ ) {
- if ( $1 eq "none" ) {
- $indexed = 0;
- } else {
- $indexed = 1;
- }
- }
-
- if ( $line =~ /^End\ of\ peak\ list$/ ) {
-
- close(TMP);
-
- my $show;
-
- if ( $only eq "indexed" ) {
- if ( $indexed ) {
- $show = 1;
- } else {
- $show = 0;
- }
- } elsif ( $only eq "notindexed" ) {
- if ( $indexed ) {
- $show = 0;
- } else {
- $show = 1;
- }
- } else {
- $show = 1;
- }
-
- if ( !$show ) {
- printf(STDERR "Not showing %s\n", $filename);
- unlink("list.tmp");
- open(TMP, "> list.tmp");
- $in_image = 0;
- next;
- }
-
- # Example of how to do "basename" and "prefix":
- # $filename = "images-old/".basename($filename);
-
- my $ev;
- my $evr;
- if ( $event eq "" ) {
- $ev = "";
- $evr = "";
- } else {
- $ev = " --event=".$event;
- $evr = ", event ".$event;
- }
-
- $n_seen++;
- if ( $n_seen > $skip ) {
-
- my $statbuf = stat($filename);
- if ( not $statbuf ) {
- printf("Couldn't stat image file '%s' - does it exist?\n",
- $filename);
- exit;
- }
- my $image_mtime = $statbuf->mtime;
- if ( $image_mtime > $stream_mtime ) {
- printf(STDERR "WARNING: Image file is newer than stream\n");
- }
-
- printf(STDERR "Viewing %s%s\n", $filename, $evr);
- system("hdfsee ".$filename.$ev.
- " --peak-overlay=list.tmp ".$args);
- if ( $? != 0 ) { exit; }
- } else {
- printf(STDERR "Skipping %s%s\n", $filename, $evr);
- }
-
- unlink("list.tmp");
- open(TMP, "> list.tmp");
- $in_image = 0;
- $event = "";
-
- }
-
-}
diff --git a/scripts/display-hdf5 b/scripts/display-hdf5
new file mode 100755
index 00000000..f65da9e4
--- /dev/null
+++ b/scripts/display-hdf5
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+
+import h5py
+import sys
+import matplotlib.pyplot as plt
+
+if len(sys.argv) != 3:
+ print("Syntax: {} file.h5 /data/location\n".format(sys.argv[0]))
+ sys.exit(1)
+
+fh = h5py.File(sys.argv[1], 'r')
+dataset = fh[sys.argv[2]]
+
+show = plt.figure()
+plt.imshow(dataset)
+plt.title("{} {}".format(sys.argv[1], sys.argv[2]))
+plt.show()
+
+fh.close()
diff --git a/scripts/make-csplit b/scripts/make-csplit
new file mode 100755
index 00000000..0f289056
--- /dev/null
+++ b/scripts/make-csplit
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Create custom split file for partialator, based on pulse sequence
+#
+# Copyright © 2020 Deutsches Elektronen-Synchrotron DESY,
+# a research centre of the Helmholtz Association.
+#
+# Author:
+# 2020 Thomas White <taw@physics.org>
+
+import sys
+
+f = open(sys.argv[1])
+
+fn = None
+ev = None
+pulseid = None
+
+def dataset(pulse):
+ # Divide 8 because we are at 0.5 MHz instead of 4 MHz
+ # Pulse sequence is light-dark1-dark2-dark3
+ if (pulse/8) % 4 == 0: return 'light'
+ if (pulse/8) % 4 == 1: return 'dark1'
+ if (pulse/8) % 4 == 2: return 'dark2'
+ if (pulse/8) % 4 == 3: return 'dark3'
+
+while True:
+ fline = f.readline()
+ if not fline:
+ break
+ if fline.find("Image filename: ") != -1:
+ if not fn == None:
+ print("Duplicate filename {}".format(fn), file=sys.stderr)
+ fn = fline.split(': ')[1].split(' ')[0].rstrip("\r\n")
+ if fline.find("Event: ") != -1:
+ if not ev == None:
+ print("Duplicate event ID {}".format(ev), file=sys.stderr)
+ ev = fline.split(': ')[1].split(' ')[0].rstrip("\r\n")
+ if fline.find("hdf5/instrument/pulseID = ") != -1:
+ if not pulseid == None:
+ print("Duplicate pulse ID {}".format(pulseid), file=sys.stderr)
+ pulseid = int(fline.split(' = ')[1].split(' ')[0].rstrip("\r\n"))
+ if fline.find("Begin chunk") != -1:
+ fn = None
+ ev = None
+ pulseid = None
+ if fline.find("End chunk") != -1:
+ if (fn == None) or (ev == None) or (pulseid == None):
+ print('Incomplete chunk! {} {} {}'.format(fn, ev, pulseid), file=sys.stderr)
+ else:
+ if pulseid == 0:
+ print("Zero pulse ID for {} {}".format(fn, ev), file=sys.stderr)
+ else:
+ print('{} {} {}'.format(fn, ev, dataset(pulseid)))
+
+
+f.close()
diff --git a/scripts/random-image b/scripts/random-image
deleted file mode 100755
index cabd1e73..00000000
--- a/scripts/random-image
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-
-FILE=$1
-TEMPFILE=`mktemp $1.XXXXXX`
-
-trap "rm -f $TEMPFILE" EXIT
-sort -R $FILE > $TEMPFILE
-
-for FILENAME in `cat $TEMPFILE`; do
-
- echo $FILENAME
- hdfsee --int-boost=10 ${2}${FILENAME}
-
-done
diff --git a/scripts/sequence-image b/scripts/sequence-image
deleted file mode 100755
index 196cdc7e..00000000
--- a/scripts/sequence-image
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-for FILENAME in `cat $1`; do
-
- ~/crystfel/src/hdfsee $2$FILENAME --binning=4 \
- --int-boost=20 --filter-noise
-
-done
diff --git a/src/ambigator.c b/src/ambigator.c
index 800c05de..298002a7 100644
--- a/src/ambigator.c
+++ b/src/ambigator.c
@@ -3,12 +3,12 @@
*
* Resolve indexing ambiguities
*
- * Copyright © 2014-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2014-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2014 Wolfgang Brehm
*
* Authors:
- * 2014-2016 Thomas White <taw@physics.org>
+ * 2014-2020 Thomas White <taw@physics.org>
* 2014 Wolfgang Brehm <wolfgang.brehm@gmail.com>
*
* This file is part of CrystFEL.
@@ -43,6 +43,7 @@
#include <gsl/gsl_rng.h>
#include <gsl/gsl_permutation.h>
#include <gsl/gsl_randist.h>
+#include <hdf5.h>
#include <image.h>
#include <utils.h>
@@ -54,6 +55,8 @@
#include <cell-utils.h>
#include <thread-pool.h>
+#include "version.h"
+
static void show_help(const char *s)
{
@@ -370,7 +373,7 @@ struct cc_list
};
-struct queue_args
+struct ambigator_queue_args
{
int n_started;
int n_finished;
@@ -405,7 +408,7 @@ struct cc_job
static void *get_task(void *vp)
{
- struct queue_args *qargs = vp;
+ struct ambigator_queue_args *qargs = vp;
struct cc_job *job;
if ( qargs->n_started == qargs->n_to_do ) return NULL;
@@ -428,7 +431,7 @@ static void *get_task(void *vp)
static void final(void *qp, void *wp)
{
- struct queue_args *qargs = qp;
+ struct ambigator_queue_args *qargs = qp;
struct cc_job *job = wp;
qargs->mean_nac += job->mean_nac;
@@ -560,7 +563,7 @@ static struct cc_list *calc_ccs(struct flist **crystals, int n_crystals,
float *pmean_nac, int nthreads)
{
struct cc_list *ccs;
- struct queue_args qargs;
+ struct ambigator_queue_args qargs;
int i;
assert(n_crystals >= ncorr);
@@ -764,7 +767,8 @@ static void write_reindexed_stream(const char *infile, const char *outfile,
done = 1;
/* Add our own header */
- fprintf(ofh, "Re-indexed by ambigator "CRYSTFEL_VERSIONSTRING"\n");
+ fprintf(ofh, "Re-indexed by ambigator %s\n",
+ crystfel_version_string());
if ( argc > 0 ) {
for ( i=0; i<argc; i++ ) {
if ( i > 0 ) fprintf(ofh, " ");
@@ -873,10 +877,10 @@ static void write_reindexed_stream(const char *infile, const char *outfile,
}
- /* Not a bug: REFLECTION_START_MARKER gets passed through */
+ /* Not a bug: STREAM_REFLECTION_START_MARKER gets passed through */
if ( !d ) fputs(line, ofh);
- if ( strcmp(line, REFLECTION_START_MARKER"\n") == 0 ) {
+ if ( strcmp(line, STREAM_REFLECTION_START_MARKER"\n") == 0 ) {
reindex_reflections(fh, ofh, assignments[i++], amb);
}
@@ -1093,8 +1097,10 @@ int main(int argc, char *argv[])
return 0;
case 10 :
- printf("CrystFEL: " CRYSTFEL_VERSIONSTRING "\n");
- printf(CRYSTFEL_BOILERPLATE"\n");
+ printf("CrystFEL: %s\n",
+ crystfel_version_string());
+ printf("%s\n",
+ crystfel_licence_string());
return 0;
case 'o' :
@@ -1238,38 +1244,33 @@ int main(int argc, char *argv[])
}
infile = argv[optind++];
- st = open_stream_for_read(infile);
+ st = stream_open_for_read(infile);
if ( st == NULL ) {
ERROR("Failed to open input stream '%s'\n", infile);
return 1;
}
-
crystals = NULL;
n_crystals = 0;
max_crystals = 0;
n_chunks = 0;
do {
- struct image cur;
+ struct image *image;
int i;
- cur.det = NULL;
-
- if ( read_chunk_2(st, &cur, STREAM_READ_UNITCELL
- | STREAM_READ_REFLECTIONS) != 0 ) {
- break;
- }
+ image = stream_read_chunk(st, STREAM_REFLECTIONS);
+ if ( image == NULL ) break;
- image_feature_list_free(cur.features);
+ image_feature_list_free(image->features);
- for ( i=0; i<cur.n_crystals; i++ ) {
+ for ( i=0; i<image->n_crystals; i++ ) {
Crystal *cr;
RefList *list;
UnitCell *cell;
- cr = cur.crystals[i];
+ cr = image->crystals[i];
cell = crystal_get_cell(cr);
if ( n_crystals == max_crystals ) {
@@ -1311,7 +1312,7 @@ int main(int argc, char *argv[])
} while ( 1 );
fprintf(stderr, "\n");
- close_stream(st);
+ stream_close(st);
assignments = malloc(n_crystals*sizeof(int));
if ( assignments == NULL ) {
diff --git a/src/cell_explorer.c b/src/cell_explorer.c
index 4ae406ce..1f67ec56 100644
--- a/src/cell_explorer.c
+++ b/src/cell_explorer.c
@@ -3,11 +3,11 @@
*
* Examine cell parameter histograms
*
- * Copyright © 2014-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2014-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2014,2017 Thomas White <taw@physics.org>
+ * 2014-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -48,6 +48,7 @@
#include "cell-utils.h"
#include "multihistogram.h"
+#include "version.h"
static void show_help(const char *s)
@@ -1927,98 +1928,44 @@ static void indexing_method_list(CellWindow *w, GtkWidget *vbox)
}
-int main(int argc, char *argv[])
+static int add_stream(CellWindow *w, const char *stream_filename,
+ int *pmax_cells, int *pn_total_chunks)
{
- int c;
Stream *st;
- int max_cells = 0;
- char *stream_filename;
- GtkWidget *box, *vbox;
- char title[1024];
- char *bn;
- CellWindow w;
int n_chunks = 0;
- int i;
-
- /* Long options */
- const struct option longopts[] = {
- {"help", 0, NULL, 'h'},
- {"version", 0, NULL, 1 },
- {0, 0, NULL, 0}
- };
+ int n_cells = 0;
+ int max_cells = *pmax_cells;
- /* Short options */
- while ((c = getopt_long(argc, argv, "h",
- longopts, NULL)) != -1) {
-
- switch (c) {
-
- case 'h' :
- show_help(argv[0]);
- return 0;
-
- case 1 :
- printf("CrystFEL: " CRYSTFEL_VERSIONSTRING "\n");
- printf(CRYSTFEL_BOILERPLATE"\n");
- return 0;
-
- default :
- return 1;
-
- }
+ fprintf(stderr, "%s\r", stream_filename);
- }
-
- /* This isn't great, but necessary to make the command-line UI and file
- * formats consistent with the other programs, which all use the C
- * locale. Better would be to have all the programs call
- * setlocale(LC_ALL, "") and use the C locale temporarily when reading
- * or writing a stream, reflection file, geometry file etc. */
- gtk_disable_setlocale();
-
- gtk_init(&argc, &argv);
-
- if ( argc != (optind+1) ) {
- fprintf(stderr, "Please provide exactly one stream filename.\n");
- return 1;
- }
- stream_filename = strdup(argv[optind]);
- st = open_stream_for_read(stream_filename);
+ st = stream_open_for_read(stream_filename);
if ( st == NULL ) {
- fprintf(stderr, "Failed to open '%s'\n", stream_filename);
- return 1;
+ fprintf(stderr, "Failed to open '%s' (skipping)\n",
+ stream_filename);
+ return 0;
}
-
- gsl_set_error_handler_off();
-
- w.cells = NULL;
- w.indms = NULL;
- w.n_cells = 0;
do {
- struct image cur;
+ struct image *image;
int i;
- cur.det = NULL;
-
- if ( read_chunk_2(st, &cur, STREAM_READ_UNITCELL) != 0 ) {
- break;
- }
+ image = stream_read_chunk(st, 0);
+ if ( image == NULL ) break;
- for ( i=0; i<cur.n_crystals; i++ ) {
+ for ( i=0; i<image->n_crystals; i++ ) {
Crystal *cr;
- cr = cur.crystals[i];
+ cr = image->crystals[i];
- if ( w.n_cells == max_cells ) {
+ if ( w->n_cells == max_cells ) {
UnitCell **cells_new;
IndexingMethod *indms_new;
size_t nsz;
nsz = (max_cells+1024)*sizeof(UnitCell *);
- cells_new = realloc(w.cells, nsz);
+ cells_new = realloc(w->cells, nsz);
if ( cells_new == NULL ) {
fprintf(stderr, "Failed to allocate "
"memory for cells.\n");
@@ -2026,7 +1973,7 @@ int main(int argc, char *argv[])
}
nsz = (max_cells+1024)*sizeof(IndexingMethod);
- indms_new = realloc(w.indms, nsz);
+ indms_new = realloc(w->indms, nsz);
if ( indms_new == NULL ) {
fprintf(stderr, "Failed to allocate "
"memory for methods.\n");
@@ -2034,30 +1981,31 @@ int main(int argc, char *argv[])
}
max_cells += 1024;
- w.cells = cells_new;
- w.indms = indms_new;
+ *pmax_cells = max_cells;
+ w->cells = cells_new;
+ w->indms = indms_new;
}
- w.cells[w.n_cells] = crystal_get_cell(cr);
- if ( !right_handed(w.cells[w.n_cells]) ) {
+ w->cells[w->n_cells] = cell_new_from_cell(crystal_get_cell(cr));
+ if ( !right_handed(w->cells[w->n_cells]) ) {
ERROR("WARNING: Left-handed cell encountered\n");
}
- w.indms[w.n_cells] = cur.indexed_by;
- w.n_cells++;
-
- crystal_free(cr);
+ w->indms[w->n_cells] = image->indexed_by;
+ w->n_cells++;
+ n_cells++;
}
n_chunks++;
if ( n_chunks % 1000 == 0 ) {
- fprintf(stderr, "Loaded %i cells from %i chunks\r",
- w.n_cells, n_chunks);
+ fprintf(stderr, "%s: Loaded %i cells from %i chunks\r",
+ stream_filename, n_cells, n_chunks);
}
+ image_free(image);
+
} while ( 1 );
- fprintf(stderr, "Loaded %i cells from %i chunks\n", w.n_cells, n_chunks);
fprintf(stderr, "\n");
@@ -2072,7 +2020,88 @@ int main(int argc, char *argv[])
ERROR("To simplify matters, it's best to re-run indexamajig.\n");
ERROR("------------------\n");
}
- close_stream(st);
+
+ stream_close(st);
+
+ *pn_total_chunks += n_chunks;
+ return 0;
+}
+
+
+int main(int argc, char *argv[])
+{
+ int c;
+ int max_cells = 0;
+ int n_chunks = 0;
+ GtkWidget *box, *vbox;
+ char title[1024];
+ CellWindow w;
+ int i;
+ char *name_for_title;
+
+ /* Long options */
+ const struct option longopts[] = {
+ {"help", 0, NULL, 'h'},
+ {"version", 0, NULL, 1 },
+ {0, 0, NULL, 0}
+ };
+
+ /* Short options */
+ while ((c = getopt_long(argc, argv, "h",
+ longopts, NULL)) != -1) {
+
+ switch (c) {
+
+ case 'h' :
+ show_help(argv[0]);
+ return 0;
+
+ case 1 :
+ printf("CrystFEL: %s\n",
+ crystfel_version_string());
+ printf("%s\n",
+ crystfel_licence_string());
+ return 0;
+
+ default :
+ return 1;
+
+ }
+
+ }
+
+ /* This isn't great, but necessary to make the command-line UI and file
+ * formats consistent with the other programs, which all use the C
+ * locale. Better would be to have all the programs call
+ * setlocale(LC_ALL, "") and use the C locale temporarily when reading
+ * or writing a stream, reflection file, geometry file etc. */
+ gtk_disable_setlocale();
+
+ gtk_init(&argc, &argv);
+
+ if ( argc < optind ) {
+ fprintf(stderr, "Please provide at least one stream filename.\n");
+ return 1;
+ }
+
+ name_for_title = safe_basename(argv[optind]);
+
+ gsl_set_error_handler_off();
+
+ w.cells = NULL;
+ w.indms = NULL;
+ w.n_cells = 0;
+
+ while ( optind < argc ) {
+ if ( add_stream(&w, argv[optind++],
+ &max_cells, &n_chunks) )
+ {
+ return 1;
+ }
+ }
+
+ fprintf(stderr, "Loaded %i cells from %i total chunks\n",
+ w.n_cells, n_chunks);
w.cols_on[0] = 1;
for ( i=1; i<8; i++ ) w.cols_on[i] = 2;
@@ -2096,9 +2125,8 @@ int main(int argc, char *argv[])
reset_axes(w.hist_ga);
w.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- bn = safe_basename(stream_filename);
- snprintf(title, 1023, "%s - Unit Cell Explorer", bn);
- free(bn);
+ snprintf(title, 1023, "%s - Unit Cell Explorer",
+ name_for_title);
gtk_window_set_title(GTK_WINDOW(w.window), title);
g_signal_connect(G_OBJECT(w.window), "destroy", G_CALLBACK(destroy_sig),
&w);
diff --git a/src/cell_tool.c b/src/cell_tool.c
index 8170b27b..493334b4 100644
--- a/src/cell_tool.c
+++ b/src/cell_tool.c
@@ -3,11 +3,11 @@
*
* Unit cell tool
*
- * Copyright © 2018-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2018-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2012-2018 Thomas White <taw@physics.org>
+ * 2012-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -39,10 +39,12 @@
#include <getopt.h>
#include <assert.h>
-#include "cell.h"
-#include "cell-utils.h"
-#include "reflist-utils.h"
-#include "reflist.h"
+#include <cell.h>
+#include <cell-utils.h>
+#include <reflist-utils.h>
+#include <reflist.h>
+
+#include "version.h"
static void show_help(const char *s)
@@ -54,6 +56,7 @@ static void show_help(const char *s)
" -h, --help Display this help message.\n"
" -p, --pdb=<file> Get unit cell from <file> (PDB or CrystFEL format).\n"
" -o <file> Output unit cell file.\n"
+" --version Print CrystFEL version number and exit.\n"
"\n"
" Actions:\n"
" --find-ambi Find indexing ambiguities for the cell.\n"
@@ -487,6 +490,7 @@ int main(int argc, char *argv[])
{"pdb", 1, NULL, 'p'},
{"tolerance", 1, NULL, 2},
{"output", 1, NULL, 'o'},
+ {"version", 0, NULL, 6},
/* Modes of operation */
{"find-ambi", 0, &mode, CT_FINDAMBI},
@@ -546,6 +550,13 @@ int main(int argc, char *argv[])
rmax = 1.0 / (highres/1e10);
break;
+ case 6 :
+ printf("CrystFEL: %s\n",
+ crystfel_version_string());
+ printf("%s\n",
+ crystfel_licence_string());
+ return 0;
+
case 0 :
break;
diff --git a/src/check_hkl.c b/src/check_hkl.c
index f36c9ed4..c4532f31 100644
--- a/src/check_hkl.c
+++ b/src/check_hkl.c
@@ -3,11 +3,11 @@
*
* Characterise reflection lists
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2017 Thomas White <taw@physics.org>
+ * 2010-2021 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -40,11 +40,14 @@
#include <gsl/gsl_fit.h>
#include <assert.h>
-#include "utils.h"
-#include "symmetry.h"
-#include "reflist.h"
-#include "reflist-utils.h"
-#include "cell-utils.h"
+#include <utils.h>
+#include <symmetry.h>
+#include <reflist.h>
+#include <reflist-utils.h>
+#include <cell-utils.h>
+#include <fom.h>
+
+#include "version.h"
static void show_help(const char *s)
@@ -388,67 +391,15 @@ static void plot_shells(RefList *list, UnitCell *cell, const SymOpList *sym,
double rmin_fix, double rmax_fix, int nshells,
const char *shell_file)
{
- unsigned long *possible;
- unsigned long *measurements;
- unsigned long *measured;
- unsigned long *snr_measured;
- double total_vol, vol_per_shell;
- double *rmins;
- double *rmaxs;
- double *snr;
- double *mean;
- double *var;
double rmin, rmax;
- signed int h, k, l;
int i;
FILE *fh;
- double snr_total = 0;
- unsigned long nrefl = 0;
- unsigned long nmeastot = 0;
- unsigned long nout = 0;
- unsigned long possible_tot = 0;
- unsigned long nsilly = 0;
- Reflection *refl;
- RefListIterator *iter;
- RefList *counted;
- int hmax, kmax, lmax;
- double ax, ay, az;
- double bx, by, bz;
- double cx, cy, cz;
-
- possible = malloc(nshells*sizeof(unsigned long));
- measurements = malloc(nshells*sizeof(unsigned long));
- measured = malloc(nshells*sizeof(unsigned long));
- snr_measured = malloc(nshells*sizeof(unsigned long));
- if ( (possible == NULL) || (measurements == NULL)
- || (measured == NULL) || (snr_measured == NULL) ) {
- ERROR("Couldn't allocate memory.\n");
- free(possible);
- free(measurements);
- free(measured);
- free(snr_measured);
- return;
- }
-
- rmins = malloc(nshells*sizeof(double));
- rmaxs = malloc(nshells*sizeof(double));
- snr = malloc(nshells*sizeof(double));
- mean = malloc(nshells*sizeof(double));
- var = malloc(nshells*sizeof(double));
- if ( (rmins == NULL) || (rmaxs == NULL) || (snr == NULL)
- || (mean == NULL) || (var == NULL) ) {
- ERROR("Couldn't allocate memory.\n");
- free(possible);
- free(measurements);
- free(measured);
- free(snr_measured);
- free(rmins);
- free(rmaxs);
- free(snr);
- free(mean);
- free(var);
- return;
- }
+ struct fom_shells *shells;
+ struct fom_context *nmeas_ctx;
+ struct fom_context *red_ctx;
+ struct fom_context *snr_ctx;
+ struct fom_context *mean_ctx;
+ struct fom_context *compl_ctx;
fh = fopen(shell_file, "w");
if ( fh == NULL ) {
@@ -456,224 +407,69 @@ static void plot_shells(RefList *list, UnitCell *cell, const SymOpList *sym,
return;
}
- for ( i=0; i<nshells; i++ ) {
- possible[i] = 0;
- measured[i] = 0;
- snr_measured[i] = 0;
- measurements[i] = 0;
- snr[i] = 0;
- var[i] = 0;
- mean[i] = 0;
- }
-
resolution_limits(list, cell, &rmin, &rmax);
STATUS("1/d goes from %f to %f nm^-1\n", rmin/1e9, rmax/1e9);
- /* Widen the range just a little bit */
- rmin -= 0.001e9;
- rmax += 0.001e9;
-
/* Fixed resolution shells if needed */
if ( rmin_fix > 0.0 ) rmin = rmin_fix;
if ( rmax_fix > 0.0 ) rmax = rmax_fix;
- total_vol = pow(rmax, 3.0) - pow(rmin, 3.0);
- vol_per_shell = total_vol / nshells;
- rmins[0] = rmin;
- for ( i=1; i<nshells; i++ ) {
-
- double r;
-
- r = vol_per_shell + pow(rmins[i-1], 3.0);
- r = pow(r, 1.0/3.0);
-
- /* Shells of constant volume */
- rmaxs[i-1] = r;
- rmins[i] = r;
- }
- rmaxs[nshells-1] = rmax;
-
- /* Count the number of reflections possible in each shell */
- counted = reflist_new();
- cell_get_cartesian(cell, &ax, &ay, &az,
- &bx, &by, &bz,
- &cx, &cy, &cz);
- hmax = rmax * modulus(ax, ay, az);
- kmax = rmax * modulus(bx, by, bz);
- lmax = rmax * modulus(cx, cy, cz);
- for ( h=-hmax; h<=hmax; h++ ) {
- for ( k=-kmax; k<=kmax; k++ ) {
- for ( l=-lmax; l<=lmax; l++ ) {
-
- double d;
- signed int hs, ks, ls;
- int bin;
-
- get_asymm(sym, h, k, l, &hs, &ks, &ls);
- d = 2.0 * resolution(cell, hs, ks, ls);
-
- if ( forbidden_reflection(cell, h, k, l) ) continue;
-
- bin = -1;
- for ( i=0; i<nshells; i++ ) {
- if ( (d>rmins[i]) && (d<=rmaxs[i]) ) {
- bin = i;
- break;
- }
- }
- if ( bin == -1 ) continue;
-
- if ( find_refl(counted, hs, ks, ls) != NULL ) continue;
- add_refl(counted, hs, ks, ls);
-
- possible[bin]++;
- possible_tot++;
-
- }
- }
- }
- reflist_free(counted);
-
- /* Calculate means */
- for ( refl = first_refl(list, &iter);
- refl != NULL;
- refl = next_refl(refl, iter) )
- {
- signed int h, k, l, hs, ks, ls;
- double d, val, esd;
- int bin;
- int j;
-
- get_indices(refl, &h, &k, &l);
- if ( forbidden_reflection(cell, h, k, l) ) continue;
-
- get_asymm(sym, h, k, l, &hs, &ks, &ls);
- d = resolution(cell, hs, ks, ls) * 2.0;
- val = get_intensity(refl);
- esd = get_esd_intensity(refl);
-
- bin = -1;
- for ( j=0; j<nshells; j++ ) {
- if ( (d>rmins[j]) && (d<=rmaxs[j]) ) {
- bin = j;
- break;
- }
- }
- if ( bin == -1 ) continue;
-
- measured[bin]++;
- mean[bin] += get_intensity(refl);
-
- if ( !isfinite(val/esd) ) nsilly++;
-
- }
-
- for ( i=0; i<nshells; i++ ) {
- mean[i] /= (double)measured[i];
- }
-
- /* Characterise the data set */
- for ( refl = first_refl(list, &iter);
- refl != NULL;
- refl = next_refl(refl, iter) )
- {
- signed int h, k, l;
- double d;
- int bin;
- int j;
- double val, esd;
-
- get_indices(refl, &h, &k, &l);
- if ( forbidden_reflection(cell, h, k, l) ) continue;
-
- d = resolution(cell, h, k, l) * 2.0;
- val = get_intensity(refl);
- esd = get_esd_intensity(refl);
-
- bin = -1;
- for ( j=0; j<nshells; j++ ) {
- if ( (d>rmins[j]) && (d<=rmaxs[j]) ) {
- bin = j;
- break;
- }
- }
- if ( bin == -1 ) {
- nout++;
- continue;
- }
-
- /* measured[bin] was done earlier */
- measurements[bin] += get_redundancy(refl);
-
- if ( isfinite(val/esd) ) {
- snr[bin] += val / esd;
- snr_total += val / esd;
- snr_measured[bin]++;
- } else {
- nsilly++;
- }
-
- nrefl++;
- nmeastot += get_redundancy(refl);
-
- var[bin] += pow(val-mean[bin], 2.0);
-
- }
+ shells = fom_make_resolution_shells(rmin, rmax, nshells);
STATUS("Overall values within specified resolution range:\n");
- STATUS("%li measurements in total.\n", nmeastot);
- STATUS("%li reflections in total.\n", nrefl);
- STATUS("%li reflections possible.\n", possible_tot);
- STATUS("Overall <snr> = %f\n", snr_total/(double)nrefl);
- STATUS("Overall redundancy = %f measurements/unique reflection\n",
- nmeastot/(double)nrefl);
- STATUS("Overall completeness = %f %%\n", 100.0*nrefl/(double)possible_tot);
- if ( nout ) {
- STATUS("WARNING; %li reflections outside resolution range.\n",
- nout);
- }
-
- if ( nsilly ) {
- STATUS("WARNING; %li reflections had infinite or invalid values"
- " of I/sigma(I).\n", nsilly);
- }
+ nmeas_ctx = fom_calculate(list, NULL, cell, shells,
+ FOM_NUM_MEASUREMENTS, 0, sym);
+ red_ctx = fom_calculate(list, NULL, cell, shells,
+ FOM_REDUNDANCY, 0, sym);
+ snr_ctx = fom_calculate(list, NULL, cell, shells,
+ FOM_SNR, 0, sym);
+ mean_ctx = fom_calculate(list, NULL, cell, shells,
+ FOM_MEAN_INTENSITY, 0, sym);
+ compl_ctx = fom_calculate(list, NULL, cell, shells,
+ FOM_COMPLETENESS, 0, sym);
+
+ STATUS("%.0f measurements in total.\n",
+ fom_overall_value(nmeas_ctx));
+ STATUS("%li reflections in total.\n",
+ fom_overall_num_reflections(compl_ctx));
+ STATUS("%li reflections possible.\n",
+ fom_overall_num_possible(compl_ctx));
+ STATUS("Overall <snr> = %f\n", fom_overall_value(snr_ctx));
+ STATUS("Overall redundancy = %f measurements/unique reflection\n",
+ fom_overall_value(red_ctx));
+ STATUS("Overall completeness = %f %%\n",
+ 100.0*fom_overall_value(compl_ctx));
fprintf(fh, "Center 1/nm # refs Possible Compl "
- "Meas Red SNR Std dev Mean d(A) "
+ "Meas Red SNR Mean I d(A) "
"Min 1/nm Max 1/nm\n");
for ( i=0; i<nshells; i++ ) {
- double cen;
- cen = rmins[i] + (rmaxs[i] - rmins[i])/2.0;
- fprintf(fh, "%10.3f %8li %8li %6.2f %10li %5.1f"
- " %5.2f %10.2f %10.2f %8.2f %10.3f %10.3f\n",
- cen*1.0e-9,
- measured[i],
- possible[i],
- 100.0*(double)measured[i]/possible[i],
- measurements[i],
- (double)measurements[i]/measured[i],
- snr[i]/(double)snr_measured[i],
- sqrt(var[i]/measured[i]),
- mean[i], (1.0/cen)*1e10,
- rmins[i]*1.0e-9, rmaxs[i]*1.0e-9);
+ long int measured, possible;
+
+ measured = fom_shell_num_reflections(compl_ctx, i);
+ possible = fom_shell_num_possible(compl_ctx, i);
+
+ fprintf(fh, "%10.3f %8li %8li %6.2f %10.0f %5.1f"
+ " %5.2f %10.2f %8.2f %10.3f %10.3f\n",
+ fom_shell_centre(shells, i)*1.0e-9,
+ measured,
+ possible,
+ 100.0*fom_shell_value(compl_ctx, i),
+ fom_shell_value(nmeas_ctx, i),
+ fom_shell_value(red_ctx, i),
+ fom_shell_value(snr_ctx, i),
+ fom_shell_value(mean_ctx, i),
+ (1.0/fom_shell_centre(shells, i))*1e10,
+ shells->rmins[i]*1.0e-9,
+ shells->rmaxs[i]*1.0e-9);
}
fclose(fh);
STATUS("Resolution shell information written to %s.\n", shell_file);
-
- free(possible);
- free(measurements);
- free(measured);
- free(snr_measured);
- free(rmins);
- free(rmaxs);
- free(snr);
- free(mean);
- free(var);
}
@@ -709,10 +505,7 @@ int main(int argc, char *argv[])
SymOpList *sym;
RefList *raw_list;
RefList *list;
- Reflection *refl;
- RefListIterator *iter;
char *cellfile = NULL;
- int rej = 0;
float rmin_fix = -1.0;
float rmax_fix = -1.0;
float sigma_cutoff = -INFINITY;
@@ -723,9 +516,8 @@ int main(int argc, char *argv[])
int ltest = 0;
int ignorenegs = 0;
int zeronegs = 0;
- int nneg = 0;
- int nres = 0;
float highres, lowres;
+ struct fom_rejections rej;
/* Long options */
const struct option longopts[] = {
@@ -761,8 +553,10 @@ int main(int argc, char *argv[])
return 0;
case 9 :
- printf("CrystFEL: " CRYSTFEL_VERSIONSTRING "\n");
- printf(CRYSTFEL_BOILERPLATE"\n");
+ printf("CrystFEL: %s\n",
+ crystfel_version_string());
+ printf("%s\n",
+ crystfel_licence_string());
return 0;
case 'y' :
@@ -901,74 +695,32 @@ int main(int argc, char *argv[])
}
/* Reject some reflections */
- list = reflist_new();
- for ( refl = first_refl(raw_list, &iter);
- refl != NULL;
- refl = next_refl(refl, iter) ) {
-
- signed int h, k, l;
- double val, sig;
- int ig = 0;
- Reflection *new;
-
- get_indices(refl, &h, &k, &l);
+ rej = fom_select_reflections(raw_list, &list, cell, sym,
+ rmin_fix, rmax_fix, sigma_cutoff,
+ ignorenegs, zeronegs, 0);
- val = get_intensity(refl);
- sig = get_esd_intensity(refl);
-
- if ( val < sigma_cutoff * sig ) {
- rej++;
- ig = 1;
- }
-
- if ( ignorenegs && (val < 0.0) ) {
- nneg++;
- ig = 1;
- }
-
- if ( zeronegs && (val < 0.0) ) {
- set_intensity(refl, 0.0);
- nneg++;
- }
-
- if ( rmin_fix > 0.0 ) {
- double res = 2.0*resolution(cell, h, k, l);
- if ( res < rmin_fix ) {
- nres++;
- continue;
- }
- }
-
- if ( rmax_fix > 0.0 ) {
- double res = 2.0*resolution(cell, h, k, l);
- if ( res > rmax_fix ) {
- nres++;
- continue;
- }
- }
-
- if ( ig ) continue;
-
- new = add_refl(list, h, k, l);
- copy_data(new, refl);
-
- }
STATUS("Discarded %i reflections (out of %i) with I/sigma(I) < %f\n",
- rej, num_reflections(raw_list), sigma_cutoff);
+ rej.low_snr, num_reflections(raw_list), sigma_cutoff);
reflist_free(raw_list);
- if ( ignorenegs && (nneg > 0) ) {
+ if ( rej.negative_deleted > 0 ) {
STATUS("Discarded %i reflections because they had negative "
- "intensities.\n", nneg);
+ "intensities.\n", rej.negative_deleted);
}
- if ( zeronegs && (nneg > 0) ) {
- STATUS("Set %i negative intensities to zero\n", nneg);
+ if ( rej.negative_zeroed > 0 ) {
+ STATUS("Set %i negative intensities to zero\n",
+ rej.negative_zeroed);
}
- if ( nres > 0 ) {
+ if ( rej.outside_resolution_range > 0 ) {
STATUS("%i reflections rejected because they were outside the "
- "resolution range.\n", nres);
+ "resolution range.\n", rej.outside_resolution_range);
+ }
+
+ if ( rej.nan_inf_value ) {
+ STATUS("WARNING: %i reflections had infinite or invalid values"
+ " of I or sigma(I).\n", rej.nan_inf_value);
}
if ( wilson ) {
diff --git a/src/cl-utils.c b/src/cl-utils.c
index 6aab85b2..ec449435 100644
--- a/src/cl-utils.c
+++ b/src/cl-utils.c
@@ -3,11 +3,11 @@
*
* OpenCL utility functions
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2019 Thomas White <taw@physics.org>
+ * 2010-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -34,6 +34,7 @@
#include <stdio.h>
#include <string.h>
+#define CL_TARGET_OPENCL_VERSION 220
#ifdef HAVE_CL_CL_H
#include <CL/cl.h>
#else
diff --git a/src/cl-utils.h b/src/cl-utils.h
index b0027d6d..d72ee6d5 100644
--- a/src/cl-utils.h
+++ b/src/cl-utils.h
@@ -3,11 +3,11 @@
*
* OpenCL utility functions
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2019 Thomas White <taw@physics.org>
+ * 2010-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -33,7 +33,7 @@
#include <config.h>
#endif
-
+#define CL_TARGET_OPENCL_VERSION 220
#ifdef HAVE_CL_CL_H
#include <CL/cl.h>
#else
diff --git a/src/compare_hkl.c b/src/compare_hkl.c
index 5b0c6aa8..f3f174d8 100644
--- a/src/compare_hkl.c
+++ b/src/compare_hkl.c
@@ -3,11 +3,11 @@
*
* Compare reflection lists
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2017 Thomas White <taw@physics.org>
+ * 2010-2021 Thomas White <taw@physics.org>
* 2013 Lorenzo Galli <lorenzo.galli@desy.de>
*
* This file is part of CrystFEL.
@@ -39,50 +39,14 @@
#include <unistd.h>
#include <getopt.h>
#include <assert.h>
-#include <gsl/gsl_errno.h>
-#include <gsl/gsl_statistics.h>
-#include <gsl/gsl_fit.h>
-#include "utils.h"
-#include "symmetry.h"
-#include "reflist-utils.h"
-#include "cell-utils.h"
+#include <utils.h>
+#include <symmetry.h>
+#include <reflist-utils.h>
+#include <cell-utils.h>
+#include <fom.h>
-enum fom
-{
- FOM_R1I,
- FOM_R1F,
- FOM_R2,
- FOM_RSPLIT,
- FOM_CC,
- FOM_CCSTAR,
- FOM_CCANO,
- FOM_CRDANO,
- FOM_RANO,
- FOM_RANORSPLIT,
- FOM_D1SIG,
- FOM_D2SIG
-};
-
-
-static enum fom get_fom(const char *s)
-{
- if ( strcasecmp(s, "r1i") == 0 ) return FOM_R1I;
- if ( strcasecmp(s, "r1f") == 0 ) return FOM_R1F;
- if ( strcasecmp(s, "r2") == 0 ) return FOM_R2;
- if ( strcasecmp(s, "rsplit") == 0 ) return FOM_RSPLIT;
- if ( strcasecmp(s, "cc") == 0 ) return FOM_CC;
- if ( strcasecmp(s, "ccstar") == 0 ) return FOM_CCSTAR;
- if ( strcasecmp(s, "ccano") == 0 ) return FOM_CCANO;
- if ( strcasecmp(s, "crdano") == 0 ) return FOM_CRDANO;
- if ( strcasecmp(s, "rano") == 0 ) return FOM_RANO;
- if ( strcasecmp(s, "rano/rsplit") == 0 ) return FOM_RANORSPLIT;
- if ( strcasecmp(s, "d1sig") == 0 ) return FOM_D1SIG;
- if ( strcasecmp(s, "d2sig") == 0 ) return FOM_D2SIG;
-
- ERROR("Unknown figure of merit '%s'.\n", s);
- exit(1);
-}
+#include "version.h"
static void show_help(const char *s)
@@ -110,7 +74,6 @@ static void show_help(const char *s)
" --rmax=<res> High resolution cutoff (1/d in m^-1).\n"
" --lowres=<n> Low resolution cutoff in (d in A).\n"
" --highres=<n> High resolution cutoff in (d in A).\n"
-" --intensity-shells Use shells of intensity instead of resolution.\n"
"\n"
" -h, --help Display this help message.\n"
" --version Print CrystFEL version number and exit.\n"
@@ -118,833 +81,102 @@ static void show_help(const char *s)
}
-struct fom_context
-{
- enum fom fom;
- int nshells;
- int *cts;
-
- /* For R-factors */
- double *num;
- double *den;
-
- /* For "double" R-factors */
- double *num2;
- double *den2;
-
- /* For CCs */
- double **vec1;
- double **vec2;
- int *n;
- int nmax;
-
- /* For "counting" things e.g. d1sig or d2sig */
- int *n_within;
-};
-
-
-static struct fom_context *init_fom(enum fom fom, int nmax, int nshells)
-{
- struct fom_context *fctx;
- int i;
-
- fctx = malloc(sizeof(struct fom_context));
- if ( fctx == NULL ) return NULL;
-
- fctx->fom = fom;
- fctx->nshells = nshells;
- fctx->cts = malloc(nshells*sizeof(int));
- for ( i=0; i<nshells; i++ ) {
- fctx->cts[i] = 0;
- }
-
- switch ( fctx->fom ) {
-
- case FOM_RANORSPLIT :
- fctx->num2 = malloc(nshells*sizeof(double));
- fctx->den2 = malloc(nshells*sizeof(double));
- if ( (fctx->num2 == NULL) || (fctx->den2 == NULL) ) return NULL;
- for ( i=0; i<nshells; i++ ) {
- fctx->num2[i] = 0.0;
- fctx->den2[i] = 0.0;
- }
- /* Intentional fall-through (no break) */
-
- case FOM_R1I :
- case FOM_R1F :
- case FOM_R2 :
- case FOM_RSPLIT :
- case FOM_RANO :
- fctx->num = malloc(nshells*sizeof(double));
- fctx->den = malloc(nshells*sizeof(double));
- if ( (fctx->num == NULL) || (fctx->den == NULL) ) return NULL;
- for ( i=0; i<nshells; i++ ) {
- fctx->num[i] = 0.0;
- fctx->den[i] = 0.0;
- }
- break;
-
- case FOM_CC :
- case FOM_CCSTAR :
- case FOM_CCANO :
- case FOM_CRDANO :
- fctx->vec1 = malloc(nshells*sizeof(double *));
- fctx->vec2 = malloc(nshells*sizeof(double *));
- if ( (fctx->vec1 == NULL) || (fctx->vec2 == NULL) ) return NULL;
- for ( i=0; i<nshells; i++ ) {
- fctx->vec1[i] = malloc(nmax*sizeof(double));
- if ( fctx->vec1[i] == NULL ) return NULL;
- fctx->vec2[i] = malloc(nmax*sizeof(double));
- if ( fctx->vec2[i] == NULL ) return NULL;
- fctx->n = malloc(nshells*sizeof(int));
- if ( fctx->n == NULL ) return NULL;
- }
- for ( i=0; i<nshells; i++ ) {
- fctx->n[i] = 0;
- }
- fctx->nmax = nmax;
- break;
-
- case FOM_D1SIG :
- case FOM_D2SIG :
- fctx->n_within = malloc(nshells*sizeof(int));
- if ( fctx->n_within == NULL ) return NULL;
- for ( i=0; i<nshells; i++ ) {
- fctx->n_within[i] = 0;
- }
- break;
-
- }
-
- return fctx;
-}
-
-
-static void add_to_fom(struct fom_context *fctx, double i1, double i2,
- double i1bij, double i2bij, double sig1, double sig2,
- int bin)
-{
- double f1, f2;
- double im, imbij;
-
- fctx->cts[bin]++;
-
- /* Negative intensities have already been weeded out. */
- f1 = sqrt(i1);
- f2 = sqrt(i2);
-
- switch ( fctx->fom ) {
-
- case FOM_R1I :
- fctx->num[bin] += fabs(i1 - i2);
- fctx->den[bin] += i1;
- break;
-
- case FOM_R1F :
- fctx->num[bin] += fabs(f1 - f2);
- fctx->den[bin] += f1;
- break;
-
- case FOM_R2 :
- fctx->num[bin] += pow(i1 - i2, 2.0);
- fctx->den[bin] += pow(i1, 2.0);
- break;
-
- case FOM_RSPLIT :
- fctx->num[bin] += fabs(i1 - i2);
- fctx->den[bin] += i1 + i2;
- break;
-
- case FOM_CC :
- case FOM_CCSTAR :
- assert(fctx->n[bin] < fctx->nmax);
- fctx->vec1[bin][fctx->n[bin]] = i1;
- fctx->vec2[bin][fctx->n[bin]] = i2;
- fctx->n[bin]++;
- break;
-
- case FOM_CCANO :
- case FOM_CRDANO :
- assert(fctx->n[bin] < fctx->nmax);
- fctx->vec1[bin][fctx->n[bin]] = i1 - i1bij;
- fctx->vec2[bin][fctx->n[bin]] = i2 - i2bij;
- fctx->n[bin]++;
- break;
-
- case FOM_RANORSPLIT :
- fctx->num2[bin] += fabs(i1 - i2);
- fctx->den2[bin] += i1 + i2;
- /* Intentional fall-through (no break) */
-
- case FOM_RANO :
- im = (i1 + i2)/2.0;
- imbij = (i1bij + i2bij)/2.0;
- fctx->num[bin] += fabs(im - imbij);
- fctx->den[bin] += im + imbij;
- break;
-
- case FOM_D1SIG :
- if ( fabs(i1-i2) < sqrt(sig1*sig1 + sig2*sig2) ) {
- fctx->n_within[bin]++;
- }
- break;
-
- case FOM_D2SIG :
- if ( fabs(i1-i2) < 2.0*sqrt(sig1*sig1 + sig2*sig2) ) {
- fctx->n_within[bin]++;
- }
- break;
-
- }
-}
-
-
-static double fom_overall(struct fom_context *fctx)
-{
- double overall_num = INFINITY;
- double overall_den = 0.0;
- double overall_num2 = INFINITY;
- double overall_den2 = 0.0;
- int i;
- double *overall_vec1;
- double *overall_vec2;
- int overall_n;
- double *overall_along_diagonal;
- double *overall_perpend_diagonal;
- double variance_signal;
- double variance_error;
- double cc = INFINITY;
-
- switch ( fctx->fom ) {
-
- case FOM_R1I :
- case FOM_R1F :
- case FOM_R2 :
- case FOM_RSPLIT :
- case FOM_RANO :
- overall_num = 0.0;
- overall_den = 0.0;
- for ( i=0; i<fctx->nshells; i++ ) {
- overall_num += fctx->num[i];
- overall_den += fctx->den[i];
- }
- break;
-
- case FOM_RANORSPLIT :
- overall_num = 0.0;
- overall_den = 0.0;
- for ( i=0; i<fctx->nshells; i++ ) {
- overall_num += fctx->num[i];
- overall_den += fctx->den[i];
- }
- overall_num2 = 0.0;
- overall_den2 = 0.0;
- for ( i=0; i<fctx->nshells; i++ ) {
- overall_num2 += fctx->num2[i];
- overall_den2 += fctx->den2[i];
- }
- break;
-
- case FOM_CC :
- case FOM_CCSTAR :
- case FOM_CCANO :
- overall_vec1 = malloc(fctx->nmax*sizeof(double));
- overall_vec2 = malloc(fctx->nmax*sizeof(double));
- overall_n = 0;
- for ( i=0; i<fctx->nshells; i++ ) {
- int j;
- for ( j=0; j<fctx->n[i]; j++ ) {
- overall_vec1[overall_n] = fctx->vec1[i][j];
- overall_vec2[overall_n] = fctx->vec2[i][j];
- overall_n++;
- }
- }
- cc = gsl_stats_correlation(overall_vec1, 1, overall_vec2, 1,
- overall_n);
- free(overall_vec1);
- free(overall_vec2);
- break;
-
- case FOM_CRDANO :
- overall_along_diagonal = malloc(fctx->nmax*sizeof(double));
- overall_perpend_diagonal = malloc(fctx->nmax*sizeof(double));
- overall_n = 0;
- for ( i=0; i<fctx->nshells; i++ ) {
- int j;
- for ( j=0; j<fctx->n[i]; j++ ) {
- overall_along_diagonal[overall_n] =
- ( fctx->vec1[i][j] + fctx->vec2[i][j] )
- / sqrt(2.0);
- overall_perpend_diagonal[overall_n] =
- ( fctx->vec1[i][j] - fctx->vec2[i][j] )
- / sqrt(2.0);
- overall_n++;
- }
- }
- variance_signal = gsl_stats_variance_m(overall_along_diagonal,
- 1, overall_n, 0.0);
- variance_error = gsl_stats_variance_m(overall_perpend_diagonal,
- 1, overall_n, 0.0);
- cc = sqrt(variance_signal / variance_error );
-
- free(overall_along_diagonal);
- free(overall_perpend_diagonal);
- break;
-
- case FOM_D1SIG :
- case FOM_D2SIG :
- overall_num = 0.0;
- overall_den = 0.0;
- for ( i=0; i<fctx->nshells; i++ ) {
- overall_num += fctx->n_within[i];
- overall_den += fctx->cts[i];
- }
- break;
-
- }
-
- switch ( fctx->fom ) {
-
- case FOM_R1I :
- case FOM_R1F :
- return overall_num/overall_den;
-
- case FOM_R2 :
- return sqrt(overall_num/overall_den);
-
- case FOM_RSPLIT :
- return 2.0*(overall_num/overall_den) / sqrt(2.0);
-
- case FOM_CC :
- case FOM_CCANO :
- case FOM_CRDANO :
- return cc;
-
- case FOM_CCSTAR :
- return sqrt((2.0*cc)/(1.0+cc));
-
- case FOM_RANO :
- return 2.0*(overall_num/overall_den);
-
- case FOM_RANORSPLIT :
- return (2.0*(overall_num/overall_den)) /
- (2.0*(overall_num2/overall_den2) / sqrt(2.0));
-
- case FOM_D1SIG :
- case FOM_D2SIG :
- return overall_num/overall_den;
-
- }
-
- ERROR("This point is never reached.\n");
- abort();
-}
-
-
-static double fom_shell(struct fom_context *fctx, int i)
-{
- double cc;
- int j;
- double variance_signal;
- double variance_error;
- double *along_diagonal;
- double *perpend_diagonal;
-
- switch ( fctx->fom ) {
-
- case FOM_R1I :
- case FOM_R1F :
- return fctx->num[i]/fctx->den[i];
-
- case FOM_R2 :
- return sqrt(fctx->num[i]/fctx->den[i]);
-
- case FOM_RSPLIT :
- return 2.0*(fctx->num[i]/fctx->den[i]) / sqrt(2.0);
-
- case FOM_CC :
- case FOM_CCANO :
- return gsl_stats_correlation(fctx->vec1[i], 1, fctx->vec2[i], 1,
- fctx->n[i]);
-
- case FOM_CCSTAR :
- cc = gsl_stats_correlation(fctx->vec1[i], 1, fctx->vec2[i], 1,
- fctx->n[i]);
- return sqrt((2.0*cc)/(1.0+cc));
-
- case FOM_RANO :
- return 2.0 * fctx->num[i]/fctx->den[i];
-
- case FOM_RANORSPLIT :
- return (2.0*fctx->num[i]/fctx->den[i]) /
- (2.0*(fctx->num2[i]/fctx->den2[i]) / sqrt(2.0));
-
- case FOM_CRDANO :
- along_diagonal = malloc(fctx->n[i] * sizeof(double));
- perpend_diagonal = malloc(fctx->n[i] * sizeof(double));
- for ( j=0; j<fctx->n[i]; j++ ) {
- along_diagonal[j] = ( fctx->vec1[i][j] +
- fctx->vec2[i][j] ) / sqrt(2.0);
- perpend_diagonal[j] = ( fctx->vec1[i][j] -
- fctx->vec2[i][j] ) / sqrt(2.0);
- }
- variance_signal = gsl_stats_variance_m(along_diagonal, 1,
- fctx->n[i], 0.0);
- variance_error = gsl_stats_variance_m(perpend_diagonal, 1,
- fctx->n[i], 0.0);
- free(along_diagonal);
- free(perpend_diagonal);
- return sqrt(variance_signal / variance_error);
-
- case FOM_D1SIG :
- case FOM_D2SIG :
- return (double)fctx->n_within[i] / fctx->cts[i];
-
- }
-
- ERROR("This point is never reached.\n");
- abort();
-}
-
-
-struct shells
-{
- int config_intshells;
- int nshells;
- double *rmins;
- double *rmaxs;
-};
-
-
-static struct shells *set_intensity_shells(double min_I, double max_I,
- int nshells)
-{
- struct shells *s;
- int i;
-
- if ( min_I >= max_I ) {
- ERROR("Invalid intensity range.\n");
- return NULL;
- }
-
- /* Adjust minimum and maximum intensities to get the most densely
- * populated part of the reflections */
- max_I = min_I + (max_I-min_I)/5000.0;
-
- s = malloc(sizeof(struct shells));
- if ( s == NULL ) return NULL;
-
- s->rmins = malloc(nshells*sizeof(double));
- s->rmaxs = malloc(nshells*sizeof(double));
-
- if ( (s->rmins==NULL) || (s->rmaxs==NULL) ) {
- ERROR("Couldn't allocate memory for shells.\n");
- free(s);
- return NULL;
- }
-
- s->config_intshells = 1;
- s->nshells = nshells;
-
- for ( i=0; i<nshells; i++ ) {
-
- s->rmins[i] = min_I + i*(max_I - min_I)/nshells;;
- s->rmaxs[i] = min_I + (i+1)*(max_I - min_I)/nshells;;
-
- }
-
- return s;
-}
-
-
-static struct shells *set_resolution_shells(double rmin, double rmax,
- int nshells)
-{
- struct shells *s;
- double total_vol, vol_per_shell;
- int i;
-
- s = malloc(sizeof(struct shells));
- if ( s == NULL ) return NULL;
-
- s->rmins = malloc(nshells*sizeof(double));
- s->rmaxs = malloc(nshells*sizeof(double));
-
- if ( (s->rmins==NULL) || (s->rmaxs==NULL) ) {
- ERROR("Couldn't allocate memory for resolution shells.\n");
- free(s);
- return NULL;
- }
-
- s->config_intshells = 0;
- s->nshells = nshells;
-
- total_vol = pow(rmax, 3.0) - pow(rmin, 3.0);
- vol_per_shell = total_vol / nshells;
- s->rmins[0] = rmin;
- for ( i=1; i<nshells; i++ ) {
-
- double r;
-
- r = vol_per_shell + pow(s->rmins[i-1], 3.0);
- r = pow(r, 1.0/3.0);
-
- /* Shells of constant volume */
- s->rmaxs[i-1] = r;
- s->rmins[i] = r;
-
- }
- s->rmaxs[nshells-1] = rmax;
-
- return s;
-}
-
-
-static double shell_label(struct shells *s, int i)
-{
- if ( s->config_intshells ) {
- return (i+0.5) / s->nshells;
- } else {
- return s->rmins[i] + (s->rmaxs[i] - s->rmins[i])/2.0;
- }
-}
-
-
-static int get_bin(struct shells *s, Reflection *refl, UnitCell *cell)
-{
- if ( s->config_intshells ) {
-
- double intensity;
- int bin, j;
-
- intensity = get_intensity(refl);
-
- bin = -1;
- for ( j=0; j<s->nshells; j++ ) {
- if ( (intensity>s->rmins[j])
- && (intensity<=s->rmaxs[j]) )
- {
- bin = j;
- break;
- }
- }
-
- return bin;
-
-
- } else {
-
- double d;
- int bin, j;
- signed int h, k, l;
-
- get_indices(refl, &h, &k, &l);
- d = 2.0 * resolution(cell, h, k, l);
-
- bin = -1;
- for ( j=0; j<s->nshells; j++ ) {
- if ( (d>s->rmins[j]) && (d<=s->rmaxs[j]) ) {
- bin = j;
- break;
- }
- }
-
- /* Allow for slight rounding errors */
- if ( (bin == -1) && (d <= s->rmins[0]) ) bin = 0;
- if ( (bin == -1) && (d >= s->rmaxs[s->nshells-1]) ) bin = 0;
- assert(bin != -1);
-
- return bin;
-
- }
-}
-
-
-static int wilson_scale(RefList *list1, RefList *list2, UnitCell *cell)
+static enum fom_type fom_type_from_string(const char *s)
{
- Reflection *refl1;
- Reflection *refl2;
- RefListIterator *iter;
- int max_n = 256;
- int n = 0;
- double *x;
- double *y;
- int r;
- double G, B;
- double c0, c1, cov00, cov01, cov11, chisq;
-
- x = malloc(max_n*sizeof(double));
- y = malloc(max_n*sizeof(double));
- if ( (x==NULL) || (y==NULL) ) {
- ERROR("Failed to allocate memory for scaling.\n");
- return 1;
- }
-
- for ( refl1 = first_refl(list1, &iter);
- refl1 != NULL;
- refl1 = next_refl(refl1, iter) )
- {
- signed int h, k, l;
- double Ih1, Ih2;
- double res;
-
- get_indices(refl1, &h, &k, &l);
- res = resolution(cell, h, k, l);
-
- refl2 = find_refl(list2, h, k, l);
- assert(refl2 != NULL);
-
- Ih1 = get_intensity(refl1);
- Ih2 = get_intensity(refl2);
-
- if ( (Ih1 <= 0.0) || (Ih2 <= 0.0) ) continue;
- if ( isnan(Ih1) || isinf(Ih1) ) continue;
- if ( isnan(Ih2) || isinf(Ih2) ) continue;
-
- if ( n == max_n ) {
- max_n *= 2;
- x = realloc(x, max_n*sizeof(double));
- y = realloc(y, max_n*sizeof(double));
- if ( (x==NULL) || (y==NULL) ) {
- ERROR("Failed to allocate memory for scaling.\n");
- return 1;
- }
- }
-
- x[n] = res*res;
- y[n] = log(Ih1/Ih2);
- n++;
-
- }
-
- if ( n < 2 ) {
- ERROR("Not enough reflections for scaling\n");
- return 1;
- }
-
- r = gsl_fit_linear(x, 1, y, 1, n, &c0, &c1,
- &cov00, &cov01, &cov11, &chisq);
-
- if ( r ) {
- ERROR("Scaling failed.\n");
- return 1;
- }
-
- G = exp(c0);
- B = c1/2.0;
-
- STATUS("Relative scale factor = %f, relative B factor = %f A^2\n",
- G, B*1e20);
- STATUS("A scale factor greater than 1 means that the second reflection "
- "list is weaker than the first.\n");
- STATUS("A positive relative B factor means that the second reflection "
- "list falls off with resolution more quickly than the first.\n");
-
- free(x);
- free(y);
-
- /* Apply the scaling factor */
- for ( refl2 = first_refl(list2, &iter);
- refl2 != NULL;
- refl2 = next_refl(refl2, iter) )
- {
- signed int h, k, l;
- double res;
- double corr;
-
- get_indices(refl2, &h, &k, &l);
- res = resolution(cell, h, k, l);
-
- corr = G * exp(2.0*B*res*res);
- set_intensity(refl2, get_intensity(refl2)*corr);
- set_esd_intensity(refl2, get_esd_intensity(refl2)*corr);
+ if ( strcasecmp(s, "r1i") == 0 ) return FOM_R1I;
+ if ( strcasecmp(s, "r1f") == 0 ) return FOM_R1F;
+ if ( strcasecmp(s, "r2") == 0 ) return FOM_R2;
+ if ( strcasecmp(s, "rsplit") == 0 ) return FOM_RSPLIT;
+ if ( strcasecmp(s, "cc") == 0 ) return FOM_CC;
+ if ( strcasecmp(s, "ccstar") == 0 ) return FOM_CCSTAR;
+ if ( strcasecmp(s, "ccano") == 0 ) return FOM_CCANO;
+ if ( strcasecmp(s, "crdano") == 0 ) return FOM_CRDANO;
+ if ( strcasecmp(s, "rano") == 0 ) return FOM_RANO;
+ if ( strcasecmp(s, "rano/rsplit") == 0 ) return FOM_RANORSPLIT;
+ if ( strcasecmp(s, "d1sig") == 0 ) return FOM_D1SIG;
+ if ( strcasecmp(s, "d2sig") == 0 ) return FOM_D2SIG;
- }
- return 0;
+ ERROR("Unknown figure of merit '%s'.\n", s);
+ exit(1);
}
-
static void do_fom(RefList *list1, RefList *list2, UnitCell *cell,
- double rmin, double rmax, enum fom fom,
+ double rmin, double rmax, enum fom_type fom,
int config_unity, int nshells, const char *filename,
- int config_intshells, double min_I, double max_I,
SymOpList *sym)
{
- int i;
- Reflection *refl1;
- RefListIterator *iter;
- FILE *fh;
+ struct fom_shells *shells;
struct fom_context *fctx;
- struct shells *shells;
+ FILE *fh;
+ int i;
const char *t1, *t2;
- int n_out;
-
- fctx = init_fom(fom, num_reflections(list1), nshells);
-
- if ( fctx==NULL ) {
- ERROR("Couldn't allocate memory for resolution shells.\n");
- return;
- }
-
- if ( !config_unity && wilson_scale(list1, list2, cell) ) {
- ERROR("Error with scaling.\n");
- return;
- }
/* Calculate the bins */
- if ( config_intshells ) {
- shells = set_intensity_shells(min_I, max_I, nshells);
- } else {
- shells = set_resolution_shells(rmin, rmax, nshells);
- }
+ shells = fom_make_resolution_shells(rmin, rmax, nshells);
if ( shells == NULL ) {
ERROR("Failed to set up shells.\n");
return;
}
- for ( refl1 = first_refl(list1, &iter);
- refl1 != NULL;
- refl1 = next_refl(refl1, iter) )
- {
- Reflection *refl2;
- signed int h, k, l;
- set_flag(refl1, 0);
- get_indices(refl1, &h, &k, &l);
- refl2 = find_refl(list2, h, k, l);
- assert(refl2 != NULL);
- set_flag(refl2, 0);
- }
-
- n_out = 0;
- for ( refl1 = first_refl(list1, &iter);
- refl1 != NULL;
- refl1 = next_refl(refl1, iter) )
- {
- signed int h, k, l;
- int bin;
- double i1, i2;
- double i1bij, i2bij;
- double sig1, sig2;
- Reflection *refl2;
-
- get_indices(refl1, &h, &k, &l);
-
- refl2 = find_refl(list2, h, k, l);
- if ( refl2 == NULL ) continue;
-
- bin = get_bin(shells, refl1, cell);
- if ( bin == -1 ) {
- n_out++;
- continue;
- }
-
- i1 = get_intensity(refl1);
- i2 = get_intensity(refl2);
- sig1 = get_esd_intensity(refl1);
- sig2 = get_esd_intensity(refl2);
-
- if ( (fom == FOM_CCANO) || (fom == FOM_CRDANO)
- || (fom == FOM_RANO) || (fom == FOM_RANORSPLIT) )
- {
-
- Reflection *refl1_bij = NULL;
- Reflection *refl2_bij = NULL;
- signed int hb, kb, lb;
-
- if ( find_equiv_in_list(list1, -h, -k, -l, sym,
- &hb, &kb, &lb) )
- {
- refl1_bij = find_refl(list1, hb, kb, lb);
- }
-
- if ( find_equiv_in_list(list2, -h, -k, -l, sym,
- &hb, &kb, &lb) )
- {
- refl2_bij = find_refl(list2, hb, kb, lb);
- }
-
- /* Each reflection must only be counted once, whether
- * we are visiting it now as "normal" or "bij" */
- if ( get_flag(refl1) ) continue;
- assert(!get_flag(refl2));
- set_flag(refl1, 1);
- set_flag(refl1_bij, 1);
- set_flag(refl2, 1);
- set_flag(refl2_bij, 1);
-
- assert(refl1_bij != NULL);
- assert(refl2_bij != NULL);
-
- i1bij = get_intensity(refl1_bij);
- i2bij = get_intensity(refl2_bij);
-
- } else {
-
- /* Make it obvious if these get used by mistake */
- i1bij = +INFINITY;
- i2bij = +INFINITY;
-
- }
-
- add_to_fom(fctx, i1, i2, i1bij, i2bij, sig1, sig2, bin);
- }
- if ( n_out) {
- ERROR("WARNING: %i reflection pairs outside range.\n", n_out);
- }
+ fctx = fom_calculate(list1, list2, cell, shells, fom,
+ config_unity, sym);
switch ( fom ) {
case FOM_R1I :
- STATUS("Overall R1(I) = %.2f %%\n", 100.0*fom_overall(fctx));
+ STATUS("Overall R1(I) = %.2f %%\n", 100.0*fom_overall_value(fctx));
break;
case FOM_R1F :
- STATUS("Overall R1(F) = %.2f %%\n", 100.0*fom_overall(fctx));
+ STATUS("Overall R1(F) = %.2f %%\n", 100.0*fom_overall_value(fctx));
break;
case FOM_R2 :
- STATUS("Overall R(2) = %.2f %%\n", 100.0*fom_overall(fctx));
+ STATUS("Overall R(2) = %.2f %%\n", 100.0*fom_overall_value(fctx));
break;
case FOM_RSPLIT :
- STATUS("Overall Rsplit = %.2f %%\n", 100.0*fom_overall(fctx));
+ STATUS("Overall Rsplit = %.2f %%\n", 100.0*fom_overall_value(fctx));
break;
case FOM_CC :
- STATUS("Overall CC = %.7f\n", fom_overall(fctx));
+ STATUS("Overall CC = %.7f\n", fom_overall_value(fctx));
break;
case FOM_CCSTAR :
- STATUS("Overall CC* = %.7f\n", fom_overall(fctx));
+ STATUS("Overall CC* = %.7f\n", fom_overall_value(fctx));
break;
case FOM_CCANO :
- STATUS("Overall CCano = %.7f\n", fom_overall(fctx));
+ STATUS("Overall CCano = %.7f\n", fom_overall_value(fctx));
break;
case FOM_CRDANO :
- STATUS("Overall CRDano = %.7f\n", fom_overall(fctx));
+ STATUS("Overall CRDano = %.7f\n", fom_overall_value(fctx));
break;
case FOM_RANO :
- STATUS("Overall Rano = %.2f %%\n", 100.0*fom_overall(fctx));
+ STATUS("Overall Rano = %.2f %%\n", 100.0*fom_overall_value(fctx));
break;
case FOM_RANORSPLIT :
- STATUS("Overall Rano/Rsplit = %.7f\n", fom_overall(fctx));
+ STATUS("Overall Rano/Rsplit = %.7f\n", fom_overall_value(fctx));
break;
case FOM_D1SIG :
STATUS("Fraction of differences less than 1 sigma = %.7f %%\n",
- 100.0*fom_overall(fctx));
+ 100.0*fom_overall_value(fctx));
break;
case FOM_D2SIG :
STATUS("Fraction of differences less than 2 sigma = %.7f %%\n",
- 100.0*fom_overall(fctx));
+ 100.0*fom_overall_value(fctx));
break;
+ default :
+ ERROR("Unhandled figure of merit type\n");
+ break;
}
@@ -954,13 +186,8 @@ static void do_fom(RefList *list1, RefList *list2, UnitCell *cell,
return;
}
- if ( config_intshells ) {
- t1 = "Relative I ";
- t2 = "";
- } else {
- t1 = " 1/d centre";
- t2 = " d / A Min 1/nm Max 1/nm";
- }
+ t1 = " 1/d centre";
+ t2 = " d / A Min 1/nm Max 1/nm";
switch ( fom ) {
@@ -1012,80 +239,72 @@ static void do_fom(RefList *list1, RefList *list2, UnitCell *cell,
fprintf(fh, "%s D<2sigma/%% nref%s\n", t1, t2);
break;
+ default :
+ break;
+
}
for ( i=0; i<nshells; i++ ) {
double r, cen;
- cen = shell_label(shells, i);
- r = fom_shell(fctx, i);
+ cen = fom_shell_centre(shells, i);
+ r = fom_shell_value(fctx, i);
switch ( fom ) {
- case FOM_R1I :
- case FOM_R1F :
- case FOM_R2 :
- case FOM_RSPLIT :
- case FOM_RANO :
- if ( config_intshells ) {
- fprintf(fh, "%10.3f %10.2f %10i\n",
- cen, r*100.0, fctx->cts[i]);
- } else {
+ case FOM_R1I :
+ case FOM_R1F :
+ case FOM_R2 :
+ case FOM_RSPLIT :
+ case FOM_RANO :
fprintf(fh, "%10.3f %10.2f %10i %10.2f "
- "%10.3f %10.3f\n",
- cen*1.0e-9, r*100.0, fctx->cts[i],
+ "%10.3f %10.3f\n",
+ cen*1.0e-9, r*100.0,
+ fom_shell_num_reflections(fctx, i),
(1.0/cen)*1e10,
shells->rmins[i]*1.0e-9,
shells->rmaxs[i]*1.0e-9);
- }
- break;
+ break;
- case FOM_CC :
- case FOM_CCSTAR :
- case FOM_CCANO :
- case FOM_CRDANO :
- if ( config_intshells ) {
- fprintf(fh, "%10.3f %10.7f %10i\n",
- cen, r, fctx->cts[i]);
- } else {
+ case FOM_CC :
+ case FOM_CCSTAR :
+ case FOM_CCANO :
+ case FOM_CRDANO :
fprintf(fh, "%10.3f %10.7f %10i %10.2f "
- "%10.3f %10.3f\n",
- cen*1.0e-9, r, fctx->cts[i], (1.0/cen)*1e10,
+ "%10.3f %10.3f\n",
+ cen*1.0e-9, r,
+ fom_shell_num_reflections(fctx, i),
+ (1.0/cen)*1e10,
shells->rmins[i]*1.0e-9,
shells->rmaxs[i]*1.0e-9);
- }
- break;
+ break;
- case FOM_RANORSPLIT :
- if ( config_intshells ) {
- fprintf(fh, "%10.3f %10.7f %10i\n",
- cen, r, fctx->cts[i]);
- } else {
+ case FOM_RANORSPLIT :
fprintf(fh, "%10.3f %10.7f %10i %10.2f "
- "%10.3f %10.3f\n",
- cen*1.0e-9, r, fctx->cts[i], (1.0/cen)*1e10,
+ "%10.3f %10.3f\n",
+ cen*1.0e-9, r,
+ fom_shell_num_reflections(fctx, i),
+ (1.0/cen)*1e10,
shells->rmins[i]*1.0e-9,
shells->rmaxs[i]*1.0e-9);
- }
- break;
+ break;
- case FOM_D1SIG :
- case FOM_D2SIG :
- if ( config_intshells ) {
- fprintf(fh, "%10.3f %10.2f %10i\n",
- cen, r*100.0, fctx->cts[i]);
- } else {
+ case FOM_D1SIG :
+ case FOM_D2SIG :
fprintf(fh, "%10.3f %10.2f %10i %10.2f "
- "%10.3f %10.3f\n",
- cen*1.0e-9, r*100.0, fctx->cts[i],
+ "%10.3f %10.3f\n",
+ cen*1.0e-9, r*100.0,
+ fom_shell_num_reflections(fctx, i),
(1.0/cen)*1e10,
shells->rmins[i]*1.0e-9,
shells->rmaxs[i]*1.0e-9);
- }
- break;
+ break;
- }
+ default :
+ break;
+
+ }
}
@@ -1126,31 +345,27 @@ int main(int argc, char *argv[])
char *sym_str_fromfile1 = NULL;
char *sym_str_fromfile2 = NULL;
SymOpList *sym;
- int ncom, nrej, nmul, nneg, nres, nbij, ncen;
RefList *list1_acc;
RefList *list2_acc;
RefList *list1;
RefList *list2;
RefList *list1_raw;
RefList *list2_raw;
- enum fom fom = FOM_R1I;
+ enum fom_type fom = FOM_R1I;
char *cellfile = NULL;
float rmin_fix = -1.0;
float rmax_fix = -1.0;
double rmin, rmax;
- Reflection *refl1;
- RefListIterator *iter;
float sigma_cutoff = -INFINITY;
int config_ignorenegs = 0;
int config_zeronegs = 0;
int config_unity = 0;
- int config_intshells = 0;
int nshells = 10;
char *shell_file = NULL;
- double min_I = +INFINITY;
- double max_I = -INFINITY;
float highres, lowres;
int mul_cutoff = 0;
+ int anom;
+ struct fom_rejections rej;
/* Long options */
const struct option longopts[] = {
@@ -1169,7 +384,6 @@ int main(int argc, char *argv[])
{"min-measurements", 1, NULL, 11},
{"ignore-negs", 0, &config_ignorenegs, 1},
{"zero-negs", 0, &config_zeronegs, 1},
- {"intensity-shells", 0, &config_intshells, 1},
{0, 0, NULL, 0}
};
@@ -1185,8 +399,10 @@ int main(int argc, char *argv[])
return 0;
case 10 :
- printf("CrystFEL: " CRYSTFEL_VERSIONSTRING "\n");
- printf(CRYSTFEL_BOILERPLATE"\n");
+ printf("CrystFEL: %s\n",
+ crystfel_version_string());
+ printf("%s\n",
+ crystfel_licence_string());
return 0;
case 'y' :
@@ -1221,7 +437,7 @@ int main(int argc, char *argv[])
break;
case 4 :
- fom = get_fom(optarg);
+ fom = fom_type_from_string(optarg);
break;
case 5 :
@@ -1296,7 +512,7 @@ int main(int argc, char *argv[])
" intensities.\n");
ERROR("Please try again with --ignore-negs or"
" --zero-negs.\n");
- exit(1);
+ return 1;
case FOM_R2 :
case FOM_R1I :
@@ -1310,6 +526,10 @@ int main(int argc, char *argv[])
case FOM_D1SIG :
case FOM_D2SIG :
break;
+
+ default :
+ ERROR("Unhandled figure of merit!\n");
+ return 1;
}
}
@@ -1397,6 +617,10 @@ int main(int argc, char *argv[])
" try again using a non-centrosymmetric point"
" group for '-y'.\n");
return 1;
+
+ default :
+ ERROR("Unhandled figure of merit type!\n");
+ return 1;
}
}
@@ -1440,216 +664,60 @@ int main(int argc, char *argv[])
reflist_free(list1_raw);
reflist_free(list2_raw);
- /* Select reflections to be used */
- ncom = 0;
- nrej = 0;
- nmul = 0;
- nneg = 0;
- nres = 0;
- nbij = 0;
- ncen = 0;
- list1_acc = reflist_new();
- list2_acc = reflist_new();
- for ( refl1 = first_refl(list1, &iter);
- refl1 != NULL;
- refl1 = next_refl(refl1, iter) )
- {
- signed int h, k, l;
- double val1, val2;
- double esd1, esd2;
- int mul1, mul2;
- Reflection *refl2;
- Reflection *refl1_acc;
- Reflection *refl2_acc;
-
- get_indices(refl1, &h, &k, &l);
-
- refl2 = find_refl(list2, h, k, l);
- if ( refl2 == NULL ) continue;
-
- val1 = get_intensity(refl1);
- val2 = get_intensity(refl2);
-
- esd1 = get_esd_intensity(refl1);
- esd2 = get_esd_intensity(refl2);
-
- mul1 = get_redundancy(refl1);
- mul2 = get_redundancy(refl2);
-
- if ( (val1 < sigma_cutoff * esd1)
- || (val2 < sigma_cutoff * esd2) )
- {
- nrej++;
- continue;
- }
-
- if ( config_ignorenegs && ((val1 < 0.0) || (val2 < 0.0)) ) {
- nneg++;
- continue;
- }
-
- if ( (mul1 < mul_cutoff) || (mul2 < mul_cutoff) ) {
- nmul++;
- continue;
- }
-
- if ( config_zeronegs ) {
- int d = 0;
- if ( val1 < 0.0 ) {
- val1 = 0.0;
- d = 1;
- }
- if ( val2 < 0.0 ) {
- val2 = 0.0;
- d = 1;
- }
- if ( d ) nneg++;
- }
-
- if ( rmin_fix > 0.0 ) {
- double res = 2.0*resolution(cell, h, k, l);
- if ( res < rmin_fix ) {
- nres++;
- continue;
- }
- }
-
- if ( rmax_fix > 0.0 ) {
- double res = 2.0*resolution(cell, h, k, l);
- if ( res > rmax_fix ) {
- nres++;
- continue;
- }
- }
-
- refl1_acc = add_refl(list1_acc, h, k, l);
- copy_data(refl1_acc, refl1);
- set_intensity(refl1_acc, val1);
-
- refl2_acc = add_refl(list2_acc, h, k, l);
- copy_data(refl2_acc, refl2);
- set_intensity(refl2_acc, val2);
-
- if ( val1 > max_I ) max_I = val1;
- if ( val1 < min_I ) min_I = val1;
-
- ncom++;
-
- }
-
+ anom = ( (fom == FOM_CCANO) || (fom == FOM_CRDANO)
+ || (fom == FOM_RANO) || (fom == FOM_RANORSPLIT) );
+ rej = fom_select_reflection_pairs(list1, list2, &list1_acc, &list2_acc,
+ cell, sym,
+ anom, rmin_fix, rmax_fix, sigma_cutoff,
+ config_ignorenegs, config_zeronegs,
+ mul_cutoff);
reflist_free(list1);
reflist_free(list2);
- /* For anomalous figures of merit, we additionally require that we have
- * all the Bijvoet pairs after the above rejection tests */
- if ( (fom == FOM_CCANO) || (fom == FOM_CRDANO)
- || (fom == FOM_RANO) || (fom == FOM_RANORSPLIT) )
- {
- list1 = list1_acc;
- list2 = list2_acc;
- list1_acc = reflist_new();
- list2_acc = reflist_new();
-
- min_I = +INFINITY;
- max_I = -INFINITY;
- ncom = 0;
-
- for ( refl1 = first_refl(list1, &iter);
- refl1 != NULL;
- refl1 = next_refl(refl1, iter) )
- {
- Reflection *refl1_bij = NULL;
- Reflection *refl2_bij = NULL;
- signed int h, k, l;
- signed int hb, kb, lb;
- Reflection *refl1_acc;
- Reflection *refl2_acc;
- Reflection *refl2;
- double val1, val2;
-
- get_indices(refl1, &h, &k, &l);
-
- refl2 = find_refl(list2, h, k, l);
- assert(refl2 != NULL);
-
- val1 = get_intensity(refl1);
- val2 = get_intensity(refl2);
-
- if ( is_centric(h, k, l, sym) ) {
- ncen++;
- continue;
- }
-
- if ( find_equiv_in_list(list1, -h, -k, -l, sym,
- &hb, &kb, &lb) )
- {
- refl1_bij = find_refl(list1, hb, kb, lb);
- }
-
- if ( find_equiv_in_list(list2, -h, -k, -l, sym,
- &hb, &kb, &lb) )
- {
- refl2_bij = find_refl(list2, hb, kb, lb);
- }
-
- if ( (refl1_bij == NULL) || (refl2_bij == NULL) ) {
- nbij++;
- continue;
- }
-
- refl1_acc = add_refl(list1_acc, h, k, l);
- copy_data(refl1_acc, refl1);
- set_intensity(refl1_acc, val1);
-
- refl2_acc = add_refl(list2_acc, h, k, l);
- copy_data(refl2_acc, refl2);
- set_intensity(refl2_acc, val2);
-
- if ( val1 > max_I ) max_I = val1;
- if ( val1 < min_I ) min_I = val1;
-
- ncom++;
- }
- }
-
gsl_set_error_handler_off();
- if ( nrej > 0 ) {
+ if ( rej.low_snr > 0 ) {
STATUS("Discarded %i reflection pairs because either or both"
- " versions had I/sigma(I) < %f.\n", nrej, sigma_cutoff);
+ " versions had I/sigma(I) < %f.\n",
+ rej.low_snr, sigma_cutoff);
}
- if ( config_ignorenegs && (nneg > 0) ) {
+ if ( rej.negative_deleted > 0 ) {
STATUS("Discarded %i reflection pairs because either or both"
- " versions had negative intensities.\n", nneg);
+ " versions had negative intensities.\n",
+ rej.negative_deleted);
}
- if ( config_zeronegs && (nneg > 0) ) {
+ if ( rej.negative_zeroed > 0 ) {
STATUS("For %i reflection pairs, either or both versions had"
- " negative intensities which were set to zero.\n", nneg);
+ " negative intensities which were set to zero.\n",
+ rej.negative_zeroed);
}
- if ( nmul > 0 ) {
+ if ( rej.few_measurements > 0 ) {
STATUS("%i reflection pairs rejected because either or both"
- " versions had too few measurements.\n", nmul);
+ " versions had too few measurements.\n",
+ rej.few_measurements);
}
- if ( nres > 0 ) {
+ if ( rej.outside_resolution_range > 0 ) {
STATUS("%i reflection pairs rejected because either or both"
- " versions were outside the resolution range.\n", nres);
+ " versions were outside the resolution range.\n",
+ rej.outside_resolution_range);
}
- if ( nbij > 0 ) {
+ if ( rej.no_bijvoet > 0 ) {
STATUS("%i reflection pairs rejected because either or both"
- " versions did not have Bijvoet partners.\n", nres);
+ " versions did not have Bijvoet partners.\n",
+ rej.no_bijvoet);
}
- if ( ncen > 0 ) {
+ if ( rej.centric > 0 ) {
STATUS("%i reflection pairs rejected because they were"
- " centric.\n", ncen);
+ " centric.\n", rej.centric);
}
- STATUS("%i reflection pairs accepted.\n", ncom);
+ STATUS("%i reflection pairs accepted.\n", rej.common);
resolution_limits(list1_acc, cell, &rmin, &rmax);
resolution_limits(list2_acc, cell, &rmin, &rmax);
@@ -1669,7 +737,7 @@ int main(int argc, char *argv[])
rmin/1e9, rmax/1e9, 1e10/rmin, 1e10/rmax);
}
do_fom(list1_acc, list2_acc, cell, rmin, rmax, fom, config_unity,
- nshells, shell_file, config_intshells, min_I, max_I, sym);
+ nshells, shell_file, sym);
free(shell_file);
reflist_free(list1_acc);
diff --git a/src/crystfel_gui.c b/src/crystfel_gui.c
new file mode 100644
index 00000000..159b8ec2
--- /dev/null
+++ b/src/crystfel_gui.c
@@ -0,0 +1,1260 @@
+/*
+ * crystfel_gui.c
+ *
+ * CrystFEL's main graphical user interface
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms-compat.h>
+#include <assert.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <datatemplate.h>
+#include <peaks.h>
+#include <cell-utils.h>
+
+#include "crystfelimageview.h"
+#include "crystfelimageview.h"
+#include "crystfel_gui.h"
+#include "gui_import.h"
+#include "gui_peaksearch.h"
+#include "gui_index.h"
+#include "gui_merge.h"
+#include "gui_fom.h"
+#include "gui_export.h"
+#include "gui_ambi.h"
+#include "gui_project.h"
+#include "version.h"
+
+
+static void show_help(const char *s)
+{
+ printf("Syntax: %s\n\n", s);
+ printf(
+"CrystFEL graphical user interface.\n"
+"\n"
+" -h, --help Display this help message.\n"
+" --version Print CrystFEL version number and exit.\n"
+
+);
+}
+
+static int confirm_exit(struct crystfelproject *proj)
+{
+ int r;
+ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(proj->window),
+ 0,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ "Do you want to save the session?");
+ gtk_dialog_add_buttons(GTK_DIALOG(dialog),
+ "Save", GTK_RESPONSE_YES,
+ "Don't save", GTK_RESPONSE_NO,
+ "Cancel", GTK_RESPONSE_CANCEL,
+ NULL);
+ r = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ if ( r == GTK_RESPONSE_YES ) {
+ save_project(proj);
+ return 1;
+ }
+ if ( r == GTK_RESPONSE_NO ) return 1;
+ return 0;
+}
+
+
+void error_box(struct crystfelproject *proj, const char *message)
+{
+ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(proj->window),
+ 0,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ message);
+ gtk_dialog_add_buttons(GTK_DIALOG(dialog),
+ "OK", GTK_RESPONSE_OK,
+ NULL);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+}
+
+
+/* Main window destroyed */
+static gboolean delete_event_sig(GtkWidget *da, GdkEvent *event,
+ struct crystfelproject *proj)
+{
+ if ( proj->unsaved ) {
+ if ( !confirm_exit(proj) ) return TRUE;
+ }
+ gtk_main_quit();
+ return FALSE;
+}
+
+
+static void add_ui_sig(GtkUIManager *ui, GtkWidget *widget,
+ GtkContainer *container)
+{
+ gtk_box_pack_start(GTK_BOX(container), widget, FALSE, FALSE, 0);
+ if ( GTK_IS_TOOLBAR(widget) ) {
+ gtk_toolbar_set_show_arrow(GTK_TOOLBAR(widget), TRUE);
+ }
+}
+
+
+static void swap_data_arrays(struct image *a, struct image *b)
+{
+ float **swap;
+ int **swap_bad;
+
+ swap = a->dp;
+ a->dp = b->dp;
+ b->dp = swap;
+
+ swap = a->sat;
+ a->sat = b->sat;
+ b->sat = swap;
+
+ swap_bad = a->bad;
+ a->bad = b->bad;
+ b->bad = swap_bad;
+}
+
+
+void select_result(struct crystfelproject *proj,
+ const char *result_name)
+{
+ gtk_combo_box_set_active_id(GTK_COMBO_BOX(proj->results_combo),
+ result_name);
+}
+
+
+const char *selected_result(struct crystfelproject *proj)
+{
+ return gtk_combo_box_get_active_id(GTK_COMBO_BOX(proj->results_combo));
+}
+
+
+/* Return non-zero if there are any jobs running.
+ * If not, it makes no sense to re-scan any result streams.
+ * Possible future improvement: exclude jobs which don't produce streams
+ * (i.e. merging) */
+static int have_running_jobs(struct crystfelproject *proj)
+{
+ int i;
+
+ for ( i=0; i<proj->n_running_tasks; i++ ) {
+ if ( proj->tasks[i].running ) return 1;
+ }
+
+ return 0;
+}
+
+
+/* Bring the image view up to date after changing the selected image */
+void update_imageview(struct crystfelproject *proj)
+{
+ char tmp[1024];
+ char *ev_str;
+ char *ev_sep;
+ struct image *image;
+ const gchar *results_name;
+
+ if ( proj->image_info == NULL ) return;
+
+ if ( (proj->dtempl == NULL)
+ || (proj->filenames == NULL)
+ || (proj->events == NULL)
+ || (proj->n_frames == 0) )
+ {
+ gtk_label_set_text(GTK_LABEL(proj->image_info),
+ "Ready to load images");
+ return;
+ }
+
+ image = image_read(proj->dtempl,
+ proj->filenames[proj->cur_frame],
+ proj->events[proj->cur_frame],
+ 0, 0);
+
+ if ( proj->events[proj->cur_frame] != NULL ) {
+ ev_str = proj->events[proj->cur_frame];
+ ev_sep = " ";
+ } else {
+ ev_str = "";
+ ev_sep = "";
+ }
+ snprintf(tmp, 1023, "%s%s%s (frame %i of %i%s)",
+ proj->filenames[proj->cur_frame],
+ ev_sep,
+ ev_str,
+ proj->cur_frame+1,
+ proj->n_frames,
+ (image==NULL)?", load error":"");
+ gtk_label_set_text(GTK_LABEL(proj->image_info), tmp);
+
+ if ( image == NULL ) {
+ ERROR("Failed to load image\n");
+ return;
+ }
+
+ /* Give CrystFELImageView a chance to free resources */
+ crystfel_image_view_set_image(CRYSTFEL_IMAGE_VIEW(proj->imageview),
+ NULL);
+ image_free(proj->cur_image);
+ proj->cur_image = image;
+
+ /* Look up results, if applicable */
+ results_name = gtk_combo_box_get_active_id(GTK_COMBO_BOX(proj->results_combo));
+ if ( strcmp(results_name, "crystfel-gui-internal") == 0 ) {
+ update_peaks(proj);
+ } else {
+ struct image *res_im;
+
+ res_im = find_indexed_image(proj,
+ results_name,
+ image->filename,
+ image->ev,
+ have_running_jobs(proj));
+ if ( res_im != NULL ) {
+ swap_data_arrays(image, res_im);
+ image_free(proj->cur_image);
+ proj->cur_image = res_im;
+ }
+ }
+
+ crystfel_image_view_set_show_reflections(CRYSTFEL_IMAGE_VIEW(proj->imageview),
+ proj->show_refls);
+ crystfel_image_view_set_label_reflections(CRYSTFEL_IMAGE_VIEW(proj->imageview),
+ proj->label_refls);
+ crystfel_image_view_set_refl_box_size(CRYSTFEL_IMAGE_VIEW(proj->imageview),
+ proj->indexing_params.ir_inn);
+ crystfel_image_view_set_show_peaks(CRYSTFEL_IMAGE_VIEW(proj->imageview),
+ proj->show_peaks);
+ crystfel_image_view_set_image(CRYSTFEL_IMAGE_VIEW(proj->imageview),
+ proj->cur_image);
+
+ gtk_widget_set_sensitive(proj->next_button,
+ !(proj->cur_frame == proj->n_frames-1));
+ gtk_widget_set_sensitive(proj->last_button,
+ !(proj->cur_frame == proj->n_frames-1));
+ gtk_widget_set_sensitive(proj->prev_button,
+ !(proj->cur_frame == 0));
+ gtk_widget_set_sensitive(proj->first_button,
+ !(proj->cur_frame == 0));
+}
+
+
+static void push_random_frame(struct crystfelproject *proj, int fr)
+{
+ memmove(&proj->random_history[1],
+ &proj->random_history[0],
+ (N_RANDOM_HISTORY-1)*sizeof(int));
+ proj->random_history[0] = fr;
+ proj->n_random_history++;
+ if ( proj->n_random_history > N_RANDOM_HISTORY ) {
+ proj->n_random_history = N_RANDOM_HISTORY;
+ }
+}
+
+
+static int pop_random_frame(struct crystfelproject *proj)
+{
+ int fr;
+ assert(proj->n_random_history > 0);
+ fr = proj->random_history[0];
+ memmove(&proj->random_history[0],
+ &proj->random_history[1],
+ (N_RANDOM_HISTORY-1)*sizeof(int));
+ proj->n_random_history--;
+ return fr;
+}
+
+
+/* File->Quit */
+static gint quit_sig(GtkWidget *widget, struct crystfelproject *proj)
+{
+ if ( proj->unsaved ) {
+ if ( !confirm_exit(proj) ) return TRUE;
+ }
+ gtk_main_quit();
+ return FALSE;
+}
+
+
+static gint save_sig(GtkWidget *widget, struct crystfelproject *proj)
+{
+ if ( save_project(proj) == 0 ) {
+ STATUS("Saved project.\n");
+ } else {
+ ERROR("Could not save project.\n");
+ }
+ return FALSE;
+}
+
+
+static gint rescan_sig(GtkWidget *widget, struct crystfelproject *proj)
+{
+ const char *results_name;
+
+ results_name = gtk_combo_box_get_active_id(GTK_COMBO_BOX(proj->results_combo));
+ if ( strcmp(results_name, "crystfel-gui-internal") != 0 ) {
+ struct gui_indexing_result *res;
+ res = find_indexing_result_by_name(proj, results_name);
+ if ( res != NULL ) {
+ update_result_index(res);
+ } else {
+ ERROR("Couldn't find result '%s'\n", results_name);
+ }
+ }
+ return FALSE;
+}
+
+
+static gint reset_zoom_sig(GtkWidget *widget, struct crystfelproject *proj)
+{
+ crystfel_image_view_reset_zoom(CRYSTFEL_IMAGE_VIEW(proj->imageview));
+ return FALSE;
+}
+
+
+static gint first_frame_sig(GtkWidget *widget,
+ struct crystfelproject *proj)
+{
+ proj->cur_frame = 0;
+ update_imageview(proj);
+ return FALSE;
+}
+
+
+static gint prev_frame_sig(GtkWidget *widget,
+ struct crystfelproject *proj)
+{
+ if ( proj->cur_frame == 0 ) return FALSE;
+ proj->cur_frame--;
+ update_imageview(proj);
+ return FALSE;
+}
+
+
+static gint random_frame_sig(GtkWidget *widget,
+ GdkEventButton *event,
+ struct crystfelproject *proj)
+{
+ if ( event->state & GDK_SHIFT_MASK ) {
+ if ( proj->n_random_history > 0 ) {
+ proj->cur_frame = pop_random_frame(proj);
+ update_imageview(proj);
+ }
+ } else {
+ push_random_frame(proj, proj->cur_frame);
+ proj->cur_frame = random()*proj->n_frames / RAND_MAX;
+ update_imageview(proj);
+ }
+ return FALSE;
+}
+
+
+static gint next_frame_sig(GtkWidget *widget,
+ struct crystfelproject *proj)
+{
+ if ( proj->cur_frame == proj->n_frames - 1 ) return FALSE;
+ proj->cur_frame++;
+ update_imageview(proj);
+ return FALSE;
+}
+
+
+static gint last_frame_sig(GtkWidget *widget,
+ struct crystfelproject *proj)
+{
+ proj->cur_frame = proj->n_frames - 1;
+ update_imageview(proj);
+ return FALSE;
+}
+
+
+static gint about_sig(GtkWidget *widget, struct crystfelproject *proj)
+{
+ GtkWidget *window;
+
+ const gchar *authors[] = {
+ "Thomas White <taw@physics.org>",
+ NULL
+ };
+
+ window = gtk_about_dialog_new();
+ gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(proj->window));
+
+ gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(window),
+ "CrystFEL graphical user interface");
+ gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(window),
+ crystfel_version_string());
+ gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(window),
+ "© 2020 Deutsches Elektronen-Synchrotron DESY, "
+ "a research centre of the Helmholtz Association.");
+ gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(window),
+ "https://www.desy.de/~twhite/crystfel");
+ gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(window), authors);
+
+ g_signal_connect(window, "response", G_CALLBACK(gtk_widget_destroy),
+ NULL);
+
+ gtk_widget_show_all(window);
+
+ return 0;
+}
+
+
+static gint image_info_clicked_sig(GtkWidget *widget,
+ struct crystfelproject *proj)
+{
+ GtkWidget *popover;
+ GtkWidget *grid;
+ GtkWidget *label;
+ char tmp[64];
+
+ if ( proj->cur_image == NULL ) return FALSE;
+
+ popover = gtk_popover_new(widget);
+ gtk_popover_set_position(GTK_POPOVER(popover),
+ GTK_POS_BOTTOM);
+
+ grid = gtk_grid_new();
+ gtk_grid_set_row_spacing(GTK_GRID(grid), 4);
+ gtk_grid_set_column_spacing(GTK_GRID(grid), 4);
+ gtk_container_set_border_width(GTK_CONTAINER(grid), 6);
+
+ label = gtk_label_new("Number of peaks:");
+ gtk_grid_attach(GTK_GRID(grid), label, 0, 0, 1, 1);
+ snprintf(tmp, 63, "%i", image_feature_count(proj->cur_image->features));
+ label = gtk_label_new(tmp);
+ gtk_grid_attach(GTK_GRID(grid), label, 1, 0, 1, 1);
+
+ label = gtk_label_new("Number of crystals:");
+ gtk_grid_attach(GTK_GRID(grid), label, 0, 1, 1, 1);
+ snprintf(tmp, 63, "%i", proj->cur_image->n_crystals);
+ label = gtk_label_new(tmp);
+ gtk_grid_attach(GTK_GRID(grid), label, 1, 1, 1, 1);
+
+ gtk_container_add(GTK_CONTAINER(popover), grid);
+ gtk_widget_show_all(grid);
+
+#if GTK_CHECK_VERSION(3,22,0)
+ gtk_popover_popup(GTK_POPOVER(popover));
+#else
+ gtk_widget_show_all(GTK_WIDGET(popover));
+#endif
+
+ return FALSE;
+}
+
+
+static gint results_combo_changed_sig(GtkComboBox *w,
+ struct crystfelproject *proj)
+{
+ update_imageview(proj);
+ return FALSE;
+}
+
+
+static gint show_peaks_sig(GtkWidget *w, struct crystfelproject *proj)
+{
+ proj->show_peaks = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w));
+ crystfel_image_view_set_show_peaks(CRYSTFEL_IMAGE_VIEW(proj->imageview),
+ proj->show_peaks);
+ return FALSE;
+}
+
+
+static gint show_refls_sig(GtkWidget *w, struct crystfelproject *proj)
+{
+ proj->show_refls = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w));
+ crystfel_image_view_set_show_reflections(CRYSTFEL_IMAGE_VIEW(proj->imageview),
+ proj->show_refls);
+ return FALSE;
+}
+
+
+static gint label_refls_sig(GtkWidget *w, struct crystfelproject *proj)
+{
+ proj->label_refls = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w));
+ crystfel_image_view_set_label_reflections(CRYSTFEL_IMAGE_VIEW(proj->imageview),
+ proj->label_refls);
+ return FALSE;
+}
+
+
+static void add_menu_bar(struct crystfelproject *proj, GtkWidget *vbox)
+{
+ GError *error = NULL;
+
+ const char *ui = "<ui> <menubar name=\"mainwindow\">"
+ "<menu name=\"file\" action=\"FileAction\">"
+ " <menuitem name=\"save\" action=\"SaveAction\" />"
+ " <menuitem name=\"quit\" action=\"QuitAction\" />"
+ "</menu>"
+ "<menu name=\"view\" action=\"ViewAction\" >"
+ " <menuitem name=\"peaks\" action=\"PeaksAction\" />"
+ " <menuitem name=\"refls\" action=\"ReflsAction\" />"
+ " <menuitem name=\"labelrefls\" action=\"LabelReflsAction\" />"
+ " <separator />"
+ " <menuitem name=\"resetzoom\" action=\"ResetZoomAction\" />"
+ "</menu>"
+ "<menu name=\"tools\" action=\"ToolsAction\" >"
+ " <menuitem name=\"rescan\" action=\"RescanAction\" />"
+ "</menu>"
+ "<menu name=\"help\" action=\"HelpAction\">"
+ " <menuitem name=\"about\" action=\"AboutAction\" />"
+ "</menu>"
+ "</menubar></ui>";
+
+ GtkActionEntry entries[] = {
+
+ { "FileAction", NULL, "_File", NULL, NULL, NULL },
+ { "SaveAction", GTK_STOCK_SAVE, "_Save", NULL, NULL,
+ G_CALLBACK(save_sig) },
+ { "QuitAction", GTK_STOCK_QUIT, "_Quit", NULL, NULL,
+ G_CALLBACK(quit_sig) },
+
+ { "ViewAction", NULL, "_View", NULL, NULL, NULL },
+ { "ResetZoomAction", NULL, "Reset zoom", NULL, NULL,
+ G_CALLBACK(reset_zoom_sig) },
+
+ { "ToolsAction", NULL, "_Tools", NULL, NULL, NULL },
+ { "RescanAction", NULL, "Rescan streams", NULL, NULL,
+ G_CALLBACK(rescan_sig) },
+
+ { "HelpAction", NULL, "_Help", NULL, NULL, NULL },
+ { "AboutAction", GTK_STOCK_ABOUT, "_About", NULL, NULL,
+ G_CALLBACK(about_sig) },
+
+ };
+
+ GtkToggleActionEntry toggles[] = {
+ { "PeaksAction", NULL, "Peak detection results", NULL, NULL,
+ G_CALLBACK(show_peaks_sig), FALSE },
+ { "ReflsAction", NULL, "Calculated reflection positions", NULL, NULL,
+ G_CALLBACK(show_refls_sig), FALSE },
+ { "LabelReflsAction", NULL, "Show reflection indices", NULL, NULL,
+ G_CALLBACK(label_refls_sig), FALSE },
+ };
+
+ proj->action_group = gtk_action_group_new("cellwindow");
+ gtk_action_group_add_actions(proj->action_group, entries,
+ G_N_ELEMENTS(entries), proj);
+ gtk_action_group_add_toggle_actions(proj->action_group, toggles,
+ G_N_ELEMENTS(toggles), proj);
+
+ proj->ui = gtk_ui_manager_new();
+ gtk_ui_manager_insert_action_group(proj->ui, proj->action_group, 0);
+ g_signal_connect(proj->ui, "add_widget", G_CALLBACK(add_ui_sig), vbox);
+ if ( gtk_ui_manager_add_ui_from_string(proj->ui, ui, -1, &error) == 0 )
+ {
+ fprintf(stderr, "Error loading message window menu bar: %s\n",
+ error->message);
+ return;
+ }
+
+ gtk_window_add_accel_group(GTK_WINDOW(proj->window),
+ gtk_ui_manager_get_accel_group(proj->ui));
+ gtk_ui_manager_ensure_update(proj->ui);
+}
+
+
+static void add_button(GtkWidget *vbox, const char *label, const char *imagen,
+ GCallback callback, struct crystfelproject *proj)
+{
+ GtkWidget *button;
+ GtkWidget *image;
+
+ button = gtk_button_new_with_label(label);
+ g_object_set(G_OBJECT(button), "image-position", GTK_POS_TOP, NULL);
+ image = gtk_image_new_from_icon_name(imagen, GTK_ICON_SIZE_DIALOG);
+ g_object_set(G_OBJECT(button), "image", image, NULL);
+ g_object_set(G_OBJECT(button), "always-show-image", TRUE, NULL);
+ gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 4);
+
+ if ( callback != NULL ) {
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(callback), proj);
+ }
+}
+
+
+static void add_task_buttons(GtkWidget *vbox, struct crystfelproject *proj)
+{
+ /* FIXME: All these icons are placeholders */
+ add_button(vbox, "Load data", "folder-pictures",
+ G_CALLBACK(import_sig), proj);
+ add_button(vbox, "Peak detection", "edit-find",
+ G_CALLBACK(peaksearch_sig), proj);
+ add_button(vbox, "Index this frame", "system-run",
+ G_CALLBACK(index_one_sig), proj);
+ add_button(vbox, "Index all frames", "view-grid",
+ G_CALLBACK(index_all_sig), proj);
+ add_button(vbox, "Determine unit cell", "applications-engineering",
+ G_CALLBACK(cell_explorer_sig), proj);
+ add_button(vbox, "Indexing ambiguity", "face-worried",
+ G_CALLBACK(ambi_sig), proj);
+ add_button(vbox, "Merge", "applications-science",
+ G_CALLBACK(merge_sig), proj);
+ add_button(vbox, "Figures of merit", "trophy-gold",
+ G_CALLBACK(fom_sig), proj);
+ add_button(vbox, "Export data", "document-send",
+ G_CALLBACK(export_sig), proj);
+}
+
+
+static void add_gui_message(enum log_msg_type type, const char *msg,
+ void *vp)
+{
+ GtkTextBuffer *buf;
+ GtkTextIter iter;
+ GtkTextMark *mark;
+ struct crystfelproject *proj = vp;
+
+ buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(proj->report));
+ gtk_text_buffer_get_end_iter(buf, &iter);
+ gtk_text_buffer_insert(buf, &iter, msg, -1);
+
+ mark = gtk_text_mark_new(NULL, FALSE);
+ gtk_text_buffer_get_end_iter(buf, &iter);
+ gtk_text_buffer_add_mark(buf, mark, &iter);
+ gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(proj->report),
+ mark, 0.0, FALSE, 0.0, 0.0);
+ gtk_text_buffer_delete_mark(buf, mark);
+}
+
+
+static void clear_log_sig(GtkMenuItem *widget,
+ struct crystfelproject *proj)
+{
+ GtkTextBuffer *buf;
+
+ buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(proj->report));
+ if ( buf != NULL ) {
+ gtk_text_buffer_set_text(buf, "", -1);
+ }
+}
+
+
+static void add_log_menu_items(GtkTextView *textview,
+ GtkWidget *popup,
+ struct crystfelproject *proj)
+{
+ GtkWidget *item;
+
+ if ( !GTK_IS_MENU(popup) ) return;
+
+ item = gtk_separator_menu_item_new();
+ gtk_menu_shell_append(GTK_MENU_SHELL(popup), item);
+ gtk_widget_show(item);
+
+ item = gtk_menu_item_new_with_label("Clear log");
+ gtk_menu_shell_append(GTK_MENU_SHELL(popup), item);
+ gtk_widget_show(item);
+ g_signal_connect(item, "activate", G_CALLBACK(clear_log_sig), proj);
+}
+
+
+int main(int argc, char *argv[])
+{
+ int c;
+ struct crystfelproject proj;
+ GtkWidget *vbox;
+ GtkWidget *vpaned;
+ GtkWidget *hpaned;
+ GtkWidget *scroll;
+ GtkWidget *frame;
+ GtkWidget *main_vbox;
+ GtkWidget *toolbar;
+ GtkWidget *results_toolbar;
+ GtkWidget *button;
+ GtkWidget *label;
+ GtkWidget *w;
+
+ /* Long options */
+ const struct option longopts[] = {
+ {"help", 0, NULL, 'h'},
+ {"version", 0, NULL, 1 },
+ {0, 0, NULL, 0}
+ };
+
+ /* Short options */
+ while ((c = getopt_long(argc, argv, "h",
+ longopts, NULL)) != -1) {
+
+ switch (c) {
+
+ case 'h' :
+ show_help(argv[0]);
+ return 0;
+
+ case 1 :
+ printf("CrystFEL: %s\n",
+ crystfel_version_string());
+ printf("%s\n",
+ crystfel_licence_string());
+ return 0;
+
+ default :
+ return 1;
+
+ }
+
+ }
+
+ /* This isn't great, but necessary to make the command-line UI and file
+ * formats consistent with the other programs, which all use the C
+ * locale. Better would be to have all the programs call
+ * setlocale(LC_ALL, "") and use the C locale temporarily when reading
+ * or writing a stream, reflection file, geometry file etc. */
+ gtk_disable_setlocale();
+
+ gtk_init(&argc, &argv);
+
+ default_project(&proj);
+
+ proj.image_info = NULL;
+
+ proj.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(proj.window), "CrystFEL");
+ gtk_window_set_default_icon_name("crystfel");
+ g_signal_connect(G_OBJECT(proj.window), "delete-event",
+ G_CALLBACK(delete_event_sig),
+ &proj);
+
+ vbox = gtk_vbox_new(FALSE, 0.0);
+ gtk_container_add(GTK_CONTAINER(proj.window), vbox);
+ add_menu_bar(&proj, vbox);
+
+ vpaned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
+ gtk_box_pack_end(GTK_BOX(vbox), vpaned, TRUE, TRUE, 0.0);
+
+ hpaned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
+ gtk_paned_pack1(GTK_PANED(vpaned), hpaned, TRUE, TRUE);
+
+ toolbar = gtk_hbox_new(FALSE, 0.0);
+
+ /* First */
+ proj.first_button = gtk_button_new_from_icon_name("go-first", GTK_ICON_SIZE_LARGE_TOOLBAR);
+ gtk_box_pack_start(GTK_BOX(toolbar), proj.first_button, FALSE, FALSE, 2.0);
+ g_signal_connect(G_OBJECT(proj.first_button), "clicked",
+ G_CALLBACK(first_frame_sig), &proj);
+ gtk_widget_set_tooltip_text(proj.first_button, "First image");
+
+ /* Prev */
+ proj.prev_button = gtk_button_new_from_icon_name("go-previous", GTK_ICON_SIZE_LARGE_TOOLBAR);
+ gtk_box_pack_start(GTK_BOX(toolbar), proj.prev_button, FALSE, FALSE, 2.0);
+ g_signal_connect(G_OBJECT(proj.prev_button), "clicked",
+ G_CALLBACK(prev_frame_sig), &proj);
+ gtk_widget_set_tooltip_text(proj.prev_button, "Previous image");
+
+ /* Random */
+ button = gtk_button_new_from_icon_name("media-playlist-shuffle",
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
+ gtk_box_pack_start(GTK_BOX(toolbar), button, FALSE, FALSE, 2.0);
+ g_signal_connect(G_OBJECT(button), "button-press-event",
+ G_CALLBACK(random_frame_sig), &proj);
+ gtk_widget_set_tooltip_text(button, "Jump to a random image. "
+ "Shift-click to go back");
+
+ /* Next */
+ proj.next_button = gtk_button_new_from_icon_name("go-next", GTK_ICON_SIZE_LARGE_TOOLBAR);
+ gtk_box_pack_start(GTK_BOX(toolbar), proj.next_button, FALSE, FALSE, 2.0);
+ g_signal_connect(G_OBJECT(proj.next_button), "clicked",
+ G_CALLBACK(next_frame_sig), &proj);
+ gtk_widget_set_tooltip_text(proj.next_button, "Next image");
+
+ /* Last */
+ proj.last_button = gtk_button_new_from_icon_name("go-last", GTK_ICON_SIZE_LARGE_TOOLBAR);
+ gtk_box_pack_start(GTK_BOX(toolbar), proj.last_button, FALSE, FALSE, 2.0);
+ g_signal_connect(G_OBJECT(proj.last_button), "clicked",
+ G_CALLBACK(last_frame_sig), &proj);
+ gtk_widget_set_tooltip_text(proj.last_button, "Last image");
+
+ /* Information about image */
+ button = gtk_button_new_from_icon_name("document-properties",
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
+ gtk_box_pack_end(GTK_BOX(toolbar), button, FALSE, FALSE, 2.0);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(image_info_clicked_sig), &proj);
+
+ results_toolbar = gtk_hbox_new(FALSE, 0.0);
+ label = gtk_label_new("Show results from:");
+ gtk_box_pack_start(GTK_BOX(results_toolbar), label,
+ FALSE, FALSE, 4.0);
+ proj.results_combo = gtk_combo_box_text_new();
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(proj.results_combo),
+ "crystfel-gui-internal",
+ "Calculations within GUI");
+ gtk_combo_box_set_active(GTK_COMBO_BOX(proj.results_combo), 0);
+ gtk_box_pack_start(GTK_BOX(results_toolbar), proj.results_combo,
+ FALSE, FALSE, 4.0);
+ g_signal_connect(G_OBJECT(proj.results_combo), "changed",
+ G_CALLBACK(results_combo_changed_sig), &proj);
+
+ /* Filename */
+ proj.image_info = gtk_label_new("Ready to load images");
+ gtk_label_set_selectable(GTK_LABEL(proj.image_info), TRUE);
+ gtk_label_set_ellipsize(GTK_LABEL(proj.image_info),
+ PANGO_ELLIPSIZE_START);
+ gtk_box_pack_end(GTK_BOX(toolbar), proj.image_info, TRUE, TRUE, 0.0);
+
+ main_vbox = gtk_vbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(main_vbox), toolbar,
+ FALSE, FALSE, 2.0);
+ gtk_box_pack_start(GTK_BOX(main_vbox), results_toolbar,
+ FALSE, FALSE, 2.0);
+
+ /* Main area stuff (toolbar and imageview) at right */
+ proj.imageview = crystfel_image_view_new();
+ proj.cur_frame = 0;
+ frame = gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
+ scroll = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
+ GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS);
+ gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(proj.imageview));
+ gtk_box_pack_start(GTK_BOX(main_vbox), scroll, TRUE, TRUE, 0.0);
+ gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(main_vbox));
+ gtk_paned_pack2(GTK_PANED(hpaned), GTK_WIDGET(frame), TRUE, TRUE);
+ proj.main_vbox = main_vbox;
+
+ /* Icon region at left */
+ proj.icons = gtk_vbox_new(FALSE, 0.0);
+ scroll = gtk_scrolled_window_new(NULL, NULL);
+ gtk_container_set_border_width(GTK_CONTAINER(proj.icons), 16);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ frame = gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
+ gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(scroll));
+ gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(proj.icons));
+ gtk_paned_pack1(GTK_PANED(hpaned), GTK_WIDGET(frame), FALSE, FALSE);
+ add_task_buttons(proj.icons, &proj);
+
+ /* Report (text) region at bottom */
+ proj.report = gtk_text_view_new();
+ gtk_text_view_set_editable(GTK_TEXT_VIEW(proj.report), FALSE);
+ gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(proj.report), FALSE);
+ scroll = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+ g_signal_connect(proj.report, "populate-popup",
+ G_CALLBACK(add_log_menu_items), &proj);
+ frame = gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
+ gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(scroll));
+ gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(proj.report));
+ gtk_paned_pack2(GTK_PANED(vpaned), GTK_WIDGET(frame), FALSE, FALSE);
+
+ /* Send messages to report region */
+ set_log_message_func(add_gui_message, &proj);
+
+ /* Load state from disk */
+ if ( load_project(&proj) == 0 ) {
+ DataTemplate *dtempl;
+ GtkAction *w;
+ proj.cur_frame = 0;
+
+ if ( proj.geom_filename != NULL ) {
+
+ dtempl = data_template_new_from_file(proj.geom_filename);
+ if ( dtempl != NULL ) {
+ proj.dtempl = dtempl;
+ }
+ } else if ( proj.stream_filename != NULL ) {
+
+ Stream *st;
+ st = stream_open_for_read(proj.stream_filename);
+ if ( st != NULL ) {
+ char *geom_str = stream_geometry_file(st);
+ if ( geom_str != NULL ) {
+ proj.dtempl = data_template_new_from_string(geom_str);
+ }
+ }
+ stream_close(st);
+ }
+
+ w = gtk_ui_manager_get_action(proj.ui, "/mainwindow/view/peaks");
+ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(w),
+ proj.show_peaks);
+
+ w = gtk_ui_manager_get_action(proj.ui, "/mainwindow/view/refls");
+ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(w),
+ proj.show_refls);
+
+ w = gtk_ui_manager_get_action(proj.ui, "/mainwindow/view/labelrefls");
+ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(w),
+ proj.label_refls);
+
+ update_imageview(&proj);
+ }
+
+ w = gtk_ui_manager_get_widget(proj.ui, "/ui/mainwindow/view/peaks");
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), proj.show_peaks);
+ w = gtk_ui_manager_get_widget(proj.ui, "/ui/mainwindow/view/refls");
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), proj.show_refls);
+ w = gtk_ui_manager_get_widget(proj.ui, "/ui/mainwindow/view/labelrefls");
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), proj.label_refls);
+
+ gtk_window_set_default_size(GTK_WINDOW(proj.window), 1024, 768);
+ gtk_paned_set_position(GTK_PANED(hpaned), 172);
+ gtk_paned_set_position(GTK_PANED(vpaned), 600);
+ gtk_widget_show_all(proj.window);
+ gtk_main();
+
+ return 0;
+}
+
+
+static void infobar_response_sig(GtkInfoBar *infobar, gint resp,
+ gpointer data)
+{
+ struct gui_task *task = data;
+
+ if ( resp == GTK_RESPONSE_CANCEL ) {
+ task->backend->cancel_task(task->job_priv);
+
+ } else if ( resp == GTK_RESPONSE_CLOSE ) {
+
+ gtk_widget_destroy(GTK_WIDGET(infobar));
+ /* FIXME: Remove task from list */
+
+ } else {
+ ERROR("Unrecognised infobar response!\n");
+ }
+}
+
+
+static gboolean update_info_bar(gpointer data)
+{
+ struct gui_task *task = data;
+ int running;
+ float frac_complete;
+
+ if ( task->backend->task_status(task->job_priv,
+ &running, &frac_complete) ) {
+ ERROR("Error retrieving task status\n");
+ return G_SOURCE_CONTINUE;
+ }
+
+ gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(task->progress_bar),
+ frac_complete);
+
+ if ( !running && task->running ) {
+ /* Task is no longer running */
+ task->running = 0;
+ gtk_widget_destroy(task->cancel_button);
+ gtk_info_bar_set_show_close_button(GTK_INFO_BAR(task->info_bar),
+ TRUE);
+ return G_SOURCE_REMOVE;
+ }
+
+ return G_SOURCE_CONTINUE;
+}
+
+
+void add_running_task(struct crystfelproject *proj,
+ const char *task_desc,
+ struct crystfel_backend *backend,
+ void *job_priv)
+{
+ struct gui_task *task;
+ GtkWidget *bar_area;
+
+ task = &proj->tasks[proj->n_running_tasks++];
+ task->job_priv = job_priv;
+ task->backend = backend;
+ task->running = 1;
+
+ /* Progress info bar */
+ task->info_bar = gtk_info_bar_new();
+ gtk_info_bar_set_message_type(GTK_INFO_BAR(task->info_bar),
+ GTK_MESSAGE_INFO);
+
+ task->cancel_button = gtk_info_bar_add_button(GTK_INFO_BAR(task->info_bar),
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL);
+
+ gtk_box_pack_end(GTK_BOX(proj->main_vbox), GTK_WIDGET(task->info_bar),
+ FALSE, FALSE, 0.0);
+
+ bar_area = gtk_info_bar_get_content_area(GTK_INFO_BAR(task->info_bar));
+
+ /* Create progress bar */
+ task->progress_bar = gtk_progress_bar_new();
+ gtk_box_pack_start(GTK_BOX(bar_area),
+ GTK_WIDGET(task->progress_bar),
+ TRUE, TRUE, 0.0);
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(task->progress_bar),
+ task_desc);
+ gtk_progress_bar_set_show_text(GTK_PROGRESS_BAR(task->progress_bar),
+ TRUE);
+
+ g_signal_connect(G_OBJECT(task->info_bar), "response",
+ G_CALLBACK(infobar_response_sig), task);
+
+ gtk_widget_show_all(task->info_bar);
+
+#if GTK_CHECK_VERSION(3,22,29)
+ gtk_info_bar_set_revealed(GTK_INFO_BAR(task->info_bar), TRUE);
+#endif
+
+ g_timeout_add(500, update_info_bar, task);
+}
+
+
+static GFile *get_crystfel_path_gfile()
+{
+ GFile *self;
+ GFileInfo *self_info;
+ const char *self_target;
+ GFile *tar;
+ GFile *parent_dir;
+ GError *error = NULL;
+
+ self = g_file_new_for_path("/proc/self/exe");
+ self_info = g_file_query_info(self, "standard",
+ G_FILE_QUERY_INFO_NONE,
+ NULL, &error);
+ if ( self_info == NULL ) return NULL;
+
+ self_target = g_file_info_get_symlink_target(self_info);
+ if ( self_target == NULL ) return NULL;
+
+ tar = g_file_new_for_path(self_target);
+ if ( tar == NULL ) return NULL;
+
+ parent_dir = g_file_get_parent(tar);
+ if ( parent_dir == NULL ) return NULL;
+
+ g_object_unref(self);
+ g_object_unref(self_info);
+ g_object_unref(tar);
+
+ return parent_dir;
+}
+
+
+char *get_crystfel_path_str()
+{
+ char *path;
+ GFile *crystfel_path = get_crystfel_path_gfile();
+ if ( crystfel_path == NULL ) return NULL;
+ path = g_file_get_path(crystfel_path);
+ g_object_unref(crystfel_path);
+ return path;
+}
+
+
+char *get_crystfel_exe(const char *program)
+{
+ GFile *crystfel_path;
+ char *exe_path;
+ GFile *exe;
+
+ crystfel_path = get_crystfel_path_gfile();
+ if ( crystfel_path == NULL ) return NULL;
+
+ exe = g_file_get_child(crystfel_path, program);
+ if ( exe == NULL ) {
+ ERROR("Couldn't determine executable path. "
+ "This is OK provided the executable "
+ "path is set correctly.\n");
+ exe_path = strdup(program);
+ }
+
+ exe_path = g_file_get_path(exe);
+ g_object_unref(exe);
+ g_object_unref(crystfel_path);
+
+ return exe_path;
+}
+
+
+struct gui_job_notes_page *add_job_notes_page(GtkWidget *notebook)
+{
+ GtkWidget *box;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ GtkWidget *scroll;
+ struct gui_job_notes_page *notes;
+
+ notes = malloc(sizeof(struct gui_job_notes_page));
+ if ( notes == NULL ) return NULL;
+
+ box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+ gtk_container_set_border_width(GTK_CONTAINER(box), 8);
+
+ label = gtk_label_new("Whatever you enter here will be placed in "
+ "the job's folder as 'notes.txt'");
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ TRUE, TRUE, 0);
+ notes->textview = gtk_text_view_new();
+ gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(notes->textview),
+ GTK_WRAP_WORD_CHAR);
+ scroll = gtk_scrolled_window_new(NULL, NULL);
+ gtk_container_add(GTK_CONTAINER(scroll), notes->textview);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll),
+ GTK_SHADOW_ETCHED_IN);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(scroll),
+ TRUE, TRUE, 2.0);
+
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook), box,
+ gtk_label_new("Notes"));
+ return notes;
+}
+
+
+static int job_name_valid(const char *job_title)
+{
+ if ( strchr(job_title, '/') != NULL ) return 0;
+ if ( strchr(job_title, '\\') != NULL ) return 0;
+ return 1;
+}
+
+
+GFile *make_job_folder(const char *job_title, const char *job_notes)
+{
+ struct stat s;
+ char *workdir;
+ GFile *workdir_file;
+ GFile *cwd_file;
+ GFile *notes_file;
+ char *notes_path;
+ FILE *fh;
+
+ if ( !job_name_valid(job_title) ) {
+ ERROR("Invalid job name '%s'\n", job_title);
+ return NULL;
+ }
+
+ workdir = strdup(job_title);
+ if ( workdir == NULL ) return NULL;
+
+ if ( stat(workdir, &s) != -1 ) {
+ ERROR("Working directory already exists. "
+ "Choose a different job name.\n");
+ return NULL;
+ }
+
+ if ( mkdir(workdir, S_IRWXU) ) {
+ ERROR("Failed to create working directory: %s\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ cwd_file = g_file_new_for_path(".");
+ workdir_file = g_file_get_child(cwd_file, workdir);
+ g_object_unref(cwd_file);
+
+ /* Write the notes into notes.txt */
+ notes_file = g_file_get_child(workdir_file, "notes.txt");
+ notes_path = g_file_get_path(notes_file);
+ fh = fopen(notes_path, "w");
+ fputs(job_notes, fh);
+ fclose(fh);
+ g_free(notes_path);
+ g_object_unref(notes_file);
+
+ return workdir_file;
+}
+
+
+void force_peaks_on(struct crystfelproject *proj)
+{
+ GtkWidget *w;
+ proj->show_peaks = 1;
+ crystfel_image_view_set_show_peaks(CRYSTFEL_IMAGE_VIEW(proj->imageview),
+ proj->show_peaks);
+
+ w = gtk_ui_manager_get_widget(proj->ui, "/ui/mainwindow/view/peaks");
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), 1);
+}
+
+
+void force_refls_on(struct crystfelproject *proj)
+{
+ GtkWidget *w;
+ proj->show_refls = 1;
+ crystfel_image_view_set_show_peaks(CRYSTFEL_IMAGE_VIEW(proj->imageview),
+ proj->show_refls);
+
+ w = gtk_ui_manager_get_widget(proj->ui, "/ui/mainwindow/view/refls");
+ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), 1);
+}
+
+
+/* Given an "old" job title (possibly NULL), generate a new job title */
+char *make_new_job_title(const char *orig_old_title)
+{
+ size_t len, i;
+ char *old_title;
+
+ if ( orig_old_title == NULL ) return NULL;
+
+ old_title = strdup(orig_old_title);
+ if ( old_title == NULL ) return NULL;
+
+ len = strlen(old_title);
+
+ for ( i=len-1; i>0; i-- ) {
+ if ( !isdigit(old_title[i]) ) break;
+ }
+ if ( i == len-1 ) {
+ /* No digits at end */
+ char *new_title = malloc(len+3);
+ if ( new_title == NULL ) return NULL;
+ strcpy(new_title, old_title);
+ strcat(new_title, "-2");
+ return new_title;
+ } else {
+ /* Digits at end */
+ int n = atoi(&old_title[i+1]);
+ char *new_title = malloc(len+6);
+ if ( new_title == NULL ) return NULL;
+ old_title[i+1] = '\0';
+ snprintf(new_title, len+6, "%s%i", old_title, n+1);
+ return new_title;
+ }
+}
diff --git a/src/crystfel_gui.h b/src/crystfel_gui.h
new file mode 100644
index 00000000..868b4cb8
--- /dev/null
+++ b/src/crystfel_gui.h
@@ -0,0 +1,75 @@
+/*
+ * crystfel_gui.h
+ *
+ * CrystFEL's main graphical user interface
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef CRYSTFEL_GUI_H
+#define CRYSTFEL_GUI_H
+
+#include "gui_project.h"
+
+
+struct gui_job_notes_page
+{
+ GtkWidget *textview;
+};
+
+
+enum gui_job_type
+{
+ GUI_JOB_INDEXING,
+ GUI_JOB_PROCESS_HKL,
+ GUI_JOB_PROCESS_HKL_SCALE,
+ GUI_JOB_PARTIALATOR,
+ GUI_JOB_AMBIGATOR,
+};
+
+extern void error_box(struct crystfelproject *proj, const char *message);
+
+extern void add_running_task(struct crystfelproject *proj,
+ const char *task_desc,
+ struct crystfel_backend *backend,
+ void *job_priv);
+
+extern void update_imageview(struct crystfelproject *proj);
+extern void select_result(struct crystfelproject *proj,
+ const char *result_name);
+extern const char *selected_result(struct crystfelproject *proj);
+
+extern char *get_crystfel_path_str(void);
+
+extern char *get_crystfel_exe(const char *program);
+
+extern struct gui_job_notes_page *add_job_notes_page(GtkWidget *notebook);
+
+extern GFile *make_job_folder(const char *job_title, const char *job_notes);
+
+extern void force_peaks_on(struct crystfelproject *proj);
+extern void force_refls_on(struct crystfelproject *proj);
+
+extern char *make_new_job_title(const char *old_title);
+
+#endif
diff --git a/src/crystfelimageview.c b/src/crystfelimageview.c
new file mode 100644
index 00000000..d5c0b51f
--- /dev/null
+++ b/src/crystfelimageview.c
@@ -0,0 +1,1061 @@
+/*
+ * crystfelimageview.c
+ *
+ * CrystFEL's image viewer widget
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <gtk/gtk.h>
+#include <glib-object.h>
+#include <gsl/gsl_statistics_float.h>
+
+#include <utils.h>
+#include <detgeom.h>
+#include <colscale.h>
+
+#include "crystfelimageview.h"
+
+
+static int rerender_image(CrystFELImageView *iv);
+
+
+static void scroll_interface_init(GtkScrollable *iface)
+{
+}
+
+
+enum
+{
+ CRYSTFELIMAGEVIEW_0,
+ CRYSTFELIMAGEVIEW_VADJ,
+ CRYSTFELIMAGEVIEW_HADJ,
+ CRYSTFELIMAGEVIEW_VPOL,
+ CRYSTFELIMAGEVIEW_HPOL,
+};
+
+
+G_DEFINE_TYPE_WITH_CODE(CrystFELImageView, crystfel_image_view,
+ GTK_TYPE_DRAWING_AREA,
+ G_IMPLEMENT_INTERFACE(GTK_TYPE_SCROLLABLE,
+ scroll_interface_init))
+
+static void redraw(CrystFELImageView *iv)
+{
+ gint w, h;
+ w = gtk_widget_get_allocated_width(GTK_WIDGET(iv));
+ h = gtk_widget_get_allocated_height(GTK_WIDGET(iv));
+ gtk_widget_queue_draw_area(GTK_WIDGET(iv), 0, 0, w, h);
+}
+
+
+static void cleanup_image(CrystFELImageView *iv)
+{
+ if ( iv->pixbufs != NULL ) {
+ int i;
+ for ( i=0; i<iv->image->detgeom->n_panels; i++ ) {
+ if ( iv->pixbufs[i] != NULL ) {
+ gdk_pixbuf_unref(iv->pixbufs[i]);
+ }
+ }
+ }
+ free(iv->pixbufs);
+
+ iv->image = NULL;
+ iv->pixbufs = NULL;
+}
+
+
+static gint destroy_sig(GtkWidget *window, CrystFELImageView *iv)
+{
+ cleanup_image(iv);
+ return FALSE;
+}
+
+
+static gint realise_sig(GtkWidget *window, CrystFELImageView *iv)
+{
+ return FALSE;
+}
+
+
+static void configure_scroll_adjustments(CrystFELImageView *iv)
+{
+ if ( iv->hadj != NULL ) {
+ double pos = gtk_adjustment_get_value(iv->hadj);
+ double vis_size = iv->visible_width / iv->zoom;
+ gtk_adjustment_configure(iv->hadj, pos,
+ 0.0, iv->detector_w,
+ 0.0001, 0.1, vis_size);
+ }
+ if ( iv->vadj != NULL ) {
+ double pos = gtk_adjustment_get_value(iv->vadj);
+ double vis_size = iv->visible_height / iv->zoom;
+ gtk_adjustment_configure(iv->vadj, pos,
+ 0.0, iv->detector_h,
+ 0.0001, 0.1, vis_size);
+ }
+}
+
+
+static gint scroll_sig(GtkWidget *window, GdkEventScroll *event,
+ CrystFELImageView *iv)
+{
+ double zoom_scale, ratio;
+ int claim = FALSE;
+ int zoom_allowed = 1;
+
+ if ( event->direction == GDK_SCROLL_UP ) {
+ zoom_scale = 1.1;
+ claim = TRUE;
+ }
+ if ( event->direction == GDK_SCROLL_DOWN ) {
+ zoom_scale = 0.9;
+ claim = TRUE;
+ }
+ if ( event->direction == GDK_SCROLL_LEFT ) return TRUE;
+ if ( event->direction == GDK_SCROLL_RIGHT ) return TRUE;
+
+ ratio = iv->zoom / iv->image->detgeom->panels[0].pixel_pitch;
+
+ if ( (ratio < 5e6) && (zoom_scale < 1.0) ) zoom_allowed = 0;
+ if ( (ratio > 1e10) && (zoom_scale > 1.0) ) zoom_allowed = 0;
+
+ if ( claim && zoom_allowed ) {
+
+ double shift_x, shift_y;
+ double scr_x, scr_y;
+
+ scr_x = gtk_adjustment_get_value(iv->hadj);
+ scr_y = gtk_adjustment_get_value(iv->vadj);
+
+ shift_x = event->x*((1.0/(zoom_scale*iv->zoom))-(1.0/iv->zoom));
+ shift_y = event->y*((1.0/(zoom_scale*iv->zoom))-(1.0/iv->zoom));
+ iv->zoom *= zoom_scale;
+
+ configure_scroll_adjustments(iv);
+
+ gtk_adjustment_set_value(iv->hadj, scr_x - shift_x);
+ gtk_adjustment_set_value(iv->vadj, scr_y - shift_y);
+
+ redraw(iv);
+
+ }
+
+ return claim;
+}
+
+
+static gint button_press_sig(GtkWidget *window, GdkEventButton *event,
+ CrystFELImageView *iv)
+{
+ iv->drag_start_x = event->x;
+ iv->drag_start_y = event->y;
+ iv->drag_start_sp_x = gtk_adjustment_get_value(iv->hadj);
+ iv->drag_start_sp_y = gtk_adjustment_get_value(iv->vadj);
+ return FALSE;
+}
+
+
+static gint motion_sig(GtkWidget *window, GdkEventMotion *event,
+ CrystFELImageView *iv)
+{
+ double ddx, ddy;
+ ddx = event->x - iv->drag_start_x;
+ ddy = event->y - iv->drag_start_y;
+ gtk_adjustment_set_value(iv->hadj, iv->drag_start_sp_x - ddx/iv->zoom);
+ gtk_adjustment_set_value(iv->vadj, iv->drag_start_sp_y - ddy/iv->zoom);
+ redraw(iv);
+ return FALSE;
+}
+
+
+static gint configure_sig(GtkWidget *window, GdkEventConfigure *rec,
+ CrystFELImageView *iv)
+{
+ iv->visible_width = rec->width;
+ iv->visible_height = rec->height;
+ configure_scroll_adjustments(iv);
+ return FALSE;
+}
+
+
+static int clamp(double val, int min, int max)
+{
+ if ( val < min ) return min;
+ if ( val > max ) return max;
+ return val;
+}
+
+
+static void swap(int *a, int *b)
+{
+ int tmp = *a;
+ *a = *b;
+ *b = tmp;
+}
+
+
+static void draw_pixel_values(cairo_t *cr,
+ double imin_fs, double imin_ss,
+ double imax_fs, double imax_ss,
+ struct detgeom_panel p, float *dp,
+ int *bad)
+{
+ int min_fs, max_fs, min_ss, max_ss;
+ int fs, ss;
+ PangoLayout *layout;
+ PangoFontDescription *fontdesc;
+ double w, h;
+
+ /* FIXME: This is wrong for slanty pixels */
+ min_fs = clamp(imin_fs, 0, p.w-1);
+ min_ss = clamp(imin_ss, 0, p.h-1);
+ max_fs = clamp(imax_fs, 0, p.w-1);
+ max_ss = clamp(imax_ss, 0, p.h-1);
+ if ( min_ss > max_ss ) swap(&min_ss, &max_ss);
+ if ( min_fs > max_fs ) swap(&min_fs, &max_fs);
+
+ layout = pango_cairo_create_layout(cr);
+ fontdesc = pango_font_description_from_string("Sans 10");
+ pango_layout_set_font_description(layout, fontdesc);
+
+ w = 1.0;
+ h = 1.0;
+ cairo_device_to_user_distance(cr, &w, &h);
+
+ for ( fs=min_fs; fs<=max_fs; fs++ ) {
+ for ( ss=min_ss; ss<=max_ss; ss++ ) {
+
+ double x, y;
+ double fsd, ssd;
+ char tmp[64];
+ PangoRectangle rec;
+ double rw, rh;
+ const char *b1;
+ const char *b2;
+
+ fsd = fs + 0.5;
+ ssd = ss + 0.5;
+
+ x = (fsd*p.fsx + ssd*p.ssx + p.cnx)*p.pixel_pitch;
+ y = (fsd*p.fsy + ssd*p.ssy + p.cny)*p.pixel_pitch;
+
+ if ( bad[fs+ss*p.w] ) {
+ b1 = "(";
+ b2 = ")";
+ } else {
+ b1 = "";
+ b2 = "";
+ }
+
+ snprintf(tmp, 63, "%s%.f%s", b1, dp[fs+ss*p.w], b2);
+ pango_layout_set_text(layout, tmp, -1);
+
+ cairo_save(cr);
+
+ cairo_translate(cr, x, y);
+ cairo_scale(cr, w, h);
+ pango_cairo_update_layout(cr, layout);
+ pango_layout_get_extents(layout, NULL, &rec);
+ rw = pango_units_to_double(rec.width);
+ rh = pango_units_to_double(rec.height);
+
+ cairo_rectangle(cr, -rw/2.0, -rh/2.0, rw, rh);
+ cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+ cairo_fill(cr);
+
+ cairo_move_to(cr, -rw/2.0, -rh/2.0);
+ cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+ pango_cairo_show_layout(cr, layout);
+
+ cairo_restore(cr);
+
+ }
+ }
+
+ pango_font_description_free(fontdesc);
+ g_object_unref(layout);
+
+ cairo_arc(cr, p.cnx*p.pixel_pitch, p.cny*p.pixel_pitch, 0.00002,
+ 0, 2.0*M_PI);
+ cairo_set_source_rgba(cr, 0.0, 1.0, 1.0, 1.0);
+ cairo_fill(cr);
+}
+
+
+static void draw_panel_rectangle(cairo_t *cr, CrystFELImageView *iv,
+ int i, cairo_matrix_t *gtkmatrix)
+{
+ struct detgeom_panel p = iv->image->detgeom->panels[i];
+ cairo_matrix_t m;
+ cairo_pattern_t *patt;
+ double min_x, min_y, max_x, max_y;
+ double xs, ys, pixel_size_on_screen;
+ int have_pixels = 1;
+
+ cairo_save(cr);
+
+ /* Move to the right location */
+ cairo_translate(cr, p.cnx*p.pixel_pitch, p.cny*p.pixel_pitch);
+
+ /* Twiddle directions according to matrix */
+ cairo_matrix_init(&m, p.fsx, p.fsy, p.ssx, p.ssy,
+ 0.0, 0.0);
+ cairo_transform(cr, &m);
+
+ gdk_cairo_set_source_pixbuf(cr, iv->pixbufs[i], 0.0, 0.0);
+ patt = cairo_get_source(cr);
+
+ cairo_pattern_get_matrix(patt, &m);
+ cairo_matrix_scale(&m, 1.0/p.pixel_pitch, 1.0/p.pixel_pitch);
+ cairo_pattern_set_matrix(patt, &m);
+
+ cairo_pattern_set_filter(patt, CAIRO_FILTER_NEAREST);
+
+ cairo_rectangle(cr, 0.0, 0.0, p.w*p.pixel_pitch, p.h*p.pixel_pitch);
+ cairo_fill_preserve(cr);
+ cairo_set_line_width(cr, 0.00001);
+ cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
+ cairo_stroke(cr);
+
+ /* Are any pixels from this panel visible? */
+ min_x = 0.0;
+ min_y = 0.0;
+ max_x = iv->visible_width;
+ max_y = iv->visible_height;
+
+ /* Take into account the transformation which GTK already
+ * has in effect on the widget (translation from parent
+ * window's origin). */
+ cairo_matrix_transform_point(gtkmatrix, &min_x, &min_y);
+ cairo_matrix_transform_point(gtkmatrix, &max_x, &max_y);
+ cairo_device_to_user(cr, &min_x, &min_y);
+ cairo_device_to_user(cr, &max_x, &max_y);
+
+ min_x /= p.pixel_pitch;
+ min_y /= p.pixel_pitch;
+ max_x /= p.pixel_pitch;
+ max_y /= p.pixel_pitch;
+ if ( (min_x < 0.0) && (max_x < 0.0) ) have_pixels = 0;
+ if ( (min_y < 0.0) && (max_y < 0.0) ) have_pixels = 0;
+ if ( (min_x > p.w) && (max_x > p.w) ) have_pixels = 0;
+ if ( (min_y > p.h) && (max_y > p.h) ) have_pixels = 0;
+
+ cairo_restore(cr);
+
+ cairo_arc(cr, 0.0, 0.0, 0.006, 0, 2.0*M_PI);
+ cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
+ cairo_set_line_width(cr, 0.00001);
+ cairo_stroke(cr);
+
+ xs = p.pixel_pitch;
+ ys = p.pixel_pitch;
+ cairo_user_to_device_distance(cr, &xs, &ys);
+ pixel_size_on_screen = smallest(fabs(xs), fabs(ys));
+ if ( (pixel_size_on_screen > 40.0) && have_pixels ) {
+ draw_pixel_values(cr, min_x, min_y, max_x, max_y, p,
+ iv->image->dp[i], iv->image->bad[i]);
+ }
+}
+
+
+static void draw_peaks(cairo_t *cr, CrystFELImageView *iv,
+ ImageFeatureList *pks)
+{
+ int i, n_pks;
+ double bs, lw;
+
+ bs = 5.0; /* Box size in pixels on screen */
+ lw = 1.0; /* Line width in pixels on screen */
+ cairo_device_to_user_distance(cr, &bs, &lw);
+ bs = fabs(bs);
+ lw = fabs(lw);
+
+ n_pks = image_feature_count(pks);
+ for ( i=0; i<n_pks; i++ ) {
+
+ const struct imagefeature *f;
+ struct detgeom_panel *p;
+ double x, y;
+ double this_bs;
+ double this_lw;
+ int show_cen = 0;
+
+ f = image_get_feature_const(pks, i);
+ if ( f == NULL ) continue;
+ p = &iv->image->detgeom->panels[f->pn];
+
+ this_lw = biggest(0.1*p->pixel_pitch, lw);
+ this_bs = biggest(iv->peak_box_size * p->pixel_pitch,
+ bs);
+
+ if ( this_bs > bs ) {
+ show_cen = 1;
+ }
+
+ x = p->pixel_pitch*(p->cnx + p->fsx*f->fs + p->ssx*f->ss);
+ y = p->pixel_pitch*(p->cny + p->fsy*f->fs + p->ssy*f->ss);
+ cairo_rectangle(cr, x-this_bs, y-this_bs, 2*this_bs, 2*this_bs);
+ cairo_set_line_width(cr, this_lw);
+ cairo_set_source_rgba(cr, 1.0, 1.0, 0.0, 0.9);
+ cairo_stroke(cr);
+
+ if ( show_cen ) {
+ cairo_move_to(cr, x-0.2*p->pixel_pitch, y);
+ cairo_line_to(cr, x+0.2*p->pixel_pitch, y);
+ cairo_move_to(cr, x, y-0.2*p->pixel_pitch);
+ cairo_line_to(cr, x, y+0.2*p->pixel_pitch);
+ cairo_set_source_rgba(cr, 0.4, 0.4, 0.0, 0.9);
+ cairo_stroke(cr);
+ }
+
+ }
+}
+
+
+static void draw_refls(cairo_t *cr,
+ CrystFELImageView *iv,
+ RefList *list,
+ int label_reflections,
+ double *colour)
+{
+ const Reflection *refl;
+ RefListIterator *iter;
+ double bs, lw;
+
+ if ( list == NULL ) return;
+
+ bs = 5.0;
+ lw = 1.0;
+ cairo_device_to_user_distance(cr, &bs, &lw);
+ bs = fabs(bs);
+ lw = fabs(lw);
+
+ for ( refl = first_refl_const(list, &iter);
+ refl != NULL;
+ refl = next_refl_const(refl, iter) )
+ {
+ struct detgeom_panel *p;
+ double fs, ss;
+ int pn;
+ double x, y;
+ float this_bs;
+ float this_lw;
+ int show_cen = 0;
+
+ get_detector_pos(refl, &fs, &ss);
+ pn = get_panel_number(refl);
+ p = &iv->image->detgeom->panels[pn];
+
+ this_lw = biggest(0.1*p->pixel_pitch, lw);
+ this_bs = biggest(iv->refl_box_size * p->pixel_pitch,
+ bs);
+
+ if ( this_bs > bs ) {
+ show_cen = 1;
+ }
+
+ x = p->pixel_pitch*(p->cnx + p->fsx*fs + p->ssx*ss);
+ y = p->pixel_pitch*(p->cny + p->fsy*fs + p->ssy*ss);
+
+ cairo_arc(cr, x, y, this_bs, 0, 2*M_PI);
+ cairo_set_line_width(cr, this_lw);
+
+ if ( get_redundancy(refl) == 0 ) {
+ cairo_set_source_rgba(cr, 0.7, 0.0, 0.0, 0.9);
+ } else {
+ cairo_set_source_rgba(cr,
+ colour[0],
+ colour[1],
+ colour[2],
+ 0.9);
+ }
+ cairo_stroke(cr);
+
+ if ( show_cen ) {
+ cairo_move_to(cr, x-0.2*p->pixel_pitch, y);
+ cairo_line_to(cr, x+0.2*p->pixel_pitch, y);
+ cairo_move_to(cr, x, y-0.2*p->pixel_pitch);
+ cairo_line_to(cr, x, y+0.2*p->pixel_pitch);
+ cairo_set_source_rgba(cr,
+ colour[0]/2.0,
+ colour[1]/2.0,
+ colour[2]/2.0,
+ 0.9);
+ cairo_stroke(cr);
+ }
+
+ if ( label_reflections ) {
+
+ signed int h, k, l;
+ char tmp[64];
+
+ get_indices(refl, &h, &k, &l);
+ snprintf(tmp, 64, "%i %i %i", h, k, l);
+
+ cairo_save(cr);
+ cairo_new_path(cr);
+ cairo_move_to(cr, x, y);
+ cairo_set_source_rgba(cr, 0.0, 0.4, 0.0, 0.9);
+ cairo_set_font_size(cr, 11*p->pixel_pitch);
+ cairo_scale(cr, 1.0, -1.0);
+ cairo_show_text(cr, tmp);
+ cairo_fill(cr);
+ cairo_restore(cr);
+
+ }
+
+
+ }
+}
+
+
+static double crystal_cols[][3] =
+{
+ {0.0, 1.0, 0.0}, /* bright green */
+ {1.0, 1.0, 0.0}, /* bright yellow */
+ {0.0, 0.8, 0.8}, /* cyan */
+ {1.0, 1.0, 1.0}, /* white */
+};
+
+static int n_crystal_cols = 4;
+
+
+static gint draw_sig(GtkWidget *window, cairo_t *cr, CrystFELImageView *iv)
+{
+ cairo_matrix_t m;
+
+ if ( iv->image == NULL ) return FALSE;
+ if ( iv->need_rerender ) rerender_image(iv);
+
+ cairo_save(cr);
+
+ /* Overall background (light grey) */
+ cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
+ cairo_paint(cr);
+
+ /* Get the transformation matrix before my transformations */
+ cairo_get_matrix(cr, &m);
+
+ cairo_scale(cr, iv->zoom, iv->zoom);
+ cairo_translate(cr, iv->offs_x, iv->offs_y);
+ cairo_scale(cr, 1.0, -1.0);
+ cairo_translate(cr, -gtk_adjustment_get_value(iv->hadj),
+ gtk_adjustment_get_value(iv->vadj));
+
+ if ( iv->pixbufs != NULL ) {
+ int i;
+ for ( i=0; i<iv->image->detgeom->n_panels; i++ ) {
+ cairo_save(cr);
+ draw_panel_rectangle(cr, iv, i, &m);
+ cairo_restore(cr);
+ }
+ }
+
+ if ( iv->show_peaks ) {
+ draw_peaks(cr, iv, iv->image->features);
+ }
+
+ if ( iv->show_refls ) {
+ int i;
+ for ( i=0; i<iv->image->n_crystals; i++ ) {
+ Crystal *cry = iv->image->crystals[i];
+ draw_refls(cr, iv,
+ crystal_get_reflections(cry),
+ iv->label_refls,
+ crystal_cols[i % n_crystal_cols]);
+ }
+ }
+
+ cairo_restore(cr);
+
+ return FALSE;
+}
+
+
+static void scroll_adjust_sig(GtkAdjustment *adj, CrystFELImageView *iv)
+{
+ redraw(iv);
+}
+
+
+static void crystfel_image_view_set_property(GObject *obj, guint id,
+ const GValue *val,
+ GParamSpec *spec)
+{
+ CrystFELImageView *iv = CRYSTFEL_IMAGE_VIEW(obj);
+
+ switch ( id ) {
+
+ case CRYSTFELIMAGEVIEW_VPOL :
+ iv->vpol = g_value_get_enum(val);
+ break;
+
+ case CRYSTFELIMAGEVIEW_HPOL :
+ iv->hpol = g_value_get_enum(val);
+ break;
+
+ case CRYSTFELIMAGEVIEW_VADJ :
+ iv->vadj = g_value_get_object(val);
+ configure_scroll_adjustments(iv);
+ if ( iv->vadj != NULL ) {
+ g_signal_connect(G_OBJECT(iv->vadj), "value-changed",
+ G_CALLBACK(scroll_adjust_sig), iv);
+ }
+ break;
+
+ case CRYSTFELIMAGEVIEW_HADJ :
+ iv->hadj = g_value_get_object(val);
+ configure_scroll_adjustments(iv);
+ if ( iv->hadj != NULL ) {
+ g_signal_connect(G_OBJECT(iv->hadj), "value-changed",
+ G_CALLBACK(scroll_adjust_sig), iv);
+ }
+ break;
+
+ default :
+ printf("setting %i\n", id);
+ break;
+
+ }
+}
+
+
+static void crystfel_image_view_get_property(GObject *obj, guint id, GValue *val,
+ GParamSpec *spec)
+{
+ CrystFELImageView *iv = CRYSTFEL_IMAGE_VIEW(obj);
+
+ switch ( id ) {
+
+ case CRYSTFELIMAGEVIEW_VADJ :
+ g_value_set_object(val, iv->vadj);
+ break;
+
+ case CRYSTFELIMAGEVIEW_HADJ :
+ g_value_set_object(val, iv->hadj);
+ break;
+
+ case CRYSTFELIMAGEVIEW_VPOL :
+ g_value_set_enum(val, iv->vpol);
+ break;
+
+ case CRYSTFELIMAGEVIEW_HPOL :
+ g_value_set_enum(val, iv->hpol);
+ break;
+
+ default :
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, id, spec);
+ break;
+
+ }
+}
+
+
+static GtkSizeRequestMode get_request_mode(GtkWidget *widget)
+{
+ return GTK_SIZE_REQUEST_CONSTANT_SIZE;
+}
+
+
+static void get_preferred_width(GtkWidget *widget, gint *min, gint *natural)
+{
+ *min = 0;
+ *natural = 640;
+}
+
+
+static void get_preferred_height(GtkWidget *widget, gint *min, gint *natural)
+{
+ *min = 0;
+ *natural = 640;
+}
+
+
+static void crystfel_image_view_class_init(CrystFELImageViewClass *klass)
+{
+ GObjectClass *goc = G_OBJECT_CLASS(klass);
+ goc->set_property = crystfel_image_view_set_property;
+ goc->get_property = crystfel_image_view_get_property;
+ g_object_class_override_property(goc, CRYSTFELIMAGEVIEW_VADJ, "vadjustment");
+ g_object_class_override_property(goc, CRYSTFELIMAGEVIEW_HADJ, "hadjustment");
+ g_object_class_override_property(goc, CRYSTFELIMAGEVIEW_VPOL, "vscroll-policy");
+ g_object_class_override_property(goc, CRYSTFELIMAGEVIEW_HPOL, "hscroll-policy");
+
+ GTK_WIDGET_CLASS(klass)->get_request_mode = get_request_mode;
+ GTK_WIDGET_CLASS(klass)->get_preferred_width = get_preferred_width;
+ GTK_WIDGET_CLASS(klass)->get_preferred_height = get_preferred_height;
+ GTK_WIDGET_CLASS(klass)->get_preferred_height_for_width = NULL;
+}
+
+
+static void crystfel_image_view_init(CrystFELImageView *iv)
+{
+ iv->vpol = GTK_SCROLL_NATURAL;
+ iv->hpol = GTK_SCROLL_NATURAL;
+ iv->vadj = NULL;
+ iv->hadj = NULL;
+}
+
+
+GtkWidget *crystfel_image_view_new()
+{
+ CrystFELImageView *iv;
+
+ iv = g_object_new(CRYSTFEL_TYPE_IMAGE_VIEW, NULL);
+
+ /* All values initially meaningless */
+ iv->detector_w = 1.0;
+ iv->detector_h = 1.0;
+ iv->zoom = -1.0;
+ iv->image = NULL;
+ iv->show_peaks = 0;
+ iv->brightness = 1.0;
+ iv->pixbufs = NULL;
+ iv->peak_box_size = 1.0;
+ iv->refl_box_size = 1.0;
+ iv->label_refls = 1;
+ iv->need_rerender = 0;
+ iv->need_recentre = 1;
+
+ g_signal_connect(G_OBJECT(iv), "destroy",
+ G_CALLBACK(destroy_sig), iv);
+ g_signal_connect(G_OBJECT(iv), "realize",
+ G_CALLBACK(realise_sig), iv);
+ g_signal_connect(G_OBJECT(iv), "button-press-event",
+ G_CALLBACK(button_press_sig), iv);
+ g_signal_connect(G_OBJECT(iv), "scroll-event",
+ G_CALLBACK(scroll_sig), iv);
+ g_signal_connect(G_OBJECT(iv), "motion-notify-event",
+ G_CALLBACK(motion_sig), iv);
+ g_signal_connect(G_OBJECT(iv), "configure-event",
+ G_CALLBACK(configure_sig), iv);
+ g_signal_connect(G_OBJECT(iv), "draw",
+ G_CALLBACK(draw_sig), iv);
+
+ gtk_widget_set_can_focus(GTK_WIDGET(iv), TRUE);
+ gtk_widget_add_events(GTK_WIDGET(iv),
+ GDK_POINTER_MOTION_HINT_MASK
+ | GDK_BUTTON1_MOTION_MASK
+ | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
+ | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK
+ | GDK_SCROLL_MASK);
+
+ gtk_widget_grab_focus(GTK_WIDGET(iv));
+
+ gtk_widget_show(GTK_WIDGET(iv));
+
+ return GTK_WIDGET(iv);
+}
+
+
+static void check_extents(struct detgeom_panel p, double *min_x, double *min_y,
+ double *max_x, double *max_y, double fs, double ss)
+{
+ double xs, ys;
+
+ xs = (fs*p.fsx + ss*p.ssx + p.cnx) * p.pixel_pitch;
+ ys = (fs*p.fsy + ss*p.ssy + p.cny) * p.pixel_pitch;
+
+ if ( xs > *max_x ) *max_x = xs;
+ if ( ys > *max_y ) *max_y = ys;
+ if ( xs < *min_x ) *min_x = xs;
+ if ( ys < *min_y ) *min_y = ys;
+}
+
+
+static void detgeom_pixel_extents(struct detgeom *det,
+ double *min_x, double *min_y,
+ double *max_x, double *max_y)
+{
+ int i;
+
+ *min_x = 0.0;
+ *max_x = 0.0;
+ *min_y = 0.0;
+ *max_y = 0.0;
+
+ /* To determine the maximum extents of the detector, put all four
+ * corners of each panel through the transformations and watch for the
+ * biggest */
+
+ for ( i=0; i<det->n_panels; i++ ) {
+
+ check_extents(det->panels[i], min_x, min_y, max_x, max_y,
+ 0.0, 0.0);
+
+ check_extents(det->panels[i], min_x, min_y, max_x, max_y,
+ 0.0, det->panels[i].h+1);
+
+ check_extents(det->panels[i], min_x, min_y, max_x, max_y,
+ det->panels[i].w+1, 0.0);
+
+ check_extents(det->panels[i], min_x, min_y, max_x, max_y,
+ det->panels[i].w+1, det->panels[i].h+1);
+
+
+ }
+}
+
+
+static void free_pixbuf(guchar *data, gpointer p)
+{
+ free(data);
+}
+
+
+static GdkPixbuf *render_panel(float *data, int *badmap, int w, int h,
+ int scale_type, double scale_top)
+
+
+{
+ guchar *pixbuf_data;
+ long int i;
+
+ /* Rendered (colourful) version */
+ pixbuf_data = malloc(3*w*h);
+ if ( pixbuf_data == NULL ) return NULL;
+
+ for ( i=0; i<w*h; i++ ) {
+
+ double r, g, b;
+
+ if ( !badmap[i] ) {
+
+ colscale_lookup(data[i], scale_top,
+ scale_type, &r, &g, &b);
+
+ pixbuf_data[3*i+0] = 255*r;
+ pixbuf_data[3*i+1] = 255*g;
+ pixbuf_data[3*i+2] = 255*b;
+
+ } else {
+
+ /* Bad pixel indicator colour */
+ pixbuf_data[3*i+0] = 30;
+ pixbuf_data[3*i+1] = 20;
+ pixbuf_data[3*i+2] = 0;
+
+ }
+
+ }
+
+ /* Create the pixbuf from the 8-bit display data */
+ return gdk_pixbuf_new_from_data(pixbuf_data,
+ GDK_COLORSPACE_RGB,
+ FALSE, 8, w, h, w*3,
+ free_pixbuf, NULL);
+
+}
+
+
+static double auto_scale_top(const struct image *image)
+{
+ int pn;
+ double total_mean = 0.0;
+ double total_variance = 0.0;
+
+ for ( pn=0; pn<image->detgeom->n_panels; pn++ ) {
+
+ long int i, j;
+ int w, h;
+ float *data;
+ float this_mean;
+
+ w = image->detgeom->panels[pn].w;
+ h = image->detgeom->panels[pn].h;
+
+ data = malloc(w*h*sizeof(float));
+ if ( data == NULL ) return 100.0;
+
+ j = 0;
+ for ( i=0; i<w*h; i++ ) {
+ if ( !image->bad[pn][i] ) {
+ data[j++] = image->dp[pn][i];
+ }
+ }
+
+ this_mean = gsl_stats_float_mean(data, 1, j);
+
+ total_mean += this_mean;
+ total_variance += gsl_stats_float_variance_m(data, 1, j,
+ this_mean);
+
+ free(data);
+ }
+
+ return (total_mean/image->detgeom->n_panels)
+ + 10.0*sqrt(total_variance/image->detgeom->n_panels);
+}
+
+
+static void center_adjustment(GtkAdjustment *adj)
+{
+ double min = gtk_adjustment_get_lower(adj);
+ double max = gtk_adjustment_get_upper(adj);
+ double page = gtk_adjustment_get_page_size(adj);
+ gtk_adjustment_set_value(adj, min+(max-min-page)/2.0);
+}
+
+
+static int rerender_image(CrystFELImageView *iv)
+{
+ int i;
+ double min_x, min_y, max_x, max_y;
+ double border;
+ double scale_top;
+
+ if ( iv->image == NULL ) return 0;
+ if ( iv->image->detgeom == NULL ) return 0;
+
+ if ( iv->pixbufs == NULL ) {
+ iv->pixbufs = calloc(iv->image->detgeom->n_panels,
+ sizeof(GdkPixbuf *));
+ if ( iv->pixbufs == NULL ) return 1;
+ } else {
+ for ( i=0; i<iv->image->detgeom->n_panels; i++ ) {
+ gdk_pixbuf_unref(iv->pixbufs[i]);
+ }
+ }
+
+ scale_top = auto_scale_top(iv->image);
+
+ for ( i=0; i<iv->image->detgeom->n_panels; i++ ) {
+ iv->pixbufs[i] = render_panel(iv->image->dp[i],
+ iv->image->bad[i],
+ iv->image->detgeom->panels[i].w,
+ iv->image->detgeom->panels[i].h,
+ SCALE_COLOUR, scale_top);
+ if ( iv->pixbufs[i] == NULL ) return 1;
+ }
+
+ detgeom_pixel_extents(iv->image->detgeom, &min_x, &min_y,
+ &max_x, &max_y);
+ iv->detector_w = max_x - min_x;
+ iv->detector_h = max_y - min_y;
+ border = iv->detector_w * 0.1;
+ iv->detector_w += border;
+ iv->detector_h += border;
+ if ( iv->zoom < 0.0 ) {
+ /* Set initial values */
+ iv->offs_x = -min_x + border/2.0;
+ iv->offs_y = max_y + border/2.0;
+ iv->zoom = 1.0/iv->image->detgeom->panels[0].pixel_pitch;
+ }
+ configure_scroll_adjustments(iv);
+ if ( iv->need_recentre ) {
+ center_adjustment(iv->hadj);
+ center_adjustment(iv->vadj);
+ iv->need_recentre = 0;
+ }
+
+ iv->need_rerender = 0;
+ redraw(iv);
+
+ return 0;
+}
+
+
+int crystfel_image_view_set_image(CrystFELImageView *iv,
+ const struct image *image)
+{
+ cleanup_image(iv);
+ iv->image = image;
+ iv->need_rerender = 1;
+ redraw(iv);
+ return 0;
+}
+
+
+void crystfel_image_view_reset_zoom(CrystFELImageView *iv)
+{
+ iv->detector_w = 1.0;
+ iv->detector_h = 1.0;
+ iv->zoom = -1.0;
+ iv->need_recentre = 1;
+ iv->need_rerender = 1;
+ redraw(iv);
+}
+
+
+void crystfel_image_view_set_brightness(CrystFELImageView *iv,
+ double brightness)
+{
+ iv->brightness = brightness;
+ iv->need_rerender = 1;
+ redraw(iv);
+}
+
+
+void crystfel_image_view_set_show_peaks(CrystFELImageView *iv,
+ int show_peaks)
+{
+ iv->show_peaks = show_peaks;
+ iv->need_rerender = 1;
+ redraw(iv);
+}
+
+
+void crystfel_image_view_set_show_reflections(CrystFELImageView *iv,
+ int show_refls)
+{
+ iv->show_refls = show_refls;
+ iv->need_rerender = 1;
+ redraw(iv);
+}
+
+
+void crystfel_image_view_set_label_reflections(CrystFELImageView *iv,
+ int label_refls)
+{
+ iv->label_refls = label_refls;
+ iv->need_rerender = 1;
+ redraw(iv);
+}
+
+
+void crystfel_image_view_set_peak_box_size(CrystFELImageView *iv,
+ float box_size)
+{
+ iv->peak_box_size = box_size;
+ iv->need_rerender = 1;
+ redraw(iv);
+}
+
+
+void crystfel_image_view_set_refl_box_size(CrystFELImageView *iv,
+ float box_size)
+{
+ iv->refl_box_size = box_size;
+ iv->need_rerender = 1;
+ redraw(iv);
+}
diff --git a/src/crystfelimageview.h b/src/crystfelimageview.h
new file mode 100644
index 00000000..31df0fc2
--- /dev/null
+++ b/src/crystfelimageview.h
@@ -0,0 +1,132 @@
+/*
+ * crystfelimageview.h
+ *
+ * CrystFEL's image viewer widget
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef CRYSTFELIMAGEVIEW_H
+#define CRYSTFELIMAGEVIEW_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include <image.h>
+#include <datatemplate.h>
+
+#define CRYSTFEL_TYPE_IMAGE_VIEW (crystfel_image_view_get_type())
+
+#define CRYSTFEL_IMAGE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+ CRYSTFEL_TYPE_IMAGE_VIEW, CrystFELImageView))
+
+#define CRYSTFEL_IS_IMAGE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
+ CRYSTFEL_TYPE_IMAGE_VIEW))
+
+#define CRYSTFEL_IMAGE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((obj), \
+ CRYSTFEL_TYPE_IMAGE_VIEW, CrystFELImageView))
+
+#define CRYSTFEL_IS_IMAGE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), \
+ CRYSTFEL_TYPE_IMAGE_VIEW))
+
+#define CRYSTFEL_IMAGE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \
+ CRYSTFEL_TYPE_IMAGE_VIEW, CrystFELImageView))
+
+struct _crystfelimageview
+{
+ GtkDrawingArea parent_instance;
+
+ /*< private >*/
+ GtkIMContext *im_context;
+
+ /* Detector size in metres */
+ double detector_w;
+ double detector_h;
+
+ /* Redraw/scroll stuff */
+ int need_rerender;
+ int need_recentre;
+ GtkScrollablePolicy hpol;
+ GtkScrollablePolicy vpol;
+ GtkAdjustment *hadj;
+ GtkAdjustment *vadj;
+ double visible_width;
+ double visible_height;
+ double zoom;
+ double drag_start_x;
+ double drag_start_y;
+ double drag_start_sp_x;
+ double drag_start_sp_y;
+ double offs_x;
+ double offs_y;
+
+ const struct image *image;
+
+ GdkPixbuf **pixbufs;
+
+ double brightness;
+ int show_peaks;
+ int show_refls;
+ int label_refls;
+ float peak_box_size;
+ float refl_box_size;
+};
+
+struct _crystfelimageviewclass
+{
+ GtkDrawingAreaClass parent_class;
+};
+
+typedef struct _crystfelimageview CrystFELImageView;
+typedef struct _crystfelimageviewclass CrystFELImageViewClass;
+
+extern GType crystfel_image_view_get_type(void);
+extern GtkWidget *crystfel_image_view_new(void);
+
+extern int crystfel_image_view_set_image(CrystFELImageView *iv,
+ const struct image *image);
+
+extern void crystfel_image_view_reset_zoom(CrystFELImageView *iv);
+
+extern void crystfel_image_view_set_brightness(CrystFELImageView *iv,
+ double brightness);
+
+extern void crystfel_image_view_set_show_peaks(CrystFELImageView *iv,
+ int show_peaks);
+
+extern void crystfel_image_view_set_show_reflections(CrystFELImageView *iv,
+ int show_refls);
+
+extern void crystfel_image_view_set_label_reflections(CrystFELImageView *iv,
+ int label_refls);
+
+extern void crystfel_image_view_set_peak_box_size(CrystFELImageView *iv,
+ float box_size);
+
+extern void crystfel_image_view_set_refl_box_size(CrystFELImageView *iv,
+ float box_size);
+
+#endif /* CRYSTFELIMAGEVIEW_H */
diff --git a/src/crystfelindexingopts.c b/src/crystfelindexingopts.c
new file mode 100644
index 00000000..82e0fa60
--- /dev/null
+++ b/src/crystfelindexingopts.c
@@ -0,0 +1,1139 @@
+/*
+ * crystfelindexingopts.h
+ *
+ * A GTK widget to set indexing options
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <gtk/gtk.h>
+#include <glib-object.h>
+#include <errno.h>
+#include <math.h>
+
+#include <integration.h>
+#include <index.h>
+
+#include "crystfelindexingopts.h"
+#include "gtk-util-routines.h"
+
+
+G_DEFINE_TYPE(CrystFELIndexingOpts,
+ crystfel_indexing_opts,
+ GTK_TYPE_NOTEBOOK)
+
+
+static void crystfel_indexing_opts_class_init(CrystFELIndexingOptsClass *klass)
+{
+}
+
+
+static void crystfel_indexing_opts_init(CrystFELIndexingOpts *io)
+{
+}
+
+
+static void i_disable_if_not(GtkWidget *toggle, GtkWidget *widget)
+{
+ i_maybe_disable(toggle, widget);
+ g_signal_connect(G_OBJECT(toggle),
+ "toggled",
+ G_CALLBACK(i_maybe_disable),
+ widget);
+}
+
+
+static GtkWidget *add_tol(GtkGrid *grid, const char *spec_t,
+ const char *unit_t, gint left, gint top)
+{
+ GtkWidget *spec;
+ GtkWidget *entry;
+ GtkWidget *unit;
+
+ spec = gtk_label_new(spec_t);
+ g_object_set(G_OBJECT(spec), "margin-left", 12, NULL);
+ gtk_grid_attach(grid, spec, left, top, 1, 1);
+
+ entry = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(entry), 5);
+ gtk_grid_attach(grid, entry, left+1, top, 1, 1);
+
+ unit = gtk_label_new(unit_t);
+ g_object_set(G_OBJECT(unit), "margin-right", 12, NULL);
+ gtk_grid_attach(grid, unit, left+2, top, 1, 1);
+
+ return entry;
+}
+
+
+static GtkWidget *make_tolerances(CrystFELIndexingOpts *io)
+{
+ GtkWidget *grid;
+
+ grid = gtk_grid_new();
+ gtk_grid_set_row_spacing(GTK_GRID(grid), 4);
+ gtk_grid_set_column_spacing(GTK_GRID(grid), 4);
+ gtk_container_set_border_width(GTK_CONTAINER(grid), 6);
+
+ io->tols[0] = add_tol(GTK_GRID(grid), "a", "%", 0, 0);
+ io->tols[1] = add_tol(GTK_GRID(grid), "b", "%", 4, 0);
+ io->tols[2] = add_tol(GTK_GRID(grid), "c", "%", 8, 0);
+ io->tols[3] = add_tol(GTK_GRID(grid), "α", "°", 0, 1);
+ io->tols[4] = add_tol(GTK_GRID(grid), "β", "°", 4, 1);
+ io->tols[5] = add_tol(GTK_GRID(grid), "ɣ", "°", 8, 1);
+
+ return grid;
+}
+
+
+static void add_method(GtkListStore *store, const char *name,
+ const char *friendly_name,
+ gboolean enabled, gboolean prior_cell,
+ gboolean prior_latt)
+{
+ GtkTreeIter iter;
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ 0, enabled,
+ 1, friendly_name,
+ 2, prior_cell,
+ 3, prior_latt,
+ 4, name,
+ -1);
+}
+
+
+static void toggle_column(GtkListStore *store,
+ gchar *path_str, int column)
+{
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ gboolean val;
+
+ path = gtk_tree_path_new_from_string(path_str);
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(store),
+ &iter, path);
+ gtk_tree_path_free(path);
+
+ gtk_tree_model_get(GTK_TREE_MODEL(store),
+ &iter, column, &val, -1);
+
+ gtk_list_store_set(store, &iter, column, !val, -1);
+}
+
+
+static void indm_toggled(GtkCellRendererToggle *cr,
+ gchar *path_str,
+ CrystFELIndexingOpts *io)
+{
+ toggle_column(io->indm_store, path_str, 0);
+}
+
+
+static void prior_cell_toggled(GtkCellRendererToggle *cr,
+ gchar *path_str,
+ CrystFELIndexingOpts *io)
+{
+ toggle_column(io->indm_store, path_str, 2);
+}
+
+
+static void prior_latt_toggled(GtkCellRendererToggle *cr,
+ gchar *path_str,
+ CrystFELIndexingOpts *io)
+{
+ toggle_column(io->indm_store, path_str, 3);
+}
+
+
+static GtkWidget *make_indexing_methods(CrystFELIndexingOpts *io)
+{
+ GtkWidget *treeview;
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ io->indm_store = gtk_list_store_new(5,
+ G_TYPE_BOOLEAN, /* Algo on */
+ G_TYPE_STRING, /* Friendly name */
+ G_TYPE_BOOLEAN, /* Prior cell */
+ G_TYPE_BOOLEAN, /* Prior latt */
+ G_TYPE_STRING); /* Real name */
+
+ add_method(io->indm_store, "dirax", "DirAx", TRUE, FALSE, FALSE);
+ add_method(io->indm_store, "mosflm", "MOSFLM", TRUE, TRUE, TRUE);
+ add_method(io->indm_store, "xds", "XDS", TRUE, TRUE, TRUE);
+ add_method(io->indm_store, "xgandalf", "XGANDALF", TRUE, TRUE, FALSE);
+ add_method(io->indm_store, "pinkIndexer", "PinkIndexer", FALSE, TRUE, FALSE);
+ add_method(io->indm_store, "taketwo", "TakeTwo", TRUE, TRUE, FALSE);
+ add_method(io->indm_store, "asdf", "ASDF", TRUE, TRUE, FALSE);
+ add_method(io->indm_store, "felix", "Felix", FALSE, TRUE, FALSE);
+
+ treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(io->indm_store));
+
+ renderer = gtk_cell_renderer_toggle_new();
+ column = gtk_tree_view_column_new_with_attributes(NULL,
+ renderer,
+ "active", 0,
+ NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+ g_signal_connect(G_OBJECT(renderer), "toggled",
+ G_CALLBACK(indm_toggled), io);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes("Method",
+ renderer,
+ "text", 1,
+ NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+
+ renderer = gtk_cell_renderer_toggle_new();
+ column = gtk_tree_view_column_new_with_attributes("Prior unit cell",
+ renderer,
+ "active", 2,
+ NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+ g_signal_connect(G_OBJECT(renderer), "toggled",
+ G_CALLBACK(prior_cell_toggled), io);
+
+ renderer = gtk_cell_renderer_toggle_new();
+ column = gtk_tree_view_column_new_with_attributes("Prior lattice type",
+ renderer,
+ "active", 3,
+ NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+ g_signal_connect(G_OBJECT(renderer), "toggled",
+ G_CALLBACK(prior_latt_toggled), io);
+
+ return treeview;
+}
+
+
+static void cell_file_clear_sig(GtkButton *buton,
+ CrystFELIndexingOpts *io)
+{
+ io->cell_file = NULL;
+ gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(io->cell_chooser),
+ "(none)");
+}
+
+
+static void auto_indm_toggle_sig(GtkToggleButton *togglebutton,
+ CrystFELIndexingOpts *io)
+{
+ gtk_widget_set_sensitive(GTK_WIDGET(io->indm_chooser),
+ !gtk_toggle_button_get_active(togglebutton));
+}
+
+
+static void cell_file_set_sig(GtkFileChooserButton *widget,
+ CrystFELIndexingOpts *io)
+{
+ gchar *filename;
+ filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget));
+ g_free(io->cell_file);
+ io->cell_file = filename;
+}
+
+
+static GtkWidget *indexing_parameters(CrystFELIndexingOpts *io)
+{
+ GtkWidget *box;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ GtkWidget *expander;
+ GtkWidget *frame;
+ GtkWidget *tolerances;
+ GtkWidget *button;
+
+ box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
+ gtk_container_set_border_width(GTK_CONTAINER(box), 8);
+
+ /* Cell file chooser */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("Unit cell file:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ io->cell_chooser = gtk_file_chooser_button_new("Unit cell file",
+ GTK_FILE_CHOOSER_ACTION_OPEN);
+ gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(io->cell_chooser),
+ TRUE);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(io->cell_chooser),
+ FALSE, FALSE, 4.0);
+ g_signal_connect(G_OBJECT(io->cell_chooser), "file-set",
+ G_CALLBACK(cell_file_set_sig), io);
+ button = gtk_button_new_from_icon_name("edit-clear",
+ GTK_ICON_SIZE_BUTTON);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(cell_file_clear_sig), io);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button),
+ FALSE, FALSE, 4.0);
+ gtk_widget_set_tooltip_text(hbox, "-p / --pdb (or CrystFEL format)");
+
+ /* Indexing method selector */
+ io->auto_indm = gtk_check_button_new_with_label("Automatically choose the indexing methods");
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(io->auto_indm),
+ FALSE, FALSE, 4.0);
+ g_signal_connect(G_OBJECT(io->auto_indm), "toggled",
+ G_CALLBACK(auto_indm_toggle_sig), io);
+ expander = gtk_expander_new("Select indexing methods and prior information");
+ frame = gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
+ gtk_container_add(GTK_CONTAINER(expander), GTK_WIDGET(frame));
+ io->indm_chooser = make_indexing_methods(io);
+ gtk_container_add(GTK_CONTAINER(frame),
+ GTK_WIDGET(io->indm_chooser));
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(expander),
+ FALSE, FALSE, 4.0);
+ gtk_container_set_border_width(GTK_CONTAINER(frame), 6);
+
+ /* --multi */
+ io->multi = gtk_check_button_new_with_label("Attempt to find multiple lattices per frame");
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(io->multi),
+ FALSE, FALSE, 4.0);
+ gtk_widget_set_tooltip_text(io->multi, "--multi");
+
+ /* --no-refine (NB inverse) */
+ io->refine = gtk_check_button_new_with_label("Refine the indexing solution");
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(io->refine),
+ FALSE, FALSE, 4.0);
+ gtk_widget_set_tooltip_text(io->refine, "--no-refine");
+
+ /* --no-retry (NB inverse) */
+ io->retry = gtk_check_button_new_with_label("Retry indexing if unsuccessful");
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(io->retry),
+ FALSE, FALSE, 4.0);
+ gtk_widget_set_tooltip_text(io->retry, "--no-retry");
+
+ /* --no-check-peaks (NB inverse) */
+ io->check_peaks = gtk_check_button_new_with_label("Check indexing solutions match peaks");
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(io->check_peaks),
+ FALSE, FALSE, 4.0);
+ gtk_widget_set_tooltip_text(io->check_peaks, "--no-check-peaks");
+
+ /* --no-check-cell (NB inverse) and --tolerance */
+ io->check_cell = gtk_check_button_new_with_label("Check indexing solutions against reference cell");
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(io->check_cell),
+ FALSE, FALSE, 4.0);
+ gtk_widget_set_tooltip_text(io->check_cell, "--no-check-cell");
+ expander = gtk_expander_new("Unit cell tolerances");
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(expander),
+ FALSE, FALSE, 4.0);
+ tolerances = make_tolerances(io);
+ gtk_container_add(GTK_CONTAINER(expander), tolerances);
+ i_disable_if_not(io->check_cell, tolerances);
+ gtk_widget_set_tooltip_text(expander, "--tolerance");
+
+ /* --min-peaks (NB add one) */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ io->enable_hitfind = gtk_check_button_new_with_label("Skip frames with fewer than");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(io->enable_hitfind),
+ FALSE, FALSE, 0.0);
+ io->ignore_fewer_peaks = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(io->ignore_fewer_peaks), 4);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(io->ignore_fewer_peaks),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("peaks");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ i_disable_if_not(io->enable_hitfind, io->ignore_fewer_peaks);
+ gtk_widget_set_tooltip_text(hbox, "--min-peaks");
+
+ gtk_widget_show_all(box);
+
+ return box;
+}
+
+
+static GtkWidget *integration_parameters(CrystFELIndexingOpts *io)
+{
+ GtkWidget *box;
+ GtkWidget *label;
+ GtkWidget *hbox;
+
+ box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+ gtk_container_set_border_width(GTK_CONTAINER(box), 8);
+
+ /* --integration=method */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("Integration method:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ io->integration_combo = gtk_combo_box_text_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(io->integration_combo),
+ FALSE, FALSE, 4.0);
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(io->integration_combo), "none",
+ "No integration (only spot prediction)");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(io->integration_combo), "rings",
+ "Ring summation");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(io->integration_combo), "prof2d",
+ "Two dimensional profile fitting");
+ gtk_widget_set_tooltip_text(hbox, "--integration={none,rings,prof2d}");
+
+ /* -cen */
+ io->centering = gtk_check_button_new_with_label("Center integration boxes on observed reflections");
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(io->centering),
+ FALSE, FALSE, 4.0);
+ gtk_widget_set_tooltip_text(io->centering, "--integration=xxx-cen");
+
+ /* --overpredict */
+ io->overpredict = gtk_check_button_new_with_label("Over-predict reflections (for post-refinement)");
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(io->overpredict),
+ FALSE, FALSE, 4.0);
+ gtk_widget_set_tooltip_text(io->overpredict, "--overpredict");
+
+ /* --push-res */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ io->limit_res = gtk_check_button_new_with_label("Limit prediction to");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(io->limit_res),
+ FALSE, FALSE, 0.0);
+ io->push_res = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(io->push_res), 6);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(io->push_res),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("nm-1 above apparent resolution limit");
+ gtk_label_set_markup(GTK_LABEL(label),
+ "nm<sup>-1</sup> above apparent resolution limit");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ i_disable_if_not(io->limit_res, io->push_res);
+ gtk_widget_set_tooltip_text(io->limit_res, "--push-res");
+
+ /* --int-radii */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+
+ label = gtk_label_new("Integration radii - inner:");
+ gtk_widget_set_tooltip_text(label, "--int-radius=inner,middle,outer");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ io->ir_inn = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(io->ir_inn), 4);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(io->ir_inn),
+ FALSE, FALSE, 4.0);
+
+ label = gtk_label_new("middle:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ io->ir_mid = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(io->ir_mid), 4);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(io->ir_mid),
+ FALSE, FALSE, 4.0);
+
+ label = gtk_label_new("outer:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ io->ir_out = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(io->ir_out), 4);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(io->ir_out),
+ FALSE, FALSE, 4.0);
+
+ /* FIXME: fix-bandwidth, divergence, profile-radius */
+
+ gtk_widget_show_all(box);
+
+ return box;
+}
+
+
+static void add_metadata_item(GtkListStore *model, const char *string)
+{
+ GtkTreeIter iter;
+ gtk_list_store_append(model, &iter);
+ gtk_list_store_set(model, &iter, 0, strdup(string), -1);
+}
+
+
+static gboolean add_metadata_sig(GtkWidget *button, GtkListStore *model)
+{
+ add_metadata_item(model, "/instrument/something");
+ return FALSE;
+}
+
+
+static gboolean edit_metadata_sig(GtkCellRendererText *cell,
+ const gchar *path_str,
+ const gchar *new_text,
+ GtkListStore *model)
+{
+ GtkTreeIter iter;
+ gchar *old_text;
+ GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path);
+ gtk_tree_path_free(path);
+ gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &old_text, -1);
+ g_free(old_text);
+ gtk_list_store_set(model, &iter,
+ 0, g_strdup(new_text),
+ -1);
+ return FALSE;
+}
+
+
+static gboolean remove_metadata_sig(GtkWidget *button,
+ GtkTreeView *treeview)
+{
+ GtkTreeSelection *sel;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+
+ model = gtk_tree_view_get_model(treeview);
+ sel = gtk_tree_view_get_selection(treeview);
+ if ( gtk_tree_selection_get_selected(sel, NULL, &iter) != 0 ) {
+ gchar *old_text;
+ gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &old_text, -1);
+ g_free(old_text);
+ gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
+ }
+
+ return FALSE;
+}
+
+
+static GtkWidget *stream_parameters(CrystFELIndexingOpts *io)
+{
+ GtkWidget *box;
+ GtkWidget *treeview;
+ GtkCellRenderer *renderer;
+ GtkWidget *button;
+ GtkWidget *hbox;
+
+ box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+ gtk_container_set_border_width(GTK_CONTAINER(box), 8);
+
+ /* --no-non-hits-in-stream */
+ io->exclude_nonhits = gtk_check_button_new_with_label("Exclude skipped frames from stream");
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(io->exclude_nonhits),
+ FALSE, FALSE, 4.0);
+ gtk_widget_set_tooltip_text(io->exclude_nonhits,
+ "--no-non-hits-in-stream");
+
+ /* --no-peaks-in-stream */
+ io->no_peaks_in_stream = gtk_check_button_new_with_label("Exclude peak search results from stream");
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(io->no_peaks_in_stream),
+ FALSE, FALSE, 4.0);
+ gtk_widget_set_tooltip_text(io->no_peaks_in_stream,
+ "--no-peaks-in-stream");
+
+ /* --no-refls-in-stream */
+ io->no_refls_in_stream = gtk_check_button_new_with_label("Exclude integrated intensities from stream");
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(io->no_refls_in_stream),
+ FALSE, FALSE, 4.0);
+ gtk_widget_set_tooltip_text(io->no_refls_in_stream,
+ "--no-refls-in-stream");
+
+ io->copy_metadata_store = gtk_list_store_new(1, G_TYPE_STRING);
+
+ treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(io->copy_metadata_store));
+
+ renderer = gtk_cell_renderer_text_new();
+ g_object_set(renderer, "editable", TRUE, NULL);
+ g_signal_connect(G_OBJECT(renderer), "edited",
+ G_CALLBACK(edit_metadata_sig),
+ io->copy_metadata_store);
+ gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview),
+ -1,
+ "Metadata to copy to stream",
+ renderer,
+ "text", 0,
+ NULL);
+
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(treeview),
+ FALSE, FALSE, 4.0);
+ gtk_widget_set_tooltip_text(box, "--copy-header / --copy-hdf5-field");
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
+ gtk_container_set_border_width(GTK_CONTAINER(hbox), 8);
+ button = gtk_button_new_from_icon_name("list-add", GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_label(GTK_BUTTON(button), "Add item");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(add_metadata_sig), io->copy_metadata_store);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button),
+ FALSE, FALSE, 4.0);
+ button = gtk_button_new_from_icon_name("list-remove", GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_label(GTK_BUTTON(button), "Remove item");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(remove_metadata_sig), treeview);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button),
+ FALSE, FALSE, 4.0);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+
+ gtk_widget_show_all(box);
+
+ return box;
+}
+
+
+GtkWidget *crystfel_indexing_opts_new()
+{
+ CrystFELIndexingOpts *io;
+
+ io = g_object_new(CRYSTFEL_TYPE_INDEXING_OPTS, NULL);
+
+ io->cell_file = NULL;
+ gtk_notebook_set_tab_pos(GTK_NOTEBOOK(io), GTK_POS_LEFT);
+
+ gtk_notebook_append_page(GTK_NOTEBOOK(io),
+ indexing_parameters(io),
+ gtk_label_new("Indexing"));
+
+ gtk_notebook_append_page(GTK_NOTEBOOK(io),
+ integration_parameters(io),
+ gtk_label_new("Integration"));
+
+ io->stream_params = stream_parameters(io);
+ gtk_notebook_append_page(GTK_NOTEBOOK(io), io->stream_params,
+ gtk_label_new("Stream contents"));
+
+ return GTK_WIDGET(io);
+}
+
+
+char *crystfel_indexing_opts_get_cell_file(CrystFELIndexingOpts *opts)
+{
+ return safe_strdup(opts->cell_file);
+}
+
+
+/* NULL means "automatic".
+ * "none" means "no indexing" */
+char *crystfel_indexing_opts_get_indexing_method_string(CrystFELIndexingOpts *opts)
+{
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ char indm_str[1024];
+ int first = 1;
+
+ if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opts->auto_indm)) ) {
+ return NULL;
+ }
+
+ path = gtk_tree_path_new_from_string("0");
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(opts->indm_store),
+ &iter, path);
+ gtk_tree_path_free(path);
+
+ indm_str[0] = '\0';
+ do {
+ gboolean enabled, prior_cell, prior_latt;
+ gchar *name;
+
+ gtk_tree_model_get(GTK_TREE_MODEL(opts->indm_store),
+ &iter,
+ 0, &enabled,
+ 2, &prior_cell,
+ 3, &prior_latt,
+ 4, &name,
+ -1);
+
+ if ( enabled ) {
+ if ( !first ) {
+ strcat(indm_str, ",");
+ }
+ first = 0;
+ strcat(indm_str, name);
+ if ( prior_cell ) {
+ strcat(indm_str, "-cell");
+ }
+ if ( prior_latt ) {
+ strcat(indm_str, "-latt");
+ }
+ }
+
+ } while ( gtk_tree_model_iter_next(GTK_TREE_MODEL(opts->indm_store),
+ &iter) );
+
+ if ( indm_str[0] == '\0' ) {
+ strcpy(indm_str, "none");
+ }
+ return strdup(indm_str);
+}
+
+
+int crystfel_indexing_opts_get_multi_lattice(CrystFELIndexingOpts *opts)
+{
+ return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opts->multi));
+}
+
+
+int crystfel_indexing_opts_get_refine(CrystFELIndexingOpts *opts)
+{
+ return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opts->refine));
+}
+
+
+int crystfel_indexing_opts_get_retry(CrystFELIndexingOpts *opts)
+{
+ return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opts->retry));
+}
+
+
+int crystfel_indexing_opts_get_peak_check(CrystFELIndexingOpts *opts)
+{
+ return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opts->check_peaks));
+}
+
+
+int crystfel_indexing_opts_get_cell_check(CrystFELIndexingOpts *opts)
+{
+ return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opts->check_cell));
+}
+
+
+
+/* Values in 'tols' are in frac (not %) and rad */
+void crystfel_indexing_opts_get_tolerances(CrystFELIndexingOpts *opts,
+ float *tols)
+{
+ int i;
+ for ( i=0; i<3; i++ ) {
+ float tol;
+ char *rval;
+ const gchar *text = gtk_entry_get_text(GTK_ENTRY(opts->tols[i]));
+ errno = 0;
+ tol = strtod(text, &rval);
+ if ( *rval != '\0' ) {
+ printf("Invalid tolerance '%s'\n", text);
+ } else {
+ tols[i] = tol / 100.0;
+ }
+ }
+ for ( i=3; i<6; i++ ) {
+ float tol;
+ char *rval;
+ const gchar *text = gtk_entry_get_text(GTK_ENTRY(opts->tols[i]));
+ errno = 0;
+ tol = strtod(text, &rval);
+ if ( *rval != '\0' ) {
+ printf("Invalid tolerance '%s'\n", text);
+ } else {
+ tols[i] = deg2rad(tol);
+ }
+ }
+}
+
+
+int crystfel_indexing_opts_get_min_peaks(CrystFELIndexingOpts *opts)
+{
+ if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opts->enable_hitfind)) ) {
+ const gchar *text;
+ int fewer_peaks;
+ char *rval;
+ text = gtk_entry_get_text(GTK_ENTRY(opts->ignore_fewer_peaks));
+ errno = 0;
+ fewer_peaks = strtod(text, &rval);
+ if ( *rval != '\0' ) {
+ printf("Invalid value for minimum number of peaks (%s)\n",
+ rval);
+ return 0;
+ }
+ /* Subtract one because the dialog box says to skip
+ * frames with "FEWER THAN" this number */
+ return fewer_peaks - 1;
+ } else {
+ return 0;
+ }
+}
+
+
+char *crystfel_indexing_opts_get_integration_method_string(CrystFELIndexingOpts *opts)
+{
+ const gchar *id;
+ char method[64];
+
+ id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(opts->integration_combo));
+ if ( id == NULL ) return strdup("none");
+
+ strcpy(method, id);
+ if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opts->centering)) ) {
+ strcat(method, "-cen");
+ }
+
+ return strdup(method);
+}
+
+
+int crystfel_indexing_opts_get_overpredict(CrystFELIndexingOpts *opts)
+{
+ return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opts->overpredict));
+}
+
+
+float crystfel_indexing_opts_get_push_res(CrystFELIndexingOpts *opts)
+{
+ if ( !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opts->limit_res)) ) {
+ return INFINITY;
+ } else {
+ const gchar *text;
+ float push_res;
+ char *rval;
+ text = gtk_entry_get_text(GTK_ENTRY(opts->push_res));
+ errno = 0;
+ push_res = strtof(text, &rval);
+ if ( *rval != '\0' ) {
+ printf("Invalid value for push-res (%s)\n",
+ rval);
+ return INFINITY;
+ }
+ return push_res;
+ }
+}
+
+
+void crystfel_indexing_opts_get_integration_radii(CrystFELIndexingOpts *opts,
+ float *ir_inn,
+ float *ir_mid,
+ float *ir_out)
+{
+ *ir_inn = get_float(opts->ir_inn);
+ *ir_mid = get_float(opts->ir_mid);
+ *ir_out = get_float(opts->ir_out);
+}
+
+
+int crystfel_indexing_opts_get_exclude_blanks(CrystFELIndexingOpts *opts)
+{
+ return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opts->exclude_nonhits));
+}
+
+
+int crystfel_indexing_opts_get_exclude_peaks(CrystFELIndexingOpts *opts)
+{
+ return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opts->no_peaks_in_stream));
+}
+
+
+int crystfel_indexing_opts_get_exclude_reflections(CrystFELIndexingOpts *opts)
+{
+ return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opts->no_refls_in_stream));
+}
+
+
+char **crystfel_indexing_opts_get_metadata_to_copy(CrystFELIndexingOpts *opts,
+ int *pn)
+{
+ GtkTreeIter iter;
+ gboolean r;
+ int n, i;
+ char **arr;
+
+ n = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(opts->copy_metadata_store),
+ NULL);
+
+ arr = malloc(n*sizeof(char *));
+ if ( arr == NULL ) return NULL;
+
+ r = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(opts->copy_metadata_store),
+ &iter);
+ if ( r == FALSE ) return NULL;
+
+ i = 0;
+ do {
+ gchar *header;
+ gtk_tree_model_get(GTK_TREE_MODEL(opts->copy_metadata_store),
+ &iter, 0, &header, -1);
+ if ( i == n ) return NULL;
+ arr[i++] = strdup(header);
+ } while ( gtk_tree_model_iter_next(GTK_TREE_MODEL(opts->copy_metadata_store),
+ &iter) != FALSE );
+
+ *pn = n;
+ return arr;
+}
+
+
+/********************** Setters *************************/
+
+
+void crystfel_indexing_opts_set_show_stream_opts(CrystFELIndexingOpts *opts,
+ int val)
+{
+ opts->show_stream_opts = val;
+ if ( val ) {
+ gtk_widget_show_all(opts->stream_params);
+ } else {
+ gtk_widget_hide(opts->stream_params);
+ }
+}
+
+
+void crystfel_indexing_opts_set_cell_file(CrystFELIndexingOpts *opts,
+ const char *cell_file)
+{
+ if ( cell_file != NULL ) {
+ gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(opts->cell_chooser),
+ cell_file);
+ opts->cell_file = strdup(cell_file);
+ } else {
+ gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(opts->cell_chooser),
+ "(null)");
+ opts->cell_file = NULL;
+ }
+}
+
+
+static const char *integration_method_id(IntegrationMethod meth)
+{
+ switch ( meth ) {
+ case INTEGRATION_NONE : return "none";
+ case INTEGRATION_RINGS : return "rings";
+ case INTEGRATION_PROF2D : return "prof2d";
+ default : return "none";
+ }
+}
+
+
+void crystfel_indexing_opts_set_indexing_method_string(CrystFELIndexingOpts *opts,
+ const char *indm_str)
+{
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ IndexingMethod *methods;
+ int i, n;
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->auto_indm),
+ (indm_str == NULL));
+ if ( indm_str == NULL ) return;
+
+ methods = parse_indexing_methods(indm_str, &n);
+ if ( methods == NULL ) {
+ ERROR("Failed to parse '%s'\n", indm_str);
+ return;
+ }
+
+ path = gtk_tree_path_new_from_string("0");
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(opts->indm_store),
+ &iter, path);
+ gtk_tree_path_free(path);
+
+ do {
+ gchar *name;
+ IndexingMethod this_method = 0;
+
+ gtk_tree_model_get(GTK_TREE_MODEL(opts->indm_store),
+ &iter,
+ 4, &name,
+ -1);
+
+ for ( i=0; i<n; i++ ) {
+ char *str = base_indexer_str(methods[i]);
+ if ( strcmp(str, name) == 0 ) {
+ this_method = methods[i];
+ break;
+ }
+ }
+
+ gtk_list_store_set(opts->indm_store, &iter,
+ 0, (this_method != 0),
+ 2, (this_method & INDEXING_USE_CELL_PARAMETERS),
+ 3, (this_method & INDEXING_USE_LATTICE_TYPE),
+ -1);
+
+ } while ( gtk_tree_model_iter_next(GTK_TREE_MODEL(opts->indm_store),
+ &iter) );
+
+ free(methods);
+}
+
+
+void crystfel_indexing_opts_set_multi_lattice(CrystFELIndexingOpts *opts,
+ int multi)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->multi),
+ multi);
+}
+
+
+void crystfel_indexing_opts_set_refine(CrystFELIndexingOpts *opts,
+ int refine)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->refine),
+ refine);
+}
+
+
+void crystfel_indexing_opts_set_retry(CrystFELIndexingOpts *opts,
+ int retry)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->retry),
+ retry);
+}
+
+
+void crystfel_indexing_opts_set_peak_check(CrystFELIndexingOpts *opts,
+ int peak_check)
+
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->check_peaks),
+ peak_check);
+}
+
+
+void crystfel_indexing_opts_set_cell_check(CrystFELIndexingOpts *opts,
+ int cell_check)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->check_cell),
+ cell_check);
+}
+
+
+/* Values in 'tols' are in frac (not %) and rad */
+void crystfel_indexing_opts_set_tolerances(CrystFELIndexingOpts *opts,
+ float *tols)
+{
+ int i;
+ for ( i=0; i<3; i++ ) {
+ char tmp[64];
+ snprintf(tmp, 63, "%f", tols[i]*100.0);
+ gtk_entry_set_text(GTK_ENTRY(opts->tols[i]), tmp);
+ }
+ for ( i=3; i<6; i++ ) {
+ char tmp[64];
+ snprintf(tmp, 63, "%f", rad2deg(tols[i]));
+ gtk_entry_set_text(GTK_ENTRY(opts->tols[i]), tmp);
+ }
+}
+
+
+void crystfel_indexing_opts_set_min_peaks(CrystFELIndexingOpts *opts,
+ int min_peaks)
+{
+ char tmp[64];
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->enable_hitfind),
+ (min_peaks > 0));
+
+ /* Plus one because dialog says skip when "fewer than" X peaks */
+ snprintf(tmp, 63, "%i", min_peaks+1);
+ gtk_entry_set_text(GTK_ENTRY(opts->ignore_fewer_peaks), tmp);
+}
+
+
+void crystfel_indexing_opts_set_integration_method_string(CrystFELIndexingOpts *opts,
+ const char *integr_str)
+{
+ IntegrationMethod meth;
+ int err;
+
+ meth = integration_method(integr_str, &err);
+ if ( !err ) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->centering),
+ meth & INTEGRATION_CENTER);
+ gtk_combo_box_set_active_id(GTK_COMBO_BOX(opts->integration_combo),
+ integration_method_id(meth & INTEGRATION_METHOD_MASK));
+ }
+}
+
+
+void crystfel_indexing_opts_set_overpredict(CrystFELIndexingOpts *opts,
+ int overpredict)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->overpredict),
+ overpredict);
+}
+
+
+void crystfel_indexing_opts_set_push_res(CrystFELIndexingOpts *opts,
+ float push_res)
+{
+ char tmp[64];
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->limit_res),
+ !isinf(push_res));
+
+ snprintf(tmp, 63, "%f", push_res);
+ gtk_entry_set_text(GTK_ENTRY(opts->push_res), tmp);
+}
+
+
+void crystfel_indexing_opts_set_integration_radii(CrystFELIndexingOpts *opts,
+ float ir_inn,
+ float ir_mid,
+ float ir_out)
+{
+ char tmp[64];
+
+ snprintf(tmp, 63, "%.1f", ir_inn);
+ gtk_entry_set_text(GTK_ENTRY(opts->ir_inn), tmp);
+
+ snprintf(tmp, 63, "%.1f", ir_mid);
+ gtk_entry_set_text(GTK_ENTRY(opts->ir_mid), tmp);
+
+ snprintf(tmp, 63, "%.1f", ir_out);
+ gtk_entry_set_text(GTK_ENTRY(opts->ir_out), tmp);
+}
+
+
+void crystfel_indexing_opts_set_metadata_to_copy(CrystFELIndexingOpts *opts,
+ char *const *headers,
+ int n)
+{
+ int i;
+ gtk_list_store_clear(opts->copy_metadata_store);
+ if ( headers == NULL ) return;
+ for ( i=0; i<n; i++ ) {
+ add_metadata_item(opts->copy_metadata_store,
+ headers[i]);
+ }
+}
+
+
+void crystfel_indexing_opts_set_exclude_blanks(CrystFELIndexingOpts *opts,
+ int flag)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->exclude_nonhits),
+ flag);
+}
+
+
+void crystfel_indexing_opts_set_exclude_peaks(CrystFELIndexingOpts *opts,
+ int flag)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->no_peaks_in_stream),
+ flag);
+}
+
+
+void crystfel_indexing_opts_set_exclude_reflections(CrystFELIndexingOpts *opts,
+ int flag)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->no_refls_in_stream),
+ flag);
+}
diff --git a/src/crystfelindexingopts.h b/src/crystfelindexingopts.h
new file mode 100644
index 00000000..72ca8c37
--- /dev/null
+++ b/src/crystfelindexingopts.h
@@ -0,0 +1,166 @@
+/*
+ * crystfelindexingopts.h
+ *
+ * A GTK widget to set indexing options
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef CRYSTFELINDEXINGOPTS_H
+#define CRYSTFELINDEXINGOPTS_H
+
+#include <gtk/gtk.h>
+#include <glib-object.h>
+
+#define CRYSTFEL_TYPE_INDEXING_OPTS (crystfel_indexing_opts_get_type())
+
+#define CRYSTFEL_INDEXING_OPTS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+ CRYSTFEL_TYPE_INDEXING_OPTS, CrystFELIndexingOpts))
+
+#define CRYSTFEL_IS_INDEXING_OPTS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
+ CRYSTFEL_TYPE_INDEXING_OPTS))
+
+#define CRYSTFEL_INDEXING_OPTS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((obj), \
+ CRYSTFEL_TYPE_INDEXING_OPTS, CrystFELIndexingOpts))
+
+#define CRYSTFEL_IS_INDEXING_OPTS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), \
+ CRYSTFEL_TYPE_INDEXING_OPTS))
+
+#define CRYSTFEL_INDEXING_OPTS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \
+ CRYSTFEL_TYPE_INDEXING_OPTS, CrystFELIndexingOpts))
+
+struct _crystfelindexingopts
+{
+ GtkNotebook parent_instance;
+
+ /*< private >*/
+ int show_stream_opts;
+ GtkWidget *stream_params; /* Stream output page */
+
+ char *cell_file;
+ GtkWidget *cell_chooser;
+ GtkWidget *auto_indm;
+ GtkWidget *indm_chooser;
+ GtkListStore *indm_store;
+ GtkWidget *multi;
+ GtkWidget *refine;
+ GtkWidget *retry;
+ GtkWidget *check_peaks;
+ GtkWidget *check_cell;
+ GtkWidget *tols[6]; /* frac (not %) and radians */
+ GtkWidget *enable_hitfind;
+ GtkWidget *ignore_fewer_peaks;
+
+ GtkWidget *integration_combo;
+ GtkWidget *centering;
+ GtkWidget *overpredict;
+ GtkWidget *limit_res;
+ GtkWidget *push_res;
+ GtkWidget *ir_inn;
+ GtkWidget *ir_mid;
+ GtkWidget *ir_out;
+
+ GtkWidget *exclude_nonhits;
+ GtkWidget *no_peaks_in_stream;
+ GtkWidget *no_refls_in_stream;
+ GtkListStore *copy_metadata_store;
+};
+
+struct _crystfelindexingoptsclass
+{
+ GtkNotebookClass parent_class;
+};
+
+typedef struct _crystfelindexingopts CrystFELIndexingOpts;
+typedef struct _crystfelindexingoptsclass CrystFELIndexingOptsClass;
+
+extern GType crystfel_indexing_opts_get_type(void);
+extern GtkWidget *crystfel_indexing_opts_new(void);
+
+extern char *crystfel_indexing_opts_get_cell_file(CrystFELIndexingOpts *opts);
+extern char *crystfel_indexing_opts_get_indexing_method_string(CrystFELIndexingOpts *opts);
+extern int crystfel_indexing_opts_get_multi_lattice(CrystFELIndexingOpts *opts);
+extern int crystfel_indexing_opts_get_refine(CrystFELIndexingOpts *opts);
+extern int crystfel_indexing_opts_get_retry(CrystFELIndexingOpts *opts);
+extern int crystfel_indexing_opts_get_peak_check(CrystFELIndexingOpts *opts);
+extern int crystfel_indexing_opts_get_cell_check(CrystFELIndexingOpts *opts);
+extern void crystfel_indexing_opts_get_tolerances(CrystFELIndexingOpts *opts,
+ float *tols); /* frac (not %) and rad */
+extern int crystfel_indexing_opts_get_min_peaks(CrystFELIndexingOpts *opts);
+
+extern char *crystfel_indexing_opts_get_integration_method_string(CrystFELIndexingOpts *opts);
+extern int crystfel_indexing_opts_get_overpredict(CrystFELIndexingOpts *opts);
+extern float crystfel_indexing_opts_get_push_res(CrystFELIndexingOpts *opts);
+extern void crystfel_indexing_opts_get_integration_radii(CrystFELIndexingOpts *opts,
+ float *ir_inn,
+ float *ir_mid,
+ float *ir_out);
+extern int crystfel_indexing_opts_get_exclude_blanks(CrystFELIndexingOpts *opts);
+extern int crystfel_indexing_opts_get_exclude_peaks(CrystFELIndexingOpts *opts);
+extern int crystfel_indexing_opts_get_exclude_reflections(CrystFELIndexingOpts *opts);
+extern char **crystfel_indexing_opts_get_metadata_to_copy(CrystFELIndexingOpts *opts,
+ int *n);
+
+extern void crystfel_indexing_opts_set_show_stream_opts(CrystFELIndexingOpts *opts,
+ int val);
+
+extern void crystfel_indexing_opts_set_cell_file(CrystFELIndexingOpts *opts,
+ const char *cell_file);
+extern void crystfel_indexing_opts_set_indexing_method_string(CrystFELIndexingOpts *opts,
+ const char *indm_str);
+extern void crystfel_indexing_opts_set_multi_lattice(CrystFELIndexingOpts *opts,
+ int multi);
+extern void crystfel_indexing_opts_set_refine(CrystFELIndexingOpts *opts,
+ int refine);
+extern void crystfel_indexing_opts_set_retry(CrystFELIndexingOpts *opts,
+ int retry);
+extern void crystfel_indexing_opts_set_peak_check(CrystFELIndexingOpts *opts,
+ int peak_check);
+extern void crystfel_indexing_opts_set_cell_check(CrystFELIndexingOpts *opts,
+ int cell_check);
+extern void crystfel_indexing_opts_set_tolerances(CrystFELIndexingOpts *opts,
+ float *tols); /* frac (not %) and rad */
+extern void crystfel_indexing_opts_set_min_peaks(CrystFELIndexingOpts *opts,
+ int min_peaks);
+
+extern void crystfel_indexing_opts_set_integration_method_string(CrystFELIndexingOpts *opts,
+ const char *integr_str);
+extern void crystfel_indexing_opts_set_overpredict(CrystFELIndexingOpts *opts,
+ int overpredict);
+extern void crystfel_indexing_opts_set_push_res(CrystFELIndexingOpts *opts,
+ float push_res);
+extern void crystfel_indexing_opts_set_integration_radii(CrystFELIndexingOpts *opts,
+ float ir_inn,
+ float ir_mid,
+ float ir_out);
+extern void crystfel_indexing_opts_set_metadata_to_copy(CrystFELIndexingOpts *opts,
+ char *const *headers,
+ int n_headers);
+extern void crystfel_indexing_opts_set_exclude_blanks(CrystFELIndexingOpts *opts,
+ int flag);
+extern void crystfel_indexing_opts_set_exclude_peaks(CrystFELIndexingOpts *opts,
+ int flag);
+extern void crystfel_indexing_opts_set_exclude_reflections(CrystFELIndexingOpts *opts,
+ int flag);
+
+#endif /* CRYSTFELINDEXINGOPTS_H */
diff --git a/src/crystfelmergeopts.c b/src/crystfelmergeopts.c
new file mode 100644
index 00000000..40411852
--- /dev/null
+++ b/src/crystfelmergeopts.c
@@ -0,0 +1,613 @@
+/*
+ * crystfelmergeopts.h
+ *
+ * A GTK widget to set merge options
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <gtk/gtk.h>
+#include <glib-object.h>
+#include <errno.h>
+#include <math.h>
+
+#include <integration.h>
+#include <index.h>
+
+#include "crystfelmergeopts.h"
+#include "crystfelsymmetryselector.h"
+#include "gtk-util-routines.h"
+
+
+G_DEFINE_TYPE(CrystFELMergeOpts,
+ crystfel_merge_opts,
+ GTK_TYPE_NOTEBOOK)
+
+
+static void crystfel_merge_opts_class_init(CrystFELMergeOptsClass *klass)
+{
+}
+
+
+static void crystfel_merge_opts_init(CrystFELMergeOpts *mo)
+{
+}
+
+
+static void disable_if_inactive(GtkWidget *toggle, GtkWidget *widget)
+{
+ gtk_widget_set_sensitive(GTK_WIDGET(widget),
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle)));
+}
+
+
+static void deactivate_if_inactive(GtkWidget *toggle, GtkWidget *widget)
+{
+ if ( !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle)) ) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE);
+ }
+}
+
+
+static void disable_and_deactivate(GtkWidget *toggle)
+{
+ gtk_widget_set_sensitive(toggle, FALSE);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), FALSE);
+}
+
+
+static int check_greyout(GtkWidget *nothing, CrystFELMergeOpts *mo)
+{
+ int partialate;
+
+ partialate = (gtk_combo_box_get_active(GTK_COMBO_BOX(mo->model_combo)) != 0);
+
+ if ( !partialate ) {
+ gtk_widget_set_sensitive(GTK_WIDGET(mo->niter), FALSE);
+ disable_and_deactivate(mo->bscale);
+ disable_and_deactivate(mo->postref);
+ disable_and_deactivate(mo->deltacchalf);
+ disable_and_deactivate(mo->custom_split);
+ disable_and_deactivate(mo->detwin);
+ } else {
+ gtk_widget_set_sensitive(GTK_WIDGET(mo->niter), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(mo->bscale), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(mo->postref), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(mo->deltacchalf), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(mo->custom_split), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(mo->detwin), TRUE);
+ disable_if_inactive(mo->use_max_adu, mo->max_adu);
+ disable_if_inactive(mo->custom_split, mo->custom_split_file);
+ disable_if_inactive(mo->min_res, mo->min_res_val);
+ disable_if_inactive(mo->limit_res, mo->push_res);
+ disable_if_inactive(mo->detwin, mo->detwin_sym);
+ disable_if_inactive(mo->scale, mo->bscale);
+ deactivate_if_inactive(mo->scale, mo->bscale);
+ }
+
+ return FALSE;
+}
+
+
+static void check_on_toggle(GtkWidget *toggle, CrystFELMergeOpts *mo)
+{
+ g_signal_connect(G_OBJECT(toggle),
+ "toggled",
+ G_CALLBACK(check_greyout),
+ mo);
+}
+
+
+static GtkWidget *merge_parameters(CrystFELMergeOpts *mo)
+{
+ GtkWidget *box;
+ GtkWidget *hbox;
+ GtkWidget *label;
+
+ box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+ gtk_container_set_border_width(GTK_CONTAINER(box), 8);
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ label = gtk_label_new("Model:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+ mo->model_combo = gtk_combo_box_text_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->model_combo),
+ FALSE, FALSE, 0);
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(mo->model_combo),
+ "process_hkl",
+ "Simple merging (process_hkl)");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(mo->model_combo),
+ "unity",
+ "No partialities (unity)");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(mo->model_combo),
+ "xsphere",
+ "Bandwidth integral (xsphere)");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(mo->model_combo),
+ "offset",
+ "Monochromatic Ewald sphere offset (offset)");
+ g_signal_connect(G_OBJECT(mo->model_combo), "changed",
+ G_CALLBACK(check_greyout), mo);
+ gtk_widget_set_tooltip_text(hbox, "--model");
+
+ /* Symmetry */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ label = gtk_label_new("Symmetry:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+ mo->symmetry = crystfel_symmetry_selector_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->symmetry),
+ FALSE, FALSE, 0);
+ gtk_widget_set_tooltip_text(hbox, "--symmetry");
+
+ /* Scale, Bscale, post-ref on/off */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ mo->scale = gtk_check_button_new_with_label("Scale intensities");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->scale),
+ FALSE, FALSE, 0);
+ gtk_widget_set_tooltip_text(mo->scale, "--scale / --no-scale");
+ mo->bscale = gtk_check_button_new_with_label("Debye-Waller scaling");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->bscale),
+ FALSE, FALSE, 0);
+ gtk_widget_set_tooltip_text(mo->bscale, "--no-Bscale");
+ mo->postref = gtk_check_button_new_with_label("Post-refinement");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->postref),
+ FALSE, FALSE, 0);
+ gtk_widget_set_tooltip_text(mo->postref, "--no-pr");
+ check_on_toggle(mo->scale, mo);
+
+ /* Number of iterations */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ label = gtk_label_new("Number of scaling/post-refinement cycles:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+ mo->niter = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(mo->niter), 4);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->niter),
+ FALSE, FALSE, 0);
+ gtk_widget_set_tooltip_text(hbox, "--iterations");
+
+ /* Polarisation horiz/vert/unpolarized beam/no correction */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ label = gtk_label_new("Polarisation:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+ mo->polarisation = gtk_combo_box_text_new();
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(mo->polarisation), "horiz",
+ "Horizontal e-field (most synchrotrons and FELs)");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(mo->polarisation), "vert",
+ "Vertical e-field (LCLS-II hard X-ray undulator)");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(mo->polarisation), "horiz50",
+ "Unpolarized incident beam");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(mo->polarisation), "none",
+ "No correction");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->polarisation),
+ FALSE, FALSE, 0);
+ gtk_widget_set_tooltip_text(hbox, "--polarisation={horiz,vert,horiz50,none}");
+
+ /* deltaCChalf */
+ mo->deltacchalf = gtk_check_button_new_with_label("Reject bad patterns according to ΔCC½");
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(mo->deltacchalf),
+ FALSE, FALSE, 0);
+ gtk_widget_set_tooltip_text(mo->deltacchalf, "--no-deltacchalf");
+
+ /* Detector saturation value */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ mo->use_max_adu = gtk_check_button_new_with_label("Detector saturation cutoff:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->use_max_adu),
+ FALSE, FALSE, 0);
+ mo->max_adu = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(mo->max_adu), 8);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->max_adu),
+ FALSE, FALSE, 0);
+ check_on_toggle(mo->use_max_adu, mo);
+ gtk_widget_set_tooltip_text(hbox, "--max-adu");
+
+ /* Minimum measurements */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ label = gtk_label_new("Minimum number of measurements per merged reflection:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+ mo->min_measurements = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(mo->min_measurements), 6);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->min_measurements),
+ FALSE, FALSE, 0);
+ gtk_widget_set_tooltip_text(hbox, "--min-measurements");
+
+ /* Custom split */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ mo->custom_split = gtk_check_button_new_with_label("Split datasets after merging");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->custom_split),
+ FALSE, FALSE, 0);
+ mo->custom_split_file = gtk_file_chooser_button_new("Dataset assignments",
+ GTK_FILE_CHOOSER_ACTION_OPEN);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->custom_split_file),
+ FALSE, FALSE, 0);
+ check_on_toggle(mo->custom_split, mo);
+ gtk_widget_set_tooltip_text(hbox, "--custom-split");
+
+ /* Minimum pattern resolution */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ mo->min_res = gtk_check_button_new_with_label("Require minimum estimated pattern resolution");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->min_res),
+ FALSE, FALSE, 0);
+ mo->min_res_val = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(mo->min_res_val), 6);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->min_res_val),
+ FALSE, FALSE, 0);
+ label = gtk_label_new("Å");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+ check_on_toggle(mo->min_res, mo);
+ gtk_widget_set_tooltip_text(hbox, "--min-res");
+
+ /* push-res */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ mo->limit_res = gtk_check_button_new_with_label("Exclude measurements more than");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->limit_res),
+ FALSE, FALSE, 0);
+ mo->push_res = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(mo->push_res), 8);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->push_res),
+ FALSE, FALSE, 0);
+ label = gtk_label_new("nm^-1 above resolution limit");
+ gtk_label_set_markup(GTK_LABEL(label), "nm<sup>-1</sup> above resolution limit");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+ check_on_toggle(mo->limit_res, mo);
+ gtk_widget_set_tooltip_text(hbox, "--push-res");
+
+ /* Detwin */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ mo->detwin = gtk_check_button_new_with_label("Refine indexing assignments");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->detwin),
+ FALSE, FALSE, 0);
+ mo->detwin_sym = crystfel_symmetry_selector_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(mo->detwin_sym),
+ FALSE, FALSE, 0);
+ check_on_toggle(mo->detwin, mo);
+ gtk_widget_set_tooltip_text(hbox, "-w");
+
+ check_greyout(NULL, mo);
+
+ return box;
+}
+
+
+GtkWidget *crystfel_merge_opts_new()
+{
+ CrystFELMergeOpts *mo;
+
+ mo = g_object_new(CRYSTFEL_TYPE_MERGE_OPTS, NULL);
+ gtk_notebook_set_tab_pos(GTK_NOTEBOOK(mo), GTK_POS_LEFT);
+
+ gtk_notebook_append_page(GTK_NOTEBOOK(mo),
+ merge_parameters(mo),
+ gtk_label_new("Merging"));
+
+ return GTK_WIDGET(mo);
+}
+
+
+static int set_if(GtkWidget *combo, const char *a, const char *new_id)
+{
+ if ( strcmp(a, new_id) == 0 ) {
+ gtk_combo_box_set_active_id(GTK_COMBO_BOX(combo),
+ new_id);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static void set_int(GtkWidget *entry, int val)
+{
+ char tmp[64];
+ snprintf(tmp, 63, "%i", val);
+ gtk_entry_set_text(GTK_ENTRY(entry), tmp);
+}
+
+
+static void set_float(GtkWidget *entry, float val)
+{
+ char tmp[64];
+ snprintf(tmp, 63, "%f", val);
+ gtk_entry_set_text(GTK_ENTRY(entry), tmp);
+}
+
+
+void crystfel_merge_opts_set_model(CrystFELMergeOpts *opts,
+ const char *model)
+{
+ int done = 0;
+ done += set_if(opts->model_combo, model, "process_hkl");
+ done += set_if(opts->model_combo, model, "unity");
+ done += set_if(opts->model_combo, model, "xsphere");
+ done += set_if(opts->model_combo, model, "offset");
+ done += set_if(opts->model_combo, model, "ggpm");
+
+ if ( done == 0 ) {
+ ERROR("Unrecognised model '%s'\n", model);
+ }
+}
+
+
+void crystfel_merge_opts_set_polarisation(CrystFELMergeOpts *opts,
+ const char *polar)
+{
+ int done = 0;
+ done += set_if(opts->polarisation, polar, "horiz");
+ done += set_if(opts->polarisation, polar, "vert");
+ done += set_if(opts->polarisation, polar, "none");
+ done += set_if(opts->polarisation, polar, "horiz50");
+
+ if ( done == 0 ) {
+ ERROR("Unrecognised polarisation '%s'\n", polar);
+ }
+}
+
+
+void crystfel_merge_opts_set_symmetry(CrystFELMergeOpts *opts,
+ const char *sym)
+{
+ crystfel_symmetry_selector_set_group_symbol(CRYSTFEL_SYMMETRY_SELECTOR(opts->symmetry),
+ sym);
+}
+
+
+void crystfel_merge_opts_set_scale(CrystFELMergeOpts *opts,
+ int scale)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->scale),
+ scale);
+}
+
+
+void crystfel_merge_opts_set_bscale(CrystFELMergeOpts *opts,
+ int bscale)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->bscale),
+ bscale);
+}
+
+
+void crystfel_merge_opts_set_postref(CrystFELMergeOpts *opts,
+ int postref)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->postref),
+ postref);
+}
+
+
+void crystfel_merge_opts_set_niter(CrystFELMergeOpts *opts,
+ int niter)
+{
+ set_int(opts->niter, niter);
+}
+
+
+void crystfel_merge_opts_set_deltacchalf(CrystFELMergeOpts *opts,
+ int deltacchalf)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->deltacchalf),
+ deltacchalf);
+}
+
+
+void crystfel_merge_opts_set_min_measurements(CrystFELMergeOpts *opts,
+ int min_measurements)
+{
+ set_int(opts->min_measurements, min_measurements);
+}
+
+
+void crystfel_merge_opts_set_max_adu(CrystFELMergeOpts *opts,
+ float max_adu)
+{
+ set_float(opts->max_adu, max_adu);
+}
+
+
+void crystfel_merge_opts_set_custom_split(CrystFELMergeOpts *opts,
+ const char *custom_split_file)
+{
+ if ( custom_split_file != NULL ) {
+ gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(opts->custom_split_file),
+ custom_split_file);
+ }
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->custom_split),
+ (custom_split_file != NULL));
+}
+
+
+void crystfel_merge_opts_set_twin_sym(CrystFELMergeOpts *opts,
+ const char *twin_sym)
+{
+ crystfel_symmetry_selector_set_group_symbol(CRYSTFEL_SYMMETRY_SELECTOR(opts->detwin_sym),
+ twin_sym);
+}
+
+
+void crystfel_merge_opts_set_min_res(CrystFELMergeOpts *opts,
+ float min_res)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(opts->min_res),
+ !isinf(min_res));
+ set_float(opts->min_res_val, min_res);
+}
+
+
+void crystfel_merge_opts_set_push_res(CrystFELMergeOpts *mo,
+ float push_res)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mo->limit_res),
+ !isinf(push_res));
+ set_float(mo->push_res, push_res);
+}
+
+
+const char *crystfel_merge_opts_get_model(CrystFELMergeOpts *opts)
+{
+ return gtk_combo_box_get_active_id(GTK_COMBO_BOX(opts->model_combo));
+}
+
+
+const char *crystfel_merge_opts_get_symmetry(CrystFELMergeOpts *opts)
+{
+ return crystfel_symmetry_selector_get_group_symbol(CRYSTFEL_SYMMETRY_SELECTOR(opts->symmetry));
+}
+
+
+int crystfel_merge_opts_get_scale(CrystFELMergeOpts *opts)
+{
+ return get_bool(opts->scale);
+}
+
+
+int crystfel_merge_opts_get_bscale(CrystFELMergeOpts *opts)
+{
+ return get_bool(opts->bscale);
+}
+
+
+int crystfel_merge_opts_get_postref(CrystFELMergeOpts *opts)
+{
+ return get_bool(opts->postref);
+}
+
+
+int crystfel_merge_opts_get_niter(CrystFELMergeOpts *opts)
+{
+ return get_uint(opts->niter);
+}
+
+
+const char *crystfel_merge_opts_get_polarisation(CrystFELMergeOpts *opts)
+{
+ return gtk_combo_box_get_active_id(GTK_COMBO_BOX(opts->polarisation));
+}
+
+
+int crystfel_merge_opts_get_deltacchalf(CrystFELMergeOpts *opts)
+{
+ return get_bool(opts->deltacchalf);
+}
+
+
+int crystfel_merge_opts_get_min_measurements(CrystFELMergeOpts *opts)
+{
+ return get_uint(opts->min_measurements);
+}
+
+
+float crystfel_merge_opts_get_max_adu(CrystFELMergeOpts *opts)
+{
+ if ( get_bool(opts->use_max_adu) == 0 ) {
+ return INFINITY;
+ } else {
+ return get_float(opts->max_adu);
+ }
+}
+
+
+const char *crystfel_merge_opts_get_custom_split(CrystFELMergeOpts *opts)
+{
+ if ( get_bool(opts->custom_split) == 0 ) {
+ return NULL;
+ } else {
+ return gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(opts->custom_split_file));
+ }
+}
+
+
+const char *crystfel_merge_opts_get_twin_sym(CrystFELMergeOpts *opts)
+{
+ if ( get_bool(opts->detwin) == 0 ) {
+ return NULL;
+ } else {
+ return crystfel_symmetry_selector_get_group_symbol(CRYSTFEL_SYMMETRY_SELECTOR(opts->detwin_sym));
+ }
+}
+
+
+float crystfel_merge_opts_get_min_res(CrystFELMergeOpts *opts)
+{
+ if ( get_bool(opts->min_res) == 0 ) {
+ return INFINITY;
+ } else {
+ float min_res = get_float(opts->min_res_val);
+ if ( isnan(min_res) ) {
+ printf("Invalid value for min-res\n");
+ return INFINITY;
+ } else {
+ return min_res;
+ }
+ }
+}
+
+
+float crystfel_merge_opts_get_push_res(CrystFELMergeOpts *opts)
+{
+ if ( get_bool(opts->limit_res) == 0 ) {
+ return INFINITY;
+ } else {
+ float push_res = get_float(opts->push_res);
+ if ( isnan(push_res) ) {
+ printf("Invalid value for push-res\n");
+ return INFINITY;
+ } else {
+ return push_res;
+ }
+ }
+}
diff --git a/src/crystfelmergeopts.h b/src/crystfelmergeopts.h
new file mode 100644
index 00000000..a08abc66
--- /dev/null
+++ b/src/crystfelmergeopts.h
@@ -0,0 +1,133 @@
+/*
+ * crystfelmergeopts.h
+ *
+ * A GTK widget to set merge options
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef CRYSTFELMERGEOPTS_H
+#define CRYSTFELMERGEOPTS_H
+
+#include <gtk/gtk.h>
+#include <glib-object.h>
+
+#define CRYSTFEL_TYPE_MERGE_OPTS (crystfel_merge_opts_get_type())
+
+#define CRYSTFEL_MERGE_OPTS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+ CRYSTFEL_TYPE_MERGE_OPTS, CrystFELMergeOpts))
+
+#define CRYSTFEL_IS_MERGE_OPTS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
+ CRYSTFEL_TYPE_MERGE_OPTS))
+
+#define CRYSTFEL_MERGE_OPTS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((obj), \
+ CRYSTFEL_TYPE_MERGE_OPTS, CrystFELMergeOpts))
+
+#define CRYSTFEL_IS_MERGE_OPTS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), \
+ CRYSTFEL_TYPE_MERGE_OPTS))
+
+#define CRYSTFEL_MERGE_OPTS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \
+ CRYSTFEL_TYPE_MERGE_OPTS, CrystFELMergeOpts))
+
+struct _crystfelmergeopts
+{
+ GtkNotebook parent_instance;
+
+ /*< private >*/
+ GtkWidget *model_combo;
+ GtkWidget *symmetry;
+ GtkWidget *scale;
+ GtkWidget *bscale;
+ GtkWidget *postref;
+ GtkWidget *niter;
+ GtkWidget *polarisation;
+ GtkWidget *deltacchalf;
+ GtkWidget *min_measurements;
+ GtkWidget *use_max_adu;
+ GtkWidget *max_adu;
+ GtkWidget *custom_split;
+ GtkWidget *custom_split_file;
+ GtkWidget *detwin;
+ GtkWidget *detwin_sym;
+ GtkWidget *min_res;
+ GtkWidget *min_res_val;
+ GtkWidget *limit_res; /* check box for push-res < infinity */
+ GtkWidget *push_res; /* entry for push-res value */
+};
+
+struct _crystfelmergeoptsclass
+{
+ GtkNotebookClass parent_class;
+};
+
+typedef struct _crystfelmergeopts CrystFELMergeOpts;
+typedef struct _crystfelmergeoptsclass CrystFELMergeOptsClass;
+
+extern GType crystfel_merge_opts_get_type(void);
+extern GtkWidget *crystfel_merge_opts_new(void);
+
+extern void crystfel_merge_opts_set_model(CrystFELMergeOpts *opts,
+ const char *model);
+extern void crystfel_merge_opts_set_symmetry(CrystFELMergeOpts *opts,
+ const char *sym);
+extern void crystfel_merge_opts_set_scale(CrystFELMergeOpts *opts,
+ int scale);
+extern void crystfel_merge_opts_set_bscale(CrystFELMergeOpts *opts,
+ int bscale);
+extern void crystfel_merge_opts_set_postref(CrystFELMergeOpts *opts,
+ int postref);
+extern void crystfel_merge_opts_set_niter(CrystFELMergeOpts *opts,
+ int niter);
+extern void crystfel_merge_opts_set_polarisation(CrystFELMergeOpts *opts,
+ const char *polar);
+extern void crystfel_merge_opts_set_deltacchalf(CrystFELMergeOpts *opts,
+ int deltacchalf);
+extern void crystfel_merge_opts_set_min_measurements(CrystFELMergeOpts *opts,
+ int min_measurements);
+extern void crystfel_merge_opts_set_max_adu(CrystFELMergeOpts *opts,
+ float max_adu);
+extern void crystfel_merge_opts_set_custom_split(CrystFELMergeOpts *opts,
+ const char *custom_split_file);
+extern void crystfel_merge_opts_set_twin_sym(CrystFELMergeOpts *opts,
+ const char *twin_sym);
+extern void crystfel_merge_opts_set_min_res(CrystFELMergeOpts *opts,
+ float min_res);
+extern void crystfel_merge_opts_set_push_res(CrystFELMergeOpts *opts,
+ float push_res);
+
+extern const char *crystfel_merge_opts_get_model(CrystFELMergeOpts *opts);
+extern const char *crystfel_merge_opts_get_symmetry(CrystFELMergeOpts *opts);
+extern int crystfel_merge_opts_get_scale(CrystFELMergeOpts *opts);
+extern int crystfel_merge_opts_get_bscale(CrystFELMergeOpts *opts);
+extern int crystfel_merge_opts_get_postref(CrystFELMergeOpts *opts);
+extern int crystfel_merge_opts_get_niter(CrystFELMergeOpts *opts);
+extern const char *crystfel_merge_opts_get_polarisation(CrystFELMergeOpts *opts);
+extern int crystfel_merge_opts_get_deltacchalf(CrystFELMergeOpts *opts);
+extern int crystfel_merge_opts_get_min_measurements(CrystFELMergeOpts *opts);
+extern float crystfel_merge_opts_get_max_adu(CrystFELMergeOpts *opts);
+extern const char *crystfel_merge_opts_get_custom_split(CrystFELMergeOpts *opts);
+extern const char *crystfel_merge_opts_get_twin_sym(CrystFELMergeOpts *opts);
+extern float crystfel_merge_opts_get_min_res(CrystFELMergeOpts *opts);
+extern float crystfel_merge_opts_get_push_res(CrystFELMergeOpts *opts);
+
+#endif /* CRYSTFELMERGEOPTS_H */
diff --git a/src/crystfelsymmetryselector.c b/src/crystfelsymmetryselector.c
new file mode 100644
index 00000000..53295837
--- /dev/null
+++ b/src/crystfelsymmetryselector.c
@@ -0,0 +1,90 @@
+/*
+ * crystfelsymmetryselector.c
+ *
+ * A GTK widget to choose a symmetry class
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <gtk/gtk.h>
+#include <glib-object.h>
+#include <errno.h>
+
+#include "crystfelsymmetryselector.h"
+
+
+G_DEFINE_TYPE(CrystFELSymmetrySelector,
+ crystfel_symmetry_selector,
+ GTK_TYPE_BOX)
+
+
+static void crystfel_symmetry_selector_class_init(CrystFELSymmetrySelectorClass *klass)
+{
+}
+
+
+static void crystfel_symmetry_selector_init(CrystFELSymmetrySelector *mo)
+{
+}
+
+
+GtkWidget *crystfel_symmetry_selector_new()
+{
+ CrystFELSymmetrySelector *sel;
+
+ sel = g_object_new(CRYSTFEL_TYPE_SYMMETRY_SELECTOR, NULL);
+
+ sel->entry = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(sel->entry), 10);
+ gtk_box_pack_start(GTK_BOX(sel), GTK_WIDGET(sel->entry),
+ FALSE, FALSE, 0.0);
+
+ return GTK_WIDGET(sel);
+}
+
+
+char *crystfel_symmetry_selector_get_group_symbol(CrystFELSymmetrySelector *sel)
+{
+ const char *text = gtk_entry_get_text(GTK_ENTRY(sel->entry));
+ if ( text == NULL ) return NULL;
+ if ( text[0] == '\0' ) return NULL;
+ return strdup(text);
+}
+
+
+int crystfel_symmetry_selector_set_group_symbol(CrystFELSymmetrySelector *sel,
+ const char *pg_symbol)
+{
+ if ( pg_symbol != NULL ) {
+ gtk_entry_set_text(GTK_ENTRY(sel->entry), pg_symbol);
+ }
+ return 0;
+}
diff --git a/src/crystfelsymmetryselector.h b/src/crystfelsymmetryselector.h
new file mode 100644
index 00000000..f3ce3170
--- /dev/null
+++ b/src/crystfelsymmetryselector.h
@@ -0,0 +1,75 @@
+/*
+ * crystfelsymmetryselector.h
+ *
+ * A GTK widget to choose a symmetry class
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef CRYSTFELSYMMETRYSELECTOR_H
+#define CRYSTFELSYMMETRYSELECTOR_H
+
+#include <gtk/gtk.h>
+#include <glib-object.h>
+
+#define CRYSTFEL_TYPE_SYMMETRY_SELECTOR (crystfel_symmetry_selector_get_type())
+
+#define CRYSTFEL_SYMMETRY_SELECTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+ CRYSTFEL_TYPE_SYMMETRY_SELECTOR, CrystFELSymmetrySelector))
+
+#define CRYSTFEL_IS_SYMMETRY_SELECTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
+ CRYSTFEL_TYPE_SYMMETRY_SELECTOR))
+
+#define CRYSTFEL_SYMMETRY_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((obj), \
+ CRYSTFEL_TYPE_SYMMETRY_SELECTOR, CrystFELSymmetrySelector))
+
+#define CRYSTFEL_IS_SYMMETRY_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), \
+ CRYSTFEL_TYPE_SYMMETRY_SELECTOR))
+
+#define CRYSTFEL_SYMMETRY_SELECTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \
+ CRYSTFEL_TYPE_SYMMETRY_SELECTOR, CrystFELSymmetrySelector))
+
+struct _crystfelsymmetryselector
+{
+ GtkBox parent_instance;
+
+ /*< private >*/
+ GtkWidget *entry;
+};
+
+struct _crystfelsymmetryselectorclass
+{
+ GtkBoxClass parent_class;
+};
+
+typedef struct _crystfelsymmetryselector CrystFELSymmetrySelector;
+typedef struct _crystfelsymmetryselectorclass CrystFELSymmetrySelectorClass;
+
+extern GType crystfel_symmetry_selector_get_type(void);
+extern GtkWidget *crystfel_symmetry_selector_new(void);
+
+extern char *crystfel_symmetry_selector_get_group_symbol(CrystFELSymmetrySelector *sel);
+extern int crystfel_symmetry_selector_set_group_symbol(CrystFELSymmetrySelector *sel,
+ const char *pg_symbol);
+
+#endif /* CRYSTFELSYMMETRYSELECTOR_H */
diff --git a/src/diffraction-gpu.c b/src/diffraction-gpu.c
index 419b5957..7829d9da 100644
--- a/src/diffraction-gpu.c
+++ b/src/diffraction-gpu.c
@@ -3,11 +3,11 @@
*
* Calculate diffraction patterns by Fourier methods (GPU version)
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2009-2015 Thomas White <taw@physics.org>
+ * 2009-2020 Thomas White <taw@physics.org>
* 2013 Alexandra Tolstikova
* 2013-2014 Chun Hong Yoon <chun.hong.yoon@desy.de>
*
@@ -38,6 +38,7 @@
#include <string.h>
#include <complex.h>
+#define CL_TARGET_OPENCL_VERSION 220
#ifdef HAVE_CL_CL_H
#include <CL/cl.h>
#else
@@ -187,18 +188,18 @@ static int do_panels(struct gpu_context *gctx, struct image *image,
if ( set_arg_float(gctx, 2, weight) ) return 1;
/* Iterate over panels */
- for ( i=0; i<image->det->n_panels; i++ ) {
+ for ( i=0; i<image->detgeom->n_panels; i++ ) {
size_t dims[2];
size_t ldims[2];
- struct panel *p;
+ struct detgeom_panel *p;
cl_mem diff;
size_t diff_size;
float *diff_ptr;
int fs, ss;
cl_int err;
- p = &image->det->panels[i];
+ p = &image->detgeom->panels[i];
/* Buffer for the results of this panel */
diff_size = p->w * p->h * sizeof(cl_float);
@@ -220,8 +221,8 @@ static int do_panels(struct gpu_context *gctx, struct image *image,
if ( set_arg_float(gctx, 9, p->ssx) ) return 1;
if ( set_arg_float(gctx, 10, p->ssy) ) return 1;
if ( set_arg_float(gctx, 11, p->ssz) ) return 1;
- if ( set_arg_float(gctx, 12, p->res) ) return 1;
- if ( set_arg_float(gctx, 13, p->clen) ) return 1;
+ if ( set_arg_float(gctx, 12, 1.0/p->pixel_pitch) ) return 1;
+ if ( set_arg_float(gctx, 13, p->cnz*p->pixel_pitch) ) return 1;
dims[0] = p->w * sampling;
dims[1] = p->h * sampling;
@@ -325,13 +326,13 @@ int get_diffraction_gpu(struct gpu_context *gctx, struct image *image,
if ( set_arg_mem(gctx, 19, gctx->sinc_luts[nc-1]) ) return 1;
/* Allocate memory for the result */
- image->dp = malloc(image->det->n_panels * sizeof(float *));
+ image->dp = malloc(image->detgeom->n_panels * sizeof(float *));
if ( image->dp == NULL ) {
ERROR("Couldn't allocate memory for result.\n");
return 1;
}
- for ( i=0; i<image->det->n_panels; i++ ) {
- struct panel *p = &image->det->panels[i];
+ for ( i=0; i<image->detgeom->n_panels; i++ ) {
+ struct detgeom_panel *p = &image->detgeom->panels[i];
image->dp[i] = calloc(p->w * p->h, sizeof(float));
if ( image->dp[i] == NULL ) {
ERROR("Couldn't allocate memory for panel %i\n", i);
diff --git a/src/diffraction-gpu.h b/src/diffraction-gpu.h
index df1390f4..1128c8b1 100644
--- a/src/diffraction-gpu.h
+++ b/src/diffraction-gpu.h
@@ -3,11 +3,11 @@
*
* Calculate diffraction patterns by Fourier methods (GPU version)
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2017 Thomas White <taw@physics.org>
+ * 2010-2019 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
diff --git a/src/diffraction.c b/src/diffraction.c
index 8762b0af..6f360bac 100644
--- a/src/diffraction.c
+++ b/src/diffraction.c
@@ -3,11 +3,11 @@
*
* Calculate diffraction patterns by Fourier methods
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2009-2014 Thomas White <taw@physics.org>
+ * 2009-2020 Thomas White <taw@physics.org>
* 2013-2014 Chun Hong Yoon <chun.hong.yoon@desy.de>
* 2013 Alexandra Tolstikova
*
@@ -376,7 +376,7 @@ static void diffraction_panel(struct image *image, const double *intensities,
int fs, ss;
const int nxs = 4;
const int nys = 4;
- struct panel *p = &image->det->panels[pn];
+ struct detgeom_panel *p = &image->detgeom->panels[pn];
weight /= nxs*nys;
@@ -386,17 +386,22 @@ static void diffraction_panel(struct image *image, const double *intensities,
int idx;
double f_lattice, I_lattice;
double I_molecule;
- struct rvec q;
int xs, ys;
float xo, yo;
for ( xs=0; xs<nxs; xs++ ) {
for ( ys=0; ys<nys; ys++ ) {
+ double qv[3];
+ struct rvec q;
+
xo = (1.0/nxs) * xs;
yo = (1.0/nys) * ys;
- q = get_q_for_panel(p, fs+xo, ss+yo, NULL, k);
+ detgeom_transform_coords(p, fs+xo, ss+yo,
+ 0.0, 0.0, 1.0/k, qv);
+
+ q.u = qv[0]; q.v = qv[1]; q.w = qv[2];
f_lattice = lattice_factor(q, ax, ay, az,
bx, by, bz,
@@ -435,7 +440,7 @@ static void diffraction_at_k(struct image *image, const double *intensities,
{
int i;
- for ( i=0; i<image->det->n_panels; i++ ) {
+ for ( i=0; i<image->detgeom->n_panels; i++ ) {
diffraction_panel(image, intensities, phases, flags, cell, m,
sym, k, ax, ay, az, bx, by, bz, cx, cy, cz,
lut_a, lut_b, lut_c, i, weight);
diff --git a/src/diffraction.h b/src/diffraction.h
index 8e694698..63b022c9 100644
--- a/src/diffraction.h
+++ b/src/diffraction.h
@@ -3,11 +3,11 @@
*
* Calculate diffraction patterns by Fourier methods
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2009-2014 Thomas White <taw@physics.org>
+ * 2009-2019 Thomas White <taw@physics.org>
* 2013-2014 Chun Hong Yoon <chun.hong.yoon@desy.de>
* 2013 Alexandra Tolstikova
*
diff --git a/src/dw-hdfsee.c b/src/dw-hdfsee.c
deleted file mode 100644
index bc02c543..00000000
--- a/src/dw-hdfsee.c
+++ /dev/null
@@ -1,3168 +0,0 @@
-/*
- * dw-hdfsee.c
- *
- * Quick yet non-crappy HDF viewer
- *
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
- * a research centre of the Helmholtz Association.
- * Copyright © 2012 Richard Kirian
- *
- * Authors:
- * 2009-2018 Thomas White <taw@physics.org>
- * 2014 Valerio Mariani
- * 2014 Takanori Nakane
- * 2012 Richard Kirian
- *
- * This file is part of CrystFEL.
- *
- * CrystFEL is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * CrystFEL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gtk/gtk.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <cairo.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <gdk/gdkkeysyms-compat.h>
-#include <assert.h>
-
-#include "dw-hdfsee.h"
-#include "hdfsee-render.h"
-#include "render.h"
-#include "hdf5-file.h"
-#include "hdfsee.h"
-#include "utils.h"
-#include "filters.h"
-#include "events.h"
-
-static int displaywindow_update_menus(DisplayWindow *dw, const char *selectme);
-
-static void displaywindow_error(DisplayWindow *dw, const char *message)
-{
- GtkWidget *window;
-
- window = gtk_message_dialog_new(GTK_WINDOW(dw->window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_WARNING,
- GTK_BUTTONS_CLOSE, "%s", message);
- gtk_window_set_title(GTK_WINDOW(window), "Error");
-
- g_signal_connect_swapped(window, "response",
- G_CALLBACK(gtk_widget_destroy), window);
- gtk_widget_show(window);
-}
-
-
-/* Window closed - clean up */
-static gint displaywindow_closed(GtkWidget *window, DisplayWindow *dw)
-{
-
- if ( dw->imagefile != NULL ) {
- imagefile_close(dw->imagefile);
- }
-
- if ( dw->surf != NULL ) cairo_surface_destroy(dw->surf);
-
- if ( dw->pixbufs != NULL ) {
- int i;
- for ( i=0; i<dw->n_pixbufs; i++ ) {
- g_object_unref(dw->pixbufs[i]);
- }
- free(dw->pixbufs);
- }
-
- if ( dw->col_scale != NULL ) {
- g_object_unref(dw->col_scale);
- }
-
- if ( dw->image != NULL ) {
-
- free(dw->image->filename);
- free(dw->image);
- }
-
- /* Notify 'main', so it can update the master list */
- hdfsee_window_closed(dw);
-
- return 0;
-}
-
-
-static double ring_radius(struct image *image, int p, double d)
-{
- double theta, r, r_px;
-
- theta = asin(image->lambda / (2.0*d));
- r = image->det->panels[p].clen * tan(2.0*theta);
- r_px = r * image->det->panels[p].res;
-
- return r_px;
-}
-
-
-static void draw_panel_rectangle(cairo_t *cr, cairo_matrix_t *basic_m,
- DisplayWindow *dw, int i)
-{
- struct panel p = dw->image->det->panels[i];
- int w = gdk_pixbuf_get_width(dw->pixbufs[i]);
- int h = gdk_pixbuf_get_height(dw->pixbufs[i]);
- cairo_matrix_t m;
-
- /* Start with the basic coordinate system */
- cairo_set_matrix(cr, basic_m);
-
- /* Move to the right location */
- cairo_translate(cr, rint(p.cnx/dw->binning),
- rint(p.cny/dw->binning));
-
- /* Twiddle directions according to matrix */
- cairo_matrix_init(&m, rint(p.fsx), rint(p.fsy), rint(p.ssx), rint(p.ssy),
- 0.0, 0.0);
- cairo_transform(cr, &m);
-
- gdk_cairo_set_source_pixbuf(cr, dw->pixbufs[i],
- 0.0, 0.0);
- cairo_rectangle(cr, 0.0, 0.0, w, h);
-}
-
-
-static int render_adsc_uint16(DisplayWindow *dw, const char *filename)
-{
- int x, y, fs, ss;
- double dfs, dss;
- int min_x = (int)dw->min_x;
- int max_x = (int)dw->max_x;
- int min_y = (int)dw->min_y;
- int max_y = (int)dw->max_y;
- int width = max_x - min_x;
- int height = max_y - min_y;
- unsigned short *buf;
- struct image *image = dw->image;
- FILE *fh;
-
- if ( image == NULL ) return 1;
- if ( image->det == NULL ) return 1;
- if ( image->det->n_panels == 0 ) return 1;
-
- buf = calloc(width * height, sizeof(unsigned short));
- if ( buf == NULL ) return 1;
-
- fh = fopen(filename, "wb");
- if ( fh == NULL ) {
- free(buf);
- return 1;
- }
-
- fprintf(fh, "{\n"
- "HEADER_BYTES=512;\n"
- "DIM=2;\n"
- "BYTE_ORDER=little_endian;\n"
- "TYPE=unsigned_short;\n"
- "SIZE1=%d;\n"
- "SIZE2=%d;\n"
- "PIXEL_SIZE=%f;\n"
- "WAVELENGTH=%f;\n"
- "DISTANCE=%f;\n"
- "PHI=0.0;\n"
- "OSC_START=0.00;\n"
- "OSC_END=0.00;\n"
- "OSC_RANGE=0.00;\n"
- "AXIS=phi;\n"
- "BEAM_CENTER_X=%f;\n"
- "BEAM_CENTER_Y=%f;\n"
- "}\n",
- width, height, 1 / image->det->panels[0].res * 10e2,
- image->lambda * 10e9, image->det->panels[0].clen * 10e2,
- -min_x / image->det->panels[0].res * 10e2,
- -min_y / image->det->panels[0].res * 10e2);
-
- fseek(fh, 512, SEEK_SET);
-
- for ( y=min_y; y<max_y; y++ ) {
- for ( x=min_x; x<max_x; x++ ) {
-
- int val, invalid;
- unsigned short out;
- signed int pn;
- struct panel *p;
-
- invalid = reverse_2d_mapping(x, y, image->det, &p, &dfs, &dss);
- if ( invalid ) continue;
-
- fs = dfs;
- ss = dss; /* Explicit rounding */
-
- pn = panel_number(image->det, p);
- assert(pn != -1);
- val = image->dp[pn][fs + p->w* ss];
-
- if ( val < 0 ) {
- out = 0;
- } else if ( val > 65535 ) {
- out = 65535;
- } else {
- out = val;
- }
-
- buf[(x - min_x) + (y - min_y) * width] = out;
-
- }
- }
-
- fwrite(buf, sizeof(unsigned short), width * height, fh);
- free(buf);
- fclose(fh);
-
- return 0;
-}
-
-
-static void draw_calib_focus_rectangle(cairo_t *cr, cairo_matrix_t *basic_m,
- DisplayWindow *dw, int i)
-{
- struct panel p = dw->image->det->panels[i];
- int w = gdk_pixbuf_get_width(dw->pixbufs[i]);
- int h = gdk_pixbuf_get_height(dw->pixbufs[i]);
- cairo_matrix_t m;
-
- /* Start with the basic coordinate system */
- cairo_set_matrix(cr, basic_m);
-
- /* Move to the right location */
- cairo_translate(cr, p.cnx/dw->binning, p.cny/dw->binning);
-
- /* Twiddle directions according to matrix */
- cairo_matrix_init(&m, p.fsx, p.fsy, p.ssx, p.ssy, 0.0, 0.0);
- cairo_transform(cr, &m);
-
- cairo_set_line_width (cr, 3.0);
- cairo_set_source_rgb (cr, 255, 255, 255);
- cairo_rectangle(cr, 0.0, 0.0, w, h);
-
-}
-
-
-static void show_ring(cairo_t *cr, DisplayWindow *dw,
- double d, const char *label, cairo_matrix_t *basic_m,
- double r, double g, double b)
-{
- struct detector *det;
- int i;
-
- det = dw->image->det;
-
- for ( i=0; i<det->n_panels; i++ ) {
-
- draw_panel_rectangle(cr, basic_m, dw, i);
- cairo_clip(cr);
-
- cairo_text_extents_t size;
- cairo_identity_matrix(cr);
- cairo_translate(cr, -dw->min_x/dw->binning,
- dw->max_y/dw->binning);
- cairo_arc(cr, 0.0, 0.0,
- ring_radius(dw->image, i, d)/dw->binning,
- 0.0, 2.0*M_PI);
- cairo_set_source_rgb(cr, r, g, b);
- cairo_set_line_width(cr, 3.0/dw->binning);
- cairo_stroke(cr);
-
- cairo_reset_clip(cr);
-
- /* Any ideas for a better way of doing this? */
- if ( i == 0 ) {
-
- cairo_rotate(cr, -M_PI/4.0);
- cairo_translate(cr, 0.0,
- ring_radius(dw->image, i, d)/dw->binning-5.0);
- cairo_set_font_size(cr, 17.0);
- cairo_text_extents(cr, label, &size);
- cairo_translate(cr, -size.width/2.0, 0.0);
-
- cairo_show_text(cr, label);
- cairo_fill(cr);
-
- }
-
- }
-}
-
-
-static void show_simple_ring(cairo_t *cr, DisplayWindow *dw,
- double d, cairo_matrix_t *basic_m)
-{
- cairo_identity_matrix(cr);
- cairo_translate(cr, -dw->min_x/dw->binning,
- dw->max_y/dw->binning);
- cairo_arc(cr, 0.0, 0.0, d / dw->binning, 0.0, 2.0*M_PI);
- cairo_set_source_rgb(cr, 0.3, 1.0, 0.3);
- cairo_set_line_width(cr, 1.0/dw->binning);
- cairo_stroke(cr);
-}
-
-
-/* Return the rigid group for this panel */
-static struct rigid_group *find_corresponding_rigid_group(DisplayWindow *dw,
- struct panel *p)
-{
- int gi;
-
- for ( gi=0; gi<dw->rg_coll->n_rigid_groups; gi++ ) {
- if ( panel_is_in_rigid_group(dw->rg_coll->rigid_groups[gi], p) ) {
- return dw->rg_coll->rigid_groups[gi];
- }
- }
-
- return NULL;
-}
-
-
-static void maybe_draw_focus(DisplayWindow *dw, cairo_t *cr, int i,
- cairo_matrix_t *basic_m)
-{
- struct rigid_group *rg = NULL;
-
- switch ( dw->calib_mode ) {
-
- case CALIBMODE_NONE:
- break;
-
- case CALIBMODE_PANELS:
- if ( &dw->image->det->panels[i] == dw->calib_mode_curr_p) {
- draw_calib_focus_rectangle(cr, basic_m, dw, i);
- cairo_stroke(cr);
- }
- break;
-
- case CALIBMODE_GROUPS:
- rg = find_corresponding_rigid_group(dw, &dw->image->det->panels[i]);
- if ( rg == dw->calib_mode_curr_rg ) {
- draw_calib_focus_rectangle(cr, basic_m, dw, i);
- cairo_stroke(cr);
- }
- break;
-
- case CALIBMODE_ALL:
- draw_calib_focus_rectangle(cr, basic_m, dw, i);
- cairo_stroke(cr);
- break;
-
- }
-}
-
-
-static int draw_stuff(cairo_surface_t *surf, DisplayWindow *dw)
-{
- cairo_t *cr;
- cairo_matrix_t basic_m;
- cairo_matrix_t m;
-
- cr = cairo_create(surf);
-
- /* Blank grey background */
- cairo_rectangle(cr, 0.0, 0.0, dw->width, dw->height);
- cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
- cairo_fill(cr);
-
- if ( dw->image == NULL ) return 0;
-
- /* Set up basic coordinate system
- * - origin in the centre, y upwards. */
- cairo_identity_matrix(cr);
- cairo_matrix_init(&m, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
- cairo_translate(cr, -dw->min_x/dw->binning, dw->max_y/dw->binning);
- cairo_transform(cr, &m);
- cairo_get_matrix(cr, &basic_m);
-
- if ( dw->pixbufs != NULL ) {
-
- int i;
-
- for ( i=0; i<dw->image->det->n_panels; i++ ) {
-
- draw_panel_rectangle(cr, &basic_m, dw, i);
- cairo_fill(cr);
-
- if ( dw->calib_mode && dw->calib_mode_show_focus ) {
- maybe_draw_focus(dw, cr, i, &basic_m);
- }
-
- }
-
- }
-
- if ( dw->show_rings ) {
-
- /* Mark the beam */
- cairo_set_matrix(cr, &basic_m);
- cairo_arc(cr, 0.0, 0.0, 5.0/dw->binning, 0.0, 2.0*M_PI);
- cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
- cairo_fill(cr);
-
- /* Draw resolution circles */
- if ( dw->n_rings == -1 ) {
- /* n_rings == -1 means default behavior */
- show_ring(cr, dw, 10.0e-10, "10A", &basic_m,
- 1.0, 0.0, 0.0);
- show_ring(cr, dw, 9.0e-10, "9A", &basic_m,
- 1.0, 0.0, 0.0);
- show_ring(cr, dw, 8.0e-10, "8A", &basic_m,
- 1.0, 0.0, 0.0);
- show_ring(cr, dw, 7.0e-10, "7A", &basic_m,
- 1.0, 0.5, 0.0);
- show_ring(cr, dw, 6.0e-10, "6A", &basic_m,
- 1.0, 1.0, 0.0);
- show_ring(cr, dw, 5.0e-10, "5A", &basic_m,
- 0.0, 1.0, 0.0);
- show_ring(cr, dw, 4.0e-10, "4A", &basic_m,
- 0.2, 1.0, 0.2);
- show_ring(cr, dw, 3.0e-10, "3A", &basic_m,
- 0.4, 1.0, 0.4);
- show_ring(cr, dw, 2.0e-10, "2A", &basic_m,
- 0.6, 1.0, 0.6);
- show_ring(cr, dw, 1.0e-10, "1A", &basic_m,
- 0.8, 1.0, 0.8);
- show_ring(cr, dw, 0.5e-10, "0.5A", &basic_m,
- 1.0, 1.0, 1.0);
- } else {
- int i;
- for ( i=0; i<dw->n_rings; i++ ) {
- show_simple_ring(cr, dw, dw->ring_radii[i],
- &basic_m);
- }
- }
-
- }
-
- if ( (dw->show_col_scale) && (dw->col_scale != NULL) ) {
- cairo_identity_matrix(cr);
- cairo_translate(cr, dw->width, 0.0);
- cairo_rectangle(cr, 0.0, 0.0, 20.0, dw->height);
- gdk_cairo_set_source_pixbuf(cr, dw->col_scale, 0.0, 0.0);
- cairo_fill(cr);
- }
-
- /* Ensure a clean Cairo context, since the rings often cause
- * matrix trouble */
- cairo_destroy(cr);
- cr = cairo_create(surf);
-
- if ( (dw->image->features != NULL) && (dw->show_peaks) ) {
-
- int i;
-
- cairo_set_matrix(cr, &basic_m);
-
- for ( i=0; i<image_feature_count(dw->image->features); i++ ) {
-
- double fs, ss;
- double x, y;
- struct imagefeature *f;
- struct panel *p;
- double radius = dw->ring_radius;
-
- f = image_get_feature(dw->image->features, i);
- if ( f == NULL ) continue;
-
- fs = f->fs;
- ss = f->ss;
- p = f->p;
- if ( p == NULL ) continue;
-
- x = fs*p->fsx + ss*p->ssx + p->cnx;
- y = fs*p->fsy + ss*p->ssy + p->cny;
-
- cairo_arc(cr, x/dw->binning, y/dw->binning,
- radius, 0.0, 2.0*M_PI);
- switch ( dw->scale ) {
-
- case SCALE_COLOUR :
- cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
- break;
-
- case SCALE_MONO :
- cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
- break;
-
- case SCALE_INVMONO:
- cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
- break;
-
- }
-
- cairo_set_line_width(cr, 1.75/dw->binning);
- cairo_stroke(cr);
-;
- }
-
- }
-
- cairo_destroy(cr);
-
- return 0;
-}
-
-
-static void redraw_window(DisplayWindow *dw)
-{
- int width;
-
- width = dw->width;
- if ( dw->show_col_scale ) width += 20;
- if ( dw->surf != NULL ) cairo_surface_destroy(dw->surf);
- dw->surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
- width, dw->height);
- draw_stuff(dw->surf, dw);
-
- gdk_window_invalidate_rect(gtk_widget_get_window(dw->drawingarea),
- NULL, FALSE);
-}
-
-
-static void set_window_size(DisplayWindow *dw)
-{
- gint width;
-
- if ( dw->image == NULL ) {
- dw->width = 320;
- dw->height = 320;
- } else {
-
- double min_x, min_y, max_x, max_y;
-
- get_pixel_extents(dw->image->det,
- &min_x, &min_y, &max_x, &max_y);
-
- if ( min_x > 0.0 ) min_x = 0.0;
- if ( max_x < 0.0 ) max_x = 0.0;
- if ( min_y > 0.0 ) min_y = 0.0;
- if ( max_y < 0.0 ) max_y = 0.0;
- dw->min_x = min_x;
- dw->max_x = max_x;
- dw->min_y = min_y;
- dw->max_y = max_y;
-
- dw->width = (max_x - min_x) / dw->binning;
- dw->height = (max_y - min_y) / dw->binning;
-
- /* Add a thin border */
- dw->width += 2.0;;
- dw->height += 2.0;
- }
-
- width = dw->width;
- if ( dw->show_col_scale ) width += 20;
-
- gtk_widget_set_size_request(GTK_WIDGET(dw->drawingarea), width,
- dw->height);
-
- gtk_window_resize(GTK_WINDOW(dw->window), width+30, dw->height+30);
-}
-
-
-static void update_colscale(DisplayWindow *dw)
-{
- if ( dw->col_scale != NULL ) {
- g_object_unref(dw->col_scale);
- }
- dw->col_scale = render_get_colour_scale(20, dw->height, dw->scale);
-}
-
-
-static void displaywindow_update(DisplayWindow *dw)
-{
-
- set_window_size(dw);
- update_colscale(dw);
-
- /* Free old pixbufs */
- if ( dw->pixbufs != NULL ) {
- int i;
- for ( i=0; i<dw->n_pixbufs; i++ ) {
- g_object_unref(dw->pixbufs[i]);
- }
- free(dw->pixbufs);
- }
-
- if ( dw->image != NULL ) {
- dw->pixbufs = render_panels(dw->image, dw->binning,
- dw->scale, dw->boostint,
- &dw->n_pixbufs);
- } else {
- dw->pixbufs = NULL;
- }
-
- redraw_window(dw);
-}
-
-
-static gboolean displaywindow_draw(GtkWidget *da, cairo_t *cr, DisplayWindow *dw)
-{
- cairo_set_source_surface(cr, dw->surf, 0.0, 0.0);
- cairo_paint(cr);
- return FALSE;
-}
-
-
-static gboolean displaywindow_expose(GtkWidget *da, GdkEventExpose *event,
- DisplayWindow *dw)
-{
- cairo_t *cr;
- cr = gdk_cairo_create(gtk_widget_get_window(da));
- displaywindow_draw(da, cr, dw);
- cairo_destroy(cr);
- return FALSE;
-}
-
-
-static int write_png(const char *filename, DisplayWindow *dw)
-{
- cairo_status_t r;
- cairo_surface_t *surf;
-
- surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
- dw->width, dw->height);
-
- draw_stuff(surf, dw);
-
- r = cairo_surface_write_to_png(surf, filename);
- if ( r != CAIRO_STATUS_SUCCESS ) return 1;
-
- return 0;
-}
-
-
-static gint displaywindow_close(GtkWidget *widget, DisplayWindow *dw)
-{
- gtk_widget_destroy(dw->window);
- return 0;
-}
-
-
-static gint displaywindow_set_binning_response(GtkWidget *widget, gint response,
- DisplayWindow *dw)
-{
- int done = 1;
-
- if ( response == GTK_RESPONSE_OK ) {
-
- const char *sbinning;
- unsigned int binning;
- int scanval;
-
- sbinning = gtk_entry_get_text(
- GTK_ENTRY(dw->binning_dialog->entry));
- scanval = sscanf(sbinning, "%u", &binning);
- if ( (scanval != 1) || (binning <= 0) ) {
- displaywindow_error(dw,
- "Please enter a positive integer for the "
- "binning factor.");
- done = 0;
- } else {
- if ( binning < 100 ) {
- dw->binning = binning;
- displaywindow_update(dw);
- } else {
- displaywindow_error(dw,
- "Please enter a sensible value for "
- "the binning factor.");
- done = 0;
- }
- }
- }
-
- if ( done ) {
- gtk_widget_destroy(dw->binning_dialog->window);
- }
-
- return 0;
-
-}
-
-
-static gint displaywindow_set_binning_destroy(GtkWidget *widget,
- DisplayWindow *dw)
-{
- free(dw->binning_dialog);
- dw->binning_dialog = NULL;
- return 0;
-}
-
-
-static gint displaywindow_set_binning_response_ac(GtkWidget *widget,
- DisplayWindow *dw)
-{
- return displaywindow_set_binning_response(widget, GTK_RESPONSE_OK, dw);
-}
-
-
-/* Create a window to ask the user for a new binning factor */
-static gint displaywindow_set_binning(GtkWidget *widget, DisplayWindow *dw)
-{
- BinningDialog *bd;
- GtkWidget *vbox;
- GtkWidget *hbox;
- GtkWidget *table;
- GtkWidget *label;
- char tmp[64];
- double minx, maxx, miny, maxy;
- GtkWidget *dvbox;
-
- if ( dw->binning_dialog != NULL ) {
- return 0;
- }
-
- if ( dw->imagefile == NULL ) {
- return 0;
- }
-
- bd = malloc(sizeof(BinningDialog));
- if ( bd == NULL ) return 0;
- dw->binning_dialog = bd;
-
- bd->window = gtk_dialog_new_with_buttons("Set Binning",
- GTK_WINDOW(dw->window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CLOSE,
- GTK_STOCK_OK, GTK_RESPONSE_OK,
- NULL);
-
- dvbox = gtk_dialog_get_content_area((GTK_DIALOG(bd->window)));
- vbox = gtk_vbox_new(FALSE, 0);
- hbox = gtk_hbox_new(TRUE, 0);
- gtk_box_pack_start(GTK_BOX(dvbox), GTK_WIDGET(hbox), FALSE, FALSE, 7);
- gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 5);
-
- table = gtk_table_new(3, 2, FALSE);
- gtk_table_set_row_spacings(GTK_TABLE(table), 5);
- gtk_table_set_col_spacings(GTK_TABLE(table), 5);
- gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(table), FALSE, FALSE, 0);
-
- label = gtk_label_new("Smaller binning factors mean larger images on screen");
- gtk_label_set_markup(GTK_LABEL(label),
- "<span style=\"italic\" weight=\"light\">"
- "Smaller binning factors mean larger images on screen</span>");
- gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(label),
- 1, 3, 1, 2);
-
-
- get_pixel_extents(dw->image->det, &minx, &miny, &maxx, &maxy);
- snprintf(tmp, 63, "Image size at binning 1: about %.0f x %.0f pixels", maxx-minx, maxy-miny);
- label = gtk_label_new(tmp);
- gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(label),
- 1, 3, 2, 3);
-
- label = gtk_label_new("Binning Factor:");
- gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
- gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(label),
- 1, 2, 3, 4);
-
- bd->entry = gtk_entry_new();
- snprintf(tmp, 63, "%i", dw->binning);
- gtk_entry_set_text(GTK_ENTRY(bd->entry), tmp);
- gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(bd->entry),
- 2, 3, 3, 4);
-
- g_signal_connect(G_OBJECT(bd->entry), "activate",
- G_CALLBACK(displaywindow_set_binning_response_ac), dw);
- g_signal_connect(G_OBJECT(bd->window), "response",
- G_CALLBACK(displaywindow_set_binning_response), dw);
- g_signal_connect(G_OBJECT(bd->window), "destroy",
- G_CALLBACK(displaywindow_set_binning_destroy), dw);
- gtk_window_set_resizable(GTK_WINDOW(bd->window), FALSE);
- gtk_widget_show_all(bd->window);
- gtk_widget_grab_focus(GTK_WIDGET(bd->entry));
-
- return 0;
-}
-
-
-static gint displaywindow_set_boostint_response(GtkWidget *widget,
- gint response,
- DisplayWindow *dw)
-{
- int done = 1;
-
- if ( response == GTK_RESPONSE_OK ) {
-
- const char *sboostint;
- float boostint;
- int scanval;
-
- sboostint = gtk_entry_get_text(
- GTK_ENTRY(dw->boostint_dialog->entry));
- scanval = sscanf(sboostint, "%f", &boostint);
- if ( (scanval != 1) || (boostint <= 0) ) {
- displaywindow_error(dw, "Please enter a positive "
- "number for the intensity boost "
- "factor.");
- done = 0;
- } else {
- dw->boostint = boostint;
- displaywindow_update(dw);
- }
- }
-
- if ( done ) {
- gtk_widget_destroy(dw->boostint_dialog->window);
- }
-
- return 0;
-}
-
-
-static gint displaywindow_set_boostint_destroy(GtkWidget *widget,
- DisplayWindow *dw)
-{
- free(dw->boostint_dialog);
- dw->boostint_dialog = NULL;
- return 0;
-}
-
-
-static gint displaywindow_set_boostint_response_ac(GtkWidget *widget,
- DisplayWindow *dw)
-{
- return displaywindow_set_boostint_response(widget, GTK_RESPONSE_OK, dw);
-}
-
-
-/* Create a window to ask the user for a new intensity boost factor */
-static gint displaywindow_set_boostint(GtkWidget *widget, DisplayWindow *dw)
-{
- BoostIntDialog *bd;
- GtkWidget *vbox;
- GtkWidget *hbox;
- GtkWidget *table;
- GtkWidget *label;
- char tmp[64];
- GtkWidget *dvbox;
-
- if ( dw->boostint_dialog != NULL ) {
- return 0;
- }
-
- if ( dw->imagefile == NULL ) {
- return 0;
- }
-
- bd = malloc(sizeof(BoostIntDialog));
- if ( bd == NULL ) return 0;
- dw->boostint_dialog = bd;
-
- bd->window = gtk_dialog_new_with_buttons("Intensity Boost",
- GTK_WINDOW(dw->window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CLOSE,
- GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
-
- dvbox = gtk_dialog_get_content_area(GTK_DIALOG(bd->window));
- vbox = gtk_vbox_new(FALSE, 0);
- hbox = gtk_hbox_new(TRUE, 0);
- gtk_box_pack_start(GTK_BOX(dvbox), GTK_WIDGET(hbox), FALSE, FALSE, 7);
- gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 5);
-
- table = gtk_table_new(3, 2, FALSE);
- gtk_table_set_row_spacings(GTK_TABLE(table), 5);
- gtk_table_set_col_spacings(GTK_TABLE(table), 5);
- gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(table), FALSE, FALSE, 0);
-
- label = gtk_label_new("Boost Factor:");
- gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
- gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(label),
- 1, 2, 3, 4);
-
- bd->entry = gtk_entry_new();
- snprintf(tmp, 63, "%.2f", dw->boostint);
- gtk_entry_set_text(GTK_ENTRY(bd->entry), tmp);
- gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(bd->entry),
- 2, 3, 3, 4);
-
- g_signal_connect(G_OBJECT(bd->entry), "activate",
- G_CALLBACK(displaywindow_set_boostint_response_ac),
- dw);
- g_signal_connect(G_OBJECT(bd->window), "response",
- G_CALLBACK(displaywindow_set_boostint_response), dw);
- g_signal_connect(G_OBJECT(bd->window), "destroy",
- G_CALLBACK(displaywindow_set_boostint_destroy), dw);
- gtk_window_set_resizable(GTK_WINDOW(bd->window), FALSE);
- gtk_widget_show_all(bd->window);
- gtk_widget_grab_focus(GTK_WIDGET(bd->entry));
-
- return 0;
-}
-
-
-static void do_filters(DisplayWindow *dw)
-{
- if ( dw->median_filter > 0 ) {
- filter_median(dw->image, dw->median_filter);
- }
-
- if ( dw->noisefilter ) {
- filter_noise(dw->image);
- }
-}
-
-
-static void update_titlebar(DisplayWindow *dw)
-{
- char title[1024];
- char *bn = safe_basename(dw->image->filename);
- if ( dw->ev != NULL ) {
- snprintf(title, 1024, "%s - event: %s - hdfsee", bn, get_event_string(dw->ev));
- } else {
- snprintf(title, 1024, "%s - hdfsee", bn);
- }
- gtk_window_set_title(GTK_WINDOW(dw->window), title);
- free(bn);
-}
-
-
-static gint displaywindow_newevent(DisplayWindow *dw, int new_event)
-{
- int fail;
- int i;
-
- if ( dw->not_ready_yet ) return 0;
-
- float **old_dp = dw->image->dp;
- int **old_bad = dw->image->bad;
-
- if ( dw->image->det != NULL ) {
- free_detector_geometry(dw->image->det);
- }
-
- dw->image->det = copy_geom(dw->original_geom);
- fail = imagefile_read(dw->imagefile, dw->image,
- dw->ev_list->events[new_event]);
- if ( fail ) {
- ERROR("Couldn't load image");
- dw->image->dp = old_dp;
- dw->image->bad = old_bad;
- return 1;
- }
-
- dw->ev = dw->ev_list->events[new_event];
- update_titlebar(dw);
-
- do_filters(dw);
- displaywindow_update_menus(dw, NULL);
- displaywindow_update(dw);
-
-
- for (i = 0; i < dw->image->det->n_panels; i++) {
- free(old_dp[i]);
- free(old_bad[i]);
- }
- free(old_dp);
- free(old_bad);
- return 0;
-}
-
-
-static gint displaywindow_randomevent(GtkWidget *widget, DisplayWindow *dw)
-{
- int rand_event;
-
- if ( dw->not_ready_yet ) return 0;
-
- rand_event = gsl_rng_uniform_int(&dw->rng, dw->ev_list->num_events);
-
- return displaywindow_newevent(dw, rand_event);
-}
-
-
-static gint displaywindow_set_newevent_response(GtkWidget *widget,
- gint response,
- DisplayWindow *dw)
-{
- int ei;
- int matched_event;
- int done = 1;
-
- if ( response == GTK_RESPONSE_OK ) {
-
- const char *sevent;
-
-
-
- sevent = gtk_entry_get_text(
- GTK_ENTRY(dw->event_dialog->entry));
-
- matched_event = -1;
-
- for ( ei=0; ei<dw->ev_list->num_events; ei++ ) {
-
- char *ei_ev_string;
-
- ei_ev_string = get_event_string(dw->ev_list->events[ei]);
- if ( strcmp(ei_ev_string, sevent) == 0 ) {
- matched_event = ei;
- break;
- }
- }
-
- if ( matched_event == -1 ) {
- displaywindow_error(dw, "Cannot find event.\n");
- done = 0;
- } else {
- displaywindow_newevent(dw, matched_event);
- displaywindow_update(dw);
- }
- }
-
- if ( done ) {
- gtk_widget_destroy(dw->event_dialog->window);
- }
-
- return 0;
-}
-
-
-static gint displaywindow_set_newevent_destroy(GtkWidget *widget,
- DisplayWindow *dw)
-{
- free(dw->event_dialog);
- dw->event_dialog = NULL;
- return 0;
-}
-
-
-static gint displaywindow_set_newevent_response_ac(GtkWidget *widget,
- DisplayWindow *dw)
-{
- return displaywindow_set_newevent_response(widget, GTK_RESPONSE_OK, dw);
-}
-
-
-/* Create a window to ask the user for a new event ID to show */
-static gint displaywindow_set_newevent(GtkWidget *widget, DisplayWindow *dw)
-{
- EventDialog *ed;
- GtkWidget *vbox;
- GtkWidget *hbox;
- GtkWidget *table;
- GtkWidget *label;
- GtkWidget *dvbox;
- char tmp[1024];
-
- if ( dw->event_dialog != NULL ) {
- return 0;
- }
-
- if ( dw->imagefile == NULL ) {
- return 0;
- }
-
- ed = malloc(sizeof(EventDialog));
- if ( ed == NULL ) return 0;
- dw->event_dialog = ed;
-
- ed->window = gtk_dialog_new_with_buttons("Go to event",
- GTK_WINDOW(dw->window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CLOSE,
- GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
-
- dvbox = gtk_dialog_get_content_area(GTK_DIALOG(ed->window));
- vbox = gtk_vbox_new(FALSE, 0);
- hbox = gtk_hbox_new(TRUE, 0);
- gtk_box_pack_start(GTK_BOX(dvbox), GTK_WIDGET(hbox), FALSE, FALSE, 7);
- gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 5);
-
- table = gtk_table_new(3, 2, FALSE);
- gtk_table_set_row_spacings(GTK_TABLE(table), 5);
- gtk_table_set_col_spacings(GTK_TABLE(table), 5);
- gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(table), FALSE, FALSE, 0);
-
- label = gtk_label_new("Event ID:");
- gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
- gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(label),
- 1, 2, 3, 4);
-
- ed->entry = gtk_entry_new();
- snprintf(tmp, 1023, "%s", get_event_string(dw->ev));
- gtk_entry_set_text(GTK_ENTRY(ed->entry), tmp);
- gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(ed->entry),
- 2, 3, 3, 4);
-
- g_signal_connect(G_OBJECT(ed->entry), "activate",
- G_CALLBACK(displaywindow_set_newevent_response_ac),
- dw);
- g_signal_connect(G_OBJECT(ed->window), "response",
- G_CALLBACK(displaywindow_set_newevent_response), dw);
- g_signal_connect(G_OBJECT(ed->window), "destroy",
- G_CALLBACK(displaywindow_set_newevent_destroy), dw);
- gtk_window_set_resizable(GTK_WINDOW(ed->window), FALSE);
- gtk_widget_show_all(ed->window);
- gtk_widget_grab_focus(GTK_WIDGET(ed->entry));
-
- return 0;
-}
-
-
-static gint displaywindow_set_ringradius_response(GtkWidget *widget,
- gint response,
- DisplayWindow *dw)
-{
- int done = 1;
-
- if ( response == GTK_RESPONSE_OK ) {
-
- const char *srad;
- float ringrad;
- int scanval;
-
- srad = gtk_entry_get_text(
- GTK_ENTRY(dw->ringradius_dialog->entry));
- scanval = sscanf(srad, "%f", &ringrad);
- if ( (scanval != 1) || (ringrad <= 0) ) {
- displaywindow_error(dw, "Please enter a positive "
- "number for the ring radius "
- "factor.");
- done = 0;
- } else {
- dw->ring_radius = ringrad;
- displaywindow_update(dw);
- }
- }
-
- if ( done ) {
- gtk_widget_destroy(dw->ringradius_dialog->window);
- }
-
- return 0;
-}
-
-
-static gint displaywindow_set_ringradius_destroy(GtkWidget *widget,
- DisplayWindow *dw)
-{
- free(dw->ringradius_dialog);
- dw->ringradius_dialog = NULL;
- return 0;
-}
-
-
-static gint displaywindow_set_ringradius_response_ac(GtkWidget *widget,
- DisplayWindow *dw)
-{
- return displaywindow_set_ringradius_response(widget, GTK_RESPONSE_OK,
- dw);
-}
-
-/* Create a window to ask the user for a new ring radius */
-static gint displaywindow_set_ringradius(GtkWidget *widget, DisplayWindow *dw)
-{
- RingRadiusDialog *rd;
- GtkWidget *vbox;
- GtkWidget *hbox;
- GtkWidget *table;
- GtkWidget *label;
- GtkWidget *dvbox;
- char tmp[64];
-
- if ( dw->ringradius_dialog != NULL ) {
- return 0;
- }
-
- if ( dw->imagefile == NULL ) {
- return 0;
- }
-
- rd = malloc(sizeof(RingRadiusDialog));
- if ( rd == NULL ) return 0;
- dw->ringradius_dialog = rd;
-
- rd->window = gtk_dialog_new_with_buttons("Ring Radius",
- GTK_WINDOW(dw->window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CLOSE,
- GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
-
- dvbox = gtk_dialog_get_content_area(GTK_DIALOG(rd->window));
- vbox = gtk_vbox_new(FALSE, 0);
- hbox = gtk_hbox_new(TRUE, 0);
- gtk_box_pack_start(GTK_BOX(dvbox), GTK_WIDGET(hbox), FALSE, FALSE, 7);
- gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 5);
-
- table = gtk_table_new(3, 2, FALSE);
- gtk_table_set_row_spacings(GTK_TABLE(table), 5);
- gtk_table_set_col_spacings(GTK_TABLE(table), 5);
- gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(table), FALSE, FALSE, 0);
-
- label = gtk_label_new("Ring Radius:");
- gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
- gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(label),
- 1, 2, 3, 4);
-
- rd->entry = gtk_entry_new();
- snprintf(tmp, 63, "%.2f", dw->ring_radius);
- gtk_entry_set_text(GTK_ENTRY(rd->entry), tmp);
- gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(rd->entry),
- 2, 3, 3, 4);
-
- g_signal_connect(G_OBJECT(rd->entry), "activate",
- G_CALLBACK(displaywindow_set_ringradius_response_ac),
- dw);
- g_signal_connect(G_OBJECT(rd->window), "response",
- G_CALLBACK(displaywindow_set_ringradius_response), dw);
- g_signal_connect(G_OBJECT(rd->window), "destroy",
- G_CALLBACK(displaywindow_set_ringradius_destroy), dw);
- gtk_window_set_resizable(GTK_WINDOW(rd->window), FALSE);
- gtk_widget_show_all(rd->window);
- gtk_widget_grab_focus(GTK_WIDGET(rd->entry));
-
- return 0;
-}
-
-
-/* Return value:
- * 0: no peaks loaded
- * 1: peak search peaks loaded
- * 2: predicted peaks loaded
- */
-static int load_features_from_file(struct image *image, const char *filename)
-{
- FILE *fh;
- char *rval;
- int ret = 0;
-
- fh = fopen(filename, "r");
- if ( fh == NULL ) return 0;
-
- if ( image->features != NULL ) {
- image_feature_list_free(image->features);
- }
- image->features = image_feature_list_new();
-
- do {
- char line[1024];
- float intensity, sigma, fs, ss;
- char phs[1024];
- char pn[32];
- int r;
- float cts, d;
- signed int h, k, l;
- struct panel *p = NULL;
-
- rval = fgets(line, 1023, fh);
- if ( rval == NULL ) continue;
- chomp(line);
-
- r = sscanf(line, "%i %i %i %f %s %f %f %f %f %s",
- &h, &k, &l, &intensity, phs, &sigma, &cts,
- &fs, &ss, pn);
-
- if ( r == 10 ) {
-
- /* Stream reflection list format 2.3 */
- char name[32];
- snprintf(name, 31, "%i %i %i", h, k, l);
- p = find_panel_by_name(image->det, pn);
-
- if ( p == NULL ) {
-
- ERROR("Unable to find panel %s "
- "(no geometry file given?)\n", pn);
-
- } else {
-
- /* Convert coordinates to match rearranged
- * panels in memory */
- fs = fs-p->orig_min_fs;
- ss = ss-p->orig_min_ss;
-
- }
-
- image_add_feature(image->features, fs, ss, p,
- image, 1.0, strdup(name));
- ret = 2;
- continue;
-
- } else if ( r == 9 ) {
-
- /* Stream reflection list format 2.2 or 2.1 */
- char name[32];
-
- snprintf(name, 31, "%i %i %i", h, k, l);
-
- p = find_orig_panel(image->det, fs, ss);
-
- if ( p == NULL ) {
- ERROR("Unable to find panel for %s "
- "(no geometry file given?)\n", name);
- } else {
-
- /* Convert coordinates to match rearranged
- * panels in memory */
- fs = fs - p->orig_min_fs;
- ss = ss - p->orig_min_ss;
-
- }
-
- image_add_feature(image->features, fs, ss, p,
- image, 1.0, strdup(name));
- ret = 2;
- continue;
-
- }
-
-
- /* Try long peak format from stream */
- r = sscanf(line, "%f %f %f %f %s", &fs, &ss, &d,
- &intensity, pn);
- if ( r == 5 ) {
-
- p = find_panel_by_name(image->det, pn);
- if ( p == NULL ) {
- ERROR("Unable to find panel %s "
- "(no geometry file given?)\n", pn);
- } else {
-
- /* Convert coordinates to match rearranged panels
- * in memory */
- fs = fs - p->orig_min_fs;
- ss = ss - p->orig_min_ss;
-
- }
-
- image_add_feature(image->features, fs, ss, p, image,
- 1.0, "peak");
- ret = 1;
- } else if ( r == 4 ) {
-
- p = find_orig_panel(image->det, fs, ss);
-
- if ( p == NULL ) {
- ERROR("Unable to find panel "
- "(no geometry file given?)\n");
- } else {
-
- /* Convert coordinates to match rearranged
- * panels in memory */
- fs = fs - p->orig_min_fs;
- ss = ss - p->orig_min_ss;
- }
- image_add_feature(image->features, fs, ss, p, image,
- 1.0, "peak");
- ret = 1;
-
- } else if ( r == 2 ) {
-
- p = find_orig_panel(image->det, fs, ss);
-
- if ( p == NULL ) {
- ERROR("Unable to find panel "
- "(no geometry file given?)\n");
- } else {
-
- /* Convert coordinates to match rearranged
- * panels in memory */
- fs = fs - p->orig_min_fs;
- ss = ss - p->orig_min_ss;
- }
- image_add_feature(image->features, fs, ss, p, image,
- 1.0, "peak");
- ret = 1;
-
- }
-
- } while ( rval != NULL );
-
- return ret;
-}
-
-
-static gint displaywindow_peaklist_response(GtkWidget *d, gint response,
- DisplayWindow *dw)
-{
- if ( response == GTK_RESPONSE_ACCEPT ) {
-
- char *filename;
- GtkWidget *w;
-
- filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d));
-
- dw->peaktype = load_features_from_file(dw->image, filename);
- dw->show_peaks = 1;
- w = gtk_ui_manager_get_widget(dw->ui,
- "/ui/displaywindow/view/showpeaks");
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), TRUE);
-
- redraw_window(dw);
-
- g_free(filename);
-
- }
-
- gtk_widget_destroy(d);
-
- return 0;;
-}
-
-
-static gint displaywindow_about(GtkWidget *widget, DisplayWindow *dw)
-{
- GtkWidget *window;
-
- const gchar *authors[] = {
- "Thomas White <taw@physics.org>",
- NULL
- };
-
- window = gtk_about_dialog_new();
- gtk_window_set_transient_for(GTK_WINDOW(window),
- GTK_WINDOW(dw->window));
-
- gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(window), "hdfsee");
- gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(window), PACKAGE_VERSION);
- gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(window),
- "© 2012-2015 Deutsches Elektronen-Synchrotron DESY,"
- " a research centre of the Helmholtz Association.");
- gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(window),
- "Quick viewer for HDF files");
- gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(window),
- "© 2012-2015 Deutsches Elektronen-Synchrotron DESY,"
- " a research centre of the Helmholtz Association.");
- gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(window),
- "http://www.desy.de/~twhite/crystfel");
- gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(window), authors);
-
- g_signal_connect(window, "response", G_CALLBACK(gtk_widget_destroy),
- NULL);
-
- gtk_widget_show_all(window);
-
- return 0;
-}
-
-
-static int save_geometry_file(GtkWidget *widget, DisplayWindow *dw)
-{
- GtkWidget *d;
- gchar *output_filename;
- int w;
-
- d = gtk_file_chooser_dialog_new("Save Detector Geometry",
- GTK_WINDOW(dw->window),
- GTK_FILE_CHOOSER_ACTION_SAVE,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
-
- gtk_dialog_run(GTK_DIALOG(d));
- output_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (d));
- w = write_detector_geometry_2(dw->geom_filename, output_filename,
- dw->image->det, "Manually optimized with "
- "hdfsee", 0);
- if ( w != 0 && w!=2 ) {
- displaywindow_error(dw,
- "Unable to save the detector geometry.");
- }
-
- gtk_widget_destroy(d);
- g_free(output_filename);
- return w;
-}
-
-
-static gint displaywindow_peak_overlay(GtkWidget *widget, DisplayWindow *dw)
-{
- GtkWidget *d;
-
- d = gtk_file_chooser_dialog_new("Choose Peak List",
- GTK_WINDOW(dw->window),
- GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
- NULL);
-
- g_signal_connect(G_OBJECT(d), "response",
- G_CALLBACK(displaywindow_peaklist_response), dw);
-
- gtk_widget_show_all(d);
-
- return 0;
-}
-
-
-static void set_calibration_menu_sensitivity(DisplayWindow *dw, int val) {
-
- GtkAction * a;
-
- a = gtk_ui_manager_get_action(dw->ui,
- "/ui/displaywindow/calibration");
- gtk_action_set_sensitive(GTK_ACTION(a), val);
- a = gtk_ui_manager_get_action(dw->ui,
- "/ui/displaywindow/calibration/calibrationprevious");
- gtk_action_set_sensitive(GTK_ACTION(a), val);
- a = gtk_ui_manager_get_action(dw->ui,
- "/ui/displaywindow/calibration/calibrationnext");
- gtk_action_set_sensitive(GTK_ACTION(a), val);
- a = gtk_ui_manager_get_action(dw->ui,
- "/ui/displaywindow/calibration/switchcalibmode");
- gtk_action_set_sensitive(GTK_ACTION(a), val);
- a = gtk_ui_manager_get_action(dw->ui,
- "/ui/displaywindow/calibration/focus");
- gtk_action_set_sensitive(GTK_ACTION(a), val);
- a = gtk_ui_manager_get_action(dw->ui,
- "/ui/displaywindow/calibration/savegeometry");
- gtk_action_set_sensitive(GTK_ACTION(a), val);
-}
-
-
-static void set_events_menu_sensitivity(DisplayWindow *dw, int val) {
-
- GtkAction * a;
-
- a = gtk_ui_manager_get_action(dw->ui,
- "/ui/displaywindow/events");
- gtk_action_set_sensitive(GTK_ACTION(a), val);
- a = gtk_ui_manager_get_action(dw->ui,
- "/ui/displaywindow/events/eventprevious");
- gtk_action_set_sensitive(GTK_ACTION(a), val);
- a = gtk_ui_manager_get_action(dw->ui,
- "/ui/displaywindow/events/eventnext");
- gtk_action_set_sensitive(GTK_ACTION(a), val);
- a = gtk_ui_manager_get_action(dw->ui,
- "/ui/displaywindow/events/gotoevent");
- gtk_action_set_sensitive(GTK_ACTION(a), val);
- a = gtk_ui_manager_get_action(dw->ui,
- "/ui/displaywindow/events/randomevent");
- gtk_action_set_sensitive(GTK_ACTION(a), val);
-
-}
-
-
-static gint displaywindow_set_calibmode(GtkWidget *d, DisplayWindow *dw)
-{
- GtkWidget *w, *vbox;
- int val;
-
- w = gtk_ui_manager_get_widget(dw->ui, "/ui/displaywindow/tools/calibmode");
- if ( dw->geom_filename == NULL ) {
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), 0);
- return 0;
- }
-
- if ( dw->rg_coll_name == NULL ) {
- dw->rg_coll = dw->image->det->rigid_group_collections[0];
- if ( dw->rg_coll == NULL ) {
- ERROR("Cannot find a suitable rigid group collection.\n");
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), 0);
- return 0;
- }
- } else {
- dw->rg_coll = find_rigid_group_collection_by_name(dw->image->det,
- dw->rg_coll_name);
- if ( dw->rg_coll == NULL ) {
- ERROR("Cannot find rigid group collection: %s\n",
- dw->rg_coll_name);
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), 0);
- return 0;
- }
- }
-
- /* Get new value */
- val = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w));
-
- /* When entering calibration mode */
- if ( val ) {
-
- guint cc;
-
- if ( (dw->calib_mode_curr_rg == NULL)
- && (dw->calib_mode_curr_p == NULL) )
- {
- dw->calib_mode_curr_rg = dw->rg_coll->rigid_groups[0];
- dw->calib_mode_curr_p = dw->calib_mode_curr_rg->panels[0];
- }
-
- set_calibration_menu_sensitivity(dw, TRUE);
-
- dw->calib_mode = CALIBMODE_PANELS;
-
- dw->statusbar = gtk_statusbar_new();
- gtk_widget_show(dw->statusbar);
- vbox = gtk_bin_get_child(GTK_BIN(dw->window));
- gtk_box_pack_end(GTK_BOX(vbox), dw->statusbar,
- FALSE, FALSE, 0);
- cc = gtk_statusbar_get_context_id(GTK_STATUSBAR(dw->statusbar),
- "calibmode");
- gtk_statusbar_push(GTK_STATUSBAR(dw->statusbar), cc,
- "Calibration mode activated");
- displaywindow_update(dw);
-
- } else {
-
- set_calibration_menu_sensitivity(dw, FALSE);
-
- dw->calib_mode = CALIBMODE_NONE;
- gtk_widget_destroy(dw->statusbar);
- dw->statusbar = NULL;
- displaywindow_update(dw);
-
- }
-
- return 0;
-}
-
-
-static gint displaywindow_set_rings(GtkWidget *d, DisplayWindow *dw)
-{
- GtkWidget *w;
-
- /* Get new value */
- w = gtk_ui_manager_get_widget(dw->ui,
- "/ui/displaywindow/view/rings");
- dw->show_rings = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w));
-
- redraw_window(dw);
-
- return 0;
-}
-
-
-struct savedialog {
- DisplayWindow *dw;
- GtkWidget *cb;
-};
-
-
-static gint displaywindow_save_response(GtkWidget *d, gint response,
- struct savedialog *cd)
-{
- DisplayWindow *dw = cd->dw;
- int r;
-
- if ( response == GTK_RESPONSE_ACCEPT ) {
-
- char *file;
- int type;
-
- file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d));
-
- type = gtk_combo_box_get_active(GTK_COMBO_BOX(cd->cb));
-
- if ( type == 0 ) {
- r = write_png(file, dw);
- } else if ( type == 1 ) {
- if ( !single_panel_data_source(dw->image->det, NULL) ) {
- displaywindow_error(dw, "The image data isn't "
- "held in a single array in the HDF5 file. "
- "Therefore, it can't be saved as TIFF.");
- r = 0;
- } else {
- r = render_tiff_fp(dw->image, file, dw->min_x,
- dw->max_x, dw->min_y, dw->max_y);
- }
- } else if ( type == 2 ) {
- if ( !single_panel_data_source(dw->image->det, NULL) ) {
- displaywindow_error(dw, "The image data isn't "
- "held in a single array in the HDF5 file. "
- "Therefore, it can't be saved as TIFF.");
- r = 0;
- } else {
- r = render_tiff_int16(dw->image, file,
- dw->boostint, dw->min_x,
- dw->max_x, dw->min_y,
- dw->max_y);
- }
- } else if ( type == 3 ) {
- if ( !single_panel_data_source(dw->image->det, NULL) ) {
- displaywindow_error(dw, "The image data isn't "
- "held in a single array in the HDF5 file. "
- "Therefore, it can't be saved as ADSC.");
- r = 0;
- } else {
- r = render_adsc_uint16(dw, file);
- }
- } else {
- r = -1;
- }
-
- if ( r != 0 ) {
- displaywindow_error(dw, "Unable to save the image.");
- }
-
- g_free(file);
-
- }
-
- gtk_widget_destroy(d);
- free(cd);
-
- return 0;
-}
-
-
-static void move_back_one(char *a)
-{
- int i;
- size_t r = strlen(a);
- for ( i=0; i<r; i++ ) {
- a[i] = a[i+1];
- }
-}
-
-
-static void substitute_slashes(char *bfn)
-{
- size_t i;
- size_t r = strlen(bfn);
- for ( i=0; i<r; i++ ) {
- if ( bfn[i] == '/') bfn[i] = '_';
- while ( bfn[i+1] == '/' ) {
- move_back_one(&bfn[i+1]);
- }
-
- }
-}
-
-
-static gint displaywindow_save(GtkWidget *widget, DisplayWindow *dw)
-{
- GtkWidget *d, *hbox, *l, *cb;
- struct savedialog *cd;
- char *fn, *bfn;
-
- d = gtk_file_chooser_dialog_new("Save Image",
- GTK_WINDOW(dw->window),
- GTK_FILE_CHOOSER_ACTION_SAVE,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
-
- bfn = safe_basename(dw->image->filename);
- strip_extension(bfn);
- if ( bfn != NULL ) {
- size_t l = strlen(bfn)+256;
- fn = malloc(l);
- if ( fn != NULL ) {
-
- char *evs;
- const char *pk;
- const char *rings;
-
- if ( dw->ev != NULL ) {
- evs = get_event_string(dw->ev);
- substitute_slashes(evs);
- } else {
- evs = strdup("");
- }
-
- if ( dw->show_peaks ) {
- switch ( dw->peaktype ) {
-
- case 1 :
- pk = "_peaks";
- break;
-
- case 2 :
- pk = "_preds";
- break;
-
- default :
- pk = "";
- break;
- }
- } else {
- pk = "";
- }
-
- if ( dw->show_rings ) {
- rings = "_rings";
- } else {
- rings = "";
- }
-
- snprintf(fn, l, "%s%s%s%s.png", bfn, evs, pk, rings);
- free(evs);
- gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(d),
- fn);
- free(fn);
- }
- free(bfn);
- }
-
- gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(d),
- TRUE);
-
- hbox = gtk_hbox_new(FALSE, 0);
- gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(d), hbox);
- cb = gtk_combo_box_text_new();
- gtk_box_pack_end(GTK_BOX(hbox), GTK_WIDGET(cb), TRUE, TRUE, 5);
- l = gtk_label_new("Save as type:");
- gtk_box_pack_end(GTK_BOX(hbox), GTK_WIDGET(l), FALSE, FALSE, 5);
-
- gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cb),
- "PNG (colour)");
- gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cb),
- "TIFF (floating point)");
- gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cb),
- "TIFF (16 bit signed integer)");
- gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cb),
- "ADSC (16 bit unsigned integer)");
- gtk_combo_box_set_active(GTK_COMBO_BOX(cb), 0);
-
- cd = malloc(sizeof(*cd));
- cd->dw = dw;
- cd->cb = cb;
-
- g_signal_connect(G_OBJECT(d), "response",
- G_CALLBACK(displaywindow_save_response), cd);
-
- gtk_widget_show_all(d);
-
- return 0;
-}
-
-
-static gint displaywindow_set_colscale(GtkWidget *widget, DisplayWindow *dw)
-{
- GtkWidget *w;
-
- w = gtk_ui_manager_get_widget(dw->ui,
- "/ui/displaywindow/view/colscale");
- dw->show_col_scale = gtk_check_menu_item_get_active(
- GTK_CHECK_MENU_ITEM(w));
- set_window_size(dw);
- redraw_window(dw);
- return 0;
-}
-
-
-static gint displaywindow_set_peaks(GtkWidget *widget, DisplayWindow *dw)
-{
- GtkWidget *w;
-
- w = gtk_ui_manager_get_widget(dw->ui,
- "/ui/displaywindow/view/showpeaks");
- dw->show_peaks = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w));
- redraw_window(dw);
- return 0;
-}
-
-
-static gint displaywindow_numbers_response(GtkWidget *widget,
- gint response, DisplayWindow *dw)
-{
- gtk_widget_destroy(dw->numbers_window->window);
- return 0;
-}
-
-
-static gint displaywindow_numbers_destroy(GtkWidget *widget, DisplayWindow *dw)
-{
- free(dw->numbers_window);
- dw->numbers_window = NULL;
- return 0;
-}
-
-
-static gint displaywindow_show_numbers(GtkWidget *widget, DisplayWindow *dw)
-{
- struct numberswindow *nw;
- GtkWidget *vbox;
- GtkWidget *hbox;
- GtkWidget *hbox2;
- GtkWidget *table;
- GtkWidget *label;
- GtkWidget *dvbox;
- unsigned int x, y;
-
- if ( dw->numbers_window != NULL ) {
- return 0;
- }
-
- if ( dw->imagefile == NULL ) {
- return 0;
- }
-
- nw = malloc(sizeof(struct numberswindow));
- if ( nw == NULL ) return 0;
- dw->numbers_window = nw;
-
- nw->window = gtk_dialog_new_with_buttons("Numbers",
- GTK_WINDOW(dw->window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
- NULL);
-
- dvbox = gtk_dialog_get_content_area(GTK_DIALOG(nw->window));
- vbox = gtk_vbox_new(FALSE, 0);
- hbox = gtk_hbox_new(TRUE, 0);
- gtk_box_pack_start(GTK_BOX(dvbox), GTK_WIDGET(hbox), FALSE, FALSE, 7);
- gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 5);
-
- table = gtk_table_new(17, 17, FALSE);
- gtk_table_set_row_spacings(GTK_TABLE(table), 5);
- gtk_table_set_col_spacings(GTK_TABLE(table), 5);
- gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(table), FALSE, FALSE, 0);
-
- for ( x=0; x<17; x++ ) {
- for ( y=0; y<17; y++ ) {
-
- GtkWidget *label;
-
- label = gtk_label_new("--");
- gtk_widget_set_size_request(GTK_WIDGET(label), 40, -1);
-
- gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(label),
- x, x+1, y, y+1);
-
- nw->labels[x+17*y] = label;
-
- }
- }
-
- hbox2 = gtk_hbox_new(FALSE, 0);
- gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox2), FALSE, FALSE, 5);
- label = gtk_label_new("Feature:");
- gtk_box_pack_start(GTK_BOX(hbox2), GTK_WIDGET(label), FALSE, FALSE, 5);
- nw->feat = gtk_label_new("-");
- gtk_box_pack_start(GTK_BOX(hbox2), GTK_WIDGET(nw->feat),
- FALSE, FALSE, 5);
-
- g_signal_connect(G_OBJECT(nw->window), "response",
- G_CALLBACK(displaywindow_numbers_response), dw);
- g_signal_connect(G_OBJECT(nw->window), "destroy",
- G_CALLBACK(displaywindow_numbers_destroy), dw);
- gtk_window_set_resizable(GTK_WINDOW(nw->window), FALSE);
-
- gtk_widget_show_all(nw->window);
-
- return 0;
-}
-
-
-static void numbers_update(DisplayWindow *dw)
-{
- int px, py;
- int imin;
- double dmin;
- struct imagefeature *f;
- int ffs = 0;
- int fss = 0;
- struct panel *fp = NULL;
- int found = 0;
-
- for ( px=0; px<17; px++ ) {
- for ( py=0; py<17; py++ ) {
-
- char s[32];
- GtkWidget *l;
- int x, y;
- int invalid;
- double dfs, dss;
- int fs, ss;
- struct panel *p;
-
- x = dw->binning * dw->numbers_window->cx + (px-8);
- y = dw->binning * dw->numbers_window->cy + (17-py-8);
- x += dw->min_x;
- y += dw->min_y;
-
- /* Map from unbinned mapped pixel coordinates to a panel */
- invalid = reverse_2d_mapping(x, y, dw->image->det,
- &p, &dfs, &dss);
- fs = dfs; ss = dss;
-
- if ( !invalid ) {
-
- float val;
- int pn;
-
- pn = panel_number(dw->image->det, p);
- val = dw->image->dp[pn][fs+ss*p->w];
-
- if ( (val > 0.0) && (log(val)/log(10.0) >= 5) ) {
- snprintf(s, 31, "HUGE");
- } else if ( (val < 0.0) && (log(-val)/log(10) >= 4) ) {
- snprintf(s, 31, "-HUGE");
- } else {
- size_t l, i;
- snprintf(s, 31, "%.4f", val);
- l = strlen(s);
- for ( i=l-1; i>0; i-- ) {
- if ( s[i] == '0' ) s[i] = '\0';
- if ( s[i] == '.' ) {
- s[i] = '\0';
- break;
- }
- }
- }
-
- if ( (px==8) && (py==8) ) {
- ffs = fs;
- fss = ss;
- fp = p;
- found = 1;
- }
-
- } else {
- strcpy(s, "-");
- }
- l = dw->numbers_window->labels[px+17*py];
- gtk_label_set_text(GTK_LABEL(l), s);
-
- }
- }
-
- if ( found && (dw->image->features != NULL) ) {
-
- char text[1024+32+16];
-
- f = image_feature_closest(dw->image->features, ffs, fss, fp,
- &dmin, &imin);
- if ( dmin < dw->ring_radius*dw->binning ) {
- strncpy(text, f->name, 32);
- } else {
- strcpy(text, "");
- }
-
- strcat(text, " (panel ");
- strncat(text, fp->name, 1024);
- strcat(text, ")");
-
- gtk_label_set_text(GTK_LABEL(dw->numbers_window->feat), text);
-
- } else if ( fp != NULL ) {
-
- char text[1024+16];
-
- text[0] = '\0';
- strcat(text, "Panel ");
- strncat(text, fp->name, 1024);
-
- gtk_label_set_text(GTK_LABEL(dw->numbers_window->feat), text);
-
- } else {
- gtk_label_set_text(GTK_LABEL(dw->numbers_window->feat), "-");
- }
-}
-
-
-static void displaywindow_addui_callback(GtkUIManager *ui, GtkWidget *widget,
- GtkContainer *container)
-{
- gtk_box_pack_start(GTK_BOX(container), widget, FALSE, FALSE, 0);
-
- /* Enable overflow menu if this is a toolbar */
- if ( GTK_IS_TOOLBAR(widget) ) {
- gtk_toolbar_set_show_arrow(GTK_TOOLBAR(widget), TRUE);
- }
-}
-
-
-static gint displaywindow_setscale(GtkWidget *widget, GtkRadioAction *action,
- DisplayWindow *dw)
-{
- switch ( gtk_radio_action_get_current_value(action) )
- {
- case 0 : dw->scale = SCALE_COLOUR; break;
- case 1 : dw->scale = SCALE_MONO; break;
- case 2 : dw->scale = SCALE_INVMONO; break;
- }
- displaywindow_update(dw);
-
- return 0;
-}
-
-static int curr_rg_pointer_index(DisplayWindow *dw)
-{
- int r;
-
- for ( r=0; r<dw->rg_coll->n_rigid_groups; ++r) {
- if ( dw->rg_coll->rigid_groups[r] == dw->calib_mode_curr_rg ) {
- return r;
- }
- }
-
- /* Never reached (we hope) */
- ERROR("Failed to find index for rg!\n");
- return 0;
-}
-
-static int curr_p_pointer_index(DisplayWindow *dw)
-{
- int p;
-
- for ( p=0; p<dw->image->det->n_panels; ++p) {
- if ( &dw->image->det->panels[p] == dw->calib_mode_curr_p ) {
- return p;
- }
- }
-
- /* Never reached (we hope) */
- ERROR("Failed to find index for panel!\n");
- return 0;
-}
-
-
-static void select_next_group(DisplayWindow *dw)
-{
- int idx = curr_rg_pointer_index(dw);
- int n_rgs = dw->rg_coll->n_rigid_groups;
-
- if ( idx == n_rgs-1 ) {
- dw->calib_mode_curr_rg = dw->rg_coll->rigid_groups[0];
- } else {
- dw->calib_mode_curr_rg = dw->rg_coll->rigid_groups[idx+1];
- }
-}
-
-
-static void select_prev_group(DisplayWindow *dw)
-{
- int idx = curr_rg_pointer_index(dw);
- int n_rgs = dw->rg_coll->n_rigid_groups;
-
- if ( idx == 0 ) {
- dw->calib_mode_curr_rg = dw->rg_coll->rigid_groups[n_rgs-1];
- } else {
- dw->calib_mode_curr_rg = dw->rg_coll->rigid_groups[idx-1];
- }
-}
-
-
-static void select_next_panel(DisplayWindow *dw, int num_p)
-{
- if ( dw->calib_mode_curr_p == &dw->image->det->panels[num_p-1] ) {
- dw->calib_mode_curr_p = &dw->image->det->panels[0];
- } else {
- dw->calib_mode_curr_p =
- &dw->image->det->panels[curr_p_pointer_index(dw)+1];
- }
-}
-
-
-static void select_prev_panel(DisplayWindow *dw, int num_p)
-{
- if ( dw->calib_mode_curr_p == &dw->image->det->panels[0] ) {
- dw->calib_mode_curr_p = &dw->image->det->panels[num_p-1];
- } else {
- dw->calib_mode_curr_p =
- &dw->image->det->panels[curr_p_pointer_index(dw)-1];
- }
-}
-
-
-static void toggle_calibmode_groupmode(GtkWidget *widget, DisplayWindow *dw)
-{
- struct rigid_group *rg;
- struct detector *det = dw->image->det;
-
- switch ( dw->calib_mode ) {
-
- case CALIBMODE_NONE:
- break;
-
- case CALIBMODE_PANELS:
- if ( det->n_rigid_groups != det->n_panels ) {
- /* Only change if there are any rigid groups defined */
- dw->calib_mode = CALIBMODE_GROUPS;
- rg = find_corresponding_rigid_group(dw,
- dw->calib_mode_curr_p);
- if ( rg == NULL) {
- dw->calib_mode = CALIBMODE_ALL;
- } else {
- dw->calib_mode_curr_rg = rg;
- }
-
- } else {
- /* ...otherwise skip to ALL mode */
- dw->calib_mode = CALIBMODE_ALL;
- }
- break;
-
- case CALIBMODE_GROUPS:
- dw->calib_mode = CALIBMODE_ALL;
- break;
-
- case CALIBMODE_ALL:
- dw->calib_mode = CALIBMODE_PANELS;
- dw->calib_mode_curr_p = dw->calib_mode_curr_rg->panels[0];
- break;
-
- }
- redraw_window(dw);
-}
-
-
-static void toggle_calibmode_focus(GtkWidget *widget, DisplayWindow *dw)
-{
- dw->calib_mode_show_focus = 1 - dw->calib_mode_show_focus;
- redraw_window(dw);
-}
-
-
-static void calibmode_next(GtkWidget *widget, DisplayWindow *dw)
-{
- int n;
-
- switch ( dw->calib_mode ) {
-
- case CALIBMODE_NONE:
- break;
-
- case CALIBMODE_PANELS:
- n = dw->image->det->n_panels;
- select_next_panel(dw, n);
- break;
-
- case CALIBMODE_GROUPS:
- select_next_group(dw);
- break;
-
- case CALIBMODE_ALL:
- break;
-
- }
- redraw_window(dw);
-}
-
-
-static void calibmode_prev(GtkWidget *widget, DisplayWindow *dw)
-{
- int n;
-
- switch ( dw->calib_mode ) {
-
- case CALIBMODE_NONE:
- break;
-
- case CALIBMODE_PANELS:
- n = dw->image->det->n_panels;
- select_prev_panel(dw, n);
- break;
-
- case CALIBMODE_GROUPS:
- n = dw->image->det->n_rigid_groups;
- select_prev_group(dw);
- break;
-
- case CALIBMODE_ALL:
- break;
-
- }
- redraw_window(dw);
-}
-
-
-static void event_next(GtkWidget *widget, DisplayWindow *dw)
-{
- int new_event, curr_event;
-
- curr_event = find_event(dw->ev, dw->ev_list);
-
- if ( curr_event >= dw->ev_list->num_events-1 ) {
- new_event = 0;
- } else {
- new_event = curr_event+1;
- }
- displaywindow_newevent(dw, new_event);
-}
-
-
-static void event_prev(GtkWidget *widget, DisplayWindow *dw)
-{
- int new_event, curr_event;
-
- curr_event = find_event(dw->ev, dw->ev_list);
-
- if ( curr_event == 0 ) {
- new_event = dw->ev_list->num_events-1;
- } else {
- new_event = curr_event-1;
- }
- displaywindow_newevent(dw, new_event);
-}
-
-
-static void displaywindow_addmenubar(DisplayWindow *dw, GtkWidget *vbox,
- int colscale)
-{
- GError *error = NULL;
-
- const char *ui="<ui>"
- "<menubar name=\"displaywindow\">"
- "<menu name=\"file\" action=\"FileAction\">"
- "<menuitem name=\"save\" action=\"SaveAction\" />"
- "<separator />"
- "<menuitem name=\"close\" action=\"CloseAction\" />"
- "</menu>"
- "<menu name=\"view\" action=\"ViewAction\">"
- "<menuitem name=\"images\" action=\"ImagesAction\" />"
- "<separator />"
- "<menuitem name=\"binning\" action=\"BinningAction\" />"
- "<menuitem name=\"boostint\" action=\"BoostIntAction\" />"
- "<menuitem name=\"rings\" action=\"RingsAction\" />"
- "<menuitem name=\"showpeaks\" action=\"ShowPeaksAction\" />"
- "<menuitem name=\"ringradius\" action=\"RingRadiusAction\" />"
- "<separator />"
- "<menuitem name=\"col\" action=\"ColAction\" />"
- "<menuitem name=\"monoscale\" action=\"MonoAction\" />"
- "<menuitem name=\"invmonoscale\" action=\"InvMonoAction\" />"
- "<separator />"
- "<menuitem name=\"colscale\" action=\"ColScaleAction\" />"
- "</menu>"
- "<menu name=\"tools\" action=\"ToolsAction\">"
- "<menuitem name=\"calibmode\" action=\"CalibModeAction\" />"
- "<menuitem name=\"numbers\" action=\"NumbersAction\" />"
- "<menuitem name=\"peaks\" action=\"PeaksAction\" />"
- "</menu>"
- "<menu name=\"calibration\" action=\"CalibrationAction\">"
- "<menuitem name=\"calibrationprevious\" action=\"CalibPreviousAction\" />"
- "<menuitem name=\"calibrationnext\" action=\"CalibNextAction\" />"
- "<menuitem name=\"switchcalibmode\" action=\"SwitchCalibModeAction\" />"
- "<menuitem name=\"focus\" action=\"ToggleFocusAction\" />"
- "<menuitem name=\"savegeometry\" action=\"SaveGeometryAction\" />"
- "</menu>"
- "<menu name=\"events\" action=\"EventsAction\">"
- "<menuitem name=\"eventprevious\" action=\"EventPreviousAction\" />"
- "<menuitem name=\"eventnext\" action=\"EventNextAction\" />"
- "<menuitem name=\"gotoevent\" action=\"GotoEventAction\" />"
- "<menuitem name=\"randomevent\" action=\"RandomEventAction\" />"
- "</menu>"
- "<menu name=\"help\" action=\"HelpAction\">"
- "<menuitem name=\"about\" action=\"AboutAction\" />"
- "</menu>"
- "</menubar>"
- "</ui>";
-
- GtkActionEntry entries[] = {
-
- { "FileAction", NULL, "_File", NULL, NULL, NULL },
- { "SaveAction", GTK_STOCK_SAVE, "Save Image...", NULL, NULL,
- G_CALLBACK(displaywindow_save) },
- { "CloseAction", GTK_STOCK_CLOSE, "_Close", NULL, NULL,
- G_CALLBACK(displaywindow_close) },
-
- { "ViewAction", NULL, "_View", NULL, NULL, NULL },
- { "ImagesAction", NULL, "Images", NULL, NULL, NULL },
- { "BinningAction", NULL, "Set Binning...", "F3", NULL,
- G_CALLBACK(displaywindow_set_binning) },
- { "BoostIntAction", NULL, "Boost Intensity...", "F5", NULL,
- G_CALLBACK(displaywindow_set_boostint) },
- { "RingRadiusAction", NULL, "Ring Radius...", "F6", NULL,
- G_CALLBACK(displaywindow_set_ringradius) },
-
- { "ToolsAction", NULL, "_Tools", NULL, NULL, NULL },
- { "NumbersAction", NULL, "View Numbers...", "F2", NULL,
- G_CALLBACK(displaywindow_show_numbers) },
- { "PeaksAction", NULL, "Load Feature List...", NULL, NULL,
- G_CALLBACK(displaywindow_peak_overlay) },
-
- { "CalibrationAction", NULL, "_Calibration", NULL, NULL, NULL },
- { "CalibPreviousAction", NULL, "Previous Item", "minus", NULL,
- G_CALLBACK(calibmode_prev) },
- { "CalibNextAction", NULL, "Next Item", "plus", NULL,
- G_CALLBACK(calibmode_next) },
- { "SwitchCalibModeAction", NULL, "Toggle Panel/Group/All", "g",
- NULL, G_CALLBACK(toggle_calibmode_groupmode) },
- { "ToggleFocusAction", NULL, "Toggle Focus Rectangle", "i",
- NULL, G_CALLBACK(toggle_calibmode_focus) },
- { "SaveGeometryAction", NULL, "Save Geometry", "s", NULL,
- G_CALLBACK(save_geometry_file) },
-
- { "EventsAction", NULL, "_Event", NULL, NULL, NULL },
- { "EventPreviousAction", NULL, "Previous", "p", NULL,
- G_CALLBACK(event_prev) },
- { "EventNextAction", NULL, "Next", "n", NULL,
- G_CALLBACK(event_next) },
- { "GotoEventAction", NULL, "Go To Event", "e", NULL,
- G_CALLBACK(displaywindow_set_newevent) },
- { "RandomEventAction", NULL, "Go To Random Event", "r", NULL,
- G_CALLBACK(displaywindow_randomevent) },
-
- { "HelpAction", NULL, "_Help", NULL, NULL, NULL },
- { "AboutAction", GTK_STOCK_ABOUT, "_About hdfsee...",
- NULL, NULL,
- G_CALLBACK(displaywindow_about) },
-
- };
- guint n_entries = G_N_ELEMENTS(entries);
-
- GtkToggleActionEntry toggles[] = {
- { "ColScaleAction", NULL, "Colour Scale", NULL, NULL,
- G_CALLBACK(displaywindow_set_colscale), FALSE },
- { "CalibModeAction", NULL, "Calibration Mode", NULL, NULL,
- G_CALLBACK(displaywindow_set_calibmode), FALSE },
- { "RingsAction", NULL, "Resolution Rings", "F9", NULL,
- G_CALLBACK(displaywindow_set_rings), dw->show_rings },
- { "ShowPeaksAction", NULL, "Features", "F8", NULL,
- G_CALLBACK(displaywindow_set_peaks), dw->show_peaks },
- };
- guint n_toggles = G_N_ELEMENTS(toggles);
- GtkRadioActionEntry radios[] = {
- { "ColAction", NULL, "Colour", NULL, NULL,
- SCALE_COLOUR },
- { "MonoAction", NULL, "Monochrome", NULL, NULL,
- SCALE_MONO },
- { "InvMonoAction", NULL, "Inverse Monochrome", NULL, NULL,
- SCALE_INVMONO },
- };
- guint n_radios = G_N_ELEMENTS(radios);
-
- dw->action_group = gtk_action_group_new("hdfseedisplaywindow");
- gtk_action_group_add_actions(dw->action_group, entries, n_entries, dw);
- gtk_action_group_add_toggle_actions(dw->action_group, toggles,
- n_toggles, dw);
- gtk_action_group_add_radio_actions(dw->action_group, radios, n_radios,
- colscale,
- G_CALLBACK(displaywindow_setscale),
- dw);
-
- dw->ui = gtk_ui_manager_new();
- gtk_ui_manager_insert_action_group(dw->ui, dw->action_group, 0);
- g_signal_connect(dw->ui, "add_widget",
- G_CALLBACK(displaywindow_addui_callback), vbox);
- if ( gtk_ui_manager_add_ui_from_string(dw->ui, ui, -1, &error) == 0 ) {
- fprintf(stderr, "Error loading message window menu bar: %s\n",
- error->message);
- return;
- }
-
- gtk_window_add_accel_group(GTK_WINDOW(dw->window),
- gtk_ui_manager_get_accel_group(dw->ui));
- gtk_ui_manager_ensure_update(dw->ui);
-}
-
-
-struct newhdf {
- DisplayWindow *dw;
- GtkWidget *widget;
- char name[1024];
-};
-
-/* New HDF5 element selected from menu */
-static gint displaywindow_newhdf(GtkMenuItem *item, struct newhdf *nh)
-{
- gboolean a;
- int fail;
-
- if ( nh->dw->not_ready_yet ) return 0;
- assert(imagefile_get_type(nh->dw->imagefile) == IMAGEFILE_HDF5);
-
- a = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(nh->widget));
- if ( !a ) return 0;
-
- /* hdf5_read() will create a new simple geom, so get rid of the old
- * one */
- free_detector_geometry(nh->dw->image->det);
- nh->dw->image->det = NULL;
- fail = hdf5_read(imagefile_get_hdfile(nh->dw->imagefile),
- nh->dw->image, nh->name, 0);
- if ( fail ) {
- ERROR("Couldn't load image");
- return 1;
- }
-
- do_filters(nh->dw);
- displaywindow_update(nh->dw);
- return 0;
-}
-
-
-static GtkWidget *displaywindow_addhdfgroup(struct hdfile *hdfile,
- const char *group,
- DisplayWindow *dw, GSList **rgp,
- const char *selectme)
-{
- char **names;
- int *is_group;
- int *is_image;
- GtkWidget *ms;
- int n, i;
-
- names = hdfile_read_group(hdfile, &n, group, &is_group, &is_image);
- if ( n == 0 ) return NULL;
-
- ms = gtk_menu_new();
-
- for ( i=0; i<n; i++ ) {
-
- GtkWidget *item;
- GtkWidget *sub;
-
- if ( names[i] == NULL ) return NULL;
-
- if ( is_group[i] ) {
-
- item = gtk_menu_item_new_with_label(names[i]);
-
- sub = displaywindow_addhdfgroup(hdfile, names[i],
- dw, rgp, selectme);
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), sub);
-
- /* No changing image if we're using multiple events,
- * or if we have a geometry file (already saying where to
- * find the data. */
- } else if ( is_image[i] && (dw->ev == NULL)
- && (dw->original_geom == NULL) )
- {
- struct newhdf *nh;
-
- item = gtk_radio_menu_item_new_with_label(*rgp,
- names[i]);
-
- nh = malloc(sizeof(struct newhdf));
- if ( nh != NULL ) {
- strncpy(nh->name, names[i], 1023);
- nh->dw = dw;
- nh->widget = item;
- g_signal_connect(G_OBJECT(item), "toggled",
- G_CALLBACK(displaywindow_newhdf), nh);
- }
-
- if ( (selectme != NULL)
- && (strcmp(names[i], selectme) == 0) ) {
- gtk_check_menu_item_set_active(
- GTK_CHECK_MENU_ITEM(item), TRUE);
- } else {
- gtk_check_menu_item_set_active(
- GTK_CHECK_MENU_ITEM(item), FALSE);
- }
-
- *rgp = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item));
-
- } else {
-
- char *tmp;
-
- item = gtk_menu_item_new_with_label(names[i]);
- tmp = hdfile_get_string_value(hdfile, names[i], dw->ev);
- if ( tmp != NULL ) {
-
- GtkWidget *ss;
- GtkWidget *mss;
-
- mss = gtk_menu_new();
- ss = gtk_menu_item_new_with_label(tmp);
- gtk_widget_set_sensitive(ss, FALSE);
- gtk_menu_shell_append(GTK_MENU_SHELL(mss), ss);
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(item),
- mss);
- }
-
- }
-
- gtk_menu_shell_append(GTK_MENU_SHELL(ms), item);
-
- free(names[i]);
-
- }
-
- free(is_group);
- free(is_image);
- free(names);
-
- return ms;
-}
-
-
-static GtkWidget *displaywindow_createhdfmenus(struct hdfile *hdfile,
- DisplayWindow *dw,
- const char *selectme)
-{
- GSList *rg = NULL;
- GtkWidget *w;
-
- w = displaywindow_addhdfgroup(hdfile, "/", dw, &rg, selectme);
-
- return w;
-}
-
-
-struct newev {
- DisplayWindow *dw;
- GtkWidget *widget;
- int new_ev;
-};
-
-
-static int displaywindow_update_menus(DisplayWindow *dw, const char *selectme)
-{
- GtkWidget *ms;
- GtkWidget *w;
-
- if ( imagefile_get_type(dw->imagefile) != IMAGEFILE_HDF5 ) {
- return 0;
- }
-
- ms = displaywindow_createhdfmenus(imagefile_get_hdfile(dw->imagefile),
- dw, selectme);
-
- if ( ms == NULL ) return 1;
-
- /* Make new menu be the submenu for File->Images */
- w = gtk_ui_manager_get_widget(dw->ui, "/ui/displaywindow/view/images");
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(w), ms);
-
- gtk_widget_show_all(ms);
-
- return 0;
-}
-
-
-static gint displaywindow_release(GtkWidget *widget, GdkEventButton *event,
- DisplayWindow *dw)
-{
- if ( (event->type == GDK_BUTTON_RELEASE) && (event->button == 1) ) {
-
- g_signal_handler_disconnect(G_OBJECT(dw->drawingarea),
- dw->motion_callback);
- dw->motion_callback = 0;
-
- }
-
- return 0;
-}
-
-
-static gint displaywindow_motion(GtkWidget *widget, GdkEventMotion *event,
- DisplayWindow *dw)
-{
- if ( dw->numbers_window == NULL ) return 0;
-
- dw->numbers_window->cx = event->x;
- dw->numbers_window->cy = dw->height - 1 - event->y;
-
- /* Schedule redraw */
- gtk_widget_queue_draw_area(dw->drawingarea, 0, 0,
- dw->width, dw->height);
-
- /* Update numbers window */
- numbers_update(dw);
-
- return 0;
-
-}
-
-
-static void calibmode_press(DisplayWindow *dw, GdkEventButton *event)
-{
- int x,y;
- double dfs, dss;
- int fs, ss, revmap_return_value;
- char statusbar_string[256];
- guint cc;
- struct panel *p;
-
- cc = gtk_statusbar_get_context_id(GTK_STATUSBAR(dw->statusbar),
- "calibmode");
-
- x = dw->binning * (event->x);
- y = dw->binning * (dw->height - 1 - event->y);
- x += dw->min_x;
- y += dw->min_y;
- snprintf(statusbar_string, 80,
- "Last clicked position: x: %i, y: %i (Not in panel)", x, y);
-
- revmap_return_value = reverse_2d_mapping(x, y, dw->image->det,
- &p, &dfs, &dss);
- if ( revmap_return_value == 0 ) {
- fs = dfs;
- ss = dss;
- if ( snprintf(statusbar_string, 256,
- "Last clicked position: x: %i, y: %i, fs: %u, ss: %u,"
- " (panel %s)", x, y, fs, ss, p->name) >= 256 )
- {
- ERROR("Panel name is too long for status bar.\n");
- }
- }
- gtk_statusbar_push(GTK_STATUSBAR(dw->statusbar), cc, statusbar_string);
-}
-
-
-static gint displaywindow_press(GtkWidget *widget, GdkEventButton *event,
- DisplayWindow *dw)
-{
- if ( dw->motion_callback != 0 ) {
- return 0;
- }
-
- if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 1) ) {
-
- dw->motion_callback = g_signal_connect(
- G_OBJECT(dw->drawingarea),
- "motion-notify-event",
- G_CALLBACK(displaywindow_motion),
- dw);
-
- if ( dw->numbers_window != NULL ) {
- dw->numbers_window->cx = event->x;
- dw->numbers_window->cy = dw->height - 1 - event->y;
- numbers_update(dw);
- }
-
- if ( dw->statusbar != NULL ) {
- calibmode_press(dw, event);
- }
-
- }
-
- return 0;
-}
-
-static void calibmode_up(DisplayWindow *dw)
-{
- int pi;
-
- switch ( dw->calib_mode ) {
-
- case CALIBMODE_NONE:
- break;
-
- case CALIBMODE_PANELS:
- dw->calib_mode_curr_p->cny += 1.0;
- break;
-
- case CALIBMODE_GROUPS:
- for ( pi=0; pi<dw->calib_mode_curr_rg->n_panels; ++pi ) {
- dw->calib_mode_curr_rg->panels[pi]->cny += 1.0;
- }
- break;
-
- case CALIBMODE_ALL:
- for ( pi=0; pi<dw->image->det->n_panels; ++pi ) {
- dw->image->det->panels[pi].cny += 1.0;
- }
- break;
-
- }
-}
-
-
-static void calibmode_down(DisplayWindow *dw)
-{
- int pi;
-
- switch ( dw->calib_mode ) {
-
- case CALIBMODE_NONE:
- break;
-
- case CALIBMODE_PANELS:
- dw->calib_mode_curr_p->cny -= 1.0;
- break;
-
- case CALIBMODE_GROUPS:
- for ( pi=0; pi<dw->calib_mode_curr_rg->n_panels; ++pi ) {
- dw->calib_mode_curr_rg->panels[pi]->cny -= 1.0;
- }
- break;
-
- case CALIBMODE_ALL:
- for ( pi=0; pi<dw->image->det->n_panels; ++pi ) {
- dw->image->det->panels[pi].cny -= 1.0;
- }
- break;
-
- }
-}
-
-
-static void calibmode_left(DisplayWindow *dw)
-{
- int pi;
-
- switch ( dw->calib_mode ) {
-
- case CALIBMODE_NONE:
- break;
-
- case CALIBMODE_PANELS:
- dw->calib_mode_curr_p->cnx -= 1.0;
- break;
-
- case CALIBMODE_GROUPS:
- for ( pi=0; pi<dw->calib_mode_curr_rg->n_panels; ++pi ) {
- dw->calib_mode_curr_rg->panels[pi]->cnx -= 1.0;
- }
- break;
-
- case CALIBMODE_ALL:
- for ( pi=0; pi<dw->image->det->n_panels; ++pi ) {
- dw->image->det->panels[pi].cnx -= 1.0;
- }
- break;
-
- }
-}
-
-
-static void calibmode_right(DisplayWindow *dw)
-{
- int pi;
-
- switch ( dw->calib_mode ) {
-
- case CALIBMODE_NONE:
- break;
-
- case CALIBMODE_PANELS:
- dw->calib_mode_curr_p->cnx += 1.0;
- break;
-
- case CALIBMODE_GROUPS:
- for ( pi=0; pi<dw->calib_mode_curr_rg->n_panels; ++pi ) {
- dw->calib_mode_curr_rg->panels[pi]->cnx += 1.0;
- }
- break;
-
- case CALIBMODE_ALL:
- for ( pi=0; pi<dw->image->det->n_panels; ++pi ) {
- dw->image->det->panels[pi].cnx += 1.0;
- }
- break;
-
- }
-}
-
-
-static void change_ring(DisplayWindow *dw, double inc)
-{
- if ( dw->n_rings < 1 ) return;
- if ( dw->n_rings == 1 ) {
- dw->ring_radii[0] += inc;
- STATUS("Ring radius = %.1f px\n", dw->ring_radii[0]);
- } else {
- dw->ring_radii[1] += inc;
- STATUS("Ring radius = %.1f px\n", dw->ring_radii[1]);
- }
-}
-
-
-static gint displaywindow_keypress(GtkWidget *widget, GdkEventKey *event,
- DisplayWindow *dw)
-{
- if ( dw->calib_mode ) {
-
- switch ( event->keyval ) {
-
- case GDK_Up:
- case GDK_KP_Up:
- calibmode_up(dw);
- redraw_window(dw);
- break;
-
- case GDK_Down:
- case GDK_KP_Down:
- calibmode_down(dw);
- redraw_window(dw);
- break;
-
- case GDK_Left:
- case GDK_KP_Left:
- calibmode_left(dw);
- redraw_window(dw);
- break;
-
- case GDK_Right:
- case GDK_KP_Right:
- calibmode_right(dw);
- redraw_window(dw);
- break;
-
- case GDK_KP_Add:
- calibmode_next(NULL, dw);
- break;
-
- case GDK_KP_Subtract:
- calibmode_prev(NULL, dw);
- break;
- }
-
- }
-
- switch ( event->keyval ) {
-
- case GDK_a:
- change_ring(dw, +1.0);
- redraw_window(dw);
- break;
-
- case GDK_b:
- change_ring(dw, -1.0);
- redraw_window(dw);
- break;
-
- }
-
- return 0;
-}
-
-
-static void impose_twod_geometry(DisplayWindow *dw, const char *twod_element)
-{
-
- int i;
-
- for ( i=0; i<dw->image->det->n_panels; i++ ) {
-
- struct panel *p;
-
- p = &dw->image->det->panels[i];
-
- if ( p->data != NULL ) free(p->data);
- p->data = strdup(twod_element);
-
- if ( p->dim_structure ) free_dim_structure(p->dim_structure);
- p->dim_structure = default_dim_structure();
- }
-
- dw->image->det->path_dim = 0;
- dw->image->det->dim_dim = 0;
-
-}
-
-
-DisplayWindow *displaywindow_open(char *filename, char *geom_filename,
- const char *peaks,
- double boost, int binning,
- int noisefilter, int calibmode, int colscale,
- const char *element, const char *event,
- struct detector *det_geom,
- struct beam_params *beam,
- const char* rgcoll_name,
- int show_rings, double *ring_radii,
- int n_rings, double ring_size,
- int median_filter)
-{
- DisplayWindow *dw;
- GtkWidget *vbox;
- int check;
- FILE *fh;
- unsigned long int seed;
-
- dw = calloc(1, sizeof(DisplayWindow));
- if ( dw == NULL ) return NULL;
-
- dw->pixbufs = NULL;
- dw->peaktype = 0;
- dw->binning_dialog = NULL;
- dw->show_col_scale = 0;
- dw->col_scale = NULL;
- dw->boostint_dialog = NULL;
- dw->boostint = 1;
- dw->motion_callback = 0;
- dw->numbers_window = NULL;
- dw->image = NULL;
- dw->show_rings = show_rings;
- dw->show_peaks = 0;
- dw->scale = colscale;
- dw->binning = binning;
- dw->boostint = boost;
- dw->noisefilter = noisefilter;
- dw->not_ready_yet = 1;
- dw->surf = NULL;
- dw->ring_radius = ring_size;
- dw->ring_radii = ring_radii;
- dw->n_rings = n_rings;
- dw->median_filter = median_filter;
- dw->image = calloc(1, sizeof(struct image));
- dw->calib_mode = CALIBMODE_NONE;
- dw->calib_mode_curr_rg = NULL;
- dw->calib_mode_curr_p = NULL;
- dw->calib_mode_show_focus = 1;
- dw->statusbar = NULL;
- dw->ev_list = NULL;
- dw->ev = NULL;
- dw->rng = *gsl_rng_alloc(gsl_rng_mt19937);
-
- fh = fopen("/dev/urandom", "r");
- fread(&seed, sizeof(seed), 1, fh);
- fclose(fh);
- gsl_rng_set(&dw->rng, seed);
-
- if ( geom_filename != NULL ) {
- dw->geom_filename = strdup(geom_filename);
- } else {
- dw->geom_filename = NULL;
- }
- if ( rgcoll_name != NULL ) {
- dw->rg_coll_name = strdup(rgcoll_name);
- } else {
- dw->rg_coll_name = NULL;
- }
-
- dw->original_geom = det_geom;
- dw->image->det = copy_geom(det_geom);
- dw->image->beam = beam;
- dw->image->lambda = 0.0;
- dw->image->filename = filename;
-
- dw->imagefile = imagefile_open(filename);
- if ( dw->imagefile == NULL ) {
- ERROR("Couldn't open file: %s\n", filename);
- free(dw->geom_filename);
- free(dw);
- return NULL;
- }
-
- if ( dw->image->det != NULL && element != NULL ) {
- impose_twod_geometry(dw, element);
- }
-
- if ( element != NULL ) {
- if ( imagefile_get_type(dw->imagefile) != IMAGEFILE_HDF5 ) {
- ERROR("Can only use -e/--image with HDF5 files\n");
- return NULL;
- }
- hdfile_set_image(imagefile_get_hdfile(dw->imagefile), element);
- }
-
- if ( (dw->image->det != NULL)
- && (multi_event_geometry(dw->image->det)) )
- {
- struct hdfile *hdfile;
-
- if ( imagefile_get_type(dw->imagefile) != IMAGEFILE_HDF5 ) {
- ERROR("Multi-event geometry, but not HDF5 file!\n");
- return NULL;
- }
- hdfile = imagefile_get_hdfile(dw->imagefile);
-
- dw->ev_list = fill_event_list(hdfile, dw->image->det);
-
- if ( dw->ev_list == NULL ) {
- ERROR("Error while parsing file structure\n");
- free(dw->geom_filename);
- free(dw);
- return NULL;
- }
- if ( dw->ev_list->num_events == 0 ) {
- ERROR("Multi-event geometry file but no events found "
- "in data file\n");
- free_event_list(dw->ev_list);
- free(dw->geom_filename);
- free(dw);
- return NULL;
- }
-
- if ( event != NULL ) {
- int curr_event;
- dw->ev = get_event_from_event_string(event);
- curr_event = find_event(dw->ev, dw->ev_list);
- if ( curr_event == dw->ev_list->num_events ) {
- ERROR("Invalid event\n");
- return NULL;
- }
- } else {
- dw->ev = dw->ev_list->events[0];
- }
-
- check = imagefile_read(dw->imagefile, dw->image, dw->ev);
-
- } else {
-
- dw->ev = NULL;
-
- if ( dw->image->det == NULL ) {
- check = imagefile_read_simple(dw->imagefile, dw->image);
- } else {
- check = imagefile_read(dw->imagefile, dw->image, dw->ev);
- }
-
- }
-
- if ( check ) {
- ERROR("Couldn't load file\n");
- imagefile_close(dw->imagefile);
- free(dw->geom_filename);
- return NULL;
- }
-
- dw->image->filename = strdup(filename);
-
- /* Filters need geometry */
- do_filters(dw);
-
- /* Peak list provided at startup? */
- if ( peaks != NULL ) {
- dw->peaktype = load_features_from_file(dw->image, peaks);
- dw->show_peaks = 1;
- }
-
- dw->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- update_titlebar(dw);
-
- g_signal_connect(G_OBJECT(dw->window), "destroy",
- G_CALLBACK(displaywindow_closed), dw);
-
- vbox = gtk_vbox_new(FALSE, 0);
- gtk_container_add(GTK_CONTAINER(dw->window), vbox);
- displaywindow_addmenubar(dw, vbox, colscale);
-
- dw->drawingarea = gtk_drawing_area_new();
- dw->scrollarea = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dw->scrollarea),
- GTK_POLICY_AUTOMATIC,
- GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(dw->scrollarea),
- dw->drawingarea);
- gtk_box_pack_start(GTK_BOX(vbox), dw->scrollarea, TRUE, TRUE, 0);
-
- if ( g_signal_lookup("draw", GTK_TYPE_DRAWING_AREA) ) {
- g_signal_connect(G_OBJECT(dw->drawingarea), "draw",
- G_CALLBACK(displaywindow_draw), dw);
- } else {
- g_signal_connect(G_OBJECT(dw->drawingarea), "expose-event",
- G_CALLBACK(displaywindow_expose), dw);
- }
-
- gtk_window_set_resizable(GTK_WINDOW(dw->window), TRUE);
- gtk_widget_show_all(dw->window);
-
- if ( dw->ev_list == NULL ) {
- set_events_menu_sensitivity(dw, FALSE);
- }
-
- set_calibration_menu_sensitivity(dw, FALSE);
-
- displaywindow_update(dw);
-
- gtk_widget_add_events(GTK_WIDGET(dw->drawingarea),
- GDK_BUTTON_PRESS_MASK
- | GDK_BUTTON_RELEASE_MASK
- | GDK_BUTTON1_MOTION_MASK
- | GDK_KEY_PRESS_MASK);
- g_object_set(G_OBJECT(dw->drawingarea), "can-focus", TRUE, NULL);
-
- gtk_widget_grab_focus(dw->drawingarea);
-
- g_signal_connect(G_OBJECT(dw->drawingarea), "button-press-event",
- G_CALLBACK(displaywindow_press), dw);
- g_signal_connect(G_OBJECT(dw->drawingarea), "button-release-event",
- G_CALLBACK(displaywindow_release), dw);
- g_signal_connect(G_OBJECT(dw->drawingarea), "key-press-event",
- G_CALLBACK(displaywindow_keypress), dw);
-
- displaywindow_update_menus(dw, element);
-
- dw->not_ready_yet = 0;
-
- return dw;
-}
diff --git a/src/dw-hdfsee.h b/src/dw-hdfsee.h
deleted file mode 100644
index 439425a5..00000000
--- a/src/dw-hdfsee.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * dw-hdfsee.h
- *
- * Quick yet non-crappy HDF viewer
- *
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
- * a research centre of the Helmholtz Association.
- * Copyright © 2012 Richard Kirian
- *
- * Authors:
- * 2009-2017 Thomas White <taw@physics.org>
- * 2014 Valerio Mariani
- * 2014 Takanori Nakane <nakane.t@gmail.com>
- * 2012 Richard Kirian
- *
- * This file is part of CrystFEL.
- *
- * CrystFEL is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * CrystFEL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifndef DISPLAYWINDOW_H
-#define DISPLAYWINDOW_H
-
-#include "events.h"
-#include "image.h"
-#include <gtk/gtk.h>
-
-typedef struct {
- GtkWidget *window;
- GtkWidget *entry;
-} BinningDialog;
-
-
-typedef struct {
- GtkWidget *window;
- GtkWidget *entry;
-} BoostIntDialog;
-
-
-typedef struct {
- GtkWidget *window;
- GtkWidget *entry;
-} RingRadiusDialog;
-
-
-typedef struct {
- GtkWidget *window;
- GtkWidget *entry;
-} EventDialog;
-
-
-struct numberswindow {
- GtkWidget *window;
- GtkWidget *labels[17*17];
- GtkWidget *feat;
- unsigned int cx;
- unsigned int cy;
-};
-
-
-typedef enum {
- CALIBMODE_NONE,
- CALIBMODE_PANELS,
- CALIBMODE_GROUPS,
- CALIBMODE_ALL
-} CalibMode;
-
-
-typedef struct {
-
- GtkWidget *window;
- GtkWidget *drawingarea;
- GtkWidget *scrollarea;
- GtkUIManager *ui;
- GtkActionGroup *action_group;
- GtkActionGroup *calibration_action_group;
- GtkActionGroup *events_action_group;
-
- int n_pixbufs;
- GdkPixbuf **pixbufs;
- gulong motion_callback;
- cairo_surface_t *surf;
- struct detector *original_geom;
-
- int not_ready_yet;
-
- struct imagefile *imagefile;
- struct image *image;
- int peaktype;
-
- char *geom_filename;
- char *rg_coll_name;
-
- /* Dialog boxes */
- BinningDialog *binning_dialog;
- BoostIntDialog *boostint_dialog;
- RingRadiusDialog *ringradius_dialog;
- EventDialog *event_dialog;
- struct numberswindow *numbers_window;
-
- int width;
- int height; /* Size of the drawing area */
- double min_x;
- double min_y;
- double max_x;
- double max_y;
-
- int binning;
- double boostint;
- int noisefilter; /* Use aggressive noise filter */
- int median_filter;
- int show_rings;
- int show_peaks;
- double ring_radius;
- double *ring_radii;
- int n_rings;
-
- CalibMode calib_mode;
- struct rg_collection *rg_coll;
- struct rigid_group *calib_mode_curr_rg;
- struct panel *calib_mode_curr_p;
- int calib_mode_show_focus;
- GtkWidget *statusbar;
-
- int show_col_scale;
- int scale;
- GdkPixbuf *col_scale;
-
- struct event_list *ev_list;
- struct event *ev;
-
- gsl_rng rng;
-
-
-} DisplayWindow;
-
-/* Open an image display window showing the given filename, or NULL */
-extern DisplayWindow *displaywindow_open(char *filename, char *geom_filename,
- const char *peaks, double boost,
- int binning,
- int noisefilter, int calibmode,
- int colscale, const char *element,
- const char *event,
- struct detector *det_geom,
- struct beam_params *beam,
- const char *rgcoll_name, int show_rings,
- double *ring_radii, int n_rings,
- double ring_size, int median_filter);
-
-
-#endif /* DISPLAYWINDOW_H */
diff --git a/src/geoptimiser.c b/src/geoptimiser.c
index 233edac4..24a159de 100644
--- a/src/geoptimiser.c
+++ b/src/geoptimiser.c
@@ -3,13 +3,13 @@
*
* Refine detector geometry
*
- * Copyright © 2014-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2014-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
* 2014-2015 Oleksandr Yefanov
* 2014-2015 Valerio Mariani
- * 2014-2019 Thomas White <taw@physics.org>
+ * 2014-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -54,14 +54,16 @@
#endif /* HAVE_GDK */
#endif /* HAVE_CAIRO */
-#include "detector.h"
-#include "stream.h"
-#include "crystal.h"
-#include "image.h"
-#include "utils.h"
-#include "render.h"
+#include <detgeom.h>
+#include <datatemplate.h>
+#include <stream.h>
+#include <crystal.h>
+#include <image.h>
+#include <utils.h>
+#include <colscale.h>
+
+#include "version.h"
-#include "hdfsee-render.h"
struct imagefeature;
@@ -144,7 +146,7 @@ struct single_pixel_displ
struct gpanel
{
- struct panel *p;
+ struct detgeom_panel *p;
/* Individual pixel displacements */
struct single_pixel_displ *pix_displ_list;
@@ -158,7 +160,56 @@ struct gpanel
};
-static void compute_x_y(double fs, double ss, struct panel *p,
+static void free_pixbuf_data(guchar *data, gpointer p)
+{
+ free(data);
+}
+
+
+static GdkPixbuf *render_get_colour_scale(size_t w, size_t h, int scale)
+{
+ guchar *data;
+ size_t x, y;
+ int max;
+
+ data = malloc(3*w*h);
+ if ( data == NULL ) return NULL;
+
+ max = h-(h/6);
+
+ for ( y=0; y<h; y++ ) {
+
+ double r, g, b;
+ int val;
+
+ val = y-(h/6);
+
+ colscale_lookup(val, max, scale, &r, &g, &b);
+
+ data[3*( 0+w*(h-1-y) )+0] = 0;
+ data[3*( 0+w*(h-1-y) )+1] = 0;
+ data[3*( 0+w*(h-1-y) )+2] = 0;
+ for ( x=1; x<w; x++ ) {
+ data[3*( x+w*(h-1-y) )+0] = 255*r;
+ data[3*( x+w*(h-1-y) )+1] = 255*g;
+ data[3*( x+w*(h-1-y) )+2] = 255*b;
+ }
+ }
+
+ y = h/6;
+ for ( x=1; x<w; x++ ) {
+ data[3*( x+w*(h-1-y) )+0] = 255;
+ data[3*( x+w*(h-1-y) )+1] = 255;
+ data[3*( x+w*(h-1-y) )+2] = 255;
+ }
+
+ return gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB,
+ FALSE, 8, w, h, w*3,
+ free_pixbuf_data, NULL);
+}
+
+
+static void compute_x_y(double fs, double ss, struct detgeom_panel *p,
double *x, double *y)
{
double xs, ys;
@@ -192,10 +243,14 @@ static Reflection *find_closest_reflection(struct image *image,
double ds;
double rfs, rss;
double rx, ry;
+ int pn;
get_detector_pos(refl, &rfs, &rss);
+ pn = get_panel_number(refl);
- compute_x_y(rfs, rss, get_panel(refl), &rx, &ry);
+ compute_x_y(rfs, rss,
+ &image->detgeom->panels[pn],
+ &rx, &ry);
ds = distance(rx+det_shift[0], ry+det_shift[1], fx, fy);
@@ -217,39 +272,28 @@ static Reflection *find_closest_reflection(struct image *image,
}
-static double get_average_clen(struct image *image)
+static double avg_clen(struct detgeom *det)
{
int i;
- struct stuff_from_stream *stuff = image->stuff_from_stream;
-
- if ( stuff == NULL ) {
- ERROR("No 'stuff' from stream!\n");
- return -1.0;
- }
+ double av = 0.0;
- for ( i=0; i<stuff->n_fields; i++ ) {
-
- if ( strncmp(stuff->fields[i], "average_camera_length = ",
- 24) == 0 )
- {
- return atof(stuff->fields[i]+24);
- }
+ for ( i=0; i<det->n_panels; i++ ) {
+ av += det->panels[i].cnz * det->panels[i].pixel_pitch;
}
-
- ERROR("Failed to recover average camera length from stream file\n");
- return -1.0;
+ return av / i;
}
-static struct image *read_patterns_from_stream(Stream *st,
- struct detector *det, int *n)
+static struct image **read_patterns_from_stream(Stream *st,
+ const DataTemplate *dtempl,
+ int *n)
{
- struct image *images;
+ struct image **images;
int n_chunks = 0;
int max_images = 1024;
int n_images = 0;
- images = malloc(max_images * sizeof(struct image));
+ images = malloc(max_images * sizeof(struct image *));
if ( images == NULL ) {
ERROR("Failed to allocate memory for images.\n");
return NULL;
@@ -257,28 +301,25 @@ static struct image *read_patterns_from_stream(Stream *st,
do {
- images[n_images].det = det;
-
- if ( read_chunk_2(st, &images[n_images],
- STREAM_READ_REFLECTIONS
- | STREAM_READ_PEAKS
- | STREAM_READ_UNITCELL) != 0 ) break;
+ images[n_images] = stream_read_chunk(st, dtempl,
+ STREAM_REFLECTIONS
+ | STREAM_PEAKS
+ | STREAM_UNITCELL);
+ if ( images[n_images] == NULL ) break;
n_chunks++; /* Number of chunks processed */
/* Reject if there are no crystals (not indexed) */
- if ( images[n_images].n_crystals == 0 ) continue;
-
- images[n_images].avg_clen = get_average_clen(&images[n_images]);
+ if ( images[n_images]->n_crystals == 0 ) continue;
n_images++; /* Number of images accepted */
if ( n_images == max_images ) {
- struct image *images_new;
+ struct image **images_new;
images_new = realloc(images,
- (max_images+1024)*sizeof(struct image));
+ (max_images+1024)*sizeof(struct image *));
if ( images_new == NULL ) {
ERROR("Failed to allocate memory for "
"patterns.\n");
@@ -323,7 +364,8 @@ static struct rvec get_q_from_xyz(double rx, double ry, double dist, double l)
}
-static UnitCell *compute_avg_cell_parameters(struct image *images, int n)
+static UnitCell *compute_avg_cell_parameters(struct image **images,
+ int n)
{
int numavc;
int j, i;
@@ -344,9 +386,9 @@ static UnitCell *compute_avg_cell_parameters(struct image *images, int n)
double cpar[6];
int j, cri;
- image = &images[i];
+ image = images[i];
- for ( cri=0; cri<images->n_crystals; cri++ ) {
+ for ( cri=0; cri<image->n_crystals; cri++ ) {
UnitCell *cell = crystal_get_cell(image->crystals[cri]);
@@ -402,7 +444,7 @@ static UnitCell *compute_avg_cell_parameters(struct image *images, int n)
static double pick_clen_to_use(struct geoptimiser_params *gparams,
- struct image *images, int n,
+ struct image **images, int n,
double avg_res, UnitCell *avg)
{
int cp, i, u;
@@ -439,9 +481,9 @@ static double pick_clen_to_use(struct geoptimiser_params *gparams,
int found = 0;
for ( i=0; i<num_clens; i++ ) {
- if ( fabs(images[cp].avg_clen - clens[i]) <0.0001 ) {
+ if ( fabs(avg_clen(images[cp]->detgeom) - clens[i]) <0.0001 ) {
clens_population[i]++;
- lambdas[i] += images[cp].lambda;
+ lambdas[i] += images[cp]->lambda;
found = 1;
break;
}
@@ -449,9 +491,9 @@ static double pick_clen_to_use(struct geoptimiser_params *gparams,
if ( found ) continue;
- clens[num_clens] = images[cp].avg_clen;
+ clens[num_clens] = avg_clen(images[cp]->detgeom);
clens_population[num_clens] = 1;
- lambdas[num_clens] = images[cp].lambda;
+ lambdas[num_clens] = images[cp]->lambda;
num_clens++;
}
@@ -526,18 +568,29 @@ static double comp_median(double *arr, long n)
}
+static int panel_in_rigid_group(struct rigid_group *rg,
+ int panel_number)
+{
+ int i;
+ for ( i=0; i<rg->n_panels; i++ ) {
+ if ( panel_number == rg->panel_numbers[i] ) return 1;
+ }
+ return 0;
+}
+
+
+/* Go up a level in the detector hierarchy, e.g. from "dominoes" to
+ * "quadrants", by finding the first panel in "rg" (a rigid group of
+ * the finer grained type) in the collection of coarser-grained
+ * groups */
static int find_quad_for_connected(struct rigid_group *rg,
struct rg_collection *quadrants)
{
- struct panel *p;
int qi;
- /* The quadrant for a group of connected panels is the quadrant to which
- * the first panel in the connected set belongs */
- p = rg->panels[0];
-
for ( qi=0; qi<quadrants->n_rigid_groups; qi++ ) {
- if ( panel_is_in_rigid_group(quadrants->rigid_groups[qi], p) ) {
+ if ( panel_in_rigid_group(quadrants->rigid_groups[qi],
+ rg->panel_numbers[0]) ) {
return qi;
}
}
@@ -648,7 +701,7 @@ static int add_distance_to_list(struct gpanel *gp,
get_detector_pos(refl, &rfs, &rss);
- compute_x_y(rfs, rss, get_panel(refl), &crx, &cry);
+ compute_x_y(rfs, rss, gp->p, &crx, &cry);
gp->curr_pix_displ[pix_index]->dx = fx - crx - det_shift[0];
gp->curr_pix_displ[pix_index]->dy = fy - cry - det_shift[1];
gp->curr_pix_displ[pix_index]->ne = NULL;
@@ -681,7 +734,6 @@ static int count_pixels_with_min_peaks(struct gpanel *gp, int min_num_peaks,
static void adjust_min_peaks_per_conn(struct rg_collection *connected,
struct gpanel *gpanels,
- struct detector *det,
struct geoptimiser_params *gparams,
struct connected_data *conn_data)
{
@@ -701,11 +753,11 @@ static void adjust_min_peaks_per_conn(struct rg_collection *connected,
ip++ )
{
int pix_count;
- struct panel *p;
+ int pn;
struct gpanel *gp;
- p = connected->rigid_groups[di]->panels[ip];
- gp = &gpanels[panel_number(det, p)];
+ pn = connected->rigid_groups[di]->panel_numbers[ip];
+ gp = &gpanels[pn];
pix_count = count_pixels_with_min_peaks(gp,
min_num_peaks, gparams->max_num_peaks_per_pix);
@@ -728,9 +780,9 @@ static void adjust_min_peaks_per_conn(struct rg_collection *connected,
}
-static int compute_pixel_displacements(struct image *images, int n_images,
+static int compute_pixel_displacements(struct image **images,
+ int n_images,
struct gpanel *gpanels,
- struct detector *det,
struct rg_collection *connected,
struct geoptimiser_params *gparams,
double clen_to_use,
@@ -743,23 +795,23 @@ static int compute_pixel_displacements(struct image *images, int n_images,
for ( cp=0; cp<n_images; cp++ ) {
int fi;
- ImageFeatureList *flist = images[cp].features;
+ ImageFeatureList *flist = images[cp]->features;
double det_shift[2] = {0.0, 0.0};
double shift_x, shift_y;
+ struct detgeom *det = images[cp]->detgeom;
if ( gparams->only_best_distance ) {
- if ( fabs(images[cp].avg_clen - clen_to_use) > 0.0001 ) {
+ if ( fabs(avg_clen(det) - clen_to_use) > 0.0001 ) {
continue;
}
}
-
- crystal_get_det_shift(images[cp].crystals[0], &shift_x,
+ crystal_get_det_shift(images[cp]->crystals[0], &shift_x,
&shift_y);
- det_shift[0] = shift_x * det->panels[0].res;
- det_shift[1] = shift_y * det->panels[0].res;
+ det_shift[0] = shift_x / det->panels[0].pixel_pitch;
+ det_shift[1] = shift_y / det->panels[0].pixel_pitch;
- for ( fi=0; fi<image_feature_count(images[cp].features); fi++ ) {
+ for ( fi=0; fi<image_feature_count(images[cp]->features); fi++ ) {
double min_dist;
double fx, fy;
@@ -769,10 +821,11 @@ static int compute_pixel_displacements(struct image *images, int n_images,
imfe = image_get_feature(flist, fi);
if ( imfe == NULL ) continue;
- compute_x_y(imfe->fs, imfe->ss, imfe->p, &fx, &fy);
+ compute_x_y(imfe->fs, imfe->ss,
+ &det->panels[imfe->pn], &fx, &fy);
/* Find the closest reflection (from all crystals) */
- refl = find_closest_reflection(&images[cp], fx, fy,
+ refl = find_closest_reflection(images[cp], fx, fy,
&min_dist, det_shift);
if ( refl == NULL ) continue;
@@ -780,7 +833,7 @@ static int compute_pixel_displacements(struct image *images, int n_images,
struct gpanel *gp;
int r;
- gp = &gpanels[panel_number(det, imfe->p)];
+ gp = &gpanels[imfe->pn];
r = add_distance_to_list(gp, imfe, refl, fx, fy,
det_shift);
@@ -788,8 +841,8 @@ static int compute_pixel_displacements(struct image *images, int n_images,
ERROR("Error processing peak %f,%f "
"(panel %s), image %s %s\n",
imfe->fs, imfe->ss, gp->p->name,
- images[cp].filename,
- get_event_string(images[cp].event));
+ images[cp]->filename,
+ images[cp]->ev);
return r;
}
@@ -827,27 +880,25 @@ static int compute_avg_pix_displ(struct gpanel *gp, int idx,
}
-static int compute_avg_displacements(struct detector *det,
- struct rg_collection *connected,
+static int compute_avg_displacements(struct rg_collection *connected,
struct connected_data *conn_data,
struct gpanel *gpanels,
struct geoptimiser_params *gparams)
{
int di, ip, ifs, iss;
int pix_index, ret, max_peaks;
- struct panel *p;
+ struct detgeom_panel *p;
max_peaks = 0;
for ( di=0; di<connected->n_rigid_groups; di++ ) {
for ( ip=0; ip<connected->rigid_groups[di]->n_panels; ip++ ) {
- int pp;
+ int pn;
struct gpanel *gp;
- p = connected->rigid_groups[di]->panels[ip];
- pp = panel_number(det, p);
- gp = &gpanels[pp];
+ pn = connected->rigid_groups[di]->panel_numbers[ip];
+ gp = &gpanels[pn];
for ( iss=0; iss<p->h; iss++ ) {
for ( ifs=0; ifs<p->w; ifs++ ) {
@@ -873,7 +924,6 @@ static int compute_avg_displacements(struct detector *det,
static double compute_error(struct rg_collection *connected,
- struct detector *det,
struct connected_data *conn_data,
struct gpanel *gpanels)
{
@@ -883,24 +933,22 @@ static double compute_error(struct rg_collection *connected,
for ( di=0;di<connected->n_rigid_groups;di++ ) {
- struct panel *p;
double connected_error = 0;
int num_connected_error = 0;
int ifs, iss;
for ( ip=0; ip<connected->rigid_groups[di]->n_panels; ip++ ) {
- p = connected->rigid_groups[di]->panels[ip];
+ struct gpanel *gp;
+ int pn = connected->rigid_groups[di]->panel_numbers[ip];
- for ( iss=0; iss<p->h; iss++ ) {
- for ( ifs=0; ifs<p->w; ifs++ ) {
+ gp = &gpanels[pn];
- int pix_index;
- struct gpanel *gp;
- int pp = panel_number(det, p);
+ for ( iss=0; iss<gp->p->h; iss++ ) {
+ for ( ifs=0; ifs<gp->p->w; ifs++ ) {
- gp = &gpanels[pp];
- pix_index = ifs+p->w*iss;
+ int pix_index;
+ pix_index = ifs+gp->p->w*iss;
if ( gp->num_pix_displ[pix_index]
>= conn_data[di].num_peaks_per_pixel &&
@@ -1017,15 +1065,16 @@ static int compute_rot_stretch_for_empty_panels(struct rg_collection *quads,
}
-static void correct_rotation_and_stretch(struct rg_collection *connected,
- struct detector *det,
- struct gpanel *gpanels,
- struct connected_data *conn_data,
- double clen_to_use,
- double stretch_coeff,
- struct geoptimiser_params *gparams)
+static DataTemplate *correct_rotation_and_stretch(struct rg_collection *connected,
+ const DataTemplate *dtempl,
+ struct gpanel *gpanels,
+ struct connected_data *conn_data,
+ double clen_to_use,
+ double stretch_coeff,
+ struct geoptimiser_params *gparams)
{
-
+#if 0
+ /* FIXME ! */
int di, ip;
STATUS("Applying rotation and stretch corrections.\n");
@@ -1037,7 +1086,7 @@ static void correct_rotation_and_stretch(struct rg_collection *connected,
for ( ip=0; ip<connected->rigid_groups[di]->n_panels;
ip++ ) {
- struct panel *p;
+ struct detgeom_panel *p;
p = connected->rigid_groups[di]->panels[ip];
p->coffset -= (1.0-conn_data[di].cstr)*clen_to_use;
@@ -1069,7 +1118,7 @@ static void correct_rotation_and_stretch(struct rg_collection *connected,
for ( ip=0; ip<connected->rigid_groups[di]->n_panels; ip++ ) {
- struct panel *p;
+ struct detgeom_panel *p;
double new_fsx, new_fsy, new_ssx, new_ssy;
double new_cnx, new_cny;
int fs, ss;
@@ -1091,7 +1140,7 @@ static void correct_rotation_and_stretch(struct rg_collection *connected,
* NB All panels follow the first one */
if ( ip > 0 ) {
- struct panel *p0;
+ struct detgeom_panel *p0;
double dx_old, dy_old, dx_new, dy_new;
p0 = connected->rigid_groups[di]->panels[0];
@@ -1141,14 +1190,14 @@ static void correct_rotation_and_stretch(struct rg_collection *connected,
}
}
-
+#endif
+ return NULL;
}
/* Collect together all the offsets for each group in "connected"
* Only offsets which have enough peaks per pixel will be used. */
static int collate_offsets_for_rg(struct rigid_group *group,
- struct detector *det,
struct gpanel *gpanels,
int num_peaks_per_pixel,
double *list_dx, double *list_dy, int list_sz)
@@ -1159,13 +1208,13 @@ static int collate_offsets_for_rg(struct rigid_group *group,
for ( ip=0; ip<group->n_panels; ip++ ) {
int ifs, iss;
- struct panel *p = group->panels[ip];
- struct gpanel *gp = &gpanels[panel_number(det, p)];
+ int pn = group->panel_numbers[ip];
+ struct gpanel *gp = &gpanels[pn];
- for ( iss=0; iss<p->h; iss++ ) {
- for ( ifs=0; ifs<p->w; ifs++ ) {
+ for ( iss=0; iss<gp->p->h; iss++ ) {
+ for ( ifs=0; ifs<gp->p->w; ifs++ ) {
- int idx = ifs+p->w*iss;
+ int idx = ifs+gp->p->w*iss;
if ( gp->num_pix_displ[idx] < num_peaks_per_pixel ) {
continue;
@@ -1212,7 +1261,6 @@ static void fill_conn_data_sh(struct connected_data *conn_data,
static int compute_shift(struct rg_collection *connected,
struct connected_data *conn_data,
- struct detector *det,
struct geoptimiser_params *gparams,
struct gpanel *gpanels)
{
@@ -1235,7 +1283,7 @@ static int compute_shift(struct rg_collection *connected,
return 1;
}
- ct = collate_offsets_for_rg(connected->rigid_groups[di], det,
+ ct = collate_offsets_for_rg(connected->rigid_groups[di],
gpanels,
conn_data[di].num_peaks_per_pixel,
list_dx, list_dy,
@@ -1343,7 +1391,8 @@ static void correct_shift(struct rg_collection *connected,
struct connected_data *conn_data,
double clen_to_use)
{
-
+#if 0
+ /* FIXME ! */
int di;
int ip;
@@ -1352,7 +1401,7 @@ static void correct_shift(struct rg_collection *connected,
for ( di=0;di<connected->n_rigid_groups;di++ ) {
for (ip=0; ip<connected->rigid_groups[di]->n_panels; ip++) {
- struct panel *p;
+ struct detgeom_panel *p;
p = connected->rigid_groups[di]->panels[ip];
@@ -1368,12 +1417,13 @@ static void correct_shift(struct rg_collection *connected,
}
}
}
+#endif
}
static void scan_p1(int ip0, int ip1, struct rg_collection *connected,
struct connected_data *conn_data,
- struct detector *det, struct gpanel *gpanels,
+ struct gpanel *gpanels,
int di, double min_dist,
long *num_ang, int ifs0, int iss0,
double c_x0, double c_y0, double cd_x0, double cd_y0,
@@ -1381,11 +1431,11 @@ static void scan_p1(int ip0, int ip1, struct rg_collection *connected,
{
int iss1, ifs1;
- struct panel *p1;
+ int p1;
struct gpanel *gp1;
- p1 = connected->rigid_groups[di]->panels[ip1];
- gp1 = &gpanels[panel_number(det, p1)];
+ p1 = connected->rigid_groups[di]->panel_numbers[ip1];
+ gp1 = &gpanels[p1];
int min_ss_p1, min_fs_p1;
@@ -1397,19 +1447,19 @@ static void scan_p1(int ip0, int ip1, struct rg_collection *connected,
min_ss_p1 = 0;
}
- for ( iss1=min_ss_p1; iss1<p1->h; iss1++ ) {
- for ( ifs1=min_fs_p1; ifs1<p1->w; ifs1++ ) {
+ for ( iss1=min_ss_p1; iss1<gp1->p->h; iss1++ ) {
+ for ( ifs1=min_fs_p1; ifs1<gp1->p->w; ifs1++ ) {
double dist;
double c_x1, c_y1, cd_x1, cd_y1;
double d_c_x, d_c_y, d_cd_x, d_cd_y;
double len1, len2;
- int pix_index1 = ifs1+p1->w*iss1;
+ int pix_index1 = ifs1+gp1->p->w*iss1;
if ( gp1->num_pix_displ[pix_index1]
< conn_data[di].num_peaks_per_pixel ) continue;
- compute_x_y(ifs1, iss1, p1, &c_x1, &c_y1);
+ compute_x_y(ifs1, iss1, gp1->p, &c_x1, &c_y1);
cd_x1 = c_x1 - gp1->avg_displ_x[pix_index1];
cd_y1 = c_y1 - gp1->avg_displ_y[pix_index1];
d_c_x = c_x1-c_x0;
@@ -1456,28 +1506,28 @@ static void scan_p1(int ip0, int ip1, struct rg_collection *connected,
/* Executed for each panel in the connected group */
static void scan_p0(int ip0, struct rg_collection *connected,
struct connected_data *conn_data,
- struct detector *det, struct gpanel *gpanels,
+ struct gpanel *gpanels,
int di, double min_dist,
long *num_ang, int compute,
double *angles, double *stretches)
{
int iss0, ifs0, ip1;
struct gpanel *gp;
- struct panel *p0;
+ int p0;
- p0 = connected->rigid_groups[di]->panels[ip0];
- gp = &gpanels[panel_number(det, p0)];
+ p0 = connected->rigid_groups[di]->panel_numbers[ip0];
+ gp = &gpanels[p0];
- for ( iss0=0; iss0<p0->h; iss0++ ) {
- for ( ifs0=0; ifs0<p0->w; ifs0++ ) {
+ for ( iss0=0; iss0<gp->p->h; iss0++ ) {
+ for ( ifs0=0; ifs0<gp->p->w; ifs0++ ) {
double c_x0, c_y0, cd_x0, cd_y0;
- int pix_index0 = ifs0+p0->w*iss0;
+ int pix_index0 = ifs0+gp->p->w*iss0;
if ( gp->num_pix_displ[pix_index0]
< conn_data[di].num_peaks_per_pixel ) continue;
- compute_x_y(ifs0, iss0, p0, &c_x0, &c_y0);
+ compute_x_y(ifs0, iss0, gp->p, &c_x0, &c_y0);
cd_x0 = c_x0 - gp->avg_displ_x[pix_index0];
cd_y0 = c_y0 - gp->avg_displ_y[pix_index0];
@@ -1485,7 +1535,7 @@ static void scan_p0(int ip0, struct rg_collection *connected,
ip1++ )
{
scan_p1(ip0, ip1, connected,
- conn_data, det, gpanels, di, min_dist,
+ conn_data, gpanels, di, min_dist,
num_ang, ifs0, iss0, c_x0,
c_y0, cd_x0, cd_y0, compute,
angles, stretches);
@@ -1498,7 +1548,6 @@ static void scan_p0(int ip0, struct rg_collection *connected,
static double compute_rotation_and_stretch(struct rg_collection *connected,
struct connected_data *conn_data,
- struct detector *det,
struct gpanel *gpanels,
double dist_coeff_for_rot_str,
struct geoptimiser_params *gparams)
@@ -1523,7 +1572,7 @@ static double compute_rotation_and_stretch(struct rg_collection *connected,
double *angles;
double *stretches;
- struct panel *first_p;
+ struct detgeom_panel *first_p;
long num_ang = 0;
int ip0;
int num_pix_first_p;
@@ -1541,7 +1590,7 @@ static double compute_rotation_and_stretch(struct rg_collection *connected,
* connected->rigid_groups[di]->n_panels);
for ( ip0=0; ip0<connected->rigid_groups[di]->n_panels; ip0++ ) {
- scan_p0(ip0, connected, conn_data, det, gpanels,
+ scan_p0(ip0, connected, conn_data, gpanels,
di, min_dist, &num_ang, 0, NULL, NULL);
}
@@ -1563,7 +1612,7 @@ static double compute_rotation_and_stretch(struct rg_collection *connected,
num_ang = 0;
for ( ip0=0; ip0<connected->rigid_groups[di]->n_panels; ip0++ ) {
- scan_p0(ip0, connected, conn_data, det, gpanels,
+ scan_p0(ip0, connected, conn_data, gpanels,
di, min_dist, &num_ang, 1, angles, stretches);
}
@@ -1660,7 +1709,7 @@ static double compute_rotation_and_stretch(struct rg_collection *connected,
static void draw_panel(struct image *image, cairo_t *cr,
cairo_matrix_t *basic_m, GdkPixbuf **pixbufs, int i)
{
- struct panel p = image->det->panels[i];
+ struct detgeom_panel p = image->det->panels[i];
int w = gdk_pixbuf_get_width(pixbufs[i]);
int h = gdk_pixbuf_get_height(pixbufs[i]);
cairo_matrix_t m;
@@ -1760,7 +1809,7 @@ static int save_data_to_png(char *filename, struct detector *det,
for ( i=0; i<det->n_panels; i++ ) {
int fs, ss;
- struct panel *p;
+ struct detgeom_panel *p;
p = &det->panels[i];
@@ -1870,7 +1919,7 @@ static int save_stretch_to_png(char *filename, struct detector *det,
int fs, ss;
float val;
- struct panel *p;
+ struct detgeom_panel *p;
p = connected->rigid_groups[di]->panels[ip];
@@ -1971,8 +2020,8 @@ int check_and_enforce_cspad_dist(struct geoptimiser_params *gparams,
double dist2;
double cnx2, cny2;
- struct panel *ep = &det->panels[np];
- struct panel *op = &det->panels[np+1];
+ struct detgeom_panel *ep = &det->panels[np];
+ struct detgeom_panel *op = &det->panels[np+1];
cnx2 = ep->cnx + 197.0*ep->fsx;
cny2 = ep->cny + 197.0*ep->fsy;
@@ -2049,11 +2098,11 @@ int check_and_enforce_agipd_dist(struct geoptimiser_params *gparams,
double dist2;
double cnx2, cny2;
- struct panel *ep = &det->panels[np];
+ struct detgeom_panel *ep = &det->panels[np];
for ( npp=0; npp<8; npp++ ) {
- struct panel *op = &det->panels[np+npp];
+ struct detgeom_panel *op = &det->panels[np+npp];
cnx2 = ep->cnx + npp*dist_to_check*ep->ssx;
cny2 = ep->cny + npp*dist_to_check*ep->ssy;
@@ -2216,7 +2265,8 @@ static void free_displ_lists(struct gpanel *gpanels, int n)
static void recompute_panel_avg_displ(struct rg_collection *connected,
struct connected_data *conn_data,
- struct panel *p, struct gpanel *gp,
+ struct detgeom_panel *p,
+ struct gpanel *gp,
int num_peaks_per_pixel,
double sh_x, double sh_y)
{
@@ -2257,7 +2307,7 @@ void recompute_avg_displ(struct rg_collection *connected,
for (ip=0; ip<connected->rigid_groups[di]->n_panels; ip++) {
- struct panel *p;
+ struct detgeom_panel *p;
struct gpanel *gp;
p = connected->rigid_groups[di]->panels[ip];
@@ -2294,7 +2344,7 @@ int optimize_geometry(struct geoptimiser_params *gparams, Stream *st,
double stretch_coeff = 1.0;
struct connected_data *conn_data = NULL;
- struct image *images;
+ struct image **images;
int n_images = 0;
UnitCell *avg_cell;
struct gpanel *gpanels;
@@ -2396,7 +2446,7 @@ int optimize_geometry(struct geoptimiser_params *gparams, Stream *st,
}
}
- images = read_patterns_from_stream(st, det, &n_images);
+ images = read_patterns_from_stream(st, dtempl, &n_images);
if ( (n_images < 1) || (images == NULL) ) {
ERROR("Error reading stream file\n");
return 1;
@@ -2462,13 +2512,13 @@ int optimize_geometry(struct geoptimiser_params *gparams, Stream *st,
return 1;
}
- if ( compute_pixel_displacements(images, n_images, gpanels, det,
+ if ( compute_pixel_displacements(images, n_images, gpanels,
connected, gparams, clen_to_use,
conn_data) ) return 1;
- adjust_min_peaks_per_conn(connected, gpanels, det, gparams, conn_data);
+ adjust_min_peaks_per_conn(connected, gpanels, gparams, conn_data);
- if ( compute_avg_displacements(det, connected, conn_data, gpanels, gparams) ) {
+ if ( compute_avg_displacements(connected, conn_data, gpanels, gparams) ) {
free(conn_data);
free(images);
return 1;
@@ -2545,7 +2595,7 @@ int optimize_geometry(struct geoptimiser_params *gparams, Stream *st,
stretch_coeff, gparams);
}
- ret = compute_shift(connected, conn_data, det, gparams, gpanels);
+ ret = compute_shift(connected, conn_data, gparams, gpanels);
if ( ret != 0 ) {
free(conn_data);
return 1;
@@ -2620,13 +2670,16 @@ int main(int argc, char *argv[])
char *connected_coll_name = NULL;
Stream *st;
struct geoptimiser_params *gparams;
- struct detector *det = NULL;
+ DataTemplate *dtempl;
struct rg_collection *quadrants;
struct rg_collection *connected;
- struct beam_params beam;
char *geometry_filename = NULL;
gparams = malloc(sizeof(struct geoptimiser_params));
+ if ( gparams == NULL ) {
+ ERROR("Couldn't allocate params\n");
+ return 1;
+ }
gparams->outfile = NULL;
gparams->min_num_peaks_per_pix = 3;
@@ -2687,8 +2740,10 @@ int main(int argc, char *argv[])
return 0;
case 10 :
- printf("CrystFEL: " CRYSTFEL_VERSIONSTRING "\n");
- printf(CRYSTFEL_BOILERPLATE"\n");
+ printf("CrystFEL: %s\n",
+ crystfel_version_string());
+ printf("%s\n",
+ crystfel_licence_string());
return 0;
case 'o' :
@@ -2782,7 +2837,7 @@ int main(int argc, char *argv[])
#endif
#endif
- st = open_stream_for_read(infile);
+ st = stream_open_for_read(infile);
if ( st == NULL ) {
ERROR("Failed to open input stream '%s'\n", infile);
return 1;
@@ -2791,31 +2846,32 @@ int main(int argc, char *argv[])
if ( geometry_filename == NULL ) {
const char *stgeom = stream_geometry_file(st);
if ( stgeom != NULL ) {
- det = get_detector_geometry_from_string(stgeom, &beam, NULL);
+ dtempl = data_template_new_from_string(stgeom);
} else {
- ERROR("No input geometry file given, and no geometry "
- "found in stream.\n");
+ ERROR("No geometry found in stream. "
+ "Try again with --geometry=<file>.\n");
return 1;
}
} else {
- det = get_detector_geometry(geometry_filename, &beam);
+ dtempl = data_template_new_from_file(geometry_filename);
free(geometry_filename);
}
- if ( det == NULL ) {
+ if ( dtempl == NULL ) {
ERROR("Failed to read initial detector geometry.\n");
return 1;
}
- quadrants = find_rigid_group_collection_by_name(det, quadrant_coll_name);
+ quadrants = data_template_get_rigid_groups(dtempl,
+ quadrant_coll_name);
if ( quadrants == NULL ) {
ERROR("Cannot find rigid group collection for quadrants: %s\n",
quadrant_coll_name);
return 1;
}
- connected = find_rigid_group_collection_by_name(det,
- connected_coll_name);
+ connected = data_template_get_rigid_groups(dtempl,
+ connected_coll_name);
if ( connected == NULL ) {
ERROR("Cannot find rigid group collection for connected "
"asics: %s\n", connected_coll_name);
@@ -2824,7 +2880,7 @@ int main(int argc, char *argv[])
ret_val = optimize_geometry(gparams, st, det, quadrants, connected);
- close_stream(st);
+ stream_close(st);
return ret_val;
}
diff --git a/src/get_hkl.c b/src/get_hkl.c
index 3f3d6637..ea632cbb 100644
--- a/src/get_hkl.c
+++ b/src/get_hkl.c
@@ -3,11 +3,11 @@
*
* Small program to manipulate reflection lists
*
- * Copyright © 2013-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2013-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2009-2017 Thomas White <taw@physics.org>
+ * 2009-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -38,11 +38,13 @@
#include <unistd.h>
#include <getopt.h>
-#include "utils.h"
-#include "reflist-utils.h"
-#include "symmetry.h"
-#include "cell.h"
-#include "cell-utils.h"
+#include <utils.h>
+#include <reflist-utils.h>
+#include <symmetry.h>
+#include <cell.h>
+#include <cell-utils.h>
+
+#include "version.h"
static void show_help(const char *s)
@@ -503,8 +505,10 @@ int main(int argc, char *argv[])
return 0;
case 5 :
- printf("CrystFEL: " CRYSTFEL_VERSIONSTRING "\n");
- printf(CRYSTFEL_BOILERPLATE"\n");
+ printf("CrystFEL: %s\n",
+ crystfel_version_string());
+ printf("%s\n",
+ crystfel_licence_string());
return 0;
case 't' :
diff --git a/src/gtk-util-routines.c b/src/gtk-util-routines.c
new file mode 100644
index 00000000..a19027b6
--- /dev/null
+++ b/src/gtk-util-routines.c
@@ -0,0 +1,128 @@
+/*
+ * gtk-util-routines.h
+ *
+ * GTK utilities
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <math.h>
+#include <gtk/gtk.h>
+
+
+char *get_all_text(GtkTextView *view)
+{
+ GtkTextBuffer *buf;
+ GtkTextIter start, end;
+
+ buf = gtk_text_view_get_buffer(view);
+
+ gtk_text_buffer_get_start_iter(buf, &start);
+ gtk_text_buffer_get_end_iter(buf, &end);
+
+ return gtk_text_buffer_get_text(buf, &start, &end, FALSE);
+}
+
+
+float get_float(GtkWidget *entry)
+{
+ const gchar *text;
+ char *rval;
+ float val;
+ text = gtk_entry_get_text(GTK_ENTRY(entry));
+ errno = 0;
+ val = strtof(text, &rval);
+ if ( *rval != '\0' ) return NAN;
+ return val;
+}
+
+
+unsigned int get_uint(GtkWidget *entry)
+{
+ const gchar *text;
+ char *rval;
+ unsigned long int val;
+ text = gtk_entry_get_text(GTK_ENTRY(entry));
+ errno = 0;
+ val = strtoul(text, &rval, 10);
+ if ( *rval != '\0' ) {
+ printf("Invalid integer '%s'\n", text);
+ return 0;
+ }
+ return val;
+}
+
+
+int get_bool(GtkWidget *widget)
+{
+ return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+}
+
+
+int i_maybe_disable(GtkWidget *toggle, GtkWidget *widget)
+{
+ gtk_widget_set_sensitive(GTK_WIDGET(widget),
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle)));
+ return FALSE;
+}
+
+
+int i_maybe_disable_and_deselect(GtkWidget *toggle, GtkWidget *widget)
+{
+ int active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle));
+ gtk_widget_set_sensitive(GTK_WIDGET(widget), active);
+ if ( !active ) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE);
+ }
+ return FALSE;
+}
+
+
+void set_active(GtkWidget *tb, int active)
+{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tb), active);
+}
+
+
+void redraw_widget(GtkWidget *wid)
+{
+ gint w, h;
+ w = gtk_widget_get_allocated_width(GTK_WIDGET(wid));
+ h = gtk_widget_get_allocated_height(GTK_WIDGET(wid));
+ gtk_widget_queue_draw_area(GTK_WIDGET(wid), 0, 0, w, h);
+}
+
+
+const char *get_text_or_null(GtkEntry *entry)
+{
+ const char *text = gtk_entry_get_text(entry);
+ if ( text[0] == '\0' ) return NULL;
+ return text;
+}
diff --git a/src/gtk-util-routines.h b/src/gtk-util-routines.h
new file mode 100644
index 00000000..08b8537e
--- /dev/null
+++ b/src/gtk-util-routines.h
@@ -0,0 +1,44 @@
+/*
+ * gtk-util-routines.h
+ *
+ * GTK utilities
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GTK_UTIL_ROUTINES_H
+#define GTK_UTIL_ROUTINES_H
+
+#include <gtk/gtk.h>
+
+extern char *get_all_text(GtkTextView *view);
+extern int get_bool(GtkWidget *widget);
+extern unsigned int get_uint(GtkWidget *entry);
+extern float get_float(GtkWidget *entry);
+extern int i_maybe_disable(GtkWidget *toggle, GtkWidget *widget);
+extern int i_maybe_disable_and_deselect(GtkWidget *toggle, GtkWidget *widget);
+extern void set_active(GtkWidget *tb, int active);
+extern void redraw_widget(GtkWidget *wid);
+extern const char *get_text_or_null(GtkEntry *entry);
+
+#endif
diff --git a/src/gui_ambi.c b/src/gui_ambi.c
new file mode 100644
index 00000000..4403c999
--- /dev/null
+++ b/src/gui_ambi.c
@@ -0,0 +1,568 @@
+/*
+ * gui_ambi.c
+ *
+ * Resolve indexing ambiguities via CrystFEL GUI
+ *
+ * Copyright © 2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <assert.h>
+
+#include "crystfelsymmetryselector.h"
+#include "gui_project.h"
+#include "crystfel_gui.h"
+#include "gtk-util-routines.h"
+
+
+struct ambi_window
+{
+ struct crystfelproject *proj;
+ struct gui_job_notes_page *notes_page;
+ GtkWidget *jobname;
+ GtkWidget *dataset;
+ GtkWidget *limit_res;
+ GtkWidget *min_res;
+ GtkWidget *max_res;
+ GtkWidget *niter;
+ GtkWidget *use_ncorr;
+ GtkWidget *ncorr;
+ GtkWidget *sym;
+ GtkWidget *source_sym;
+ GtkWidget *operator;
+ GtkWidget *use_source_sym;
+ GtkWidget *use_operator;
+ GtkWidget *backend_combo;
+ GtkWidget *backend_opts_widget;
+ GtkWidget *backend_opts_box;
+};
+
+
+static int run_ambi(struct crystfelproject *proj,
+ const char *results_name,
+ int backend_idx,
+ const char *job_title,
+ const char *job_notes)
+{
+ struct crystfel_backend *be;
+ void *job_priv;
+ struct gui_indexing_result *input;
+
+ /* Which result to merge? */
+ input = find_indexing_result_by_name(proj, results_name);
+ if ( input == NULL ) {
+ ERROR("Please select a result first\n");
+ return 1;
+ }
+
+ be = &proj->backends[backend_idx];
+ job_priv = be->run_ambi(job_title, job_notes, proj, input,
+ be->ambi_opts_priv);
+
+ if ( job_priv != NULL ) {
+ char name[256];
+ snprintf(name, 255, "Resolving indexing ambiguity (%s)", job_title);
+ add_running_task(proj, name, be, job_priv);
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+
+
+static char *get_sym(GtkWidget *w)
+{
+ return crystfel_symmetry_selector_get_group_symbol(CRYSTFEL_SYMMETRY_SELECTOR(w));
+}
+
+
+static char *get_str(GtkWidget *w)
+{
+ const char *text = gtk_entry_get_text(GTK_ENTRY(w));
+ if ( text == NULL ) return NULL;
+ if ( text[0] == '\0' ) return NULL;
+ return strdup(text);
+}
+
+
+static void ambi_response_sig(GtkWidget *dialog, gint resp,
+ struct ambi_window *win)
+{
+ int r = 0;
+
+ if ( resp == GTK_RESPONSE_ACCEPT ) {
+
+ int backend_idx;
+ const char *job_title;
+ char *job_notes;
+ const char *results_name;
+
+ win->proj->ambi_params.use_res = get_bool(win->limit_res);
+ win->proj->ambi_params.res_min = get_float(win->min_res);
+ win->proj->ambi_params.res_max = get_float(win->max_res);
+ win->proj->ambi_params.niter = get_uint(win->niter);
+ win->proj->ambi_params.use_ncorr = get_bool(win->use_ncorr);
+ win->proj->ambi_params.ncorr = get_uint(win->ncorr);
+ win->proj->ambi_params.sym = get_sym(win->sym);
+ win->proj->ambi_params.source_sym = get_sym(win->source_sym);
+ win->proj->ambi_params.operator = get_str(win->operator);
+ win->proj->ambi_params.use_operator = get_bool(win->use_operator);
+
+ /* "Minimum resolution" should be the bigger number */
+ if ( win->proj->ambi_params.res_min < win->proj->ambi_params.res_max ) {
+ double tmp = win->proj->ambi_params.res_min;
+ win->proj->ambi_params.res_min = win->proj->ambi_params.res_max;
+ win->proj->ambi_params.res_max = tmp;
+ }
+
+ backend_idx = gtk_combo_box_get_active(GTK_COMBO_BOX(win->backend_combo));
+ if ( backend_idx < 0 ) return;
+
+ job_title = gtk_entry_get_text(GTK_ENTRY(win->jobname));
+ job_notes = get_all_text(GTK_TEXT_VIEW(win->notes_page->textview));
+
+ if ( job_title[0] == '\0' ) {
+ ERROR("You must provide a job name.\n");
+ return;
+ }
+
+ free(win->proj->ambi_new_job_title);
+ win->proj->ambi_new_job_title = strdup(job_title);
+
+ results_name = gtk_combo_box_get_active_id(GTK_COMBO_BOX(win->dataset));
+ if ( results_name == NULL ) {
+ ERROR("Please select the input\n");
+ return;
+ }
+ if ( run_ambi(win->proj, results_name,
+ backend_idx, job_title, job_notes) == 0 )
+ {
+ gtk_widget_destroy(dialog);
+ win->proj->ambi_opts = NULL;
+ }
+
+ free(job_notes);
+
+ }
+
+ if ( !r ) {
+ gtk_widget_destroy(dialog);
+ win->proj->ambi_opts = NULL;
+ }
+}
+
+
+static GtkWidget *make_ambigator_options(struct ambi_window *win)
+{
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ char tmp[64];
+ struct crystfelproject *proj = win->proj;
+
+ vbox = gtk_vbox_new(FALSE, 0.0);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("Target ('real') point group:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ win->sym = crystfel_symmetry_selector_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->sym),
+ FALSE, FALSE, 4.0);
+ crystfel_symmetry_selector_set_group_symbol(CRYSTFEL_SYMMETRY_SELECTOR(win->sym),
+ proj->ambi_params.sym);
+ gtk_widget_set_tooltip_text(hbox, "-y / --symmetry");
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ win->use_source_sym = gtk_radio_button_new_with_label(NULL, "Source ('twinned') point group:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->use_source_sym),
+ FALSE, FALSE, 4.0);
+ win->source_sym = crystfel_symmetry_selector_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->source_sym),
+ FALSE, FALSE, 4.0);
+ crystfel_symmetry_selector_set_group_symbol(CRYSTFEL_SYMMETRY_SELECTOR(win->source_sym),
+ proj->ambi_params.source_sym);
+ g_signal_connect(G_OBJECT(win->use_source_sym), "toggled",
+ G_CALLBACK(i_maybe_disable), win->source_sym);
+ gtk_widget_set_tooltip_text(hbox, "-w");
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ win->use_operator = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(win->use_source_sym),
+ "Ambiguity operation:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->use_operator),
+ FALSE, FALSE, 4.0);
+ win->operator = gtk_entry_new();
+ if ( proj->ambi_params.operator != NULL ) {
+ gtk_entry_set_text(GTK_ENTRY(win->operator), proj->ambi_params.operator);
+ }
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->operator),
+ FALSE, FALSE, 4.0);
+ g_signal_connect(G_OBJECT(win->use_operator), "toggled",
+ G_CALLBACK(i_maybe_disable), win->operator);
+ gtk_widget_set_tooltip_text(hbox, "--operator");
+
+ if ( proj->ambi_params.use_operator ) {
+ gtk_widget_set_sensitive(win->source_sym, FALSE);
+ set_active(win->use_operator, TRUE);
+ } else {
+ gtk_widget_set_sensitive(win->operator, FALSE);
+ set_active(win->use_source_sym, TRUE);
+ }
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ win->limit_res = gtk_check_button_new_with_label("Restrict resolution range:");
+ set_active(win->limit_res, proj->ambi_params.use_res);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->limit_res),
+ FALSE, FALSE, 4.0);
+ win->min_res = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(win->min_res), 6);
+ snprintf(tmp, 64, "%.2f", proj->ambi_params.res_min);
+ gtk_entry_set_text(GTK_ENTRY(win->min_res), tmp);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->min_res),
+ FALSE, FALSE, 4.0);
+ gtk_widget_set_tooltip_text(win->min_res, "--lowres");
+ label = gtk_label_new("to");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ win->max_res = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(win->max_res), 6);
+ snprintf(tmp, 64, "%.2f", proj->ambi_params.res_max);
+ gtk_entry_set_text(GTK_ENTRY(win->max_res), tmp);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->max_res),
+ FALSE, FALSE, 4.0);
+ gtk_widget_set_tooltip_text(win->max_res, "--highres");
+ label = gtk_label_new("Å");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ g_signal_connect(G_OBJECT(win->limit_res), "toggled",
+ G_CALLBACK(i_maybe_disable), win->min_res);
+ g_signal_connect(G_OBJECT(win->limit_res), "toggled",
+ G_CALLBACK(i_maybe_disable), win->max_res);
+ gtk_widget_set_sensitive(win->min_res, proj->ambi_params.use_res);
+ gtk_widget_set_sensitive(win->max_res, proj->ambi_params.use_res);
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ win->use_ncorr = gtk_check_button_new_with_label("Limit number of correlations to:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->use_ncorr),
+ FALSE, FALSE, 4.0);
+ win->ncorr = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(win->ncorr), 6);
+ snprintf(tmp, 64, "%i", proj->ambi_params.ncorr);
+ gtk_entry_set_text(GTK_ENTRY(win->ncorr), tmp);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->ncorr),
+ FALSE, FALSE, 4.0);
+ g_signal_connect(G_OBJECT(win->use_ncorr), "toggled",
+ G_CALLBACK(i_maybe_disable), win->ncorr);
+ set_active(win->use_ncorr, proj->ambi_params.use_ncorr);
+ gtk_widget_set_sensitive(win->ncorr, proj->ambi_params.use_ncorr);
+ gtk_widget_set_tooltip_text(hbox, "--ncorr");
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("Number of iterations:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ gtk_widget_set_tooltip_text(hbox, "--iterations");
+ win->niter = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(win->niter), 2);
+ snprintf(tmp, 64, "%i", proj->ambi_params.niter);
+ gtk_entry_set_text(GTK_ENTRY(win->niter), tmp);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->niter),
+ FALSE, FALSE, 4.0);
+
+ gtk_widget_show_all(vbox);
+ return vbox;
+}
+
+
+static void ambi_backend_changed_sig(GtkWidget *combo,
+ struct ambi_window *win)
+{
+ int backend_idx;
+ struct crystfel_backend *be;
+
+ backend_idx = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
+ if ( backend_idx < 0 ) return;
+ win->proj->ambi_backend_selected = backend_idx;
+
+ be = &win->proj->backends[backend_idx];
+
+ if ( win->backend_opts_widget != NULL ) {
+ gtk_widget_destroy(win->backend_opts_widget);
+ }
+
+ win->backend_opts_widget = be->make_ambi_parameters_widget(be->ambi_opts_priv);
+
+ gtk_box_pack_start(GTK_BOX(win->backend_opts_box),
+ GTK_WIDGET(win->backend_opts_widget),
+ FALSE, FALSE, 0);
+ gtk_widget_show_all(win->backend_opts_widget);
+}
+
+
+static GtkWidget *make_ambi_backend_opts(struct ambi_window *win)
+{
+ GtkWidget *box;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ int i;
+
+ box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+ gtk_container_set_border_width(GTK_CONTAINER(box), 8);
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ label = gtk_label_new("Batch system:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+
+ win->backend_combo = gtk_combo_box_text_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->backend_combo),
+ FALSE, FALSE, 0);
+
+ for ( i=0; i<win->proj->n_backends; i++ ) {
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(win->backend_combo),
+ win->proj->backends[i].name,
+ win->proj->backends[i].friendly_name);
+ }
+
+ win->backend_opts_box = gtk_box_new(GTK_ORIENTATION_VERTICAL,
+ 0);
+ gtk_box_pack_start(GTK_BOX(box),
+ GTK_WIDGET(win->backend_opts_box),
+ FALSE, FALSE, 0);
+ win->backend_opts_widget = NULL;
+
+ /* win->backend_opts{_box} must exist before the following */
+ g_signal_connect(G_OBJECT(win->backend_combo), "changed",
+ G_CALLBACK(ambi_backend_changed_sig), win);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(win->backend_combo),
+ win->proj->ambi_backend_selected);
+
+ gtk_widget_show_all(box);
+
+ return box;
+}
+
+
+gint ambi_sig(GtkWidget *widget, struct crystfelproject *proj)
+{
+ GtkWidget *dialog;
+ GtkWidget *content_area;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ GtkWidget *notebook;
+ GtkWidget *backend_page;
+ struct ambi_window *win;
+ char *new_title;
+ int i;
+
+ if ( proj->ambi_opts != NULL ) return FALSE;
+
+ win = malloc(sizeof(struct ambi_window));
+ if ( win == NULL ) return 0;
+
+ win->proj = proj;
+
+ dialog = gtk_dialog_new_with_buttons("Resolve indexing ambiguity",
+ GTK_WINDOW(proj->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ "Close", GTK_RESPONSE_CLOSE,
+ "Run", GTK_RESPONSE_ACCEPT,
+ NULL);
+ proj->ambi_opts = dialog;
+
+ g_signal_connect(G_OBJECT(dialog), "response",
+ G_CALLBACK(ambi_response_sig),
+ win);
+
+ vbox = gtk_vbox_new(FALSE, 0.0);
+ content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ gtk_container_add(GTK_CONTAINER(content_area), vbox);
+ gtk_container_set_border_width(GTK_CONTAINER(content_area), 8);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("Job/output name:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ win->jobname = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(win->jobname), 16);
+ gtk_entry_set_placeholder_text(GTK_ENTRY(win->jobname),
+ "ambi-trial-1");
+ new_title = make_new_job_title(proj->ambi_new_job_title);
+ if ( new_title != NULL ) {
+ gtk_entry_set_text(GTK_ENTRY(win->jobname), new_title);
+ free(new_title);
+ }
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->jobname),
+ TRUE, TRUE, 4.0);
+
+ label = gtk_label_new("Input:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ win->dataset = gtk_combo_box_text_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->dataset),
+ FALSE, FALSE, 4.0);
+ for ( i=0; i<proj->n_results; i++ ) {
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(win->dataset),
+ proj->results[i].name,
+ proj->results[i].name);
+ }
+
+ notebook = gtk_notebook_new();
+ gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(notebook),
+ FALSE, FALSE, 4.0);
+
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ make_ambigator_options(win),
+ gtk_label_new("Indexing ambiguity"));
+
+ backend_page = make_ambi_backend_opts(win);
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+ backend_page,
+ gtk_label_new("Cluster/batch system"));
+
+ win->notes_page = add_job_notes_page(notebook);
+
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+ GTK_RESPONSE_CLOSE);
+ gtk_widget_show_all(dialog);
+
+ return FALSE;
+}
+
+
+int write_ambigator_script(const char *filename,
+ struct gui_indexing_result *input,
+ const char *n_thread_str,
+ struct ambi_params *params,
+ const char *out_stream)
+{
+ FILE *fh;
+ char *exe_path;
+ int i;
+
+ fh = fopen(filename, "w");
+ if ( fh == NULL ) return 1;
+
+ fprintf(fh, "#!/bin/sh\n");
+
+ fprintf(fh, "cat \\\n");
+ for ( i=0; i<input->n_streams; i++ ) {
+ fprintf(fh, "%s \\\n", input->streams[i]);
+ }
+ fprintf(fh, " > ambigator-input.stream\n");
+
+ exe_path = get_crystfel_exe("ambigator");
+ if ( exe_path == NULL ) return 1;
+ fprintf(fh, "%s ambigator-input.stream \\\n", exe_path);
+
+ fprintf(fh, " -j %s", n_thread_str);
+ fprintf(fh, " -o %s", out_stream);
+ fprintf(fh, " -y %s", params->sym);
+ if ( params->use_operator ) {
+ fprintf(fh, " --operator=%s", params->operator);
+ } else {
+ fprintf(fh, " -w %s", params->source_sym);
+ }
+
+ if ( params->use_res ) {
+ fprintf(fh, " --lowres=%f", params->res_min);
+ fprintf(fh, " --highres=%f", params->res_max);
+ }
+
+ if ( params->use_ncorr ) {
+ fprintf(fh, " --ncorr=%i", params->ncorr);
+ }
+
+ fprintf(fh, " --iterations=%i", params->niter);
+ fprintf(fh, " --fg-graph=fg.dat");
+ fprintf(fh, " >stdout.log 2>stderr.log\n");
+
+ fclose(fh);
+ return 0;
+}
+
+
+double read_ambigator_progress(char *logfile_str, int niter)
+{
+ FILE *fh;
+ double iter_inc;
+ double frac_complete = 0.0;
+
+ iter_inc = 0.8/niter;
+
+ fh = fopen(logfile_str, "r");
+ if ( fh == NULL ) return 0.0;
+
+ do {
+ char line[1024];
+ int junk;
+
+ if ( fgets(line, 1024, fh) == NULL ) break;
+
+ if ( strncmp(line, "Mean number of correlations per crystal:", 40) == 0 ) {
+ frac_complete = 0.1;
+ }
+ if ( strncmp(line, "Mean f,g =", 10) == 0 ) {
+ frac_complete += iter_inc;
+ }
+ if ( sscanf(line, "%d assignments are different from "
+ "their starting values\n", &junk) == 1 )
+ {
+ frac_complete = 1.0;
+ }
+
+ } while ( 1 );
+
+ fclose(fh);
+
+ printf("got %f\n", frac_complete);
+ return frac_complete;
+}
diff --git a/src/gui_ambi.h b/src/gui_ambi.h
new file mode 100644
index 00000000..c6b68b35
--- /dev/null
+++ b/src/gui_ambi.h
@@ -0,0 +1,47 @@
+/*
+ * gui_ambi.h
+ *
+ * Resolve indexing ambiguities via CrystFEL GUI
+ *
+ * Copyright © 2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GUI_AMBI_H
+#define GUI_AMBI_H
+
+#include <gtk/gtk.h>
+
+#include "gui_project.h"
+
+extern gint ambi_sig(GtkWidget *widget,
+ struct crystfelproject *proj);
+
+extern int write_ambigator_script(const char *filename,
+ struct gui_indexing_result *input,
+ const char *n_thread_str,
+ struct ambi_params *params,
+ const char *out_stream);
+
+extern double read_ambigator_progress(char *logfile_str, int niter);
+
+#endif
diff --git a/src/gui_backend_local.c b/src/gui_backend_local.c
new file mode 100644
index 00000000..96d6c6b3
--- /dev/null
+++ b/src/gui_backend_local.c
@@ -0,0 +1,704 @@
+/*
+ * gui_backend_local.c
+ *
+ * GUI backend for running jobs on the local machine
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <glib.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <gtk/gtk.h>
+
+#include <utils.h>
+
+#include "crystfel_gui.h"
+#include "gui_project.h"
+#include "gui_index.h"
+#include "gui_merge.h"
+#include "gui_ambi.h"
+
+
+struct local_indexing_opts
+{
+ int n_processes;
+};
+
+
+struct local_merging_opts
+{
+ int n_threads;
+};
+
+
+struct local_ambi_opts
+{
+ int n_threads;
+};
+
+
+struct local_job
+{
+ enum gui_job_type type;
+
+ int n_frames;
+ int niter;
+
+ /* When both these are true, free the job resources */
+ int running;
+ int cancelled;
+
+ char *stderr_filename;
+
+ GPid pid;
+ guint child_watch_source;
+ GFile *workdir;
+};
+
+
+static void watch_subprocess(GPid pid, gint status, gpointer vp)
+{
+ struct local_job *job = vp;
+ STATUS("Subprocess exited with status %i\n", status);
+ job->running = 0;
+ g_spawn_close_pid(job->pid);
+}
+
+
+static int write_file_list(GFile *workdir,
+ const char *listname,
+ char **filenames,
+ char **events,
+ int n_frames)
+{
+ FILE *fh;
+ int i;
+ GFile *list_gfile;
+ char *list_str;
+
+ list_gfile = g_file_get_child(workdir, listname);
+ list_str = g_file_get_path(list_gfile);
+ if ( list_str == NULL ) return 1;
+
+ fh = fopen(list_str, "w");
+ free(list_str);
+ if ( fh == NULL ) return 1;
+
+ for ( i=0; i<n_frames; i++ ) {
+ if ( filenames[i][0] != '/' ) {
+ fprintf(fh, "../%s", filenames[i]);
+ } else {
+ fprintf(fh, "%s", filenames[i]);
+ }
+ if ( events[i] != NULL ) {
+ fprintf(fh, " %s\n", events[i]);
+ } else {
+ fprintf(fh, "\n");
+ }
+ }
+
+ fclose(fh);
+
+ return 0;
+}
+
+
+void setup_subprocess(gpointer user_data)
+{
+ const char *workdir = user_data;
+ setsid();
+ setpgid(0, 0);
+ chdir(workdir);
+}
+
+
+static struct local_job *start_local_job(char **args,
+ const char *job_title,
+ GFile *workdir_file,
+ struct crystfelproject *proj,
+ enum gui_job_type type)
+{
+ int i;
+ int r;
+ int ch_stderr;
+ GError *error;
+ struct local_job *job;
+ char *workdir_str;
+ GFile *stderr_gfile;
+
+ workdir_str = g_file_get_path(workdir_file);
+ if ( workdir_str == NULL ) return NULL;
+
+ job = malloc(sizeof(struct local_job));
+ if ( job == NULL ) return NULL;
+
+ job->workdir = workdir_file;
+ job->type = type;
+
+ STATUS("Running program: ");
+ i = 0;
+ while ( args[i] != NULL ) {
+ STATUS("%s ", args[i++]);
+ }
+ STATUS("\n");
+
+ error = NULL;
+ r = g_spawn_async_with_pipes(NULL, args, NULL,
+ G_SPAWN_SEARCH_PATH
+ | G_SPAWN_DO_NOT_REAP_CHILD,
+ setup_subprocess, workdir_str,
+ &job->pid,
+ NULL, NULL, &ch_stderr,
+ &error);
+ if ( r == FALSE ) {
+ ERROR("Failed to start program: %s\n", error->message);
+ free(job);
+ return NULL;
+ }
+ job->running = 1;
+
+ stderr_gfile = g_file_get_child(workdir_file, "stderr.log");
+ job->stderr_filename = g_file_get_path(stderr_gfile);
+ g_object_unref(stderr_gfile);
+
+ job->child_watch_source = g_child_watch_add(job->pid,
+ watch_subprocess,
+ job);
+
+ return job;
+}
+
+
+static int get_task_status(void *job_priv,
+ int *running,
+ float *frac_complete)
+{
+ int n_proc;
+ struct local_job *job = job_priv;
+
+ *running = job->running;
+
+ switch ( job->type ) {
+
+ case GUI_JOB_INDEXING :
+ n_proc = read_number_processed(job->stderr_filename);
+ *frac_complete = (double)n_proc / job->n_frames;
+ break;
+
+ case GUI_JOB_AMBIGATOR :
+ *frac_complete = read_ambigator_progress(job->stderr_filename,
+ job->niter);
+ break;
+
+ case GUI_JOB_PROCESS_HKL :
+ case GUI_JOB_PROCESS_HKL_SCALE :
+ case GUI_JOB_PARTIALATOR :
+ *frac_complete = read_merge_progress(job->stderr_filename,
+ job->type);
+ break;
+
+ }
+
+ return 0;
+}
+
+
+static void cancel_task(void *job_priv)
+{
+ struct local_job *job = job_priv;
+
+ if ( !job->running ) return;
+
+ ERROR("Stopping indexamajig (pid %i).\n", job->pid);
+ kill(-job->pid, SIGINT);
+}
+
+
+static void n_processes_activate_sig(GtkEntry *entry, gpointer data)
+{
+ struct local_indexing_opts *opts = data;
+ convert_int(gtk_entry_get_text(entry), &opts->n_processes);
+}
+
+
+static gboolean n_processes_focus_sig(GtkEntry *entry, GdkEvent *event,
+ gpointer data)
+{
+ n_processes_activate_sig(entry, data);
+ return FALSE;
+}
+
+
+static GtkWidget *make_indexing_parameters_widget(void *opts_priv)
+{
+ struct local_indexing_opts *opts = opts_priv;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *entry;
+ GtkWidget *label;
+ char tmp[64];
+
+ vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ label = gtk_label_new("Number of threads:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+ entry = gtk_entry_new();
+ snprintf(tmp, 63, "%i", opts->n_processes);
+ gtk_entry_set_text(GTK_ENTRY(entry), tmp);
+ gtk_entry_set_width_chars(GTK_ENTRY(entry), 5);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry),
+ FALSE, FALSE, 0);
+
+ g_signal_connect(G_OBJECT(entry), "activate",
+ G_CALLBACK(n_processes_activate_sig),
+ opts);
+ g_signal_connect(G_OBJECT(entry), "focus-out-event",
+ G_CALLBACK(n_processes_focus_sig),
+ opts);
+ return vbox;
+}
+
+
+static struct local_indexing_opts *make_default_local_indexing_opts()
+{
+ struct local_indexing_opts *opts = malloc(sizeof(struct local_indexing_opts));
+ if ( opts == NULL ) return NULL;
+
+ opts->n_processes = 4;
+
+ return opts;
+}
+
+
+static void write_indexing_opts(void *opts_priv, FILE *fh)
+{
+ struct local_indexing_opts *opts = opts_priv;
+
+ fprintf(fh, "indexing.local.n_processes %i\n",
+ opts->n_processes);
+}
+
+
+static void read_indexing_opt(void *opts_priv,
+ const char *key,
+ const char *val)
+{
+ struct local_indexing_opts *opts = opts_priv;
+
+ if ( strcmp(key, "indexing.local.n_processes") == 0 ) {
+ if ( convert_int(val, &opts->n_processes) ) {
+ ERROR("Invalid number of threads: %s\n", val);
+ }
+ }
+}
+
+
+static void n_threads_activate_sig(GtkEntry *entry, gpointer data)
+{
+ struct local_merging_opts *opts = data;
+ convert_int(gtk_entry_get_text(entry), &opts->n_threads);
+}
+
+
+static gboolean n_threads_focus_sig(GtkEntry *entry, GdkEvent *event,
+ gpointer data)
+{
+ n_threads_activate_sig(entry, data);
+ return FALSE;
+}
+
+
+static GtkWidget *make_merging_parameters_widget(void *opts_priv)
+{
+ struct local_merging_opts *opts = opts_priv;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *entry;
+ GtkWidget *label;
+ char tmp[64];
+
+ vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ label = gtk_label_new("Number of threads:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+ entry = gtk_entry_new();
+ snprintf(tmp, 63, "%i", opts->n_threads);
+ gtk_entry_set_text(GTK_ENTRY(entry), tmp);
+ gtk_entry_set_width_chars(GTK_ENTRY(entry), 5);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry),
+ FALSE, FALSE, 0);
+
+ g_signal_connect(G_OBJECT(entry), "activate",
+ G_CALLBACK(n_threads_activate_sig),
+ opts);
+ g_signal_connect(G_OBJECT(entry), "focus-out-event",
+ G_CALLBACK(n_threads_focus_sig),
+ opts);
+ return vbox;
+}
+
+
+static void *run_ambi(const char *job_title,
+ const char *job_notes,
+ struct crystfelproject *proj,
+ struct gui_indexing_result *input,
+ void *opts_priv)
+{
+ char n_thread_str[64];
+ struct local_job *job;
+ struct local_merging_opts *opts = opts_priv;
+ GFile *workdir;
+ GFile *sc_gfile;
+ gchar *sc_filename;
+ GFile *stream_gfile;
+ char *stream_str;
+
+ workdir = make_job_folder(job_title, job_notes);
+ if ( workdir == NULL ) return NULL;
+
+ stream_gfile = g_file_get_child(workdir, "ambi.stream");
+ stream_str = g_file_get_path(stream_gfile);
+ g_object_unref(stream_gfile);
+
+ snprintf(n_thread_str, 64, "%i", opts->n_threads);
+ sc_gfile = g_file_get_child(workdir, "run_ambigator.sh");
+ sc_filename = g_file_get_path(sc_gfile);
+ g_object_unref(sc_gfile);
+ if ( sc_filename == NULL ) return NULL;
+ if ( !write_ambigator_script(sc_filename, input, n_thread_str,
+ &proj->ambi_params, stream_str) )
+ {
+ char *args[3];
+ args[0] = "sh";
+ args[1] = sc_filename;
+ args[2] = NULL;
+ job = start_local_job(args, job_title, workdir,
+ proj, GUI_JOB_AMBIGATOR);
+ job->niter = proj->ambi_params.niter;
+ } else {
+ job = NULL;
+ }
+
+ if ( job != NULL ) {
+ char **streams = malloc(sizeof(char *));
+ if ( streams != NULL ) {
+ streams[0] = stream_str;
+ add_indexing_result(proj, strdup(job_title), streams, 1);
+ }
+ }
+
+ g_object_unref(workdir);
+ return job;
+}
+
+
+static void *run_merging(const char *job_title,
+ const char *job_notes,
+ struct crystfelproject *proj,
+ struct gui_indexing_result *input,
+ void *opts_priv)
+{
+ char n_thread_str[64];
+ struct local_job *job;
+ struct local_merging_opts *opts = opts_priv;
+ GFile *workdir;
+ GFile *sc_gfile;
+ gchar *sc_filename;
+
+ workdir = make_job_folder(job_title, job_notes);
+ if ( workdir == NULL ) return NULL;
+
+ snprintf(n_thread_str, 63, "%i", opts->n_threads);
+ sc_gfile = g_file_get_child(workdir, "run_merge.sh");
+ sc_filename = g_file_get_path(sc_gfile);
+ g_object_unref(sc_gfile);
+ if ( sc_filename == NULL ) return NULL;
+
+ if ( !write_merge_script(sc_filename, input, n_thread_str,
+ &proj->merging_params, "crystfel.hkl") )
+ {
+ char *args[3];
+ enum gui_job_type type;
+ args[0] = "sh";
+ args[1] = sc_filename;
+ args[2] = NULL;
+ if ( strcmp(proj->merging_params.model, "process_hkl") == 0 ) {
+ if ( proj->merging_params.scale ) {
+ type = GUI_JOB_PROCESS_HKL_SCALE;
+ } else {
+ type = GUI_JOB_PROCESS_HKL;
+ }
+ } else {
+ type = GUI_JOB_PARTIALATOR;
+ }
+ job = start_local_job(args, job_title, workdir, proj, type);
+ } else {
+ job = NULL;
+ }
+ g_free(sc_filename);
+
+ if ( job != NULL ) {
+
+ GFile *hkl_gfile;
+ char *hkl;
+ char *hkl1;
+ char *hkl2;
+
+ hkl_gfile = g_file_get_child(workdir, "crystfel.hkl");
+ hkl = g_file_get_path(hkl_gfile);
+ g_object_unref(hkl_gfile);
+
+ hkl_gfile = g_file_get_child(workdir, "crystfel.hkl1");
+ hkl1 = g_file_get_path(hkl_gfile);
+ g_object_unref(hkl_gfile);
+
+ hkl_gfile = g_file_get_child(workdir, "crystfel.hkl2");
+ hkl2 = g_file_get_path(hkl_gfile);
+ g_object_unref(hkl_gfile);
+
+ add_merge_result(proj, strdup(job_title), hkl, hkl1, hkl2);
+ }
+
+ g_object_unref(workdir);
+ return job;
+}
+
+
+static void *run_indexing(const char *job_title,
+ const char *job_notes,
+ struct crystfelproject *proj,
+ void *opts_priv)
+{
+ struct local_indexing_opts *opts = opts_priv;
+ struct local_job *job;
+ char n_thread_str[64];
+ char **streams;
+ GFile *workdir;
+ GFile *sc_gfile;
+ gchar *sc_filename;
+ GFile *stderr_gfile;
+
+ workdir = make_job_folder(job_title, job_notes);
+ if ( workdir == NULL ) return NULL;
+
+ if ( write_file_list(workdir, "files.lst",
+ proj->filenames,
+ proj->events,
+ proj->n_frames) )
+ {
+ STATUS("Failed to write list\n");
+ return NULL;
+ }
+
+ snprintf(n_thread_str, 63, "%i", opts->n_processes);
+ sc_gfile = g_file_get_child(workdir, "run_indexamajig.sh");
+ sc_filename = g_file_get_path(sc_gfile);
+ g_object_unref(sc_gfile);
+ if ( sc_filename == NULL ) return NULL;
+ if ( !write_indexamajig_script(sc_filename,
+ proj->geom_filename,
+ n_thread_str,
+ "files.lst",
+ "crystfel.stream",
+ NULL, 1,
+ &proj->peak_search_params,
+ &proj->indexing_params) )
+ {
+ char *args[3];
+ args[0] = "sh";
+ args[1] = sc_filename;
+ args[2] = NULL;
+ job = start_local_job(args, job_title, workdir,
+ proj, GUI_JOB_INDEXING);
+ } else {
+ job = NULL;
+ }
+
+ if ( job != NULL ) {
+
+ /* Indexing-specific job data */
+ job->n_frames = proj->n_frames;
+
+ stderr_gfile = g_file_get_child(workdir, "stderr.log");
+ job->stderr_filename = g_file_get_path(stderr_gfile);
+ g_object_unref(stderr_gfile);
+
+ streams = malloc(sizeof(char *));
+ if ( streams != NULL ) {
+ GFile *stream_gfile = g_file_get_child(job->workdir,
+ "crystfel.stream");
+ streams[0] = g_file_get_path(stream_gfile);
+ g_object_unref(stream_gfile);
+ add_indexing_result(proj, strdup(job_title),
+ streams, 1);
+ }
+ }
+
+ return job;
+}
+
+
+static struct local_merging_opts *make_default_local_merging_opts()
+{
+ struct local_merging_opts *opts = malloc(sizeof(struct local_merging_opts));
+ if ( opts == NULL ) return NULL;
+
+ opts->n_threads = 4;
+
+ return opts;
+}
+
+
+static void write_merging_opts(void *opts_priv, FILE *fh)
+{
+ struct local_merging_opts *opts = opts_priv;
+
+ fprintf(fh, "merging.local.n_threads %i\n",
+ opts->n_threads);
+}
+
+
+static void read_merging_opt(void *opts_priv,
+ const char *key,
+ const char *val)
+{
+ struct local_merging_opts *opts = opts_priv;
+
+ if ( strcmp(key, "merging.local.n_threads") == 0 ) {
+ if ( convert_int(val, &opts->n_threads) ) {
+ ERROR("Invalid number of threads: %s\n", val);
+ }
+ }
+}
+
+
+static GtkWidget *make_ambi_parameters_widget(void *opts_priv)
+{
+ struct local_ambi_opts *opts = opts_priv;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *entry;
+ GtkWidget *label;
+ char tmp[64];
+
+ vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ label = gtk_label_new("Number of threads:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+ entry = gtk_entry_new();
+ snprintf(tmp, 63, "%i", opts->n_threads);
+ gtk_entry_set_text(GTK_ENTRY(entry), tmp);
+ gtk_entry_set_width_chars(GTK_ENTRY(entry), 5);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry),
+ FALSE, FALSE, 0);
+
+ g_signal_connect(G_OBJECT(entry), "activate",
+ G_CALLBACK(n_threads_activate_sig),
+ opts);
+ g_signal_connect(G_OBJECT(entry), "focus-out-event",
+ G_CALLBACK(n_threads_focus_sig),
+ opts);
+ return vbox;
+}
+
+
+static struct local_ambi_opts *make_default_local_ambi_opts()
+{
+ struct local_ambi_opts *opts = malloc(sizeof(struct local_ambi_opts));
+ if ( opts == NULL ) return NULL;
+
+ opts->n_threads = 4;
+
+ return opts;
+}
+
+
+static void write_ambi_opts(void *opts_priv, FILE *fh)
+{
+ struct local_ambi_opts *opts = opts_priv;
+
+ fprintf(fh, "ambi.local.n_threads %i\n",
+ opts->n_threads);
+}
+
+
+static void read_ambi_opt(void *opts_priv,
+ const char *key,
+ const char *val)
+{
+ struct local_ambi_opts *opts = opts_priv;
+
+ if ( strcmp(key, "ambi.local.n_threads") == 0 ) {
+ if ( convert_int(val, &opts->n_threads) ) {
+ ERROR("Invalid number of threads: %s\n", val);
+ }
+ }
+}
+
+
+int make_local_backend(struct crystfel_backend *be)
+{
+ be->name = "local";
+ be->friendly_name = "Local (run on this computer)";
+
+ be->cancel_task = cancel_task;
+ be->task_status = get_task_status;
+
+ be->make_indexing_parameters_widget = make_indexing_parameters_widget;
+ be->run_indexing = run_indexing;
+ be->indexing_opts_priv = make_default_local_indexing_opts();
+ if ( be->indexing_opts_priv == NULL ) return 1;
+ be->write_indexing_opts = write_indexing_opts;
+ be->read_indexing_opt = read_indexing_opt;
+
+ be->make_merging_parameters_widget = make_merging_parameters_widget;
+ be->run_merging = run_merging;
+ be->merging_opts_priv = make_default_local_merging_opts();
+ if ( be->merging_opts_priv == NULL ) return 1;
+ be->write_merging_opts = write_merging_opts;
+ be->read_merging_opt = read_merging_opt;
+
+ be->make_ambi_parameters_widget = make_ambi_parameters_widget;
+ be->run_ambi = run_ambi;
+ be->ambi_opts_priv = make_default_local_ambi_opts();
+ if ( be->ambi_opts_priv == NULL ) return 1;
+ be->write_ambi_opts = write_ambi_opts;
+ be->read_ambi_opt = read_ambi_opt;
+
+ return 0;
+};
diff --git a/src/gui_backend_local.h b/src/gui_backend_local.h
new file mode 100644
index 00000000..98257eb7
--- /dev/null
+++ b/src/gui_backend_local.h
@@ -0,0 +1,36 @@
+/*
+ * gui_backend_local.h
+ *
+ * GUI backend for running jobs on the local machine
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GUI_BACKEND_LOCAL_H
+#define GUI_BACKEND_LOCAL_H
+
+#include "gui_project.h"
+
+extern int make_local_backend(struct crystfel_backend *be);
+
+#endif
diff --git a/src/gui_backend_slurm.c b/src/gui_backend_slurm.c
new file mode 100644
index 00000000..ed49c4c6
--- /dev/null
+++ b/src/gui_backend_slurm.c
@@ -0,0 +1,1077 @@
+/*
+ * gui_backend_slurm.c
+ *
+ * GUI backend for running jobs via SLURM
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <slurm/slurm.h>
+#include <gio/gio.h>
+
+#include <utils.h>
+
+#include "gtk-util-routines.h"
+#include "gui_project.h"
+#include "gui_index.h"
+#include "gui_merge.h"
+#include "gui_ambi.h"
+#include "crystfel_gui.h"
+
+
+struct slurm_common_opts
+{
+ char *partition;
+ char *email_address;
+ char *account;
+ char *constraint;
+};
+
+
+struct slurm_indexing_opts
+{
+ struct slurm_common_opts common;
+ char *path_add;
+ int block_size;
+};
+
+
+struct slurm_merging_opts
+{
+ struct slurm_common_opts common;
+};
+
+
+struct slurm_ambi_opts
+{
+ struct slurm_common_opts common;
+};
+
+
+struct slurm_job
+{
+ enum gui_job_type type;
+ GFile *workdir;
+ uint32_t job_id;
+
+ /* For indexing job */
+ int n_frames;
+ int n_blocks;
+
+ /* For merging/ambigator job */
+ char *stderr_filename;
+ int niter;
+};
+
+
+static int job_alive(slurm_job_info_t *job)
+{
+ switch ( job->job_state & JOB_STATE_BASE ) {
+
+ /* Only the following states are reasons to keep on watching
+ * the job */
+ case JOB_PENDING :
+ case JOB_RUNNING :
+ case JOB_SUSPENDED :
+ return 1;
+
+ default :
+ return 0;
+ }
+}
+
+
+static int job_running(uint32_t job_id)
+{
+ job_info_msg_t *job_info;
+ int running = 1;
+
+ if ( slurm_load_job(&job_info, job_id, 0) ) {
+ STATUS("Couldn't get status: %i\n",
+ slurm_strerror(slurm_get_errno()));
+ return 0;
+ }
+
+ running = job_alive(&job_info->job_array[0]);
+ slurm_free_job_info_msg(job_info);
+ return running;
+}
+
+
+static double indexing_progress(struct slurm_job *job, int *running)
+{
+ job_info_msg_t *array_job_info;
+ int i;
+ int n_running;
+ int lowest_alive_task;
+
+ if ( slurm_load_job(&array_job_info, job->job_id, 0) ) {
+ STATUS("Couldn't get status: %i\n",
+ slurm_strerror(slurm_get_errno()));
+ *running = 0;
+ return 0.0;
+ }
+
+ n_running = 0;
+ lowest_alive_task = job->n_blocks;
+ for ( i=0; i<array_job_info->record_count; i++ ) {
+
+ slurm_job_info_t *job_info = &array_job_info->job_array[i];
+
+ /* Find the array_task_id of the lowest task which is still
+ * running, or which might still run. Exclude the main array
+ * job, identified by having job_id == array_job_id. */
+ if ( job_alive(job_info) ) {
+ if ( (job_info->array_task_id < lowest_alive_task)
+ && (job_info->job_id != job_info->array_job_id) )
+ {
+ lowest_alive_task = job_info->array_task_id;
+ }
+ n_running++;
+ }
+ }
+ slurm_free_job_info_msg(array_job_info);
+
+ *running = (n_running > 0);
+
+ /* If there are lots of blocks, just count running jobs instead of
+ * reading loads of log files */
+ if ( (job->n_blocks > 15)
+ && (lowest_alive_task < job->n_blocks) )
+ {
+
+ return (double)lowest_alive_task / job->n_blocks;
+
+ } else {
+
+ int i;
+ int n_proc = 0;
+
+ for ( i=0; i<job->n_blocks; i++ ) {
+
+ char tmp[128];
+ GFile *stderr_gfile;
+ char *stderr_filename;
+
+ snprintf(tmp, 127, "stderr-%i.log", i);
+ stderr_gfile = g_file_get_child(job->workdir, tmp);
+ stderr_filename = g_file_get_path(stderr_gfile);
+ g_object_unref(stderr_gfile);
+
+ n_proc += read_number_processed(stderr_filename);
+ g_free(stderr_filename);
+
+ }
+
+ return (double)n_proc / job->n_frames;
+ }
+}
+
+
+static int get_task_status(void *job_priv,
+ int *running,
+ float *frac_complete)
+{
+ struct slurm_job *job = job_priv;
+
+ switch ( job->type ) {
+
+ case GUI_JOB_INDEXING :
+ *frac_complete = indexing_progress(job, running);
+ break;
+
+ case GUI_JOB_AMBIGATOR :
+ *frac_complete = read_ambigator_progress(job->stderr_filename,
+ job->niter);
+ *running = job_running(job->job_id);
+ break;
+
+ case GUI_JOB_PROCESS_HKL :
+ case GUI_JOB_PROCESS_HKL_SCALE :
+ case GUI_JOB_PARTIALATOR :
+ *frac_complete = read_merge_progress(job->stderr_filename,
+ job->type);
+ *running = job_running(job->job_id);
+ break;
+
+ }
+
+ return 0;
+}
+
+
+static void cancel_task(void *job_priv)
+{
+ char jobid[128];
+ const gchar *args[3];
+ GError *error = NULL;
+ GSubprocess *sp;
+ struct slurm_job *job = job_priv;
+
+ snprintf(jobid, 127, "%i", job->job_id);
+ args[0] = "scancel";
+ args[1] = jobid;
+ args[2] = NULL;
+ sp = g_subprocess_newv(args, G_SUBPROCESS_FLAGS_NONE, &error);
+ if ( sp == NULL ) {
+ ERROR("Failed to invoke scancel: %s\n", error->message);
+ g_error_free(error);
+ }
+}
+
+
+static char **create_env(int *psize, char *path_add)
+{
+ char **env;
+ const char *base_path = "PATH=/bin:/usr/bin";
+ char *crystfel_path;
+ size_t path_len;
+
+ env = malloc(10*sizeof(char *));
+ if ( env == NULL ) return NULL;
+
+ crystfel_path = get_crystfel_path_str();
+
+ path_len = 4 + strlen(base_path);
+
+ if ( path_add != NULL ) {
+ path_len += strlen(path_add);
+ }
+
+ if ( crystfel_path != NULL ) {
+ path_len += strlen(crystfel_path);
+ }
+
+ env[0] = malloc(path_len);
+ if ( env[0] == NULL ) return NULL;
+
+ strcpy(env[0], base_path);
+ if ( crystfel_path != NULL ) {
+ strcat(env[0], ":");
+ strcat(env[0], crystfel_path);
+ g_free(crystfel_path);
+ }
+ if ( path_add != NULL ) {
+ strcat(env[0], ":");
+ strcat(env[0], path_add);
+ }
+
+ *psize = 1;
+
+ return env;
+}
+
+
+static void partition_activate_sig(GtkEntry *entry, gpointer data)
+{
+ struct slurm_common_opts *opts = data;
+ opts->partition = safe_strdup(get_text_or_null(entry));
+}
+
+
+static gboolean partition_focus_sig(GtkEntry *entry, GdkEvent *event,
+ gpointer data)
+{
+ partition_activate_sig(entry, data);
+ return FALSE;
+}
+
+
+static void email_activate_sig(GtkEntry *entry, gpointer data)
+{
+ struct slurm_common_opts *opts = data;
+ opts->email_address = safe_strdup(get_text_or_null(entry));
+}
+
+
+static gboolean email_focus_sig(GtkEntry *entry, GdkEvent *event,
+ gpointer data)
+{
+ email_activate_sig(entry, data);
+ return FALSE;
+}
+
+
+static void account_activate_sig(GtkEntry *entry, gpointer data)
+{
+ struct slurm_common_opts *opts = data;
+ opts->account = safe_strdup(get_text_or_null(entry));
+}
+
+
+static gboolean account_focus_sig(GtkEntry *entry, GdkEvent *event,
+ gpointer data)
+{
+ account_activate_sig(entry, data);
+ return FALSE;
+}
+
+
+static void constraint_activate_sig(GtkEntry *entry, gpointer data)
+{
+ struct slurm_common_opts *opts = data;
+ opts->constraint = safe_strdup(get_text_or_null(entry));
+}
+
+
+static gboolean constraint_focus_sig(GtkEntry *entry, GdkEvent *event,
+ gpointer data)
+{
+ constraint_activate_sig(entry, data);
+ return FALSE;
+}
+
+
+static void add_common_opts(GtkWidget *vbox,
+ struct slurm_common_opts *opts)
+{
+ GtkWidget *hbox;
+ GtkWidget *entry;
+ GtkWidget *label;
+
+ /* Partition */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 0);
+ label = gtk_label_new("Submit job to partition:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 0);
+ entry = gtk_entry_new();
+ if ( opts->partition != NULL ) {
+ gtk_entry_set_text(GTK_ENTRY(entry), opts->partition);
+ }
+ gtk_entry_set_placeholder_text(GTK_ENTRY(entry), "maxwell");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry), FALSE, FALSE, 0);
+ g_signal_connect(G_OBJECT(entry), "activate",
+ G_CALLBACK(partition_activate_sig), opts);
+ g_signal_connect(G_OBJECT(entry), "focus-out-event",
+ G_CALLBACK(partition_focus_sig), opts);
+
+ /* Email address */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 0);
+ label = gtk_label_new("Send notifications to:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 0);
+ entry = gtk_entry_new();
+ if ( opts->email_address != NULL ) {
+ gtk_entry_set_text(GTK_ENTRY(entry), opts->email_address);
+ }
+ gtk_entry_set_placeholder_text(GTK_ENTRY(entry),
+ "myself@example.org");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry), FALSE, FALSE, 0);
+ g_signal_connect(G_OBJECT(entry), "activate",
+ G_CALLBACK(email_activate_sig), opts);
+ g_signal_connect(G_OBJECT(entry), "focus-out-event",
+ G_CALLBACK(email_focus_sig), opts);
+
+ /* Account */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 0);
+ label = gtk_label_new("Charge resource use to:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 0);
+ entry = gtk_entry_new();
+ if ( opts->account != NULL ) {
+ gtk_entry_set_text(GTK_ENTRY(entry), opts->account);
+ }
+ gtk_entry_set_placeholder_text(GTK_ENTRY(entry),
+ "SLURM account");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry), FALSE, FALSE, 0);
+ g_signal_connect(G_OBJECT(entry), "activate",
+ G_CALLBACK(account_activate_sig), opts);
+ g_signal_connect(G_OBJECT(entry), "focus-out-event",
+ G_CALLBACK(account_focus_sig), opts);
+
+ /* Constraint */
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 0);
+ label = gtk_label_new("Required node features:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 0);
+ entry = gtk_entry_new();
+ if ( opts->constraint != NULL ) {
+ gtk_entry_set_text(GTK_ENTRY(entry), opts->constraint);
+ }
+ gtk_entry_set_placeholder_text(GTK_ENTRY(entry),
+ "SLURM constraint");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry), FALSE, FALSE, 0);
+ g_signal_connect(G_OBJECT(entry), "activate",
+ G_CALLBACK(constraint_activate_sig), opts);
+ g_signal_connect(G_OBJECT(entry), "focus-out-event",
+ G_CALLBACK(constraint_focus_sig), opts);
+}
+
+
+static void write_common_opts(FILE *fh,
+ struct slurm_common_opts *opts,
+ const char *prefix)
+{
+ if ( opts->partition != NULL) {
+ fprintf(fh, "%s.slurm.partition %s\n",
+ prefix, opts->partition);
+ }
+
+ if ( opts->email_address != NULL ) {
+ fprintf(fh, "%s.slurm.email_address %s\n",
+ prefix, opts->email_address);
+ }
+
+ if ( opts->account != NULL ) {
+ fprintf(fh, "%s.slurm.account %s\n",
+ prefix, opts->account);
+ }
+
+ if ( opts->constraint != NULL ) {
+ fprintf(fh, "%s.slurm.constraint %s\n",
+ prefix, opts->constraint);
+ }
+}
+
+
+static struct slurm_job *start_slurm_job(enum gui_job_type type,
+ const char *script_filename,
+ const char *jobname,
+ const char *array_inx,
+ GFile *workdir,
+ const char *stdout_filename,
+ const char *stderr_filename,
+ struct slurm_common_opts *opts)
+{
+ char **env;
+ int n_env;
+ char *script;
+ struct slurm_job *job;
+ job_desc_msg_t job_desc_msg;
+ submit_response_msg_t *resp;
+ GFile *stderr_gfile;
+ int r;
+
+ script = load_entire_file(script_filename);
+ if ( script == NULL ) return NULL;
+
+ job = malloc(sizeof(struct slurm_job));
+ if ( job == NULL ) {
+ free(script);
+ return NULL;
+ }
+
+ job->type = type;
+
+ env = create_env(&n_env, NULL);
+
+ slurm_init_job_desc_msg(&job_desc_msg);
+ job_desc_msg.user_id = getuid();
+ job_desc_msg.group_id = getgid();
+ job_desc_msg.mail_user = safe_strdup(opts->email_address);
+ job_desc_msg.mail_type = MAIL_JOB_FAIL;
+ job_desc_msg.comment = "Submitted via CrystFEL GUI";
+ job_desc_msg.shared = 0;
+ job_desc_msg.time_limit = 60;
+ job_desc_msg.partition = safe_strdup(opts->partition);
+ job_desc_msg.min_nodes = 1;
+ job_desc_msg.max_nodes = 1;
+ job_desc_msg.name = safe_strdup(jobname);
+ job_desc_msg.std_err = strdup(stderr_filename);
+ job_desc_msg.std_out = strdup(stdout_filename);
+ job_desc_msg.work_dir = g_file_get_path(workdir);
+ job_desc_msg.script = script;
+ job_desc_msg.environment = env;
+ job_desc_msg.env_size = n_env;
+ job_desc_msg.features = safe_strdup(opts->constraint);
+ job_desc_msg.account = safe_strdup(opts->account);
+ job_desc_msg.array_inx = safe_strdup(array_inx);
+
+ r = slurm_submit_batch_job(&job_desc_msg, &resp);
+ free(job_desc_msg.mail_user);
+ free(job_desc_msg.partition);
+ free(job_desc_msg.name);
+ free(job_desc_msg.work_dir);
+ free(job_desc_msg.std_err);
+ free(job_desc_msg.std_out);
+ free(job_desc_msg.features);
+ free(job_desc_msg.account);
+ free(job_desc_msg.script);
+ if ( r ) {
+ ERROR("Couldn't submit job: %i\n", errno);
+ free(job);
+ return NULL;
+ }
+
+ STATUS("Submitted SLURM job ID %i\n", resp->job_id);
+
+ job->job_id = resp->job_id;
+ slurm_free_submit_response_response_msg(resp);
+
+ stderr_gfile = g_file_get_child(workdir, stderr_filename);
+ job->stderr_filename = g_file_get_path(stderr_gfile);
+ g_object_unref(stderr_gfile);
+
+ job->workdir = g_file_dup(workdir);
+
+ return job;
+}
+
+
+static void write_partial_file_list(GFile *workdir,
+ const char *list_filename,
+ int j,
+ int block_size,
+ char **filenames,
+ char **events,
+ int n_frames)
+{
+ GFile *file;
+ char *file_path;
+ FILE *fh;
+ int i;
+
+ file = g_file_get_child(workdir, list_filename);
+ file_path = g_file_get_path(file);
+
+ fh = fopen(file_path, "w");
+ for ( i=j*block_size;
+ (i<(j+1)*block_size) && (i<n_frames);
+ i++ )
+ {
+ if ( filenames[i][0] != '/' ) {
+ fprintf(fh, "../%s", filenames[i]);
+ } else {
+ fprintf(fh, "%s", filenames[i]);
+ }
+ if ( events[i] != NULL ) {
+ fprintf(fh, " %s\n", events[i]);
+ } else {
+ fprintf(fh, "\n");
+ }
+ }
+
+ fclose(fh);
+ g_free(file_path);
+ g_object_unref(file);
+}
+
+
+static void *run_indexing(const char *job_title,
+ const char *job_notes,
+ struct crystfelproject *proj,
+ void *opts_priv)
+{
+ struct slurm_indexing_opts *opts = opts_priv;
+ struct slurm_job *job;
+ int i;
+ char **streams;
+ GFile *workdir;
+ GFile *sc_gfile;
+ char *sc_filename;
+ int n_blocks;
+ char array_inx[128];
+ char serial_offs[128];
+
+ workdir = make_job_folder(job_title, job_notes);
+ if ( workdir == NULL ) return NULL;
+
+ n_blocks = proj->n_frames / opts->block_size;
+ if ( proj->n_frames % opts->block_size ) n_blocks++;
+ STATUS("Splitting job into %i blocks of max %i frames\n",
+ n_blocks, opts->block_size);
+
+ streams = malloc(n_blocks*sizeof(char *));
+ if ( streams == NULL ) return NULL;
+
+ for ( i=0; i<n_blocks; i++ ) {
+
+ char file_list[128];
+ char stream_filename[128];
+ GFile *stream_gfile;
+
+ /* Create (sub-)list of files */
+ snprintf(file_list, 127, "files-%i.lst", i);
+ write_partial_file_list(workdir,
+ file_list,
+ i,
+ opts->block_size,
+ proj->filenames,
+ proj->events,
+ proj->n_frames);
+
+ /* Work out the stream filename */
+ snprintf(stream_filename, 127, "crystfel-%i.stream", i);
+ stream_gfile = g_file_get_child(workdir,
+ stream_filename);
+ streams[i] = g_file_get_path(stream_gfile);
+ g_object_unref(stream_gfile);
+ }
+
+ sc_gfile = g_file_get_child(workdir, "run_indexamajig.sh");
+ sc_filename = g_file_get_path(sc_gfile);
+ g_object_unref(sc_gfile);
+ if ( sc_filename == NULL ) return NULL;
+
+ snprintf(array_inx, 127, "0-%i", n_blocks-1);
+ snprintf(serial_offs, 127, "$((${SLURM_ARRAY_TASK_ID}*%i+1))",
+ opts->block_size);
+
+ if ( !write_indexamajig_script(sc_filename,
+ proj->geom_filename,
+ "`nproc`",
+ "files-${SLURM_ARRAY_TASK_ID}.lst",
+ "crystfel-${SLURM_ARRAY_TASK_ID}.stream",
+ serial_offs, 0,
+ &proj->peak_search_params,
+ &proj->indexing_params) )
+ {
+ job = start_slurm_job(GUI_JOB_INDEXING,
+ sc_filename,
+ job_title,
+ array_inx,
+ workdir,
+ "stdout-%a.log",
+ "stderr-%a.log",
+ &opts->common);
+ } else {
+ job = NULL;
+ }
+ g_free(sc_filename);
+
+ if ( job != NULL ) {
+ job->n_frames = proj->n_frames;
+ job->n_blocks = n_blocks;
+ add_indexing_result(proj, strdup(job_title), streams, n_blocks);
+ }
+
+ g_object_unref(workdir);
+
+ return job;
+}
+
+
+static void block_size_activate_sig(GtkEntry *entry, gpointer data)
+{
+ struct slurm_indexing_opts *opts = data;
+ convert_int(gtk_entry_get_text(entry), &opts->block_size);
+}
+
+
+static gboolean block_size_focus_sig(GtkEntry *entry, GdkEvent *event,
+ gpointer data)
+{
+ block_size_activate_sig(entry, data);
+ return FALSE;
+}
+
+
+static void pathadd_activate_sig(GtkEntry *entry, gpointer data)
+{
+ struct slurm_indexing_opts *opts = data;
+ opts->path_add = strdup(gtk_entry_get_text(entry));
+}
+
+
+static gboolean pathadd_focus_sig(GtkEntry *entry, GdkEvent *event,
+ gpointer data)
+{
+ pathadd_activate_sig(entry, data);
+ return FALSE;
+}
+
+
+static GtkWidget *make_indexing_parameters_widget(void *opts_priv)
+{
+ struct slurm_indexing_opts *opts = opts_priv;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *entry;
+ GtkWidget *label;
+ char tmp[64];
+
+ vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+
+ add_common_opts(vbox, &opts->common);
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ label = gtk_label_new("Split job into blocks of");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+ snprintf(tmp, 63, "%i", opts->block_size);
+ entry = gtk_entry_new();
+ gtk_entry_set_text(GTK_ENTRY(entry), tmp);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry),
+ FALSE, FALSE, 0);
+ g_signal_connect(G_OBJECT(entry), "activate",
+ G_CALLBACK(block_size_activate_sig),
+ opts);
+ g_signal_connect(G_OBJECT(entry), "focus-out-event",
+ G_CALLBACK(block_size_focus_sig),
+ opts);
+ label = gtk_label_new("frames");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ label = gtk_label_new("Search path for executables:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+ entry = gtk_entry_new();
+ if ( opts->path_add != NULL ) {
+ gtk_entry_set_text(GTK_ENTRY(entry), opts->path_add);
+ }
+ gtk_entry_set_placeholder_text(GTK_ENTRY(entry),
+ "/path/to/indexing/programs");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry),
+ FALSE, FALSE, 0);
+ g_signal_connect(G_OBJECT(entry), "activate",
+ G_CALLBACK(pathadd_activate_sig),
+ opts);
+ g_signal_connect(G_OBJECT(entry), "focus-out-event",
+ G_CALLBACK(pathadd_focus_sig),
+ opts);
+
+ return vbox;
+}
+
+
+static void set_default_common_opts(struct slurm_common_opts *opts)
+{
+ opts->partition = NULL;
+ opts->email_address = NULL;
+ opts->account = NULL;
+ opts->constraint = NULL;
+}
+
+
+static struct slurm_indexing_opts *make_default_slurm_indexing_opts()
+{
+ struct slurm_indexing_opts *opts = malloc(sizeof(struct slurm_indexing_opts));
+ if ( opts == NULL ) return NULL;
+
+ set_default_common_opts(&opts->common);
+ opts->block_size = 1000;
+ opts->path_add = NULL;
+
+ return opts;
+}
+
+
+static void write_indexing_opts(void *opts_priv, FILE *fh)
+{
+ struct slurm_indexing_opts *opts = opts_priv;
+
+ write_common_opts(fh, &opts->common, "indexing");
+
+ fprintf(fh, "indexing.slurm.block_size %i\n",
+ opts->block_size);
+
+ if ( opts->path_add != NULL ) {
+ fprintf(fh, "indexing.slurm.path_add %s\n",
+ opts->path_add);
+ }
+}
+
+
+static void read_indexing_opt(void *opts_priv,
+ const char *key,
+ const char *val)
+{
+ struct slurm_indexing_opts *opts = opts_priv;
+
+ if ( strcmp(key, "indexing.slurm.block_size") == 0 ) {
+ if ( convert_int(val, &opts->block_size) ) {
+ ERROR("Invalid block size: %s\n", val);
+ }
+ }
+
+ if ( strcmp(key, "indexing.slurm.email_address") == 0 ) {
+ opts->common.email_address = strdup(val);
+ }
+
+ if ( strcmp(key, "indexing.slurm.partition") == 0 ) {
+ opts->common.partition = strdup(val);
+ }
+
+ if ( strcmp(key, "indexing.slurm.path_add") == 0 ) {
+ opts->path_add = strdup(val);
+ }
+
+ if ( strcmp(key, "indexing.slurm.account") == 0 ) {
+ opts->common.account = strdup(val);
+ }
+
+ if ( strcmp(key, "indexing.slurm.constraint") == 0 ) {
+ opts->common.constraint = strdup(val);
+ }
+}
+
+
+static void *run_ambi(const char *job_title,
+ const char *job_notes,
+ struct crystfelproject *proj,
+ struct gui_indexing_result *input,
+ void *opts_priv)
+{
+ struct slurm_job *job;
+ struct slurm_ambi_opts *opts = opts_priv;
+ GFile *workdir;
+ GFile *sc_gfile;
+ char *sc_filename;
+ GFile *stream_gfile;
+ char *stream_str;
+
+ workdir = make_job_folder(job_title, job_notes);
+ if ( workdir == NULL ) return NULL;
+
+ stream_gfile = g_file_get_child(workdir, "ambi.stream");
+ stream_str = g_file_get_path(stream_gfile);
+ g_object_unref(stream_gfile);
+
+ sc_gfile = g_file_get_child(workdir, "run_ambigator.sh");
+ sc_filename = g_file_get_path(sc_gfile);
+ g_object_unref(sc_gfile);
+ if ( sc_filename == NULL ) return NULL;
+
+ if ( !write_ambigator_script(sc_filename, input, "`nproc`",
+ &proj->ambi_params, stream_str) )
+ {
+ job = start_slurm_job(GUI_JOB_AMBIGATOR,
+ sc_filename, job_title, NULL, workdir,
+ "stdout.log", "stderr.log", &opts->common);
+ job->niter = proj->ambi_params.niter;
+ } else {
+ job = NULL;
+ }
+ g_free(sc_filename);
+
+ if ( job != NULL ) {
+ char **streams = malloc(sizeof(char *));
+ if ( streams != NULL ) {
+ streams[0] = stream_str;
+ add_indexing_result(proj, strdup(job_title), streams, 1);
+ }
+ }
+
+ g_object_unref(workdir);
+ return job;
+}
+
+
+static void *run_merging(const char *job_title,
+ const char *job_notes,
+ struct crystfelproject *proj,
+ struct gui_indexing_result *input,
+ void *opts_priv)
+{
+ struct slurm_job *job;
+ struct slurm_merging_opts *opts = opts_priv;
+ GFile *workdir;
+ GFile *sc_gfile;
+ char *sc_filename;
+
+ workdir = make_job_folder(job_title, job_notes);
+ if ( workdir == NULL ) return NULL;
+
+ sc_gfile = g_file_get_child(workdir, "run_merge.sh");
+ sc_filename = g_file_get_path(sc_gfile);
+ g_object_unref(sc_gfile);
+ if ( sc_filename == NULL ) return NULL;
+
+ if ( !write_merge_script(sc_filename, input, "`nproc`",
+ &proj->merging_params, "crystfel.hkl") )
+ {
+ enum gui_job_type type;
+ if ( strcmp(proj->merging_params.model, "process_hkl") == 0 ) {
+ if ( proj->merging_params.scale ) {
+ type = GUI_JOB_PROCESS_HKL_SCALE;
+ } else {
+ type = GUI_JOB_PROCESS_HKL;
+ }
+ } else {
+ type = GUI_JOB_PARTIALATOR;
+ }
+ job = start_slurm_job(type, sc_filename, job_title, NULL,
+ workdir, "stdout.log", "stderr.log",
+ &opts->common);
+ } else {
+ job = NULL;
+ }
+ g_free(sc_filename);
+
+ if ( job != NULL ) {
+
+ GFile *hkl_gfile;
+ char *hkl;
+ char *hkl1;
+ char *hkl2;
+
+ hkl_gfile = g_file_get_child(workdir, "crystfel.hkl");
+ hkl = g_file_get_path(hkl_gfile);
+ g_object_unref(hkl_gfile);
+
+ hkl_gfile = g_file_get_child(workdir, "crystfel.hkl1");
+ hkl1 = g_file_get_path(hkl_gfile);
+ g_object_unref(hkl_gfile);
+
+ hkl_gfile = g_file_get_child(workdir, "crystfel.hkl2");
+ hkl2 = g_file_get_path(hkl_gfile);
+ g_object_unref(hkl_gfile);
+
+ add_merge_result(proj, strdup(job_title), hkl, hkl1, hkl2);
+ }
+
+ g_object_unref(workdir);
+ return job;
+}
+
+
+static struct slurm_merging_opts *make_default_slurm_merging_opts()
+{
+ struct slurm_merging_opts *opts = malloc(sizeof(struct slurm_merging_opts));
+ if ( opts == NULL ) return NULL;
+ set_default_common_opts(&opts->common);
+ return opts;
+}
+
+
+static void write_merging_opts(void *opts_priv, FILE *fh)
+{
+ struct slurm_merging_opts *opts = opts_priv;
+ write_common_opts(fh, &opts->common, "merging");
+}
+
+
+static void read_merging_opt(void *opts_priv,
+ const char *key,
+ const char *val)
+{
+ struct slurm_merging_opts *opts = opts_priv;
+
+ if ( strcmp(key, "merging.slurm.email_address") == 0 ) {
+ opts->common.email_address = strdup(val);
+ }
+
+ if ( strcmp(key, "merging.slurm.partition") == 0 ) {
+ opts->common.partition = strdup(val);
+ }
+
+ if ( strcmp(key, "merging.slurm.account") == 0 ) {
+ opts->common.account = strdup(val);
+ }
+
+ if ( strcmp(key, "merging.slurm.constraint") == 0 ) {
+ opts->common.constraint = strdup(val);
+ }
+
+}
+
+
+static GtkWidget *make_merging_parameters_widget(void *opts_priv)
+{
+ GtkWidget *vbox;
+ struct slurm_merging_opts *opts = opts_priv;
+ vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+ add_common_opts(vbox, &opts->common);
+ return vbox;
+}
+
+
+static struct slurm_ambi_opts *make_default_slurm_ambi_opts()
+{
+ struct slurm_ambi_opts *opts = malloc(sizeof(struct slurm_ambi_opts));
+ if ( opts == NULL ) return NULL;
+ set_default_common_opts(&opts->common);
+ return opts;
+}
+
+
+static void write_ambi_opts(void *opts_priv, FILE *fh)
+{
+ struct slurm_ambi_opts *opts = opts_priv;
+ write_common_opts(fh, &opts->common, "ambi");
+}
+
+
+static void read_ambi_opt(void *opts_priv,
+ const char *key,
+ const char *val)
+{
+ struct slurm_ambi_opts *opts = opts_priv;
+
+ if ( strcmp(key, "ambi.slurm.email_address") == 0 ) {
+ opts->common.email_address = strdup(val);
+ }
+
+ if ( strcmp(key, "ambi.slurm.partition") == 0 ) {
+ opts->common.partition = strdup(val);
+ }
+
+ if ( strcmp(key, "ambi.slurm.account") == 0 ) {
+ opts->common.account = strdup(val);
+ }
+
+ if ( strcmp(key, "ambi.slurm.constraint") == 0 ) {
+ opts->common.constraint = strdup(val);
+ }
+}
+
+
+static GtkWidget *make_ambi_parameters_widget(void *opts_priv)
+{
+ GtkWidget *vbox;
+ struct slurm_ambi_opts *opts = opts_priv;
+ vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+ add_common_opts(vbox, &opts->common);
+ return vbox;
+}
+
+
+int make_slurm_backend(struct crystfel_backend *be)
+{
+ be->name = "slurm";
+ be->friendly_name = "SLURM";
+
+ be->cancel_task = cancel_task;
+ be->task_status = get_task_status;
+
+ be->make_indexing_parameters_widget = make_indexing_parameters_widget;
+ be->run_indexing = run_indexing;
+ be->indexing_opts_priv = make_default_slurm_indexing_opts();
+ if ( be->indexing_opts_priv == NULL ) return 1;
+ be->write_indexing_opts = write_indexing_opts;
+ be->read_indexing_opt = read_indexing_opt;
+
+ be->make_merging_parameters_widget = make_merging_parameters_widget;
+ be->run_merging = run_merging;
+ be->merging_opts_priv = make_default_slurm_merging_opts();
+ if ( be->merging_opts_priv == NULL ) return 1;
+ be->write_merging_opts = write_merging_opts;
+ be->read_merging_opt = read_merging_opt;
+
+ be->make_ambi_parameters_widget = make_ambi_parameters_widget;
+ be->run_ambi = run_ambi;
+ be->ambi_opts_priv = make_default_slurm_ambi_opts();
+ if ( be->ambi_opts_priv == NULL ) return 1;
+ be->write_ambi_opts = write_ambi_opts;
+ be->read_ambi_opt = read_ambi_opt;
+
+ return 0;
+};
diff --git a/src/gui_backend_slurm.h b/src/gui_backend_slurm.h
new file mode 100644
index 00000000..1b117952
--- /dev/null
+++ b/src/gui_backend_slurm.h
@@ -0,0 +1,36 @@
+/*
+ * gui_backend_slurm.h
+ *
+ * GUI backend for running jobs via SLURM
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GUI_BACKEND_SLURM_H
+#define GUI_BACKEND_SLURM_H
+
+#include "gui_project.h"
+
+extern int make_slurm_backend(struct crystfel_backend *be);
+
+#endif
diff --git a/src/gui_export.c b/src/gui_export.c
new file mode 100644
index 00000000..c3499827
--- /dev/null
+++ b/src/gui_export.c
@@ -0,0 +1,742 @@
+/*
+ * gui_export.c
+ *
+ * Export data from CrystFEL GUI
+ *
+ * Copyright © 2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <assert.h>
+
+#ifdef HAVE_LIBCCP4
+#include <ccp4/cmtzlib.h>
+#include <ccp4/csymlib.h>
+#include <ccp4/ccp4_parser.h>
+#endif
+
+#include <utils.h>
+#include <reflist-utils.h>
+#include <cell-utils.h>
+#include <symmetry.h>
+
+#include "version.h"
+#include "gui_project.h"
+#include "crystfel_gui.h"
+#include "gtk-util-routines.h"
+
+
+struct export_window
+{
+ struct crystfelproject *proj;
+ GtkWidget *cell_chooser;
+ GtkWidget *limit_res;
+ GtkWidget *min_res;
+ GtkWidget *max_res;
+ GtkWidget *dataset;
+ GtkWidget *format;
+};
+
+
+struct point_group_conversion
+{
+ char centering;
+ const char *crystfel;
+ int friedel;
+
+ int xds_spgnum;
+
+ const char *ccp4;
+};
+
+
+/* Table for converting CrystFEL's knowledge about centering, point group
+ * and unique axis into something that can be recognised by external programs.
+ * If xds_spgnum=0, ccp4=NULL, or something is missing form this table entirely,
+ * it means that there is no way to represent the situation to that program
+ * without re-indexing the dataset. */
+struct point_group_conversion pg_conversions[] = {
+
+ /* Triclinic */
+ {'P', "1", 0, 1, "P 1"},
+ {'P', "-1", 1, 1, "P 1"},
+
+ /* Monoclinic */
+ {'P', "2_uaa", 0, 0, "P211"},
+ {'P', "m_uaa", 0, 0, "Pm11"},
+ {'P', "2/m_uaa", 1, 0, "P211"},
+ {'P', "2_uab", 0, 3, "P121"},
+ {'P', "m_uab", 0, 0, "P1m1"},
+ {'P', "2/m_uab", 1, 3, "P121"},
+ {'P', "2_uac", 0, 0, "P112"},
+ {'P', "m_uac", 0, 0, "P11m"},
+ {'P', "2/m_uac", 1, 0, "P112"},
+ {'P', "2", 0, 0, "P121"}, /* unique axis c */
+ {'P', "m", 0, 0, "P11m"}, /* unique axis c */
+ {'P', "2/m", 1, 0, "P121"}, /* unique axis c */
+
+ {'A', "2_uab", 0, 0, "A121"},
+ {'A', "m_uab", 0, 0, "A1m1"},
+ {'A', "2/m_uab", 1, 0, "A121"},
+ {'A', "2_uac", 0, 0, "A112"},
+ {'A', "m_uac", 0, 0, "A11m"},
+ {'A', "2/m_uac", 1, 0, "A112"},
+ {'A', "2", 0, 0, "A121"}, /* unique axis c */
+ {'A', "m", 0, 0, "A11m"}, /* unique axis c */
+ {'A', "2/m", 1, 0, "A121"}, /* unique axis c */
+
+ {'B', "2_uaa", 0, 0, "B211"},
+ {'B', "m_uaa", 0, 0, "Bm11"},
+ {'B', "2/m_uaa", 1, 0, "B211"},
+ {'B', "2_uac", 0, 0, "B112"},
+ {'B', "m_uac", 0, 0, "B11m"},
+ {'B', "2/m_uac", 1, 0, "B112"},
+ {'B', "2", 0, 0, "B112"}, /* unique axis c */
+ {'B', "m", 0, 0, "B11m"}, /* unique axis c */
+ {'B', "2/m", 1, 0, "B112"}, /* unique axis c */
+
+ {'C', "2_uaa", 0, 0, "C211"},
+ {'C', "m_uaa", 0, 0, "Cm11"},
+ {'C', "2/m_uaa", 1, 0, "C211"},
+ {'C', "2_uab", 0, 5, "C121"},
+ {'C', "m_uab", 0, 0, "C1m1"},
+ {'C', "2/m_uab", 1, 5, "C121"},
+
+ {'I', "2_uaa", 0, 0, "I211"},
+ {'I', "m_uaa", 0, 0, "Im11"},
+ {'I', "2/m_uaa", 1, 0, "I211"},
+ {'I', "2_uab", 0, 0, "I121"},
+ {'I', "m_uab", 0, 0, "I1m1"},
+ {'I', "2/m_uab", 1, 0, "I121"},
+ {'I', "2_uac", 0, 0, "I112"},
+ {'I', "m_uac", 0, 0, "I11m"},
+ {'I', "2/m_uac", 1, 0, "I112"},
+ {'I', "2", 0, 0, "I121"}, /* unique axis c */
+ {'I', "m", 0, 0, "I11m"}, /* unique axis c */
+ {'I', "2/m", 1, 0, "I121"}, /* unique axis c */
+
+ /* Orthorhombic */
+ {'P', "222", 0, 16, "P222"},
+ {'P', "mmm", 1, 16, "P222"},
+ {'P', "mm2", 0, 25, "Pmm2"},
+ {'A', "222", 0, 0, "A222"},
+ {'A', "mmm", 1, 0, "A222"},
+ {'A', "mm2", 0, 38, "Amm2"},
+ {'B', "222", 0, 0, "B222"},
+ {'B', "mmm", 1, 0, "B222"},
+ {'B', "mm2", 0, 0, "Bmm2"},
+ {'C', "222", 0, 21, "C222"},
+ {'C', "mmm", 1, 21, "C222"},
+ {'C', "mm2", 0, 35, "Cmm2"},
+ {'F', "222", 0, 22, "F222"},
+ {'F', "mmm", 1, 22, "F222"},
+ {'F', "mm2", 0, 42, "Fmm2"},
+ {'I', "222", 0, 23, "I222"},
+ {'I', "mmm", 1, 23, "I222"},
+ {'I', "mm2", 0, 45, "Imm2"},
+
+ /* Tetragonal */
+ {'P', "4", 0, 75, "P4"}, /* unique axis c */
+ {'P', "4/m", 1, 75, "P4"}, /* unique axis c */
+ {'P', "422", 0, 89, "P422"}, /* unique axis c */
+ {'P', "4/mmm", 1, 89, "P422"}, /* unique axis c */
+ {'P', "4mm", 0, 99, "P4mm"}, /* unique axis c */
+ {'P', "-4", 0, 81, "P-4"}, /* unique axis c */
+ {'P', "-42m", 0, 111, "P-42m"}, /* unique axis c */
+ {'P', "-4m2", 0, 115, "P-4m2"}, /* unique axis c */
+ {'P', "4_uac", 0, 75, "P4"},
+ {'P', "4/m_uac", 1, 75, "P4"},
+ {'P', "422_uac", 0, 89, "P422"},
+ {'P', "4/mmm_uac", 1, 89, "P422"},
+ {'P', "4mm_uac", 0, 99, "P4mm"},
+ {'P', "-4_uac", 0, 81, "P-4"},
+ {'P', "-42m_uac", 0, 111, "P-42m"},
+ {'P', "-4m2_uac", 0, 115, "P-4m2"},
+ {'I', "4", 0, 79, "I4"}, /* unique axis c */
+ {'I', "4/m", 1, 79, "I4"}, /* unique axis c */
+ {'I', "422", 0, 97, "I422"}, /* unique axis c */
+ {'I', "4/mmm", 1, 97, "I422"}, /* unique axis c */
+ {'I', "4mm", 0, 107, "I4mm"}, /* unique axis c */
+ {'I', "-4", 0, 82, "I-4"}, /* unique axis c */
+ {'I', "-42m", 0, 121, "I-42m"}, /* unique axis c */
+ {'I', "-4m2", 0, 119, "I-4m2"}, /* unique axis c */
+ {'I', "4_uac", 0, 79, "I4"},
+ {'I', "4/m_uac", 1, 79, "I4"},
+ {'I', "422_uac", 0, 97, "I422"},
+ {'I', "4/mmm_uac", 1, 97, "I422"},
+ {'I', "4mm_uac", 0, 107, "I4mm"},
+ {'I', "-4_uac", 0, 82, "I-4"},
+ {'I', "-42m_uac", 0, 121, "I-42m"},
+ {'I', "-4m2_uac", 0, 119, "I-4m2"},
+
+ /* Trigonal (rhombohedral) */
+ {'R', "3_R", 0, 0, "R3:R"},
+ {'R', "-3_R", 1, 0, "R3:R"},
+ {'R', "32_R", 0, 0, "R32:R"},
+ {'R', "-3m_R", 1, 0, "R32:R"},
+ {'R', "3m_R", 0, 0, "R3m:R"},
+
+ /* Trigonal (rhombohedral on hexagonal axes) */
+ {'H', "3_H", 0, 146, "R3:H"},
+ {'H', "-3_H", 1, 146, "R3:H"},
+ {'H', "32_H", 0, 155, "R3:H"},
+ {'H', "-3m_H", 1, 155, "R3:H"},
+ {'H', "3m_H", 0, 0, "R3m:H"},
+
+ /* Trigonal (hexagonal) */
+ {'P', "3_H", 0, 143, "P3"},
+ {'P', "-3_H", 1, 143, "P3"},
+ {'P', "312_H", 0, 149, "P312"},
+ {'P', "-31m_H", 1, 149, "P312"},
+ {'P', "321_H", 0, 150, "P321"},
+ {'P', "-3m1_H", 1, 150, "P321"},
+ {'P', "3m1_H", 0, 156, "P3m1"},
+ {'P', "31m_H", 0, 157, "P31m"},
+
+ /* Hexagonal */
+ {'P', "6", 0, 168, "P6"},
+ {'P', "6/m", 1, 168, "P6"},
+ {'P', "622", 0, 177, "P622"},
+ {'P', "6/mmm", 1, 177, "P622"},
+ {'P', "6mm", 0, 177, "P6mm"},
+ {'P', "-6m2", 0, 187, "P-6m2"},
+ {'P', "-62m", 0, 189, "P-62m"},
+
+ /* Cubic */
+ {'P', "23", 0, 195, "P23"},
+ {'P', "m-3", 1, 195, "P23"},
+ {'P', "432", 0, 207, "P432"},
+ {'P', "m-3m", 1, 207, "P432"},
+ {'P', "-43m", 0, 215, "P -4 3 m"},
+ {'I', "23", 0, 197, "I23"},
+ {'I', "m-3", 1, 197, "I23"},
+ {'I', "432", 0, 211, "I432"},
+ {'I', "m-3m", 1, 211, "I432"},
+ {'I', "-43m", 0, 217, "I -4 3 m"},
+ {'F', "23", 0, 196, "F23"},
+ {'F', "m-3", 1, 196, "F23"},
+ {'F', "432", 0, 209, "F432"},
+ {'F', "m-3m", 1, 209, "F432"},
+ {'F', "-43m", 0, 216, "F -4 3 m"},
+
+ {'*', NULL, 0, 0, NULL}
+};
+
+
+static int space_group_for_xds(const char *sym_str, char cen)
+{
+ int i = 0;
+ do {
+ if ( (pg_conversions[i].centering == cen)
+ && (strcmp(sym_str, pg_conversions[i].crystfel) == 0) )
+ {
+ return pg_conversions[i].xds_spgnum;
+ }
+ i++;
+ } while (pg_conversions[i].centering != '*');
+
+ ERROR("Couldn't derive XDS representation of symmetry.\n");
+ return 0;
+}
+
+
+#ifdef HAVE_LIBCCP4
+static const char *space_group_for_mtz(const char *sym_str, char cen)
+{
+ int i = 0;
+ do {
+ if ( (pg_conversions[i].centering == cen)
+ && (strcmp(sym_str, pg_conversions[i].crystfel) == 0) )
+ {
+ return pg_conversions[i].ccp4;
+ }
+ i++;
+ } while (pg_conversions[i].centering != '*');
+
+ ERROR("Couldn't derive CCP4 representation of symmetry.\n");
+ return NULL;
+}
+#endif
+
+
+static int export_to_xds(struct gui_merge_result *result,
+ const char *filename, UnitCell *cell,
+ double min_res, double max_res)
+{
+ FILE *fh;
+ RefList *reflist;
+ RefListIterator *iter;
+ Reflection *refl;
+ double a, b, c, al, be,ga;
+ char *sym_str;
+ SymOpList *sym;
+ int spg;
+
+ fh = fopen(filename, "w");
+ if ( fh == NULL ) return 1;
+
+ reflist = read_reflections_2(result->hkl, &sym_str);
+ if ( reflist == NULL ) return 1;
+ if ( sym_str == NULL ) return 1;
+
+ sym = get_pointgroup(sym_str);
+ if ( sym == NULL ) return 1;
+
+ cell_get_parameters(cell, &a, &b, &c, &al, &be, &ga);
+
+ spg = space_group_for_xds(sym_str, cell_get_centering(cell));
+ if ( spg == 0 ) return 1;
+
+ fprintf(fh, "!FORMAT=XDS_ASCII MERGE=TRUE FRIEDEL'S_LAW=%s\n",
+ is_centrosymmetric(sym) ? "TRUE" : "FALSE");
+ fprintf(fh, "!SPACE_GROUP_NUMBER=%i\n", spg);
+ fprintf(fh, "!UNIT_CELL_CONSTANT= %.2f %.2f %.2f %.2f %.2f %.2f\n",
+ a*1e10, b*1e10, c*1e10, rad2deg(al), rad2deg(be), rad2deg(ga));
+ fprintf(fh, "!NUMBER_OF_ITEMS_IN_EACH_DATA_RECORD=5\n");
+ fprintf(fh, "!ITEM_H=1\n");
+ fprintf(fh, "!ITEM_K=2\n");
+ fprintf(fh, "!ITEM_L=3\n");
+ fprintf(fh, "!ITEM_IOBS=4\n");
+ fprintf(fh, "!ITEM_SIGMA(IOBS)=5\n");
+ fprintf(fh, "!END_OF_HEADER\n");
+
+ for ( refl = first_refl(reflist, &iter);
+ refl != NULL;
+ refl = next_refl(refl, iter) )
+ {
+ signed int h, k, l;
+ double one_over_d;
+
+ get_indices(refl, &h, &k, &l);
+
+ one_over_d = 2.0*resolution(cell, h, k, l);
+ if ( (one_over_d > min_res) && (one_over_d < max_res) ) {
+
+ fprintf(fh, "%6i %6i %6i %9.2f %9.2f\n",
+ h, k, l,
+ get_intensity(refl),
+ get_esd_intensity(refl));
+
+ }
+ }
+
+ fprintf(fh, "!END_OF_DATA\n");
+ free_symoplist(sym);
+ free(sym_str);
+ reflist_free(reflist);
+
+ fclose(fh);
+ return 0;
+}
+
+
+#ifdef HAVE_LIBCCP4
+static CCP4SPG *add_mtz_symmetry_header(MTZ *mtz, const char *spg_name)
+{
+ CCP4SPG *spg;
+ float rsymx[192][4][4];
+ char ltypex[2];
+ int i;
+
+ spg = ccp4spg_load_by_spgname(spg_name);
+ if ( spg == NULL ) {
+ ERROR("Couldn't look up CCP4 space group '%s'\n", spg_name);
+ return NULL;
+ }
+
+ for ( i=0; i<spg->nsymop; i++ ) {
+ rotandtrn_to_mat4(rsymx[i], spg->symop[i]);
+ }
+ ltypex[0] = spg->symbol_old[0];
+ ltypex[1] = '\0';
+
+ ccp4_lwsymm(mtz, spg->nsymop, spg->nsymop_prim,
+ rsymx, ltypex, spg->spg_ccp4_num, spg->symbol_old,
+ spg->point_group);
+
+ return spg;
+}
+#endif
+
+
+static int export_to_mtz(struct gui_merge_result *result,
+ const char *filename, UnitCell *cell,
+ double min_res, double max_res)
+{
+#ifdef HAVE_LIBCCP4
+ MTZ *mtz;
+ MTZXTAL *cr;
+ MTZSET *ds;
+ MTZCOL *columns[7];
+ double a, b, c, al, be, ga;
+ int r;
+ char tmp[128];
+ float cellp[6];
+ int refl_i;
+ RefList *reflist;
+ Reflection *refl;
+ RefListIterator *iter;
+ char *sym_str = NULL;
+ CCP4SPG *spg;
+ const char *spg_name;
+ SymOpList *sym;
+
+ reflist = read_reflections_2(result->hkl, &sym_str);
+ if ( reflist == NULL ) return 1;
+ if ( sym_str == NULL ) return 1;
+
+ sym = get_pointgroup(sym_str);
+ if ( sym == NULL ) return 1;
+
+ spg_name = space_group_for_mtz(sym_str, cell_get_centering(cell));
+ if ( spg_name == NULL ) {
+ reflist_free(reflist);
+ return 1;
+ }
+
+ mtz = MtzMalloc(0, 0);
+
+ snprintf(tmp, 128, "Data exported via CrystFEL GUI, version %s",
+ crystfel_version_string());
+ ccp4_lwtitl(mtz, tmp, 0);
+
+ mtz->refs_in_memory = 0;
+ mtz->fileout = MtzOpenForWrite(filename);
+
+ spg = add_mtz_symmetry_header(mtz, spg_name);
+ if ( spg == NULL ) {
+ return 1;
+ }
+
+ cell_get_parameters(cell, &a, &b, &c, &al, &be, &ga);
+ cellp[0] = a*1e10;
+ cellp[1] = b*1e10;
+ cellp[2] = c*1e10;
+ cellp[3] = rad2deg(al);
+ cellp[4] = rad2deg(be);
+ cellp[5] = rad2deg(ga);
+
+ /* FIXME: Proposed labelling:
+ * title = as above
+ * project = basename of folder containing crystfel.project
+ * crystal = name of indexing results run
+ * dataset = name of merge results run */
+ cr = MtzAddXtal(mtz, "Crystal_name", "Project_name", cellp);
+ ds = MtzAddDataset(mtz, cr, result->name, 0.0);
+ columns[0] = MtzAddColumn(mtz, ds, "H", "H");
+ columns[1] = MtzAddColumn(mtz, ds, "K", "H");
+ columns[2] = MtzAddColumn(mtz, ds, "L", "H");
+ columns[3] = MtzAddColumn(mtz, ds, "I+", "J");
+ columns[4] = MtzAddColumn(mtz, ds, "SIGI+", "Q");
+ columns[5] = MtzAddColumn(mtz, ds, "I-", "J");
+ columns[6] = MtzAddColumn(mtz, ds, "SIGI-", "Q");
+
+ refl_i = 1;
+ for ( refl = first_refl(reflist, &iter);
+ refl != NULL;
+ refl = next_refl(refl, iter) )
+ {
+ signed int h, k, l;
+ double one_over_d;
+ int isym;
+
+ get_indices(refl, &h, &k, &l);
+
+ one_over_d = 2.0*resolution(cell, h, k, l);
+ if ( (one_over_d > min_res) && (one_over_d < max_res) ) {
+
+ float refldata[7];
+ signed int nh, nk, nl;
+ signed int fh, fk, fl;
+ Reflection *friedel;
+ Reflection *refl_plus;
+ Reflection *refl_minus;
+
+ /* Look for Friedel partner */
+ if ( find_equiv_in_list(reflist, -h, -k, -l,
+ sym, &fh, &fk, &fl) )
+ {
+ friedel = find_refl(reflist, fh, fk, fl);
+ } else {
+ friedel = NULL;
+ }
+
+ /* Move to CCP4's idea of the ASU */
+ isym = ccp4spg_put_in_asu(spg, h, k, l, &nh, &nk, &nl);
+
+ /* Ok, do we have an I+ or an I- ? */
+ if ( is_odd(isym) ) {
+ /* I+ */
+ refl_plus = refl;
+ refl_minus = friedel;
+ } else {
+ /* I- */
+ refl_minus = refl;
+ refl_plus = friedel;
+ }
+
+ /* If we are looking at an I-, only write it out now
+ * if the corresponding I+ if not in 'reflist'.
+ * If I+ is present, then this I- will get written when
+ * the Friedel pair is processed. */
+ if ( !is_odd(isym) && (refl_plus != NULL) ) continue;
+
+ refldata[0] = nh;
+ refldata[1] = nk;
+ refldata[2] = nl;
+ if ( refl_plus != NULL ) {
+ refldata[3] = get_intensity(refl_plus);
+ refldata[4] = get_esd_intensity(refl_plus);
+ } else {
+ refldata[3] = NAN;
+ refldata[4] = NAN;
+ }
+ if ( refl_minus != NULL ) {
+ refldata[5] = get_intensity(refl_minus);
+ refldata[6] = get_esd_intensity(refl_minus);
+ } else {
+ refldata[5] = NAN;
+ refldata[6] = NAN;
+ }
+
+ ccp4_lwrefl(mtz, refldata, columns, 7, refl_i++);
+
+ }
+ }
+
+ r = MtzPut(mtz, " ");
+ ccp4spg_free(&spg);
+ MtzFree(mtz);
+ reflist_free(reflist);
+ return 1-r; /* Yes, really. MtzPut return values are backwards */
+#else
+ return 1;
+#endif
+}
+
+
+static int export_data(struct export_window *win, char *filename)
+{
+ gchar *cell_filename;
+ const char *dataset;
+ const char *format;
+ struct gui_merge_result *result;
+ UnitCell *cell;
+ int r = 0;
+ double min_res = 0;
+ double max_res = +INFINITY;
+
+ dataset = gtk_combo_box_get_active_id(GTK_COMBO_BOX(win->dataset));
+ if ( dataset == NULL ) {
+ ERROR("Please select the dataset to export.\n");
+ return 1;
+ }
+
+ format = gtk_combo_box_get_active_id(GTK_COMBO_BOX(win->format));
+ if ( format == NULL ) {
+ ERROR("Please select the data format to use.\n");
+ return 1;
+ }
+
+ cell_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(win->cell_chooser));
+ if ( cell_filename == NULL ) {
+ ERROR("Please choose the unit cell file.\n");
+ return 1;
+ }
+
+ cell = load_cell_from_file(cell_filename);
+ if ( cell == NULL ) {
+ ERROR("Failed to load unit cell file %s\n", cell_filename);
+ return 1;
+ }
+
+ if ( get_bool(win->limit_res) ) {
+ min_res = 1e10/get_float(win->min_res);
+ max_res = 1e10/get_float(win->max_res);
+ }
+
+ result = find_merge_result_by_name(win->proj, dataset);
+ if ( result == NULL ) {
+ ERROR("Couldn't find merged dataset '%s'\n", dataset);
+ return 1;
+ }
+
+ STATUS("Exporting dataset %s to %s, in format %s, using unit cell %s,"
+ "%f to %f m^-1\n", dataset, filename, format, cell_filename,
+ min_res, max_res);
+
+ if ( strcmp(format, "mtz") == 0 ) {
+ r = export_to_mtz(result, filename, cell, min_res, max_res);
+ } else if ( strcmp(format, "xds") == 0 ) {
+ r = export_to_xds(result, filename, cell, min_res, max_res);
+ } else {
+ ERROR("Unrecognised export format '%s'\n", format);
+ return 1;
+ }
+
+ if ( r ) {
+ ERROR("Export failed\n");
+ }
+
+ g_free(cell_filename);
+
+ return 0;
+}
+
+
+static void export_response_sig(GtkWidget *dialog, gint resp,
+ struct export_window *win)
+{
+ int r = 0;
+
+ if ( resp == GTK_RESPONSE_ACCEPT ) {
+ gchar *filename;
+ filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+ r = export_data(win, filename);
+ g_free(filename);
+ }
+
+ if ( !r ) gtk_widget_destroy(dialog);
+}
+
+
+gint export_sig(GtkWidget *widget, struct crystfelproject *proj)
+{
+ GtkWidget *dialog;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ char tmp[64];
+ struct export_window *win;
+ int i;
+
+ win = malloc(sizeof(struct export_window));
+ if ( win == NULL ) return 0;
+
+ win->proj = proj;
+
+ dialog = gtk_file_chooser_dialog_new("Export data",
+ GTK_WINDOW(proj->window),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog),
+ TRUE);
+
+ g_signal_connect(G_OBJECT(dialog), "response",
+ G_CALLBACK(export_response_sig),
+ win);
+
+ vbox = gtk_vbox_new(FALSE, 0.0);
+ gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(dialog),
+ GTK_WIDGET(vbox));
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("Results to export:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ win->dataset = gtk_combo_box_text_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->dataset),
+ FALSE, FALSE, 4.0);
+ for ( i=0; i<proj->n_merge_results; i++ ) {
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(win->dataset),
+ proj->merge_results[i].name,
+ proj->merge_results[i].name);
+ }
+ label = gtk_label_new("Format");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ win->format = gtk_combo_box_text_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->format),
+ FALSE, FALSE, 4.0);
+#ifdef HAVE_LIBCCP4
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(win->format), "mtz",
+ "MTZ");
+#endif
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(win->format), "xds",
+ "XDS ASCII");
+ gtk_combo_box_set_active(GTK_COMBO_BOX(win->format), 0);
+
+ label = gtk_label_new("Unit cell file:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ win->cell_chooser = gtk_file_chooser_button_new("Unit cell file",
+ GTK_FILE_CHOOSER_ACTION_OPEN);
+ gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(win->cell_chooser),
+ TRUE);
+ /* Use the "FoM" cell file because there should only be one
+ * point of truth for the "final" cell parameters. Eventually, I hope
+ * to determine this automatically. */
+ gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(win->cell_chooser),
+ proj->fom_cell_filename);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->cell_chooser),
+ FALSE, FALSE, 4.0);
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ win->limit_res = gtk_check_button_new_with_label("Restrict resolution range:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->limit_res),
+ FALSE, FALSE, 4.0);
+ win->min_res = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(win->min_res), 4);
+ snprintf(tmp, 64, "%.2f", proj->export_res_min);
+ gtk_entry_set_text(GTK_ENTRY(win->min_res), tmp);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->min_res),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("to");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ win->max_res = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(win->max_res), 4);
+ snprintf(tmp, 64, "%.2f", proj->export_res_max);
+ gtk_entry_set_text(GTK_ENTRY(win->max_res), tmp);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(win->max_res),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("Å");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ g_signal_connect(G_OBJECT(win->limit_res), "toggled",
+ G_CALLBACK(i_maybe_disable), win->min_res);
+ g_signal_connect(G_OBJECT(win->limit_res), "toggled",
+ G_CALLBACK(i_maybe_disable), win->max_res);
+ gtk_widget_set_sensitive(win->min_res, FALSE);
+ gtk_widget_set_sensitive(win->max_res, FALSE);
+
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+ GTK_RESPONSE_CLOSE);
+ gtk_widget_show_all(dialog);
+
+ return FALSE;
+}
diff --git a/src/gui_export.h b/src/gui_export.h
new file mode 100644
index 00000000..481d5d5b
--- /dev/null
+++ b/src/gui_export.h
@@ -0,0 +1,39 @@
+/*
+ * gui_export.h
+ *
+ * Export data from CrystFEL GUI
+ *
+ * Copyright © 2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GUI_EXPORT_H
+#define GUI_EXPORT_H
+
+#include <gtk/gtk.h>
+
+#include "gui_project.h"
+
+extern gint export_sig(GtkWidget *widget,
+ struct crystfelproject *proj);
+
+#endif
diff --git a/src/gui_fom.c b/src/gui_fom.c
new file mode 100644
index 00000000..2485e61e
--- /dev/null
+++ b/src/gui_fom.c
@@ -0,0 +1,677 @@
+/*
+ * gui_fom.c
+ *
+ * Figures of merit via CrystFEL GUI
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <assert.h>
+
+#include <utils.h>
+#include <fom.h>
+#include <reflist-utils.h>
+#include <cell-utils.h>
+
+#include "gui_project.h"
+#include "crystfel_gui.h"
+#include "gtk-util-routines.h"
+
+#define MAX_DATASETS (64)
+
+
+struct fom_window
+{
+ struct crystfelproject *proj;
+ GtkWidget *min_res;
+ GtkWidget *max_res;
+ GtkWidget *num_bins;
+ GtkWidget *min_snr;
+ GtkWidget *min_meas;
+ GtkWidget *cell_chooser;
+
+ int n_datasets;
+ GtkWidget *dataset_checkboxes[MAX_DATASETS];
+ char *dataset_names[MAX_DATASETS];
+
+ int n_foms;
+ GtkWidget *fom_checkboxes[16];
+ enum fom_type fom_types[16];
+};
+
+
+static int menu_selected(GtkWidget *w)
+{
+ return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w));
+}
+
+
+static int fom_selected(struct fom_window *f, int i)
+{
+ return menu_selected(f->fom_checkboxes[i]);
+}
+
+
+static int anomalous_foms_selected(struct fom_window *f)
+{
+ int i;
+ for ( i=0; i<f->n_foms; i++ ) {
+ if ( fom_selected(f, i) ) {
+ if ( fom_is_anomalous(f->fom_types[i]) ) return 1;
+ }
+ }
+ return 0;
+}
+
+
+static void show_fom(enum fom_type fom,
+ struct fom_context *fctx,
+ struct fom_shells *shells)
+{
+ int i;
+
+ STATUS("Overall %s: %f (%i reflections)\n",
+ fom_name(fom), fom_overall_value(fctx),
+ fom_overall_num_reflections(fctx));
+ STATUS("%10s %10s %10s\n", "1/d / nm^-1", fom_name(fom), "num refl");
+ for ( i=0; i<shells->nshells; i++ ) {
+ STATUS("%10f %10f %10i\n",
+ fom_shell_centre(shells, i)/1e9,
+ fom_shell_value(fctx, i),
+ fom_shell_num_reflections(fctx, i));
+ }
+}
+
+
+static int load_dataset(struct gui_merge_result *result,
+ int need_ano, UnitCell *cell,
+ double min_res, double max_res,
+ int min_meas, double min_snr,
+ SymOpList **psym,
+ RefList **pall_refls,
+ RefList **pall_refls_anom,
+ RefList **ppart1,
+ RefList **ppart2,
+ RefList **ppart1_anom,
+ RefList **ppart2_anom)
+{
+ RefList *raw_refl;
+ RefList *raw_part1;
+ RefList *raw_part2;
+ RefList *all_refls = NULL;
+ RefList *all_refls_anom = NULL;
+ RefList *part1 = NULL;
+ RefList *part2 = NULL;
+ RefList *part1_anom = NULL;
+ RefList *part2_anom = NULL;
+ SymOpList *sym;
+ char *sym_str;
+ char *sym_str_part1;
+ char *sym_str_part2;
+
+ raw_refl = read_reflections_2(result->hkl, &sym_str);
+ if ( raw_refl == NULL ) {
+ ERROR("Failed to load dataset %s (%s)\n",
+ result->name, result->hkl);
+ return 1;
+ }
+
+ raw_part1 = read_reflections_2(result->hkl1, &sym_str_part1);
+ if ( raw_part1 == NULL ) {
+ ERROR("Failed to load part 1 dataset %s (%s)\n",
+ result->name, result->hkl1);
+ return 1;
+ }
+
+ raw_part2 = read_reflections_2(result->hkl2, &sym_str_part2);
+ if ( raw_part2 == NULL ) {
+ ERROR("Failed to load part 2 dataset %s (%s)\n",
+ result->name, result->hkl2);
+ return 1;
+ }
+
+ if ( (sym_str == NULL)
+ || (sym_str_part1 == NULL)
+ || (sym_str_part2 == NULL) )
+ {
+ ERROR("Reflection list has no point group\n");
+ reflist_free(raw_refl);
+ reflist_free(raw_part1);
+ reflist_free(raw_part2);
+ return 1;
+ }
+
+ if ( (strcmp(sym_str, sym_str_part1) != 0)
+ || (strcmp(sym_str, sym_str_part2) != 0) )
+ {
+ ERROR("Datasets do not have the same point group!\n");
+ free(sym_str);
+ free(sym_str_part1);
+ free(sym_str_part2);
+ reflist_free(raw_refl);
+ reflist_free(raw_part1);
+ reflist_free(raw_part2);
+ return 1;
+ }
+
+ sym = get_pointgroup(sym_str);
+ free(sym_str);
+ free(sym_str_part1);
+ free(sym_str_part2);
+
+ fom_select_reflections(raw_refl, &all_refls,
+ cell, sym,
+ 1e10/min_res, 1e10/max_res,
+ min_snr, 0, 0, min_meas);
+ if ( all_refls == NULL ) {
+ ERROR("Failed to select reflections for dataset '%s'\n",
+ result->name);
+ reflist_free(raw_refl);
+ reflist_free(raw_part1);
+ reflist_free(raw_part2);
+ return 1;
+ }
+
+ fom_select_reflection_pairs(raw_part1, raw_part2,
+ &part1, &part2,
+ cell, sym, 0,
+ 1e10/min_res, 1e10/max_res,
+ min_snr, 0, 0, min_meas);
+ if ( (part1 == NULL) || (part2 == NULL) ) {
+ ERROR("Failed to select reflection pairs for dataset '%s'\n",
+ result->name);
+ reflist_free(all_refls);
+ reflist_free(raw_refl);
+ reflist_free(raw_part1);
+ reflist_free(raw_part2);
+ return 1;
+ }
+
+ STATUS("%s: accepted %i reflections out of %i\n",
+ result->hkl,
+ num_reflections(all_refls),
+ num_reflections(raw_refl));
+
+ if ( need_ano ) {
+
+ fom_select_reflections(raw_refl, &all_refls_anom,
+ cell, sym,
+ 1e10/min_res, 1e10/max_res,
+ min_snr, 0, 0, min_meas);
+ if ( all_refls_anom == NULL ) {
+ ERROR("Failed to load dataset '%s'\n",
+ result->name);
+ reflist_free(raw_refl);
+ return 1;
+ }
+
+ fom_select_reflection_pairs(raw_part1, raw_part2,
+ &part1_anom, &part2_anom,
+ cell, sym, 1,
+ 1e10/min_res, 1e10/max_res,
+ min_snr, 0, 0, min_meas);
+ if ( (part1_anom == NULL) || (part2_anom == NULL) ) {
+ ERROR("Failed to select anomalous reflection pairs "
+ "for dataset '%s'\n", result->name);
+ reflist_free(part1);
+ reflist_free(part2);
+ reflist_free(all_refls);
+ reflist_free(raw_refl);
+ reflist_free(raw_part1);
+ reflist_free(raw_part2);
+ return 1;
+ }
+ }
+
+ reflist_free(raw_refl);
+ reflist_free(raw_part1);
+ reflist_free(raw_part2);
+
+ *pall_refls = all_refls;
+ *pall_refls_anom = all_refls_anom;
+ *ppart1 = part1;
+ *ppart2 = part2;
+ *ppart1_anom = part1_anom;
+ *ppart2_anom = part2_anom;
+ *psym = sym;
+ return 0;
+}
+
+
+static struct fom_context *dispatch_fom(RefList *all_refls,
+ RefList *all_refls_anom,
+ RefList *part1,
+ RefList *part2,
+ RefList *part1_anom,
+ RefList *part2_anom,
+ UnitCell *cell,
+ struct fom_shells *shells,
+ const SymOpList *sym,
+ enum fom_type fom)
+{
+ if ( fom_is_anomalous(fom) ) {
+ if ( fom_is_comparison(fom) ) {
+ if ( part1_anom == NULL ) return NULL;
+ if ( part2_anom == NULL ) return NULL;
+ return fom_calculate(part1_anom, part2_anom,
+ cell, shells, fom, 1, sym);
+ } else {
+ if ( all_refls_anom == NULL ) return NULL;
+ return fom_calculate(all_refls_anom, NULL,
+ cell, shells, fom, 1, sym);
+ }
+ } else {
+ if ( fom_is_comparison(fom) ) {
+ if ( part1 == NULL ) return NULL;
+ if ( part2 == NULL ) return NULL;
+ return fom_calculate(part1, part2,
+ cell, shells, fom, 1, sym);
+ } else {
+ if ( all_refls == NULL ) return NULL;
+ return fom_calculate(all_refls, NULL,
+ cell, shells, fom, 1, sym);
+ }
+ }
+}
+
+
+static void fom_response_sig(GtkWidget *dialog, gint resp,
+ struct fom_window *f)
+{
+ int ds, fom;
+ int need_ano;
+ UnitCell *cell;
+ struct fom_shells *shells;
+
+ if ( resp != GTK_RESPONSE_APPLY ) {
+ gtk_widget_destroy(dialog);
+ return;
+ }
+
+ f->proj->fom_res_min = get_float(f->min_res);
+ f->proj->fom_res_max = get_float(f->max_res);
+ f->proj->fom_min_snr = get_float(f->min_snr);
+ f->proj->fom_min_meas = get_float(f->min_meas);
+ f->proj->fom_nbins = get_uint(f->num_bins);
+ if ( isnan(f->proj->fom_res_min)
+ || isnan(f->proj->fom_res_max)
+ || isnan(f->proj->fom_min_snr) )
+ {
+ ERROR("Invalid parameters\n");
+ return;
+ }
+
+ /* "Minimum resolution" should be the bigger number */
+ if ( f->proj->fom_res_min < f->proj->fom_res_max ) {
+ double tmp = f->proj->fom_res_min;
+ f->proj->fom_res_min = f->proj->fom_res_max;
+ f->proj->fom_res_max = tmp;
+ }
+
+ shells = fom_make_resolution_shells(1e10/f->proj->fom_res_min,
+ 1e10/f->proj->fom_res_max,
+ f->proj->fom_nbins);
+ if ( shells == NULL ) {
+ ERROR("Failed to make resolution shells\n");
+ return;
+ }
+
+ f->proj->fom_cell_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(f->cell_chooser));
+ cell = load_cell_from_file(f->proj->fom_cell_filename);
+ if ( cell == NULL ) {
+ ERROR("Invalid cell file '%s'\n", f->proj->fom_cell_filename);
+ return;
+ }
+
+ need_ano = anomalous_foms_selected(f);
+
+ for ( ds=0; ds<f->n_datasets; ds++ ) {
+
+ struct gui_merge_result *result;
+ SymOpList *sym = NULL;
+ RefList *all_refls = NULL;
+ RefList *all_refls_anom = NULL;
+ RefList *part1 = NULL;
+ RefList *part2 = NULL;
+ RefList *part1_anom = NULL;
+ RefList *part2_anom = NULL;
+
+ if ( !menu_selected(f->dataset_checkboxes[ds]) ) continue;
+
+ /* Load dataset */
+ result = find_merge_result_by_name(f->proj,
+ f->dataset_names[ds]);
+
+ if ( load_dataset(result, need_ano, cell,
+ f->proj->fom_res_min,
+ f->proj->fom_res_max,
+ f->proj->fom_min_meas,
+ f->proj->fom_min_snr,
+ &sym, &all_refls, &all_refls_anom,
+ &part1, &part2, &part1_anom, &part2_anom) )
+ {
+ continue;
+ }
+
+ for ( fom=0; fom<f->n_foms; fom++ ) {
+
+ struct fom_context *fctx;
+
+ if ( !fom_selected(f, fom) ) continue;
+
+ fctx = dispatch_fom(all_refls, all_refls_anom,
+ part1, part2,
+ part1_anom, part2_anom,
+ cell, shells, sym,
+ f->fom_types[fom]);
+ if ( fctx == NULL ) {
+ ERROR("Failed to calculate FoM %i for dataset %s\n",
+ f->fom_types[fom], f->dataset_names[ds]);
+ continue;
+ }
+ show_fom(f->fom_types[fom], fctx, shells);
+ }
+
+ reflist_free(all_refls);
+ reflist_free(all_refls_anom);
+ free_symoplist(sym);
+
+ }
+
+}
+
+
+static GtkWidget *add_item(GtkWidget *menu,
+ const char *text,
+ const char *markup)
+{
+ GtkWidget *label;
+ GtkWidget *item;
+
+ item = gtk_check_menu_item_new();
+
+ label = gtk_label_new(text);
+ if ( markup != NULL ) {
+ gtk_label_set_markup(GTK_LABEL(label), markup);
+ }
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+
+ gtk_container_add(GTK_CONTAINER(item), label);
+ gtk_widget_show_all(item);
+
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+
+ return item;
+}
+
+
+static void add_separator(GtkWidget *menu)
+{
+ GtkWidget *item;
+ item = gtk_separator_menu_item_new();
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+ gtk_widget_show_all(item);
+}
+
+
+static GtkWidget *make_fom_menu(struct fom_window *fom)
+{
+ GtkWidget *menu;
+ GtkWidget *item;
+
+ menu = gtk_menu_new();
+
+ item = gtk_tearoff_menu_item_new();
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+ gtk_widget_show_all(item);
+
+ /* Order of FoMs must match list below */
+ fom->fom_checkboxes[0] = add_item(menu, "I/σ(I)", NULL);
+ fom->fom_checkboxes[1] = add_item(menu, "Completeness", NULL);
+ fom->fom_checkboxes[2] = add_item(menu, "Redundancy", NULL);
+ add_separator(menu);
+ fom->fom_checkboxes[3] = add_item(menu, "Rsplit", "R<sub>split</sub>");
+ fom->fom_checkboxes[4] = add_item(menu, "CC", "CC<sub>½</sub>");
+ fom->fom_checkboxes[5] = add_item(menu, "CC*", "CC<sup>*</sup>");
+ add_separator(menu);
+ fom->fom_checkboxes[6] = add_item(menu, "CCano", "CC<sub>ano</sub>");
+ fom->fom_checkboxes[7] = add_item(menu, "Rano", "R<sub>ano</sub>");
+ fom->fom_checkboxes[8] = add_item(menu, "Rano ÷ Rsplit",
+ "R<sub>ano</sub> ÷ R<sub>split</sub>");
+ fom->fom_checkboxes[9] = add_item(menu, "RMS anomalous correlation ratio", NULL);
+ add_separator(menu);
+ fom->fom_checkboxes[10] = add_item(menu, "Fraction of differences within 1σ(I)", NULL);
+ fom->fom_checkboxes[11] = add_item(menu, "Fraction of differences within 2σ(I)", NULL);
+
+ /* Order must match the list above */
+ fom->fom_types[0] = FOM_SNR;
+ fom->fom_types[1] = FOM_COMPLETENESS;
+ fom->fom_types[2] = FOM_REDUNDANCY;
+
+ fom->fom_types[3] = FOM_RSPLIT;
+ fom->fom_types[4] = FOM_CC;
+ fom->fom_types[5] = FOM_CCSTAR;
+
+ fom->fom_types[6] = FOM_CCANO;
+ fom->fom_types[7] = FOM_RANO;
+ fom->fom_types[8] = FOM_RANORSPLIT;
+ fom->fom_types[9] = FOM_CRDANO;
+
+ fom->fom_types[10] = FOM_D1SIG;
+ fom->fom_types[11] = FOM_D2SIG;
+
+ fom->n_foms = 12;
+
+ return menu;
+}
+
+
+static GtkWidget *make_dataset_menu(struct fom_window *win)
+{
+ GtkWidget *menu;
+ GtkWidget *item;
+ int i;
+
+ menu = gtk_menu_new();
+
+ item = gtk_tearoff_menu_item_new();
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+ gtk_widget_show_all(item);
+
+ for ( i=0; i<win->proj->n_merge_results; i++ ) {
+
+ const char *ds_name = win->proj->merge_results[i].name;
+
+ /* Yes, I'm lazy */
+ if ( i >= MAX_DATASETS ) {
+ ERROR("Too many datasets - ignoring %s\n", ds_name);
+ continue;
+ }
+
+ win->dataset_checkboxes[i] = add_item(menu, ds_name, NULL);
+ win->dataset_names[i] = strdup(ds_name);
+ win->n_datasets++;
+ }
+
+ return menu;
+}
+
+
+static void cell_file_clear_sig(GtkButton *buton,
+ struct fom_window *f)
+{
+ gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(f->cell_chooser),
+ "(none)");
+}
+
+
+gint fom_sig(GtkWidget *widget, struct crystfelproject *proj)
+{
+ GtkWidget *dialog;
+ GtkWidget *content_area;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ GtkWidget *button;
+ GtkWidget *da;
+ char tmp[64];
+ struct fom_window *f;
+
+ f = malloc(sizeof(struct fom_window));
+ if ( f == NULL ) return 0;
+
+ f->proj = proj;
+ f->n_datasets = 0;
+ f->n_foms = 0;
+
+ dialog = gtk_dialog_new_with_buttons("Calculate figures of merit",
+ GTK_WINDOW(proj->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ "Calculate", GTK_RESPONSE_APPLY,
+ "Close", GTK_RESPONSE_CLOSE,
+ NULL);
+
+ g_signal_connect(G_OBJECT(dialog), "response",
+ G_CALLBACK(fom_response_sig),
+ f);
+
+ vbox = gtk_vbox_new(FALSE, 0.0);
+ content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ gtk_container_add(GTK_CONTAINER(content_area), vbox);
+ gtk_container_set_border_width(GTK_CONTAINER(content_area), 8);
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("Results to show:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ button = gtk_menu_button_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button),
+ FALSE, FALSE, 4.0);
+ gtk_menu_button_set_popup(GTK_MENU_BUTTON(button),
+ make_dataset_menu(f));
+
+ label = gtk_label_new("Figures of merit to show:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ button = gtk_menu_button_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button),
+ FALSE, FALSE, 4.0);
+ gtk_menu_button_set_popup(GTK_MENU_BUTTON(button),
+ make_fom_menu(f));
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("Resolution range:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ f->min_res = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(f->min_res), 4);
+ snprintf(tmp, 64, "%.2f", proj->fom_res_min);
+ gtk_entry_set_text(GTK_ENTRY(f->min_res), tmp);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(f->min_res),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("to");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ f->max_res = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(f->max_res), 4);
+ snprintf(tmp, 64, "%.2f", proj->fom_res_max);
+ gtk_entry_set_text(GTK_ENTRY(f->max_res), tmp);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(f->max_res),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("Å. Number of bins:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ f->num_bins = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(f->num_bins), 4);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(f->num_bins),
+ FALSE, FALSE, 4.0);
+ snprintf(tmp, 64, "%i", proj->fom_nbins);
+ gtk_entry_set_text(GTK_ENTRY(f->num_bins), tmp);
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("Minimum I/sigI:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ f->min_snr = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(f->min_snr), 4);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(f->min_snr),
+ FALSE, FALSE, 4.0);
+ snprintf(tmp, 64, "%.2f", proj->fom_min_snr);
+ gtk_entry_set_text(GTK_ENTRY(f->min_snr), tmp);
+ label = gtk_label_new("Minimum measurements per reflection:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ f->min_meas = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(f->min_meas), 4);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(f->min_meas),
+ FALSE, FALSE, 4.0);
+ snprintf(tmp, 64, "%i", proj->fom_min_meas);
+ gtk_entry_set_text(GTK_ENTRY(f->min_meas), tmp);
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("Unit cell file:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ f->cell_chooser = gtk_file_chooser_button_new("Unit cell file",
+ GTK_FILE_CHOOSER_ACTION_OPEN);
+ gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(f->cell_chooser),
+ TRUE);
+ if ( proj->fom_cell_filename != NULL ) {
+ gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(f->cell_chooser),
+ proj->fom_cell_filename);
+ }
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(f->cell_chooser),
+ FALSE, FALSE, 4.0);
+ button = gtk_button_new_from_icon_name("edit-clear",
+ GTK_ICON_SIZE_BUTTON);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(cell_file_clear_sig), f);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(button),
+ FALSE, FALSE, 4.0);
+
+ da = gtk_drawing_area_new();
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(da),
+ FALSE, FALSE, 4.0);
+
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+ GTK_RESPONSE_CLOSE);
+ gtk_widget_show_all(dialog);
+
+ return FALSE;
+}
diff --git a/src/hdfsee.h b/src/gui_fom.h
index b09fff0a..903c2f1c 100644
--- a/src/hdfsee.h
+++ b/src/gui_fom.h
@@ -1,13 +1,13 @@
/*
- * hdfsee.c
+ * gui_fom.h
*
- * Quick yet non-crappy HDF viewer
+ * Figures of merit via CrystFEL GUI
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2009, 2011-2012 Thomas White <taw@physics.org>
+ * 2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -26,16 +26,14 @@
*
*/
+#ifndef GUI_FOM_H
+#define GUI_FOM_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifndef HDFSEE_H
-#define HDFSEE_H
+#include <gtk/gtk.h>
-#include "dw-hdfsee.h"
+#include "gui_project.h"
-extern void hdfsee_window_closed(DisplayWindow *dw);
+extern gint fom_sig(GtkWidget *widget,
+ struct crystfelproject *proj);
-#endif /* HDFSEE_H */
+#endif
diff --git a/src/gui_import.c b/src/gui_import.c
new file mode 100644
index 00000000..11d5f7f2
--- /dev/null
+++ b/src/gui_import.c
@@ -0,0 +1,608 @@
+/*
+ * gui_import.c
+ *
+ * Data import to GUI
+ *
+ * Copyright © 2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <assert.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <datatemplate.h>
+
+#include "crystfelimageview.h"
+#include "gui_project.h"
+#include "crystfel_gui.h"
+#include "gtk-util-routines.h"
+
+#include "version.h"
+
+static void add_all_events(struct crystfelproject *proj,
+ const char *filename,
+ const DataTemplate *dtempl)
+{
+ char **events;
+ int i;
+ int n_events;
+
+ events = image_expand_frames(dtempl, filename, &n_events);
+ if ( events == NULL ) {
+ ERROR("Couldn't expand event list\n");
+ return;
+ }
+
+ for ( i=0; i<n_events; i++ ) {
+ add_file_to_project(proj, filename, events[i]);
+ free(events[i]);
+ }
+ free(events);
+}
+
+
+static void add_files(struct crystfelproject *proj, GFile *folder,
+ enum match_type_id type,
+ const DataTemplate *dtempl)
+{
+ GFileEnumerator *fenum;
+ GFileInfo *finfo;
+ GError *error = NULL;
+
+ fenum = g_file_enumerate_children(folder, "standard::name,standard::type",
+ G_FILE_QUERY_INFO_NONE,
+ NULL, &error);
+
+ do {
+
+ GFile *file;
+
+ finfo = g_file_enumerator_next_file(fenum, NULL, &error);
+
+ if ( error != NULL ) {
+ STATUS("Error!\n");
+ g_object_unref(fenum);
+ return;
+ }
+
+ if ( finfo == NULL ) continue;
+
+ file = g_file_get_child(folder, g_file_info_get_name(finfo));
+
+ if ( g_file_info_get_file_type(finfo) == G_FILE_TYPE_DIRECTORY ) {
+
+ add_files(proj, file, type, dtempl);
+
+ } else {
+
+ char *bn = g_file_get_basename(file);
+ if ( match_filename(bn, type) ) {
+ add_all_events(proj, g_file_get_path(file),
+ dtempl);
+ }
+
+ }
+
+ g_object_unref(finfo);
+
+ } while ( finfo != NULL );
+
+ g_object_unref(fenum);
+}
+
+
+static void add_frames_from_stream(Stream *st,
+ DataTemplate *dtempl,
+ struct crystfelproject *proj)
+{
+ do {
+ struct image *image;
+ image = stream_read_chunk(st, 0);
+ if ( image == NULL ) break;
+ add_file_to_project(proj, image->filename, image->ev);
+ image_free(image);
+
+ } while ( 1 );
+}
+
+
+struct finddata_ctx
+{
+ struct crystfelproject *proj;
+
+ GtkWidget *replace_geom;
+ GtkWidget *geom_file;
+
+ /* "Select individual file" */
+ GtkWidget *indiv;
+ GtkWidget *indiv_chooser;
+
+ /* Read list of files */
+ GtkWidget *list; /* "Import list" radio */
+ GtkWidget *list_chooser;
+
+ /* Search for files */
+ GtkWidget *search;
+ GtkWidget *search_chooser;
+ GtkWidget *search_pattern;
+
+ /* Load stream */
+ GtkWidget *stream;
+ GtkWidget *stream_chooser;
+
+ GtkWidget *dump;
+ GtkWidget *dump_results;
+};
+
+enum import_mode
+{
+ IMPORT_FILES,
+ IMPORT_LIST,
+ IMPORT_SEARCH,
+ IMPORT_STREAM
+};
+
+
+static enum import_mode import_mode(struct finddata_ctx *ctx)
+{
+ if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctx->indiv))) {
+ return IMPORT_FILES;
+ } else if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctx->list))) {
+ return IMPORT_LIST;
+ } else if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctx->search))) {
+ return IMPORT_SEARCH;
+ } else {
+ return IMPORT_STREAM;
+ }
+}
+
+
+static void finddata_typetoggle_sig(GtkWidget *radio,
+ struct finddata_ctx *ctx)
+{
+ gtk_widget_set_sensitive(ctx->indiv_chooser, FALSE);
+ gtk_widget_set_sensitive(ctx->list_chooser, FALSE);
+ gtk_widget_set_sensitive(ctx->search_chooser, FALSE);
+ gtk_widget_set_sensitive(ctx->search_pattern, FALSE);
+ gtk_widget_set_sensitive(ctx->stream_chooser, FALSE);
+
+ gtk_widget_set_sensitive(ctx->geom_file, TRUE);
+
+ switch ( import_mode(ctx) ) {
+
+ case IMPORT_FILES :
+ gtk_widget_set_sensitive(ctx->indiv_chooser, TRUE);
+ break;
+
+ case IMPORT_LIST :
+ gtk_widget_set_sensitive(ctx->list_chooser, TRUE);
+ break;
+
+ case IMPORT_SEARCH :
+ gtk_widget_set_sensitive(ctx->search_chooser, TRUE);
+ gtk_widget_set_sensitive(ctx->search_pattern, TRUE);
+ break;
+
+ case IMPORT_STREAM :
+ gtk_widget_set_sensitive(ctx->geom_file, FALSE);
+ gtk_widget_set_sensitive(ctx->stream_chooser, TRUE);
+ break;
+ }
+}
+
+
+static void import_via_search(struct finddata_ctx *ctx)
+{
+ GFile *top;
+ const char *type_id;
+ struct crystfelproject *proj = ctx->proj;
+
+ top = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(ctx->search_chooser));
+ if ( top == NULL ) return;
+
+ type_id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(ctx->search_pattern));
+ proj->data_search_pattern = decode_matchtype(type_id);
+
+ g_free(proj->data_top_folder);
+ proj->data_top_folder = g_file_get_path(top);
+
+ add_files(proj, top, proj->data_search_pattern, proj->dtempl);
+
+ g_object_unref(top);
+}
+
+
+static void import_stream(struct finddata_ctx *ctx)
+{
+ struct crystfelproject *proj = ctx->proj;
+ Stream *st;
+ char *stream_filename;
+ DataTemplate *dtempl;
+ const char *geom_str;
+ char **streams;
+
+ stream_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(ctx->stream_chooser));
+ if ( stream_filename == NULL ) return;
+
+ st = stream_open_for_read(stream_filename);
+ if ( st == NULL ) return;
+
+ geom_str = stream_geometry_file(st);
+ if ( geom_str == NULL ) {
+ ERROR("No geometry file\n");
+ stream_close(st);
+ return;
+ }
+
+ dtempl = data_template_new_from_string(geom_str);
+ if ( dtempl == NULL ) {
+ stream_close(st);
+ return;
+ }
+
+ /* If we do not yet have a DataTemplate, the one from the file
+ * becomes it. If we already have one, it will be kept. Note that the
+ * stream's DataTemplate will always be used for display in the GUI. */
+ if ( proj->dtempl == NULL ) {
+ proj->dtempl = dtempl;
+ }
+
+ /* Use the user's nominated DataTemplate over the one from the stream.
+ * If it doesn't match, better that things break earlier. */
+ add_frames_from_stream(st, proj->dtempl, proj);
+ proj->stream_filename = stream_filename;
+ stream_close(st);
+
+ streams = malloc(sizeof(char *));
+ if ( streams != NULL ) {
+ char *result_name = safe_basename(stream_filename);
+ streams[0] = strdup(stream_filename);
+ add_indexing_result(proj, result_name, streams, 1);
+ select_result(proj, result_name);
+ }
+}
+
+
+static void import_file_list(struct finddata_ctx *ctx)
+{
+ struct crystfelproject *proj = ctx->proj;
+ char *list_filename;
+ FILE *fh;
+
+ list_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(ctx->list_chooser));
+ if ( list_filename == NULL ) return;
+
+ fh = fopen(list_filename, "r");
+ if ( fh == NULL ) return;
+
+ do {
+
+ char line[1024];
+ char *event = "//";
+ size_t n;
+
+ if ( fgets(line, 1024, fh) == NULL ) break;
+ chomp(line);
+
+ /* Chop off event ID */
+ n = strlen(line);
+ while ( line[n] != ' ' && n > 2 ) n--;
+ if ( n != 2 ) {
+ /* Event descriptor must contain "//".
+ * If it doesn't, assume the filename just contains a
+ * space. */
+ if ( strstr(&line[n], "//") != NULL ) {
+ line[n] = '\0';
+ event = &line[n+1];
+ }
+ } /* else no spaces at all */
+
+ if ( event != NULL ) {
+ /* Explicit event ID given */
+ add_file_to_project(proj, line, event);
+ } else {
+ /* No event ID - expand (possibly 1:1) */
+ add_all_events(proj, line, proj->dtempl);
+ }
+
+ } while ( 1 );
+
+ fclose(fh);
+}
+
+
+static void import_file(struct finddata_ctx *ctx)
+{
+ struct crystfelproject *proj = ctx->proj;
+ char *filename;
+
+ filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(ctx->indiv_chooser));
+ if ( filename == NULL ) return;
+
+ add_all_events(proj, filename, proj->dtempl);
+}
+
+
+static void finddata_response_sig(GtkWidget *dialog, gint resp,
+ struct finddata_ctx *ctx)
+{
+ struct crystfelproject *proj = ctx->proj;
+
+ if ( (resp == GTK_RESPONSE_DELETE_EVENT)
+ || (resp == GTK_RESPONSE_CANCEL) )
+ {
+ gtk_widget_destroy(dialog);
+ free(ctx);
+ return;
+ }
+
+ if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctx->dump)) ) {
+ clear_project_files(proj);
+ crystfel_image_view_set_image(CRYSTFEL_IMAGE_VIEW(proj->imageview),
+ NULL);
+
+ if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctx->dump_results)) ) {
+ clear_indexing_results(proj);
+ }
+ }
+
+ if ( import_mode(ctx) != IMPORT_STREAM ) {
+ if ( (ctx->replace_geom == NULL)
+ || (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctx->replace_geom))) )
+ {
+ gchar *geom_filename;
+
+ geom_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(ctx->geom_file));
+ if ( geom_filename == NULL ) {
+ error_box(proj, "Geometry file not found");
+ return;
+ }
+ g_free(proj->geom_filename);
+ proj->geom_filename = geom_filename;
+
+ data_template_free(proj->dtempl);
+ proj->dtempl = data_template_new_from_file(geom_filename);
+ if ( proj->dtempl == NULL ) {
+ error_box(proj, "Invalid geometry file");
+ return;
+ }
+ }
+ } /* else don't touch the geometry */
+
+ if ( (import_mode(ctx) != IMPORT_STREAM) && (proj->dtempl == NULL) ) {
+ error_box(proj, "You must specify the geometry file.");
+ return;
+ }
+
+ switch ( import_mode(ctx) ) {
+
+ case IMPORT_FILES :
+ import_file(ctx);
+ break;
+
+ case IMPORT_LIST :
+ import_file_list(ctx);
+ break;
+
+ case IMPORT_SEARCH :
+ import_via_search(ctx);
+ break;
+
+ case IMPORT_STREAM :
+ import_stream(ctx);
+ break;
+ }
+
+ proj->unsaved = 1;
+ proj->cur_frame = 0;
+ crystfel_image_view_reset_zoom(CRYSTFEL_IMAGE_VIEW(proj->imageview));
+ update_imageview(proj);
+
+ free(ctx);
+ gtk_widget_destroy(dialog);
+}
+
+
+gint import_sig(GtkWidget *widget, struct crystfelproject *proj)
+{
+ GtkWidget *dialog;
+ GtkWidget *content_area;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ struct finddata_ctx *ctx;
+
+ ctx = malloc(sizeof(struct finddata_ctx));
+ if ( ctx == NULL ) return FALSE;
+
+ ctx->proj = proj;
+
+ dialog = gtk_dialog_new_with_buttons("Import data",
+ GTK_WINDOW(proj->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ "Cancel", GTK_RESPONSE_CANCEL,
+ "Import", GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ vbox = gtk_vbox_new(FALSE, 0.0);
+ content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ gtk_container_add(GTK_CONTAINER(content_area), vbox);
+ gtk_container_set_border_width(GTK_CONTAINER(content_area), 8);
+
+ /* Select individual files */
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0);
+ ctx->indiv = gtk_radio_button_new_with_label(NULL,
+ "Select an individual file");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->indiv),
+ FALSE, FALSE, 4.0);
+ ctx->indiv_chooser = gtk_file_chooser_button_new("Select file",
+ GTK_FILE_CHOOSER_ACTION_OPEN);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->indiv_chooser),
+ FALSE, FALSE, 4.0);
+
+ /* Pre-prepared list of files */
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0);
+ ctx->list = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ctx->indiv),
+ "Read a list of files");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->list),
+ FALSE, FALSE, 4.0);
+ ctx->list_chooser = gtk_file_chooser_button_new("Select the list of filenames",
+ GTK_FILE_CHOOSER_ACTION_OPEN);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->list_chooser),
+ FALSE, FALSE, 4.0);
+
+ /* Search in folder */
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 2.0);
+ gtk_widget_set_margin_top(hbox, 6.0);
+ ctx->search = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ctx->indiv),
+ "Search for files in folder");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->search),
+ FALSE, FALSE, 4.0);
+ ctx->search_chooser = gtk_file_chooser_button_new("Select a folder",
+ GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+ if ( proj->data_top_folder != NULL ) {
+ gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(ctx->search_chooser),
+ proj->data_top_folder);
+ }
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->search_chooser),
+ TRUE, TRUE, 2.0);
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_widget_set_margin_bottom(hbox, 6.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 2.0);
+ label = gtk_label_new("Search pattern:");
+ gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
+ gtk_widget_set_margin_start(label, 32);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 2.0);
+ ctx->search_pattern = gtk_combo_box_text_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->search_pattern), TRUE, TRUE, 2.0);
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "everything",
+ "All files in folder and subfolders");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "hdf5",
+ "All HDF5 files ('*.h5')");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "lcls-cheetah-hdf5",
+ "Individual LCLS files from Cheetah ('LCLS*.h5')");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "cheetah-cxi",
+ "Multi-event CXI files from Cheetah ('*.cxi')");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "cbf",
+ "Individual CBF files ('*.cbf')");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(ctx->search_pattern), "cbfgz",
+ "Individual gzipped CBF files ('*.cbf.gz')");
+ gtk_combo_box_set_active(GTK_COMBO_BOX(ctx->search_pattern),
+ proj->data_search_pattern);
+
+ /* Load a stream */
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0);
+ ctx->stream = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(ctx->indiv),
+ "Load stream");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->stream),
+ FALSE, FALSE, 4.0);
+ ctx->stream_chooser = gtk_file_chooser_button_new("Select stream file",
+ GTK_FILE_CHOOSER_ACTION_OPEN);
+ if ( proj->stream_filename != NULL ) {
+ gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(ctx->stream_chooser),
+ proj->stream_filename);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ctx->stream), TRUE);
+ }
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->stream_chooser),
+ TRUE, TRUE, 2.0);
+
+ /* Stuff at bottom */
+ gtk_box_pack_start(GTK_BOX(vbox),
+ gtk_separator_new(GTK_ORIENTATION_HORIZONTAL),
+ FALSE, FALSE, 4.0);
+
+ /* Geometry file */
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0);
+
+ ctx->geom_file = gtk_file_chooser_button_new("Select geometry file",
+ GTK_FILE_CHOOSER_ACTION_OPEN);
+ if ( proj->geom_filename != NULL ) {
+ gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(ctx->geom_file),
+ proj->geom_filename);
+ }
+ if ( proj->dtempl == NULL ) {
+ label = gtk_label_new("Geometry file:");
+ gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ ctx->replace_geom = NULL;
+ } else {
+ ctx->replace_geom = gtk_check_button_new_with_label("Replace geometry file:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->replace_geom),
+ FALSE, FALSE, 4.0);
+ g_signal_connect(G_OBJECT(ctx->replace_geom), "toggled",
+ G_CALLBACK(i_maybe_disable), ctx->geom_file);
+ gtk_widget_set_sensitive(ctx->geom_file, FALSE);
+ }
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->geom_file), TRUE, TRUE, 2.0);
+
+ /* Replace data toggle */
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0);
+ ctx->dump = gtk_check_button_new_with_label("Replace all the current data");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->dump),
+ FALSE, FALSE, 4.0);
+ ctx->dump_results = gtk_check_button_new_with_label("Forget about indexing results");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(ctx->dump_results),
+ FALSE, FALSE, 4.0);
+ g_signal_connect(G_OBJECT(ctx->dump), "toggled",
+ G_CALLBACK(i_maybe_disable_and_deselect),
+ ctx->dump_results);
+ gtk_widget_set_sensitive(ctx->dump_results, FALSE);
+
+ g_signal_connect(ctx->indiv, "toggled",
+ G_CALLBACK(finddata_typetoggle_sig), ctx);
+ g_signal_connect(ctx->list, "toggled",
+ G_CALLBACK(finddata_typetoggle_sig), ctx);
+ g_signal_connect(ctx->search, "toggled",
+ G_CALLBACK(finddata_typetoggle_sig), ctx);
+ g_signal_connect(ctx->stream, "toggled",
+ G_CALLBACK(finddata_typetoggle_sig), ctx);
+
+ g_signal_connect(dialog, "response",
+ G_CALLBACK(finddata_response_sig), ctx);
+
+ gtk_window_set_default_size(GTK_WINDOW(dialog), 512, 0);
+ finddata_typetoggle_sig(ctx->search, ctx);
+ gtk_widget_show_all(dialog);
+ return FALSE;
+}
+
+
diff --git a/src/gui_import.h b/src/gui_import.h
new file mode 100644
index 00000000..6d25a32e
--- /dev/null
+++ b/src/gui_import.h
@@ -0,0 +1,38 @@
+/*
+ * gui_import.h
+ *
+ * Data import to GUI
+ *
+ * Copyright © 2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GUI_IMPORT_H
+#define GUI_IMPORT_H
+
+#include <gtk/gtk.h>
+
+#include "gui_project.h"
+
+extern gint import_sig(GtkWidget *widget, struct crystfelproject *proj);
+
+#endif
diff --git a/src/gui_index.c b/src/gui_index.c
new file mode 100644
index 00000000..4b7254de
--- /dev/null
+++ b/src/gui_index.c
@@ -0,0 +1,876 @@
+/*
+ * gui_index.c
+ *
+ * Peak search parts of GUI
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms-compat.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <datatemplate.h>
+#include <peaks.h>
+#include <cell.h>
+#include <cell-utils.h>
+#include <integration.h>
+#include <predict-refine.h>
+
+#include "crystfelimageview.h"
+#include "crystfelindexingopts.h"
+#include "gui_project.h"
+#include "crystfel_gui.h"
+#include "gui_peaksearch.h"
+#include "gtk-util-routines.h"
+
+
+void cell_explorer_sig(GtkWidget *widget, struct crystfelproject *proj)
+{
+ GSubprocess *sp;
+ GError *error = NULL;
+ const gchar *results_name;
+ struct gui_indexing_result *res;
+ const gchar **streams;
+ int i;
+
+ results_name = gtk_combo_box_get_active_id(GTK_COMBO_BOX(proj->results_combo));
+ if ( strcmp(results_name, "crystfel-gui-internal") == 0 ) {
+ STATUS("Please select results first.\n");
+ return;
+ }
+
+ res = find_indexing_result_by_name(proj, results_name);
+ if ( res == NULL ) {
+ ERROR("Results for '%s' not found!\n", results_name);
+ return;
+ }
+
+ streams = malloc((res->n_streams+2)*sizeof(gchar *));
+ if ( streams == NULL ) return;
+
+ streams[0] = get_crystfel_exe("cell_explorer");
+ for ( i=0; i<res->n_streams; i++ ) {
+ streams[i+1] = res->streams[i];
+ }
+ streams[res->n_streams+1] = NULL;
+
+ sp = g_subprocess_newv(streams, G_SUBPROCESS_FLAGS_NONE,
+ &error);
+ free(streams);
+ if ( sp == NULL ) {
+ ERROR("Failed to start cell_explorer: %s\n",
+ error->message);
+ g_error_free(error);
+ return;
+ }
+
+ STATUS("Starting cell_explorer...\n");
+}
+
+
+static void get_indexing_opts(struct crystfelproject *proj,
+ CrystFELIndexingOpts *opts)
+{
+ /* Indexing */
+ proj->indexing_params.cell_file = crystfel_indexing_opts_get_cell_file(opts);
+ proj->indexing_params.indexing_methods = crystfel_indexing_opts_get_indexing_method_string(opts);
+ proj->indexing_params.multi = crystfel_indexing_opts_get_multi_lattice(opts);
+ proj->indexing_params.no_refine = !crystfel_indexing_opts_get_refine(opts);
+ proj->indexing_params.no_retry = !crystfel_indexing_opts_get_retry(opts);
+ proj->indexing_params.no_peak_check = !crystfel_indexing_opts_get_peak_check(opts);
+ proj->indexing_params.no_cell_check = !crystfel_indexing_opts_get_cell_check(opts);
+ proj->indexing_params.min_peaks = crystfel_indexing_opts_get_min_peaks(opts);
+
+ /* Integration */
+ proj->indexing_params.integration_method = crystfel_indexing_opts_get_integration_method_string(opts);
+ proj->indexing_params.overpredict = crystfel_indexing_opts_get_overpredict(opts);
+ proj->indexing_params.push_res = crystfel_indexing_opts_get_push_res(opts);
+ crystfel_indexing_opts_get_integration_radii(opts,
+ &proj->indexing_params.ir_inn,
+ &proj->indexing_params.ir_mid,
+ &proj->indexing_params.ir_out);
+
+ /* Stream output */
+ proj->indexing_params.exclude_nonhits = crystfel_indexing_opts_get_exclude_blanks(opts);
+ proj->indexing_params.exclude_peaks = crystfel_indexing_opts_get_exclude_peaks(opts);
+ proj->indexing_params.exclude_refls = crystfel_indexing_opts_get_exclude_reflections(opts);
+ proj->indexing_params.metadata_to_copy = crystfel_indexing_opts_get_metadata_to_copy(opts,
+ &proj->indexing_params.n_metadata);
+}
+
+
+static int run_indexing_all(struct crystfelproject *proj,
+ int backend_idx, const char *job_title,
+ const char *job_notes)
+{
+ struct crystfel_backend *be;
+ void *job_priv;
+
+ be = &proj->backends[backend_idx];
+ job_priv = be->run_indexing(job_title, job_notes, proj,
+ be->indexing_opts_priv);
+
+ if ( job_priv != NULL ) {
+ char name[256];
+ snprintf(name, 255, "Indexing all frames (%s)",
+ job_title);
+ add_running_task(proj, name, be, job_priv);
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+
+struct new_index_job_params {
+ struct crystfelproject *proj;
+ struct gui_job_notes_page *notes_page;
+ GtkWidget *indexing_backend_combo;
+ GtkWidget *indexing_backend_opts_widget;
+ GtkWidget *indexing_backend_opts_box;
+ GtkWidget *job_title_entry;
+};
+
+
+static void index_all_response_sig(GtkWidget *dialog, gint resp,
+ struct new_index_job_params *njp)
+{
+ if ( resp == GTK_RESPONSE_OK ) {
+
+ int backend_idx;
+ const char *job_title;
+ char *job_notes;
+
+ get_indexing_opts(njp->proj,
+ CRYSTFEL_INDEXING_OPTS(njp->proj->indexing_opts));
+
+ backend_idx = gtk_combo_box_get_active(GTK_COMBO_BOX(njp->indexing_backend_combo));
+ if ( backend_idx < 0 ) return;
+
+ job_title = gtk_entry_get_text(GTK_ENTRY(njp->job_title_entry));
+ job_notes = get_all_text(GTK_TEXT_VIEW(njp->notes_page->textview));
+
+ if ( job_title[0] == '\0' ) {
+ ERROR("You must provide a job name.\n");
+ return;
+ }
+
+ free(njp->proj->indexing_new_job_title);
+ njp->proj->indexing_new_job_title = strdup(job_title);
+
+ if ( run_indexing_all(njp->proj, backend_idx,
+ job_title, job_notes) == 0 )
+ {
+ gtk_widget_destroy(dialog);
+ njp->proj->indexing_opts = NULL;
+ }
+
+ free(job_notes);
+
+ } else {
+ gtk_widget_destroy(dialog);
+ njp->proj->indexing_opts = NULL;
+ }
+}
+
+
+static void indexing_backend_changed_sig(GtkWidget *combo,
+ struct new_index_job_params *njp)
+{
+ int backend_idx;
+ struct crystfel_backend *be;
+
+ backend_idx = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
+ if ( backend_idx < 0 ) return;
+ njp->proj->indexing_backend_selected = backend_idx;
+
+ be = &njp->proj->backends[backend_idx];
+
+ if ( njp->indexing_backend_opts_widget != NULL ) {
+ gtk_widget_destroy(njp->indexing_backend_opts_widget);
+ }
+
+ njp->indexing_backend_opts_widget = be->make_indexing_parameters_widget(be->indexing_opts_priv);
+
+ gtk_box_pack_start(GTK_BOX(njp->indexing_backend_opts_box),
+ GTK_WIDGET(njp->indexing_backend_opts_widget),
+ FALSE, FALSE, 0);
+ gtk_widget_show_all(njp->indexing_backend_opts_widget);
+}
+
+
+static GtkWidget *make_backend_opts(struct new_index_job_params *njp)
+{
+ GtkWidget *box;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ int i;
+
+ box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+ gtk_container_set_border_width(GTK_CONTAINER(box), 8);
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ label = gtk_label_new("Batch system:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+
+ njp->indexing_backend_combo = gtk_combo_box_text_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(njp->indexing_backend_combo),
+ FALSE, FALSE, 0);
+
+ for ( i=0; i<njp->proj->n_backends; i++ ) {
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(njp->indexing_backend_combo),
+ njp->proj->backends[i].name,
+ njp->proj->backends[i].friendly_name);
+ }
+
+ njp->indexing_backend_opts_box = gtk_box_new(GTK_ORIENTATION_VERTICAL,
+ 0);
+ gtk_box_pack_start(GTK_BOX(box),
+ GTK_WIDGET(njp->indexing_backend_opts_box),
+ FALSE, FALSE, 0);
+ njp->indexing_backend_opts_widget = NULL;
+
+ /* njp->indexing_backend_opts{_box} must exist before the following */
+ g_signal_connect(G_OBJECT(njp->indexing_backend_combo), "changed",
+ G_CALLBACK(indexing_backend_changed_sig), njp);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(njp->indexing_backend_combo),
+ njp->proj->indexing_backend_selected);
+
+ return box;
+}
+
+
+static void set_indexing_opts(struct crystfelproject *proj,
+ CrystFELIndexingOpts *opts)
+{
+ /* Indexing */
+ crystfel_indexing_opts_set_cell_file(opts, proj->indexing_params.cell_file);
+ crystfel_indexing_opts_set_indexing_method_string(opts, proj->indexing_params.indexing_methods);
+ crystfel_indexing_opts_set_multi_lattice(opts, proj->indexing_params.multi);
+ crystfel_indexing_opts_set_refine(opts, !proj->indexing_params.no_refine);
+ crystfel_indexing_opts_set_retry(opts, !proj->indexing_params.no_retry);
+ crystfel_indexing_opts_set_peak_check(opts, !proj->indexing_params.no_peak_check);
+ crystfel_indexing_opts_set_cell_check(opts, !proj->indexing_params.no_cell_check);
+ crystfel_indexing_opts_set_tolerances(opts, proj->indexing_params.tols);
+ crystfel_indexing_opts_set_min_peaks(opts, proj->indexing_params.min_peaks);
+
+ /* Integration */
+ crystfel_indexing_opts_set_integration_method_string(opts, proj->indexing_params.integration_method);
+ crystfel_indexing_opts_set_overpredict(opts, proj->indexing_params.overpredict);
+ crystfel_indexing_opts_set_push_res(opts, proj->indexing_params.push_res);
+ crystfel_indexing_opts_set_integration_radii(opts,
+ proj->indexing_params.ir_inn,
+ proj->indexing_params.ir_mid,
+ proj->indexing_params.ir_out);
+
+ /* Stream output */
+ crystfel_indexing_opts_set_exclude_blanks(opts,
+ proj->indexing_params.exclude_nonhits);
+ crystfel_indexing_opts_set_exclude_peaks(opts,
+ proj->indexing_params.exclude_peaks);
+ crystfel_indexing_opts_set_exclude_reflections(opts,
+ proj->indexing_params.exclude_refls);
+ crystfel_indexing_opts_set_metadata_to_copy(opts,
+ proj->indexing_params.metadata_to_copy,
+ proj->indexing_params.n_metadata);
+}
+
+
+static void free_new_index_job_params(gpointer njp, GClosure *closure)
+{
+ free(njp);
+}
+
+
+gint index_all_sig(GtkWidget *widget, struct crystfelproject *proj)
+{
+ GtkWidget *dialog;
+ GtkWidget *content_area;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ GtkWidget *backend_page;
+ char *new_title;
+ struct new_index_job_params *njp;
+
+ if ( proj->indexing_opts != NULL ) return FALSE;
+
+ njp = malloc(sizeof(struct new_index_job_params));
+ if ( njp == NULL ) return FALSE;
+
+ njp->proj = proj;
+
+ dialog = gtk_dialog_new_with_buttons("Index all frames",
+ GTK_WINDOW(proj->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ "Cancel", GTK_RESPONSE_CANCEL,
+ "Run", GTK_RESPONSE_OK,
+ NULL);
+
+ g_signal_connect_data(G_OBJECT(dialog), "response",
+ G_CALLBACK(index_all_response_sig),
+ njp, free_new_index_job_params, 0);
+
+ vbox = gtk_vbox_new(FALSE, 0.0);
+ content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ gtk_container_add(GTK_CONTAINER(content_area), vbox);
+ gtk_container_set_border_width(GTK_CONTAINER(content_area), 8);
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 4.0);
+ label = gtk_label_new("Job/output name:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ njp->job_title_entry = gtk_entry_new();
+ gtk_entry_set_width_chars(GTK_ENTRY(njp->job_title_entry), 16);
+ gtk_entry_set_placeholder_text(GTK_ENTRY(njp->job_title_entry),
+ "indexing-trial-1");
+ new_title = make_new_job_title(proj->indexing_new_job_title);
+ if ( new_title != NULL ) {
+ gtk_entry_set_text(GTK_ENTRY(njp->job_title_entry), new_title);
+ free(new_title);
+ }
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(njp->job_title_entry),
+ TRUE, TRUE, 4.0);
+
+ proj->indexing_opts = crystfel_indexing_opts_new();
+ crystfel_indexing_opts_set_show_stream_opts(CRYSTFEL_INDEXING_OPTS(proj->indexing_opts),
+ TRUE);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(proj->indexing_opts),
+ FALSE, FALSE, 8.0);
+ set_indexing_opts(proj,
+ CRYSTFEL_INDEXING_OPTS(proj->indexing_opts));
+
+ backend_page = make_backend_opts(njp);
+ gtk_notebook_append_page(GTK_NOTEBOOK(proj->indexing_opts),
+ backend_page,
+ gtk_label_new("Cluster/batch system"));
+
+ njp->notes_page = add_job_notes_page(proj->indexing_opts);
+
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+ GTK_RESPONSE_OK);
+ gtk_widget_show_all(dialog);
+
+ return FALSE;
+}
+
+
+static IndexingFlags indexing_flags(struct index_params *params)
+{
+ IndexingFlags fl = 0;
+
+ if ( !params->no_retry ) fl |= INDEXING_RETRY;
+ if ( params->multi ) fl |= INDEXING_MULTI;
+ if ( !params->no_refine ) fl |= INDEXING_REFINE;
+ if ( !params->no_peak_check ) fl |= INDEXING_CHECK_PEAKS;
+ if ( !params->no_cell_check ) fl |= INDEXING_CHECK_CELL;
+
+ return fl;
+}
+
+
+static char *enter_gui_tempdir()
+{
+ char *tmpdir;
+ struct stat s;
+
+ tmpdir = malloc(64);
+ if ( tmpdir == NULL ) {
+ ERROR("Failed to allocate temporary directory name\n");
+ return NULL;
+ }
+ snprintf(tmpdir, 63, "crystfel-gui.%i", getpid());
+
+ if ( stat(tmpdir, &s) == -1 ) {
+
+ int r;
+
+ if ( errno != ENOENT ) {
+ ERROR("Failed to stat temporary folder.\n");
+ return NULL;
+ }
+
+ r = mkdir(tmpdir, S_IRWXU);
+ if ( r ) {
+ ERROR("Failed to create temporary folder: %s\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ }
+
+ return tmpdir;
+}
+
+
+static void delete_gui_tempdir(char *tmpdir)
+{
+ char *path;
+ int i;
+
+ /* List of files which it's safe to delete */
+ char *files[] = {"gmon.out", "mosflm.lp", "SUMMARY", "XDS.INP",
+ "xfel_001.img", "xfel_001.spt", "xfel.drx",
+ "xfel.felix", "xfel.gve", "xfel.ini", "xfel.log",
+ "IDXREF.LP", "SPOT.XDS", "xfel.newmat", "XPARM.XDS"};
+
+ /* Number of items in the above list */
+ int n_files = 15;
+
+ if ( tmpdir == NULL ) return;
+
+ path = calloc(strlen(tmpdir)+64, 1);
+ if ( path == NULL ) return;
+
+ for ( i=0; i<n_files; i++ ) {
+ snprintf(path, 127, "%s/%s", tmpdir, files[i]);
+ unlink(path);
+ }
+
+ if ( rmdir(tmpdir) ) {
+ ERROR("Failed to delete GUI temporary folder: %s\n",
+ strerror(errno));
+ }
+
+ free(tmpdir);
+}
+
+
+static void run_indexing_once(struct crystfelproject *proj)
+{
+ IndexingPrivate *ipriv;
+ UnitCell *cell;
+ IntegrationMethod int_method;
+ char *methods;
+ int i;
+ int err;
+ TakeTwoOptions *taketwoopts;
+ XGandalfOptions *xgandalf_opts;
+ PinkIndexerOptions *pinkIndexer_opts;
+ FelixOptions *felix_opts;
+ char *old_cwd;
+ char *tmpdir;
+ int r;
+
+ if ( proj->indexing_params.cell_file != NULL ) {
+ cell = load_cell_from_file(proj->indexing_params.cell_file);
+ } else {
+ cell = NULL;
+ }
+
+ update_peaks(proj);
+
+ old_cwd = getcwd(NULL, 0);
+ tmpdir = enter_gui_tempdir();
+
+ if ( proj->indexing_params.indexing_methods == NULL ) {
+ methods = detect_indexing_methods(cell);
+ STATUS("Auto-detected indexng methods: %s\n",
+ methods);
+ } else {
+ methods = strdup(proj->indexing_params.indexing_methods);
+ }
+
+ /* Get default options for the indexing methods.
+ * The GUI currently does not allow them to be changed */
+ default_method_options(&taketwoopts,
+ &xgandalf_opts,
+ &pinkIndexer_opts,
+ &felix_opts);
+
+ ipriv = setup_indexing(methods, cell,
+ proj->indexing_params.tols,
+ indexing_flags(&proj->indexing_params),
+ proj->cur_image->lambda, 1,
+ taketwoopts, xgandalf_opts,
+ pinkIndexer_opts, felix_opts);
+ free(methods);
+
+ index_pattern(proj->cur_image, ipriv);
+
+ for ( i=0; i<proj->cur_image->n_crystals; i++ ) {
+ crystal_set_profile_radius(proj->cur_image->crystals[i], 0.02e9);
+ crystal_set_mosaicity(proj->cur_image->crystals[i], 0.0);
+ if ( refine_radius(proj->cur_image->crystals[i],
+ proj->cur_image) )
+ {
+ ERROR("WARNING: Radius determination failed\n");
+ }
+ }
+
+ r = chdir(old_cwd);
+ if ( r ) {
+ ERROR("Failed to chdir: %s\n", strerror(errno));
+ return;
+ }
+ free(old_cwd);
+ delete_gui_tempdir(tmpdir);
+
+ err = 0;
+ int_method = integration_method(proj->indexing_params.integration_method,
+ &err);
+
+ integrate_all_5(proj->cur_image, int_method, PMODEL_XSPHERE,
+ proj->indexing_params.push_res,
+ proj->indexing_params.ir_inn,
+ proj->indexing_params.ir_mid,
+ proj->indexing_params.ir_out,
+ INTDIAG_NONE, 0, 0, 0, NULL,
+ proj->indexing_params.overpredict);
+
+ cleanup_indexing(ipriv);
+
+ STATUS("Number of crystals: %i\n",
+ proj->cur_image->n_crystals);
+ for ( i=0; i<proj->cur_image->n_crystals; i++ ) {
+ cell_print(crystal_get_cell(proj->cur_image->crystals[i]));
+ }
+
+}
+
+
+static void index_one_response_sig(GtkWidget *dialog, gint resp,
+ struct crystfelproject *proj)
+{
+
+ if ( resp == GTK_RESPONSE_OK ) {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(proj->results_combo),
+ 0);
+ get_indexing_opts(proj,
+ CRYSTFEL_INDEXING_OPTS(proj->indexing_opts));
+ run_indexing_once(proj);
+
+ crystfel_image_view_set_refl_box_size(CRYSTFEL_IMAGE_VIEW(proj->imageview),
+ proj->indexing_params.ir_inn);
+ force_refls_on(proj);
+ redraw_widget(proj->imageview);
+ }
+
+ gtk_widget_destroy(dialog);
+ proj->indexing_opts = NULL;
+}
+
+
+gint index_one_sig(GtkWidget *widget, struct crystfelproject *proj)
+{
+ GtkWidget *dialog;
+ GtkWidget *content_area;
+ GtkWidget *vbox;
+
+ if ( proj->indexing_opts != NULL ) return FALSE;
+
+ dialog = gtk_dialog_new_with_buttons("Index one frame",
+ GTK_WINDOW(proj->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ "Cancel", GTK_RESPONSE_CANCEL,
+ "Run", GTK_RESPONSE_OK,
+ NULL);
+
+ g_signal_connect(G_OBJECT(dialog), "response",
+ G_CALLBACK(index_one_response_sig), proj);
+
+ vbox = gtk_vbox_new(FALSE, 0.0);
+ content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ gtk_container_add(GTK_CONTAINER(content_area), vbox);
+ gtk_container_set_border_width(GTK_CONTAINER(content_area), 8);
+
+ proj->indexing_opts = crystfel_indexing_opts_new();
+ gtk_box_pack_start(GTK_BOX(vbox),
+ GTK_WIDGET(proj->indexing_opts),
+ FALSE, FALSE, 8.0);
+ set_indexing_opts(proj,
+ CRYSTFEL_INDEXING_OPTS(proj->indexing_opts));
+
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+ GTK_RESPONSE_OK);
+ gtk_widget_show_all(dialog);
+ crystfel_indexing_opts_set_show_stream_opts(CRYSTFEL_INDEXING_OPTS(proj->indexing_opts),
+ FALSE);
+ return FALSE;
+}
+
+
+static void add_arg(char **args, int pos, const char *label)
+{
+ args[pos] = strdup(label);
+}
+
+
+static void add_arg_float(char **args, int pos, const char *label,
+ float val)
+{
+ char *str = malloc(64);
+ if ( str == NULL ) return;
+ snprintf(str, 63, "--%s=%f", label, val);
+ args[pos] = str;
+}
+
+
+static void add_arg_int(char **args, int pos, const char *label,
+ int val)
+{
+ char *str = malloc(64);
+ if ( str == NULL ) return;
+ snprintf(str, 63, "--%s=%i", label, val);
+ args[pos] = str;
+}
+
+
+static void add_arg_string(char **args, int pos, const char *label,
+ const char *val)
+{
+ size_t len;
+ char *str;
+
+ len = strlen(label)+strlen(val)+4;
+ str = malloc(len);
+ if ( str == NULL ) return;
+ snprintf(str, 63, "--%s=%s", label, val);
+ args[pos] = str;
+}
+
+
+static char **indexamajig_command_line(const char *geom_filename,
+ const char *n_thread_str,
+ const char *files_list,
+ const char *stream_filename,
+ const char *serial_start,
+ struct peak_params *peak_search_params,
+ struct index_params *indexing_params)
+{
+ char **args;
+ char tols[2048];
+ char *indexamajig_path;
+ int i;
+ int n_args = 0;
+
+ args = malloc(64*sizeof(char *));
+ if ( args == NULL ) return NULL;
+
+ indexamajig_path = get_crystfel_exe("indexamajig");
+ if ( indexamajig_path == NULL ) return NULL;
+
+ /* The basics */
+ add_arg(args, n_args++, indexamajig_path);
+ add_arg(args, n_args++, "-i");
+ add_arg(args, n_args++, files_list);
+ if ( geom_filename != NULL ) {
+ add_arg(args, n_args++, "-g");
+ add_arg(args, n_args++, geom_filename);
+ }
+ add_arg(args, n_args++, "-o");
+ add_arg(args, n_args++, stream_filename);
+ add_arg(args, n_args++, "-j");
+ add_arg(args, n_args++, n_thread_str);
+
+ /* Peak search */
+ add_arg(args, n_args++, "--peaks");
+ add_arg(args, n_args++, str_peaksearch(peak_search_params->method));
+
+ if ( peak_search_params->method == PEAK_ZAEF ) {
+ add_arg_float(args, n_args++, "threshold",
+ peak_search_params->threshold);
+ add_arg_float(args, n_args++, "min-squared-gradient",
+ peak_search_params->min_sq_gradient);
+ add_arg_float(args, n_args++, "min-snr",
+ peak_search_params->min_snr);
+
+ } else if ( peak_search_params->method == PEAK_PEAKFINDER8 ) {
+ add_arg_float(args, n_args++, "threshold",
+ peak_search_params->threshold);
+ add_arg_float(args, n_args++, "min-snr",
+ peak_search_params->min_snr);
+ add_arg_int(args, n_args++, "min-pix-count",
+ peak_search_params->min_pix_count);
+ add_arg_int(args, n_args++, "max-pix-count",
+ peak_search_params->max_pix_count);
+ add_arg_int(args, n_args++, "local-bg-radius",
+ peak_search_params->local_bg_radius);
+ add_arg_int(args, n_args++, "min-res",
+ peak_search_params->min_res);
+ add_arg_int(args, n_args++, "max-res",
+ peak_search_params->max_res);
+ }
+ snprintf(tols, 2048, "--peak-radius=%.1f,%.1f,%.1f",
+ peak_search_params->pk_inn,
+ peak_search_params->pk_mid,
+ peak_search_params->pk_out);
+ add_arg(args, n_args++, tols);
+
+ if ( indexing_params->min_peaks > 0 ) {
+ add_arg_int(args, n_args++, "min-peaks",
+ indexing_params->min_peaks);
+ }
+
+ /* Indexing */
+ if ( indexing_params->indexing_methods != NULL ) {
+ add_arg(args, n_args++, "--indexing");
+ add_arg(args, n_args++, indexing_params->indexing_methods);
+ }
+ if ( indexing_params->cell_file != NULL ) {
+ add_arg(args, n_args++, "-p");
+ add_arg(args, n_args++, indexing_params->cell_file);
+ }
+ /* indexing_params->tols is in frac (not %) and radians.
+ * Indexamajig command line wants percent and degrees */
+ snprintf(tols, 2048, "--tolerance=%f,%f,%f,%f,%f,%f",
+ indexing_params->tols[0]*100.0,
+ indexing_params->tols[1]*100.0,
+ indexing_params->tols[2]*100.0,
+ rad2deg(indexing_params->tols[3]),
+ rad2deg(indexing_params->tols[4]),
+ rad2deg(indexing_params->tols[5]));
+ add_arg(args, n_args++, tols);
+ if ( indexing_params->multi ) add_arg(args, n_args++, "--multi");
+ if ( indexing_params->no_refine ) add_arg(args, n_args++, "--no-refine");
+ if ( indexing_params->no_retry ) add_arg(args, n_args++, "--no-retry");
+ if ( indexing_params->no_peak_check ) add_arg(args, n_args++, "--no-check-peaks");
+ if ( indexing_params->no_cell_check ) add_arg(args, n_args++, "--no-check-cell");
+
+ /* Integration */
+ add_arg(args, n_args++, "--integration");
+ add_arg(args, n_args++, indexing_params->integration_method);
+ if ( indexing_params->overpredict ) add_arg(args, n_args++, "--overpredict");
+ if ( !isinf(indexing_params->push_res) ) {
+ add_arg_float(args, n_args++, "push-res",
+ indexing_params->push_res);
+ }
+ snprintf(tols, 2048, "--int-radius=%.1f,%.1f,%.1f",
+ indexing_params->ir_inn,
+ indexing_params->ir_mid,
+ indexing_params->ir_out);
+ add_arg(args, n_args++, tols);
+
+ /* Stream output */
+ if ( indexing_params->exclude_nonhits ) add_arg(args, n_args++, "--no-non-hits-in-stream");
+ if ( indexing_params->exclude_peaks ) add_arg(args, n_args++, "--no-peaks-in-stream");
+ if ( indexing_params->exclude_refls ) add_arg(args, n_args++, "--no-refls-in-stream");
+ for ( i=0; i<indexing_params->n_metadata; i++ ) {
+ add_arg_string(args, n_args++, "copy-header",
+ indexing_params->metadata_to_copy[i]);
+ }
+
+ if ( serial_start != NULL ) {
+ add_arg_string(args, n_args++, "serial-start", serial_start);
+ }
+
+ args[n_args] = NULL;
+ return args;
+}
+
+
+int read_number_processed(const char *filename)
+{
+ FILE *fh = fopen(filename, "r");
+ int n_proc = 0;
+
+ /* Normal situation if SLURM job hasn't started yet */
+ if ( fh == NULL ) return 0;
+
+ /* Only look at the last part of the file */
+ fseek(fh, -4096, SEEK_END);
+
+ do {
+ char line[1024];
+ if ( fgets(line, 1024, fh) == NULL ) break;
+
+ if ( strncmp(line, "Final: ", 7) == 0 ) {
+ int i;
+ if ( sscanf(line, "Final: %i images processed", &i) == 1 ) {
+ n_proc = i;
+ }
+ } else if ( strstr(line, " images processed, ") != NULL ) {
+ int i;
+ if ( sscanf(line, "%i ", &i) == 1 ) {
+ n_proc = i;
+ }
+ }
+
+ } while ( 1 );
+
+ fclose(fh);
+
+ return n_proc;
+}
+
+
+int write_indexamajig_script(const char *script_filename,
+ const char *geom_filename,
+ const char *n_thread_str,
+ const char *files_list,
+ const char *stream_filename,
+ const char *serial_start,
+ int redirect_output,
+ struct peak_params *peak_search_params,
+ struct index_params *indexing_params)
+{
+ FILE *fh;
+ int i;
+ char **cmdline;
+
+ cmdline = indexamajig_command_line(geom_filename,
+ n_thread_str,
+ files_list,
+ stream_filename,
+ serial_start,
+ peak_search_params,
+ indexing_params);
+ if ( cmdline == NULL ) return 1;
+
+ fh = fopen(script_filename, "w");
+ if ( fh == NULL ) return 1;
+
+ fprintf(fh, "#!/bin/sh\n");
+
+ i = 0;
+ while ( cmdline[i] != NULL ) {
+ fprintf(fh, "%s ", cmdline[i]);
+ free(cmdline[i]);
+ i++;
+ };
+ free(cmdline);
+ if ( redirect_output ) {
+ fprintf(fh, ">stdout.log 2>stderr.log\n");
+ }
+
+ fclose(fh);
+ return 0;
+}
diff --git a/src/gui_index.h b/src/gui_index.h
new file mode 100644
index 00000000..49392d5e
--- /dev/null
+++ b/src/gui_index.h
@@ -0,0 +1,56 @@
+/*
+ * gui_index.h
+ *
+ * Indexing parts of GUI
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GUI_INDEX_H
+#define GUI_INDEX_H
+
+#include <gtk/gtk.h>
+
+#include "gui_project.h"
+
+extern gint index_one_sig(GtkWidget *widget,
+ struct crystfelproject *proj);
+
+extern gint index_all_sig(GtkWidget *widget,
+ struct crystfelproject *proj);
+
+extern void cell_explorer_sig(struct crystfelproject *proj);
+
+extern int read_number_processed(const char *filename);
+
+extern int write_indexamajig_script(const char *script_filename,
+ const char *geom_filename,
+ const char *n_thread_str,
+ const char *files_list,
+ const char *stream_filename,
+ const char *serial_start,
+ int redirect_output,
+ struct peak_params *peak_search_params,
+ struct index_params *indexing_params);
+
+#endif
diff --git a/src/gui_merge.c b/src/gui_merge.c
new file mode 100644
index 00000000..46b37bfa
--- /dev/null
+++ b/src/gui_merge.c
@@ -0,0 +1,528 @@
+/*
+ * gui_merge.c
+ *
+ * Merging via CrystFEL GUI
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <assert.h>
+
+#include <utils.h>
+
+#include "gui_project.h"
+#include "crystfel_gui.h"
+#include "crystfelmergeopts.h"
+#include "gtk-util-routines.h"
+
+
+struct new_merging_job_params {
+ struct crystfelproject *proj;
+ struct gui_job_notes_page *notes_page;
+ GtkWidget *backend_combo;
+ GtkWidget *backend_opts_widget;
+ GtkWidget *backend_opts_box;
+ GtkWidget *job_title_entry;
+ GtkWidget *model_combo;
+ GtkWidget *input_combo;
+};
+
+
+static void free_new_merging_job_params(gpointer njp, GClosure *closure)
+{
+ free(njp);
+}
+
+
+static void get_merging_opts(struct merging_params *opts,
+ CrystFELMergeOpts *mo)
+{
+ free(opts->model);
+ opts->model = strdup(crystfel_merge_opts_get_model(mo));
+ free(opts->symmetry);
+ opts->symmetry = strdup(crystfel_merge_opts_get_symmetry(mo));
+ opts->scale = crystfel_merge_opts_get_scale(mo);
+ opts->bscale = crystfel_merge_opts_get_bscale(mo);
+ opts->postref = crystfel_merge_opts_get_postref(mo);
+ opts->niter = crystfel_merge_opts_get_niter(mo);
+ free(opts->polarisation);
+ opts->polarisation = strdup(crystfel_merge_opts_get_polarisation(mo));
+ opts->deltacchalf = crystfel_merge_opts_get_deltacchalf(mo);
+ opts->min_measurements = crystfel_merge_opts_get_min_measurements(mo);
+ opts->max_adu = crystfel_merge_opts_get_max_adu(mo);
+ free(opts->custom_split);
+ opts->custom_split = safe_strdup(crystfel_merge_opts_get_custom_split(mo));
+ free(opts->twin_sym);
+ opts->twin_sym = safe_strdup(crystfel_merge_opts_get_twin_sym(mo));
+ opts->min_res = crystfel_merge_opts_get_min_res(mo);
+ opts->push_res = crystfel_merge_opts_get_push_res(mo);
+}
+
+
+static int run_merging(struct crystfelproject *proj,
+ const char *results_name,
+ int backend_idx,
+ const char *job_title,
+ const char *job_notes)
+{
+ struct crystfel_backend *be;
+ void *job_priv;
+ struct gui_indexing_result *input;
+
+ /* Which result to merge? */
+ input = find_indexing_result_by_name(proj, results_name);
+ if ( input == NULL ) {
+ ERROR("Please select a result first\n");
+ return 1;
+ }
+
+ be = &proj->backends[backend_idx];
+ job_priv = be->run_merging(job_title, job_notes, proj, input,
+ be->merging_opts_priv);
+
+ if ( job_priv != NULL ) {
+ char name[256];
+ snprintf(name, 255, "Merging data (%s)", job_title);
+ add_running_task(proj, name, be, job_priv);
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+
+static void merging_response_sig(GtkWidget *dialog, gint resp,
+ struct new_merging_job_params *njp)
+{
+ if ( resp == GTK_RESPONSE_OK ) {
+
+ int backend_idx;
+ const char *job_title;
+ char *job_notes;
+ const char *results_name;
+
+ get_merging_opts(&njp->proj->merging_params,
+ CRYSTFEL_MERGE_OPTS(njp->proj->merging_opts));
+
+ backend_idx = gtk_combo_box_get_active(GTK_COMBO_BOX(njp->backend_combo));
+ if ( backend_idx < 0 ) return;
+
+ job_title = gtk_entry_get_text(GTK_ENTRY(njp->job_title_entry));
+ job_notes = get_all_text(GTK_TEXT_VIEW(njp->notes_page->textview));
+
+ if ( job_title[0] == '\0' ) {
+ ERROR("You must provide a job name.\n");
+ return;
+ }
+
+ free(njp->proj->merging_new_job_title);
+ njp->proj->merging_new_job_title = strdup(job_title);
+
+ results_name = gtk_combo_box_get_active_id(GTK_COMBO_BOX(njp->input_combo));
+ if ( results_name == NULL ) {
+ ERROR("Please select the input\n");
+ return;
+ }
+ if ( run_merging(njp->proj, results_name,
+ backend_idx, job_title, job_notes) == 0 )
+ {
+ gtk_widget_destroy(dialog);
+ njp->proj->merging_opts = NULL;
+ }
+
+ free(job_notes);
+
+ } else {
+ gtk_widget_destroy(dialog);
+ njp->proj->merging_opts = NULL;
+ }
+}
+
+
+static void set_merging_opts(struct merging_params *opts,
+ CrystFELMergeOpts *mo)
+{
+ crystfel_merge_opts_set_model(mo, opts->model);
+ crystfel_merge_opts_set_symmetry(mo, opts->symmetry);
+ crystfel_merge_opts_set_scale(mo, opts->scale);
+ crystfel_merge_opts_set_bscale(mo, opts->bscale);
+ crystfel_merge_opts_set_postref(mo, opts->postref);
+ crystfel_merge_opts_set_niter(mo, opts->niter);
+ crystfel_merge_opts_set_polarisation(mo, opts->polarisation);
+ crystfel_merge_opts_set_deltacchalf(mo, opts->deltacchalf);
+ crystfel_merge_opts_set_min_measurements(mo, opts->min_measurements);
+ crystfel_merge_opts_set_max_adu(mo, opts->max_adu);
+ crystfel_merge_opts_set_custom_split(mo, opts->custom_split);
+ crystfel_merge_opts_set_twin_sym(mo, opts->twin_sym);
+ crystfel_merge_opts_set_min_res(mo, opts->min_res);
+ crystfel_merge_opts_set_push_res(mo, opts->push_res);
+}
+
+
+static void merging_backend_changed_sig(GtkWidget *combo,
+ struct new_merging_job_params *njp)
+{
+ int backend_idx;
+ struct crystfel_backend *be;
+
+ backend_idx = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
+ if ( backend_idx < 0 ) return;
+ njp->proj->merging_backend_selected = backend_idx;
+
+ be = &njp->proj->backends[backend_idx];
+
+ if ( njp->backend_opts_widget != NULL ) {
+ gtk_widget_destroy(njp->backend_opts_widget);
+ }
+
+ njp->backend_opts_widget = be->make_merging_parameters_widget(be->merging_opts_priv);
+
+ gtk_box_pack_start(GTK_BOX(njp->backend_opts_box),
+ GTK_WIDGET(njp->backend_opts_widget),
+ FALSE, FALSE, 0);
+ gtk_widget_show_all(njp->backend_opts_widget);
+}
+
+
+static GtkWidget *make_merging_backend_opts(struct new_merging_job_params *njp)
+{
+ GtkWidget *box;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ int i;
+
+ box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+ gtk_container_set_border_width(GTK_CONTAINER(box), 8);
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ label = gtk_label_new("Batch system:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+
+ njp->backend_combo = gtk_combo_box_text_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(njp->backend_combo),
+ FALSE, FALSE, 0);
+
+ for ( i=0; i<njp->proj->n_backends; i++ ) {
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(njp->backend_combo),
+ njp->proj->backends[i].name,
+ njp->proj->backends[i].friendly_name);
+ }
+
+ njp->backend_opts_box = gtk_box_new(GTK_ORIENTATION_VERTICAL,
+ 0);
+ gtk_box_pack_start(GTK_BOX(box),
+ GTK_WIDGET(njp->backend_opts_box),
+ FALSE, FALSE, 0);
+ njp->backend_opts_widget = NULL;
+
+ /* njp->backend_opts{_box} must exist before the following */
+ g_signal_connect(G_OBJECT(njp->backend_combo), "changed",
+ G_CALLBACK(merging_backend_changed_sig), njp);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(njp->backend_combo),
+ njp->proj->merging_backend_selected);
+
+ return box;
+}
+
+
+gint merge_sig(GtkWidget *widget, struct crystfelproject *proj)
+{
+ GtkWidget *dialog;
+ GtkWidget *label;
+ GtkWidget *content_area;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *backend_page;
+ int i;
+ char *new_title;
+ struct new_merging_job_params *njp;
+
+ if ( proj->merging_opts != NULL ) return FALSE;
+
+ njp = malloc(sizeof(struct new_merging_job_params));
+ if ( njp == NULL ) return FALSE;
+
+ njp->proj = proj;
+
+ dialog = gtk_dialog_new_with_buttons("Merge",
+ GTK_WINDOW(proj->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ "Cancel", GTK_RESPONSE_CANCEL,
+ "Run", GTK_RESPONSE_OK,
+ NULL);
+
+ g_signal_connect_data(G_OBJECT(dialog), "response",
+ G_CALLBACK(merging_response_sig),
+ njp, free_new_merging_job_params, 0);
+
+ vbox = gtk_vbox_new(FALSE, 0.0);
+ content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ gtk_container_add(GTK_CONTAINER(content_area), vbox);
+ gtk_container_set_border_width(GTK_CONTAINER(content_area), 8);
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox),
+ FALSE, FALSE, 0);
+ label = gtk_label_new("Job/output name:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 0);
+ njp->job_title_entry = gtk_entry_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(njp->job_title_entry),
+ TRUE, TRUE, 2.0);
+ gtk_entry_set_placeholder_text(GTK_ENTRY(njp->job_title_entry),
+ "merge-trial-1");
+ new_title = make_new_job_title(proj->merging_new_job_title);
+ if ( new_title != NULL ) {
+ gtk_entry_set_text(GTK_ENTRY(njp->job_title_entry), new_title);
+ free(new_title);
+ }
+
+ label = gtk_label_new("Input:");
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 4.0);
+ njp->input_combo = gtk_combo_box_text_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(njp->input_combo),
+ FALSE, FALSE, 4.0);
+ for ( i=0; i<proj->n_results; i++ ) {
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(njp->input_combo),
+ proj->results[i].name,
+ proj->results[i].name);
+ }
+ gtk_combo_box_set_active_id(GTK_COMBO_BOX(njp->input_combo),
+ selected_result(proj));
+
+
+ proj->merging_opts = crystfel_merge_opts_new();
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(proj->merging_opts),
+ FALSE, FALSE, 8.0);
+
+ set_merging_opts(&proj->merging_params, CRYSTFEL_MERGE_OPTS(proj->merging_opts));
+
+ backend_page = make_merging_backend_opts(njp);
+ gtk_notebook_append_page(GTK_NOTEBOOK(proj->merging_opts),
+ backend_page,
+ gtk_label_new("Cluster/batch system"));
+
+ njp->notes_page = add_job_notes_page(proj->merging_opts);
+
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+ GTK_RESPONSE_OK);
+ gtk_widget_show_all(dialog);
+
+ return FALSE;
+}
+
+
+static int write_partialator_script(const char *filename,
+ struct gui_indexing_result *input,
+ const char *n_thread_str,
+ struct merging_params *params,
+ const char *out_hkl)
+{
+ FILE *fh;
+ char *exe_path;
+ int i;
+
+ fh = fopen(filename, "w");
+ if ( fh == NULL ) return 1;
+
+ fprintf(fh, "#!/bin/sh\n");
+
+ exe_path = get_crystfel_exe("partialator");
+ if ( exe_path == NULL ) return 1;
+ fprintf(fh, "%s \\\n", exe_path);
+
+ for ( i=0; i<input->n_streams; i++ ) {
+ fprintf(fh, "%s \\\n", input->streams[i]);
+ }
+
+ fprintf(fh, " -j %s", n_thread_str);
+ fprintf(fh, " -o %s", out_hkl);
+ fprintf(fh, " -y %s", params->symmetry);
+
+ fprintf(fh, " --polarisation=%s", params->polarisation);
+ fprintf(fh, " --min-measurements=%i", params->min_measurements);
+ fprintf(fh, " --max-adu=%f", params->max_adu);
+ fprintf(fh, " --min-res=%f", params->min_res);
+ fprintf(fh, " --push-res=%f", params->push_res);
+
+ if ( params->twin_sym != NULL ) {
+ fprintf(fh, " -w %s", params->twin_sym);
+ }
+
+ if ( params->custom_split != NULL ) {
+ fprintf(fh, " --custom-split=%s", params->custom_split);
+ }
+
+ if ( !params->scale ) {
+ fprintf(fh, " --no-scale");
+ }
+
+ if ( !params->bscale ) {
+ fprintf(fh, " --no-Bscale");
+ }
+
+ if ( !params->postref ) {
+ fprintf(fh, " --no-pr");
+ }
+
+ if ( !params->deltacchalf ) {
+ fprintf(fh, " --no-deltacchalf");
+ }
+
+ fprintf(fh, " --iterations=%i", params->niter);
+
+ fprintf(fh, " >stdout.log 2>stderr.log\n");
+
+ fclose(fh);
+ return 0;
+}
+
+
+static void add_process_hkl(FILE *fh,
+ const char *exe_path,
+ struct gui_indexing_result *input,
+ struct merging_params *params,
+ const char *out_hkl,
+ const char *extra_arg,
+ const char *out_suffix)
+{
+ int i;
+
+ fprintf(fh, "%s \\\n", exe_path);
+
+ for ( i=0; i<input->n_streams; i++ ) {
+ fprintf(fh, " %s \\\n", input->streams[i]);
+ }
+
+ fprintf(fh, " -o %s%s", out_hkl, out_suffix);
+ fprintf(fh, " -y %s", params->symmetry);
+
+ if ( params->scale ) {
+ fprintf(fh, " --scale");
+ }
+
+ fprintf(fh, " --polarisation=%s", params->polarisation);
+ fprintf(fh, " --min-measurements=%i", params->min_measurements);
+ fprintf(fh, " --max-adu=%f", params->max_adu);
+ fprintf(fh, " --min-res=%f", params->min_res);
+ fprintf(fh, " --push-res=%f", params->push_res);
+ fprintf(fh, " %s >>stdout.log 2>>stderr.log\n", extra_arg);
+}
+
+
+static int write_process_hkl_script(const char *filename,
+ struct gui_indexing_result *input,
+ struct merging_params *params,
+ const char *out_hkl)
+{
+ FILE *fh;
+ char *exe_path;
+
+ fh = fopen(filename, "w");
+ if ( fh == NULL ) return 1;
+
+ fprintf(fh, "#!/bin/sh\n");
+
+ exe_path = get_crystfel_exe("process_hkl");
+ if ( exe_path == NULL ) return 1;
+
+ add_process_hkl(fh, exe_path, input, params, out_hkl, "", "");
+ add_process_hkl(fh, exe_path, input, params, out_hkl, "--even-only", "1");
+ add_process_hkl(fh, exe_path, input, params, out_hkl, "--odd-only", "2");
+
+ fclose(fh);
+ return 0;
+}
+
+
+int write_merge_script(const char *filename,
+ struct gui_indexing_result *input,
+ const char *n_thread_str,
+ struct merging_params *params,
+ const char *out_hkl)
+{
+ if ( strcmp(params->model, "process_hkl") == 0 ) {
+ return write_process_hkl_script(filename, input,
+ params, out_hkl);
+ } else {
+ return write_partialator_script(filename, input, n_thread_str,
+ params, out_hkl);
+ }
+}
+
+
+double read_merge_progress(char *logfile_str, enum gui_job_type type)
+{
+ FILE *fh;
+ double frac_complete = 0.0;
+
+ fh = fopen(logfile_str, "r");
+ if ( fh == NULL ) return 0.0;
+
+ do {
+ char line[1024];
+
+ if ( fgets(line, 1024, fh) == NULL ) break;
+
+ if ( type == GUI_JOB_PROCESS_HKL ) {
+ frac_complete += 1.0/3.0;
+ } else if ( type == GUI_JOB_PROCESS_HKL_SCALE ) {
+ frac_complete += 1.0/6.0;
+ } else {
+ int cycle, max_cycles;
+ assert(type == GUI_JOB_PARTIALATOR);
+ if ( strcmp(line, "Initial partiality calculation...\n") == 0 ) {
+ frac_complete = 0.1;
+ }
+ if ( sscanf(line, "Scaling and refinement cycle %d of %d\n",
+ &cycle, &max_cycles) == 2 )
+ {
+ frac_complete = 0.1 + 0.8*(double)cycle/max_cycles;
+ }
+ if ( strcmp(line, "Final merge...\n") == 0 ) {
+ frac_complete = 0.9;
+ }
+ if ( strncmp(line, "Writing two-way split", 20) == 0 ) {
+ frac_complete = 1.0;
+ }
+
+ }
+ } while ( 1 );
+
+ fclose(fh);
+
+ return frac_complete;
+}
diff --git a/src/gui_merge.h b/src/gui_merge.h
new file mode 100644
index 00000000..e3f947c7
--- /dev/null
+++ b/src/gui_merge.h
@@ -0,0 +1,49 @@
+/*
+ * gui_merge.h
+ *
+ * Merging via CrystFEL GUI
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GUI_MERGE_H
+#define GUI_MERGE_H
+
+#include <gtk/gtk.h>
+
+#include "gui_project.h"
+#include "crystfel_gui.h"
+
+extern gint merge_sig(GtkWidget *widget,
+ struct crystfelproject *proj);
+
+extern int write_merge_script(const char *filename,
+ struct gui_indexing_result *input,
+ const char *n_thread_str,
+ struct merging_params *params,
+ const char *out_hkl);
+
+extern double read_merge_progress(const char *logfile_str,
+ enum gui_job_type type);
+
+#endif
diff --git a/src/gui_peaksearch.c b/src/gui_peaksearch.c
new file mode 100644
index 00000000..f8f370d4
--- /dev/null
+++ b/src/gui_peaksearch.c
@@ -0,0 +1,527 @@
+/*
+ * gui_peaksearch.c
+ *
+ * Peak search parts of GUI
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms-compat.h>
+#include <assert.h>
+
+#include <datatemplate.h>
+#include <peaks.h>
+
+#include "crystfelimageview.h"
+#include "gui_project.h"
+#include "crystfel_gui.h"
+
+
+void update_peaks(struct crystfelproject *proj)
+{
+ if ( proj->n_frames == 0 ) return;
+ if ( proj->cur_image == NULL ) return;
+
+ crystfel_image_view_set_peak_box_size(CRYSTFEL_IMAGE_VIEW(proj->imageview),
+ proj->peak_search_params.pk_inn);
+
+ image_feature_list_free(proj->cur_image->features);
+ proj->cur_image->features = NULL;
+
+ switch ( proj->peak_search_params.method ) {
+
+ case PEAK_ZAEF:
+ search_peaks(proj->cur_image,
+ proj->peak_search_params.threshold,
+ proj->peak_search_params.min_sq_gradient,
+ proj->peak_search_params.min_snr,
+ proj->peak_search_params.pk_inn,
+ proj->peak_search_params.pk_mid,
+ proj->peak_search_params.pk_out,
+ 1);
+ break;
+
+ case PEAK_PEAKFINDER8:
+ search_peaks_peakfinder8(proj->cur_image, 2048,
+ proj->peak_search_params.threshold,
+ proj->peak_search_params.min_snr,
+ proj->peak_search_params.min_pix_count,
+ proj->peak_search_params.max_pix_count,
+ proj->peak_search_params.local_bg_radius,
+ proj->peak_search_params.min_res,
+ proj->peak_search_params.max_res,
+ 1);
+ break;
+
+ case PEAK_PEAKFINDER9:
+ search_peaks_peakfinder9(proj->cur_image,
+ proj->peak_search_params.min_snr_biggest_pix,
+ proj->peak_search_params.min_snr_peak_pix,
+ proj->peak_search_params.min_snr,
+ proj->peak_search_params.min_sig,
+ proj->peak_search_params.min_peak_over_neighbour,
+ proj->peak_search_params.local_bg_radius);
+ break;
+
+ case PEAK_HDF5:
+ case PEAK_CXI:
+ proj->cur_image->features = image_read_peaks(proj->dtempl,
+ proj->cur_image->filename,
+ proj->cur_image->ev,
+ proj->peak_search_params.half_pixel_shift);
+ if ( proj->peak_search_params.revalidate ) {
+ validate_peaks(proj->cur_image,
+ proj->peak_search_params.min_snr,
+ proj->peak_search_params.pk_inn,
+ proj->peak_search_params.pk_mid,
+ proj->peak_search_params.pk_out,
+ 1, 0);
+ }
+ break;
+
+ default:
+ ERROR("This peak detection method not implemented!\n");
+ break;
+
+ }
+}
+
+
+struct param_callback_vals
+{
+ float *pfval;
+ int *pival;
+ char *str_val;
+ struct crystfelproject *proj;
+};
+
+
+static void check_param_callback(GtkWidget *checkbox,
+ struct param_callback_vals *vals)
+{
+ int val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox));
+ *(vals->pival) = val;
+ update_imageview(vals->proj);
+}
+
+
+static void int_param_callback(GtkWidget *entry,
+ struct param_callback_vals *cbvals)
+{
+ const char *text;
+ int val;
+
+ text = gtk_entry_get_text(GTK_ENTRY(entry));
+ if (sscanf(text, "%i", &val) != 1) {
+ ERROR("Invalid value\n");
+ return;
+ }
+
+ /* Only update peaks if value has changed */
+ if ( strcmp(cbvals->str_val, text) != 0 ) {
+ *(cbvals->pival) = val;
+ cbvals->proj->unsaved = 1;
+ update_imageview(cbvals->proj);
+ free(cbvals->str_val);
+ cbvals->str_val = strdup(text);
+ }
+}
+
+
+static gboolean int_param_focus_callback(GtkWidget *entry,
+ GdkEvent *event,
+ struct param_callback_vals *cbvals)
+{
+ int_param_callback(entry, cbvals);
+ return FALSE;
+}
+
+
+static void float_param_callback(GtkWidget *entry,
+ struct param_callback_vals *cbvals)
+{
+ const char *text;
+ float val;
+
+ text = gtk_entry_get_text(GTK_ENTRY(entry));
+ if (sscanf(text, "%f", &val) != 1) {
+ ERROR("Invalid value\n");
+ return;
+ }
+
+ /* Only update peaks if value has changed */
+ if ( strcmp(cbvals->str_val, text) != 0 ) {
+ *(cbvals->pfval) = val;
+ cbvals->proj->unsaved = 1;
+ update_imageview(cbvals->proj);
+ free(cbvals->str_val);
+ cbvals->str_val = strdup(text);
+ }
+}
+
+
+static gboolean float_param_focus_callback(GtkWidget *entry,
+ GdkEvent *event,
+ struct param_callback_vals *cbvals)
+{
+ float_param_callback(entry, cbvals);
+ return FALSE;
+}
+
+
+static void free_callback_params(gpointer cbvals,
+ GClosure *closure)
+{
+ free(cbvals);
+}
+
+
+static void add_int_param(GtkWidget *params_box, const char *labeltext,
+ int *pval, struct crystfelproject *proj,
+ const char *tooltip)
+{
+ GtkWidget *hbox;
+ GtkWidget *label;
+ GtkWidget *entry;
+ struct param_callback_vals *cbvals;
+ char tmp[64];
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(params_box),
+ GTK_WIDGET(hbox), FALSE, FALSE, 8.0);
+ label = gtk_label_new(labeltext);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 2.0);
+ entry = gtk_entry_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry),
+ TRUE, TRUE, 2.0);
+ snprintf(tmp, 63, "%i", *pval);
+ gtk_entry_set_text(GTK_ENTRY(entry), tmp);
+
+ cbvals = malloc(sizeof(struct param_callback_vals));
+ if ( cbvals != NULL ) {
+ cbvals->proj = proj;
+ cbvals->pival = pval;
+ cbvals->str_val = strdup(tmp);
+ g_signal_connect_data(G_OBJECT(entry),
+ "activate",
+ G_CALLBACK(int_param_callback),
+ cbvals, free_callback_params, 0);
+ g_signal_connect(G_OBJECT(entry),
+ "focus-out-event",
+ G_CALLBACK(int_param_focus_callback),
+ cbvals);
+ } else {
+ ERROR("Failed to connect parameter callback\n");
+ }
+
+ gtk_widget_set_tooltip_text(hbox, tooltip);
+}
+
+
+static void add_float_param(GtkWidget *params_box, const char *labeltext,
+ float *pval, struct crystfelproject *proj,
+ const char *tooltip)
+{
+ GtkWidget *hbox;
+ GtkWidget *label;
+ GtkWidget *entry;
+ struct param_callback_vals *cbvals;
+ char tmp[64];
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(params_box),
+ GTK_WIDGET(hbox), FALSE, FALSE, 8.0);
+ label = gtk_label_new(labeltext);
+ gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label),
+ FALSE, FALSE, 2.0);
+ entry = gtk_entry_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry),
+ TRUE, TRUE, 2.0);
+ snprintf(tmp, 63, "%.2f", *pval);
+ gtk_entry_set_text(GTK_ENTRY(entry), tmp);
+
+ cbvals = malloc(sizeof(struct param_callback_vals));
+ if ( cbvals != NULL ) {
+ cbvals->proj = proj;
+ cbvals->pfval = pval;
+ cbvals->str_val = strdup(tmp);
+ g_signal_connect_data(G_OBJECT(entry),
+ "activate",
+ G_CALLBACK(float_param_callback),
+ cbvals, free_callback_params, 0);
+ g_signal_connect(G_OBJECT(entry),
+ "focus-out-event",
+ G_CALLBACK(float_param_focus_callback),
+ cbvals);
+
+ } else {
+ ERROR("Failed to connect parameter callback\n");
+ }
+
+ gtk_widget_set_tooltip_text(hbox, tooltip);
+}
+
+
+static void add_check_param(GtkWidget *params_box, const char *labeltext,
+ int *pval, struct crystfelproject *proj,
+ const char *tooltip)
+{
+ GtkWidget *checkbox;
+ struct param_callback_vals *cbvals;
+
+ checkbox = gtk_check_button_new_with_label(labeltext);
+ gtk_box_pack_start(GTK_BOX(params_box),
+ GTK_WIDGET(checkbox), FALSE, FALSE, 8.0);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox),
+ *pval);
+
+ cbvals = malloc(sizeof(struct param_callback_vals));
+ if ( cbvals != NULL ) {
+ cbvals->proj = proj;
+ cbvals->pival = pval;
+ g_signal_connect_data(G_OBJECT(checkbox), "toggled",
+ G_CALLBACK(check_param_callback),
+ cbvals, free_callback_params, 0);
+ } else {
+ ERROR("Failed to connect parameter callback\n");
+ }
+
+ gtk_widget_set_tooltip_text(checkbox, tooltip);
+}
+
+
+static void add_radii(GtkWidget *params_box,
+ struct crystfelproject *proj)
+{
+ add_float_param(params_box, "Peak radius (inner):",
+ &proj->peak_search_params.pk_inn, proj,
+ "--peak-radius");
+ add_float_param(params_box, "Peak radius (middle):",
+ &proj->peak_search_params.pk_mid, proj,
+ "--peak-radius");
+ add_float_param(params_box, "Peak radius (outer):",
+ &proj->peak_search_params.pk_out, proj,
+ "--peak-radius");
+}
+
+
+static void peaksearch_algo_changed(GtkWidget *combo,
+ struct crystfelproject *proj)
+{
+ const char *algo_id;
+
+ if ( proj->peak_params != NULL ) {
+ gtk_container_remove(GTK_CONTAINER(proj->peak_vbox),
+ proj->peak_params);
+ proj->peak_params = NULL;
+ }
+
+ proj->peak_params = gtk_vbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(proj->peak_vbox),
+ GTK_WIDGET(proj->peak_params),
+ FALSE, FALSE, 8.0);
+
+ algo_id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(combo));
+
+ if ( strcmp(algo_id, "zaef") == 0 ) {
+
+ proj->peak_search_params.method = PEAK_ZAEF;
+
+ add_float_param(proj->peak_params, "Threshold:",
+ &proj->peak_search_params.threshold, proj,
+ "--threshold");
+ add_float_param(proj->peak_params, "Minimum squared gradient:",
+ &proj->peak_search_params.min_sq_gradient, proj,
+ "--min-squared-gradient (--min-gradient)");
+ add_float_param(proj->peak_params, "Minimum signal/noise ratio:",
+ &proj->peak_search_params.min_snr, proj,
+ "--min-snr");
+ add_radii(proj->peak_params, proj);
+
+ } else if ( strcmp(algo_id, "peakfinder8") == 0 ) {
+
+ proj->peak_search_params.method = PEAK_PEAKFINDER8;
+
+ add_float_param(proj->peak_params, "Threshold:",
+ &proj->peak_search_params.threshold, proj,
+ "--threshold");
+ add_float_param(proj->peak_params, "Minimum signal/noise ratio:",
+ &proj->peak_search_params.min_snr, proj,
+ "--min-snr");
+ add_int_param(proj->peak_params, "Minimum number of pixels:",
+ &proj->peak_search_params.min_pix_count, proj,
+ "--min-pix-count");
+ add_int_param(proj->peak_params, "Maximum number of pixels:",
+ &proj->peak_search_params.max_pix_count, proj,
+ "--max-pix-count");
+ add_int_param(proj->peak_params, "Local background radius:",
+ &proj->peak_search_params.local_bg_radius, proj,
+ "--local-bg-radius");
+ add_int_param(proj->peak_params, "Minimum resolution (pixels):",
+ &proj->peak_search_params.min_res, proj,
+ "--min-res");
+ add_int_param(proj->peak_params, "Maximum resolution (pixels):",
+ &proj->peak_search_params.max_res, proj,
+ "--max-res");
+
+ } else if ( strcmp(algo_id, "peakfinder9") == 0 ) {
+
+ proj->peak_search_params.method = PEAK_PEAKFINDER9;
+
+ add_float_param(proj->peak_params, "Minimum SNR of brightest pixel in peak:",
+ &proj->peak_search_params.min_snr_biggest_pix, proj,
+ "--min-snr-biggest-pix");
+ add_float_param(proj->peak_params, "Minimum SNR of peak pixel:",
+ &proj->peak_search_params.min_snr_peak_pix, proj,
+ "--min-snr-peak-pix");
+ add_float_param(proj->peak_params, "Minimum signal/noise ratio:",
+ &proj->peak_search_params.min_snr, proj,
+ "-min-snr");
+ add_float_param(proj->peak_params, "Minimum background standard deviation:",
+ &proj->peak_search_params.min_sig, proj,
+ "--min-sig");
+ add_float_param(proj->peak_params, "Brightest pixel cutoff (just for speed):",
+ &proj->peak_search_params.min_peak_over_neighbour, proj,
+ "--min-peak-over-neighbour");
+ add_int_param(proj->peak_params, "Local background radius:",
+ &proj->peak_search_params.local_bg_radius, proj,
+ "--local-bg-radius");
+
+ } else if ( strcmp(algo_id, "hdf5") == 0 ) {
+
+ proj->peak_search_params.method = PEAK_HDF5;
+
+ add_check_param(proj->peak_params, "Half pixel shift",
+ &proj->peak_search_params.half_pixel_shift,
+ proj, "--no-half-pixel-shift");
+ add_check_param(proj->peak_params, "Check peaks first",
+ &proj->peak_search_params.revalidate,
+ proj, "--no-revalidate");
+ add_radii(proj->peak_params, proj);
+
+ } else if ( strcmp(algo_id, "cxi") == 0 ) {
+ ERROR("algo_id should be hdf5, not cxi\n");
+
+ } else {
+ ERROR("Unrecognised peak search '%s'\n", algo_id);
+ }
+
+ /* FIXME: Radii */
+
+ gtk_widget_show_all(proj->peak_vbox);
+ update_peaks(proj);
+ update_imageview(proj);
+ proj->unsaved = 1;
+}
+
+
+static void peaksearch_response_sig(GtkWidget *dialog, gint resp,
+ struct crystfelproject *proj)
+{
+ if ( (resp == GTK_RESPONSE_DELETE_EVENT)
+ || (resp == GTK_RESPONSE_CANCEL) )
+ {
+ proj->peak_search_params = proj->original_params;
+ }
+
+ update_imageview(proj);
+ gtk_widget_destroy(dialog);
+ proj->peak_vbox = NULL;
+ proj->peak_params = NULL;
+}
+
+
+gint peaksearch_sig(GtkWidget *widget, struct crystfelproject *proj)
+{
+ GtkWidget *dialog;
+ GtkWidget *content_area;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ GtkWidget *combo;
+
+ if ( proj->peak_params != NULL ) return FALSE;
+
+ force_peaks_on(proj);
+
+ /* Take a copy of the original parameters, for reverting */
+ proj->original_params = proj->peak_search_params;
+
+ dialog = gtk_dialog_new_with_buttons("Peak search",
+ GTK_WINDOW(proj->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ "Discard changes", GTK_RESPONSE_CANCEL,
+ "Confirm", GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ g_signal_connect(G_OBJECT(dialog), "response",
+ G_CALLBACK(peaksearch_response_sig), proj);
+
+ vbox = gtk_vbox_new(FALSE, 0.0);
+ content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ gtk_container_add(GTK_CONTAINER(content_area), vbox);
+ gtk_container_set_border_width(GTK_CONTAINER(content_area), 8);
+ proj->peak_vbox = vbox;
+
+ hbox = gtk_hbox_new(FALSE, 0.0);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 8.0);
+ label = gtk_label_new("Peak search algorithm");
+ gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 2.0);
+ combo = gtk_combo_box_text_new();
+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(combo), TRUE, TRUE, 2.0);
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), "zaef",
+ "Zaefferer gradient search (zaef)");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), "hdf5",
+ "Use the peak lists in the data files (hdf5/cxi)");
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), "peakfinder8",
+ "Radial background estimation (peakfinder8)");
+
+ if ( crystfel_has_peakfinder9() ) {
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), "peakfinder9",
+ "Local background estimation (peakfinder9)");
+ }
+
+ g_signal_connect(G_OBJECT(combo), "changed",
+ G_CALLBACK(peaksearch_algo_changed), proj);
+ gtk_combo_box_set_active_id(GTK_COMBO_BOX(combo),
+ str_peaksearch(proj->peak_search_params.method));
+ proj->type_combo = combo;
+
+ gtk_widget_show_all(dialog);
+
+ return FALSE;
+}
diff --git a/src/gui_peaksearch.h b/src/gui_peaksearch.h
new file mode 100644
index 00000000..82750f6f
--- /dev/null
+++ b/src/gui_peaksearch.h
@@ -0,0 +1,41 @@
+/*
+ * gui_peaksearch.h
+ *
+ * Peak search parts of GUI
+ *
+ * Copyright © 2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GUI_PEAKSEARCH_H
+#define GUI_PEAKSEARCH_H
+
+#include <gtk/gtk.h>
+
+#include "gui_project.h"
+
+extern gint peaksearch_sig(GtkWidget *widget,
+ struct crystfelproject *proj);
+
+extern void update_peaks(struct crystfelproject *proj);
+
+#endif
diff --git a/src/gui_project.c b/src/gui_project.c
new file mode 100644
index 00000000..90b2b0fb
--- /dev/null
+++ b/src/gui_project.c
@@ -0,0 +1,1349 @@
+/*
+ * gui_project.c
+ *
+ * GUI project persistence
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "gui_project.h"
+#include "crystfel_gui.h"
+#include "gui_backend_local.h"
+#include "gui_backend_slurm.h"
+
+static double parse_float(const char *val)
+{
+ float v;
+
+ if (sscanf(val, "%f", &v) != 1) {
+ ERROR("Invalid float value '%s'\n", val);
+ return NAN;
+ }
+
+ return v;
+}
+
+
+static int parse_int(const char *val)
+{
+ int v;
+
+ if (sscanf(val, "%i", &v) != 1) {
+ ERROR("Invalid int value '%s'\n", val);
+ return 0;
+ }
+
+ return v;
+}
+
+
+static const char *str_matchtype(enum match_type_id mt)
+{
+ switch ( mt ) {
+ case MATCH_EVERYTHING : return "everything";
+ case MATCH_H5 : return "hdf5";
+ case MATCH_CHEETAH_LCLS_H5 : return "lcls-cheetah-hdf5";
+ case MATCH_CHEETAH_CXI : return "cheetah-cxi";
+ case MATCH_CBF : return "cbf";
+ case MATCH_CBFGZ : return "cbfgz";
+ }
+ return NULL;
+}
+
+
+enum match_type_id decode_matchtype(const char *type_id)
+{
+ if ( strcmp(type_id, "everything") == 0 ) return MATCH_EVERYTHING;
+ if ( strcmp(type_id, "hdf5") == 0 ) return MATCH_H5;
+ if ( strcmp(type_id, "lcls-cheetah-hdf5") == 0 ) return MATCH_CHEETAH_LCLS_H5;
+ if ( strcmp(type_id, "cheetah-cxi") == 0 ) return MATCH_CHEETAH_CXI;
+ if ( strcmp(type_id, "cbf") == 0 ) return MATCH_CBF;
+ if ( strcmp(type_id, "cbfgz") == 0 ) return MATCH_CBFGZ;
+ ERROR("Unknown match type id '%s'\n", type_id);
+ return MATCH_EVERYTHING;
+}
+
+
+int match_filename(const char *fn, enum match_type_id mt)
+{
+ const char *ext = NULL;
+ const char *ext2 = NULL;
+
+ if ( mt == MATCH_EVERYTHING ) return 1;
+
+ ext = filename_extension(fn, &ext2);
+ if ( ext == NULL ) return 0;
+
+ if ( mt == MATCH_H5 ) return (strcmp(ext, ".h5")==0);
+ if ( mt == MATCH_CHEETAH_LCLS_H5 ) {
+ return ((strcmp(ext, ".h5")==0)
+ && (strncmp(fn, "LCLS", 4)==0));
+ }
+ if ( mt == MATCH_CHEETAH_CXI ) return strcmp(ext, ".cxi")==0;
+ if ( mt == MATCH_CBF ) return strcmp(ext, ".cbf")==0;
+ if ( mt == MATCH_CBFGZ ) {
+ if ( ext2 != NULL ) {
+ return strcmp(ext2, ".cbf.gz")==0;
+ }
+ }
+
+ return 0;
+}
+
+
+/* "tols" is in frac (not %) and radians */
+static void parse_tols(const char *text, float *tols)
+{
+ int r;
+
+ r = sscanf(text, "%f,%f,%f,%f,%f,%f",
+ &tols[0], &tols[1], &tols[2],
+ &tols[3], &tols[4], &tols[5]);
+
+ if ( r != 6 ) {
+ STATUS("Invalid tolerances '%s'\n", text);
+ } else {
+ int i;
+ for ( i=0; i<3; i++ ) tols[i] /= 100.0;
+ for ( i=3; i<6; i++ ) tols[i] = deg2rad(tols[i]);
+ }
+}
+
+
+static int find_backend(const char *name, struct crystfelproject *proj)
+{
+ int i;
+
+ for ( i=0; i<proj->n_backends; i++ ) {
+ if ( strcmp(proj->backends[i].name, name) == 0 ) {
+ return i;
+ }
+ }
+
+ ERROR("Couldn't find backend '%s'\n", name);
+ return 0;
+}
+
+
+static void parse_peaksearch_opt(const char *key, const char *val,
+ struct crystfelproject *proj)
+{
+ if ( strcmp(key, "peak_search_params.method") == 0 ) {
+ proj->peak_search_params.method = parse_peaksearch(val);
+ if ( proj->peak_search_params.method == PEAK_ERROR ) {
+ ERROR("Unrecognised peak search method '%s'\n",
+ val);
+ }
+ }
+
+ if ( strcmp(key, "peak_search_params.threshold") == 0 ) {
+ proj->peak_search_params.threshold = parse_float(val);
+ }
+
+ if ( strcmp(key, "peak_search_params.min_sq_gradient") == 0 ) {
+ proj->peak_search_params.min_sq_gradient = parse_float(val);
+ }
+
+ if ( strcmp(key, "peak_search_params.min_snr") == 0 ) {
+ proj->peak_search_params.min_snr = parse_float(val);
+ }
+
+ if ( strcmp(key, "peak_search_params.local_bg_radius") == 0 ) {
+ proj->peak_search_params.local_bg_radius = parse_int(val);
+ }
+
+ if ( strcmp(key, "peak_search_params.min_res") == 0 ) {
+ proj->peak_search_params.min_res = parse_int(val);
+ }
+
+ if ( strcmp(key, "peak_search_params.min_sig") == 0 ) {
+ proj->peak_search_params.min_sig = parse_float(val);
+ }
+
+ if ( strcmp(key, "peak_search_params.max_res") == 0 ) {
+ proj->peak_search_params.max_res = parse_int(val);
+ }
+
+ if ( strcmp(key, "peak_search_params.min_pix_count") == 0 ) {
+ proj->peak_search_params.min_pix_count = parse_int(val);
+ }
+
+ if ( strcmp(key, "peak_search_params.max_pix_count") == 0 ) {
+ proj->peak_search_params.max_pix_count = parse_int(val);
+ }
+
+ if ( strcmp(key, "peak_search_params.min_peak_over_neighbour") == 0 ) {
+ proj->peak_search_params.min_peak_over_neighbour = parse_float(val);
+ }
+
+ if ( strcmp(key, "peak_search_params.pk_inn") == 0 ) {
+ proj->peak_search_params.pk_inn = parse_float(val);
+ }
+
+ if ( strcmp(key, "peak_search_params.pk_mid") == 0 ) {
+ proj->peak_search_params.pk_mid = parse_float(val);
+ }
+
+ if ( strcmp(key, "peak_search_params.pk_out") == 0 ) {
+ proj->peak_search_params.pk_out = parse_float(val);
+ }
+
+ if ( strcmp(key, "peak_search_params.half_pixel_shift") == 0 ) {
+ proj->peak_search_params.half_pixel_shift = parse_int(val);
+ }
+
+ if ( strcmp(key, "peak_search_params.revalidate") == 0 ) {
+ proj->peak_search_params.revalidate = parse_int(val);
+ }
+}
+
+
+static void parse_indexing_opt(const char *key, const char *val,
+ struct crystfelproject *proj)
+{
+ if ( strcmp(key, "indexing.cell_file") == 0 ) {
+ proj->indexing_params.cell_file = strdup(val);
+ }
+
+ if ( strcmp(key, "indexing.methods") == 0 ) {
+ proj->indexing_params.indexing_methods = strdup(val);
+ }
+
+ if ( strcmp(key, "indexing.multi_lattice") == 0 ) {
+ proj->indexing_params.multi = parse_int(val);
+ }
+
+ if ( strcmp(key, "indexing.no_refine") == 0 ) {
+ proj->indexing_params.no_refine = parse_int(val);
+ }
+
+ if ( strcmp(key, "indexing.no_retry") == 0 ) {
+ proj->indexing_params.no_retry = parse_int(val);
+ }
+
+ if ( strcmp(key, "indexing.no_peak_check") == 0 ) {
+ proj->indexing_params.no_peak_check = parse_int(val);
+ }
+
+ if ( strcmp(key, "indexing.no_cell_check") == 0 ) {
+ proj->indexing_params.no_cell_check = parse_int(val);
+ }
+
+ if ( strcmp(key, "indexing.cell_tolerance") == 0 ) {
+ parse_tols(val, proj->indexing_params.tols);
+ }
+
+ if ( strcmp(key, "indexing.min_peaks") == 0 ) {
+ proj->indexing_params.min_peaks = parse_int(val);
+ }
+}
+
+
+static void parse_integration_opt(const char *key, const char *val,
+ struct crystfelproject *proj)
+{
+ if ( strcmp(key, "integration.method") == 0 ) {
+ proj->indexing_params.integration_method = strdup(val);
+ }
+
+ if ( strcmp(key, "integration.overpredict") == 0 ) {
+ proj->indexing_params.overpredict = parse_int(val);
+ }
+
+ if ( strcmp(key, "integration.push_res") == 0 ) {
+ proj->indexing_params.push_res = parse_float(val);
+ }
+
+ if ( strcmp(key, "integration.ir_inn") == 0 ) {
+ proj->indexing_params.ir_inn = parse_float(val);
+ }
+
+ if ( strcmp(key, "integration.ir_mid") == 0 ) {
+ proj->indexing_params.ir_mid = parse_float(val);
+ }
+
+ if ( strcmp(key, "integration.ir_out") == 0 ) {
+ proj->indexing_params.ir_out = parse_float(val);
+ }
+}
+
+
+static void add_metadata_to_copy(struct index_params *ip,
+ const char *header)
+{
+ char **n;
+
+ n = realloc(ip->metadata_to_copy,
+ (ip->n_metadata+1)*sizeof(char *));
+ if ( n == NULL ) return;
+ ip->metadata_to_copy = n;
+
+ ip->metadata_to_copy[ip->n_metadata++] = strdup(header);
+}
+
+
+static void parse_ambi_opt(const char *key, const char *val,
+ struct crystfelproject *proj)
+{
+ if ( strcmp(key, "ambi.min_res_A") == 0 ) {
+ proj->ambi_params.res_min = parse_float(val);
+ }
+ if ( strcmp(key, "ambi.max_res_A") == 0 ) {
+ proj->ambi_params.res_max = parse_float(val);
+ }
+ if ( strcmp(key, "ambi.use_res") == 0 ) {
+ proj->ambi_params.use_res = parse_int(val);
+ }
+ if ( strcmp(key, "ambi.niter") == 0 ) {
+ proj->ambi_params.niter = parse_int(val);
+ }
+ if ( strcmp(key, "ambi.ncorr") == 0 ) {
+ proj->ambi_params.ncorr = parse_int(val);
+ }
+ if ( strcmp(key, "ambi.use_ncorr") == 0 ) {
+ proj->ambi_params.use_ncorr = parse_int(val);
+ }
+ if ( strcmp(key, "ambi.sym") == 0 ) {
+ proj->ambi_params.sym = strdup(val);
+ }
+ if ( strcmp(key, "ambi.source_sym") == 0 ) {
+ proj->ambi_params.source_sym = strdup(val);
+ }
+ if ( strcmp(key, "ambi.use_operator") == 0 ) {
+ proj->ambi_params.use_operator = parse_int(val);
+ }
+ if ( strcmp(key, "ambi.operator") == 0 ) {
+ proj->ambi_params.operator = strdup(val);
+ }
+}
+
+
+static void parse_fom_opt(const char *key, const char *val,
+ struct crystfelproject *proj)
+{
+ if ( strcmp(key, "fom.min_res_A") == 0 ) {
+ proj->fom_res_min = parse_float(val);
+ }
+ if ( strcmp(key, "fom.max_res_A") == 0 ) {
+ proj->fom_res_max = parse_float(val);
+ }
+ if ( strcmp(key, "fom.min_snr") == 0 ) {
+ proj->fom_min_snr = parse_float(val);
+ }
+ if ( strcmp(key, "fom.num_bins") == 0 ) {
+ proj->fom_nbins = parse_int(val);
+ }
+ if ( strcmp(key, "fom.min_meas") == 0 ) {
+ proj->fom_min_meas = parse_int(val);
+ }
+ if ( strcmp(key, "fom.cell_file") == 0 ) {
+ proj->fom_cell_filename = strdup(val);
+ }
+}
+
+
+static void parse_stream_opt(const char *key, const char *val,
+ struct index_params *ip)
+{
+ if ( strcmp(key, "stream.exclude_blanks") == 0 ) {
+ ip->exclude_nonhits = parse_int(val);
+ }
+ if ( strcmp(key, "stream.exclude_peaks") == 0 ) {
+ ip->exclude_peaks = parse_int(val);
+ }
+ if ( strcmp(key, "stream.exclude_refls") == 0 ) {
+ ip->exclude_refls = parse_int(val);
+ }
+ if ( strcmp(key, "stream.metadata") == 0 ) {
+ add_metadata_to_copy(ip, val);
+ }
+}
+
+
+static void parse_merging_opt(const char *key, const char *val,
+ struct crystfelproject *proj)
+{
+ if ( strcmp(key, "merging.model") == 0 ) {
+ proj->merging_params.model = strdup(val);
+ }
+
+ if ( strcmp(key, "merging.symmetry") == 0 ) {
+ proj->merging_params.symmetry = strdup(val);
+ }
+
+ if ( strcmp(key, "merging.scale") == 0 ) {
+ proj->merging_params.scale = parse_int(val);
+ }
+
+ if ( strcmp(key, "merging.bscale") == 0 ) {
+ proj->merging_params.bscale = parse_int(val);
+ }
+
+ if ( strcmp(key, "merging.postref") == 0 ) {
+ proj->merging_params.postref = parse_int(val);
+ }
+
+ if ( strcmp(key, "merging.niter") == 0 ) {
+ proj->merging_params.niter = parse_int(val);
+ }
+
+ if ( strcmp(key, "merging.polarisation") == 0 ) {
+ proj->merging_params.polarisation = strdup(val);
+ }
+
+ if ( strcmp(key, "merging.deltacchalf") == 0 ) {
+ proj->merging_params.deltacchalf = parse_int(val);
+ }
+
+ if ( strcmp(key, "merging.min_measurements") == 0 ) {
+ proj->merging_params.min_measurements = parse_int(val);
+ }
+
+ if ( strcmp(key, "merging.max_adu") == 0 ) {
+ proj->merging_params.max_adu = parse_float(val);
+ }
+
+ if ( strcmp(key, "merging.custom_split") == 0 ) {
+ proj->merging_params.custom_split = strdup(val);
+ }
+
+ if ( strcmp(key, "merging.twin_sym") == 0 ) {
+ proj->merging_params.twin_sym = strdup(val);
+ }
+
+ if ( strcmp(key, "merging.min_res") == 0 ) {
+ proj->merging_params.min_res = parse_float(val);
+ }
+
+ if ( strcmp(key, "merging.push_res") == 0 ) {
+ proj->merging_params.push_res = parse_float(val);
+ }
+}
+
+
+static void handle_var(const char *key, const char *val,
+ struct crystfelproject *proj)
+{
+ if ( strcmp(key, "indexing.new_job_title") == 0 ) {
+ free(proj->indexing_new_job_title);
+ proj->indexing_new_job_title = strdup(val);
+ }
+
+ if ( strcmp(key, "merging.new_job_title") == 0 ) {
+ free(proj->merging_new_job_title);
+ proj->merging_new_job_title = strdup(val);
+ }
+
+ if ( strcmp(key, "ambi.new_job_title") == 0 ) {
+ free(proj->ambi_new_job_title);
+ proj->ambi_new_job_title = strdup(val);
+ }
+
+ if ( strcmp(key, "indexing.backend") == 0 ) {
+ proj->indexing_backend_selected = find_backend(val, proj);
+ }
+
+ if ( strcmp(key, "merging.backend") == 0 ) {
+ proj->merging_backend_selected = find_backend(val, proj);
+ }
+
+ if ( strcmp(key, "show_peaks") == 0 ) {
+ proj->show_peaks = parse_int(val);
+ }
+
+ if ( strcmp(key, "show_refls") == 0 ) {
+ proj->show_refls = parse_int(val);
+ }
+
+ if ( strcmp(key, "label_refls") == 0 ) {
+ proj->label_refls = parse_int(val);
+ }
+
+ if ( strcmp(key, "geom") == 0 ) {
+ proj->geom_filename = strdup(val);
+ }
+
+ if ( strcmp(key, "data_folder") == 0 ) {
+ proj->data_top_folder = strdup(val);
+ }
+
+ if ( strncmp(key, "fom.", 4) == 0 ) {
+ parse_fom_opt(key, val, proj);
+ }
+
+ if ( strncmp(key, "ambi.", 4) == 0 ) {
+ parse_ambi_opt(key, val, proj);
+ }
+
+ if ( strncmp(key, "stream.", 7) == 0 ) {
+ parse_stream_opt(key, val, &proj->indexing_params);
+ } else if ( strcmp(key, "stream") == 0 ) {
+ proj->stream_filename = strdup(val);
+ }
+
+ if ( strcmp(key, "search_pattern") == 0 ) {
+ proj->data_search_pattern = decode_matchtype(val);
+ }
+
+ if ( strncmp(key, "peak_search_params.", 19) == 0 ) {
+ parse_peaksearch_opt(key, val, proj);
+ }
+
+ if ( strncmp(key, "indexing.", 9) == 0 ) {
+ int i;
+ parse_indexing_opt(key, val, proj);
+ for ( i=0; i<proj->n_backends; i++ ) {
+ struct crystfel_backend *be;
+ be = &proj->backends[i];
+ be->read_indexing_opt(be->indexing_opts_priv,
+ key, val);
+ }
+ }
+
+ if ( strncmp(key, "integration.", 12) == 0 ) {
+ parse_integration_opt(key, val, proj);
+ }
+
+ if ( strncmp(key, "merging.", 9) == 0 ) {
+ int i;
+ parse_merging_opt(key, val, proj);
+ for ( i=0; i<proj->n_backends; i++ ) {
+ struct crystfel_backend *be;
+ be = &proj->backends[i];
+ be->read_merging_opt(be->merging_opts_priv,
+ key, val);
+ }
+ }
+}
+
+
+void clear_project_files(struct crystfelproject *proj)
+{
+ int i;
+
+ if ( proj->filenames != NULL ) {
+ for ( i=0; i<proj->n_frames; i++ ) {
+ free(proj->filenames[i]);
+ free(proj->events[i]);
+ }
+ free(proj->filenames);
+ free(proj->events);
+ }
+ proj->n_frames = 0;
+ proj->max_frames = 0;
+ proj->filenames = NULL;
+ proj->events = NULL;
+ proj->cur_frame = 0;
+}
+
+
+void clear_indexing_results(struct crystfelproject *proj)
+{
+ int i;
+ for ( i=0; i<proj->n_results; i++ ) {
+ int j;
+ free(proj->results[i].name);
+ for ( j=0; j<proj->results[i].n_streams; j++ ) {
+ free(proj->results[i].streams[j]);
+ stream_index_free(proj->results[i].indices[j]);
+ }
+ free(proj->results[i].streams);
+ free(proj->results[i].indices);
+ }
+ free(proj->results);
+ proj->results = NULL;
+ proj->n_results = 0;
+
+ /* Reset the widget, as well */
+ gtk_combo_box_text_remove_all(GTK_COMBO_BOX_TEXT(proj->results_combo));
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(proj->results_combo),
+ "crystfel-gui-internal",
+ "Calculations within GUI");
+ gtk_combo_box_set_active(GTK_COMBO_BOX(proj->results_combo), 0);
+}
+
+
+void add_file_to_project(struct crystfelproject *proj,
+ const char *filename, const char *event)
+{
+ if ( proj->n_frames == proj->max_frames ) {
+ int n_max = proj->max_frames + 1024;
+ char **n_filenames;
+ char **n_events;
+ n_filenames = realloc(proj->filenames,
+ n_max*sizeof(char *));
+ n_events = realloc(proj->events,
+ n_max*sizeof(char *));
+ if ( (n_filenames == NULL) || (n_events == NULL) ) {
+ ERROR("Failed to allocate new filename\n");
+ return;
+ }
+ proj->max_frames = n_max;
+ proj->filenames = n_filenames;
+ proj->events = n_events;
+ }
+
+ proj->filenames[proj->n_frames] = strdup(filename);
+ proj->events[proj->n_frames] = safe_strdup(event);
+ proj->n_frames++;
+}
+
+
+static char **add_stream(char *new_stream,
+ char **streams,
+ int *pn_streams)
+{
+ int i = *pn_streams;
+ char **new_streams = realloc(streams,
+ (i+1)*sizeof(struct gui_indexing_result));
+ if ( new_streams == NULL ) return streams;
+
+ new_streams[i] = new_stream;
+ *pn_streams = i+1;
+ return new_streams;
+}
+
+
+static void read_parameters(FILE *fh, struct crystfelproject *proj)
+{
+ char *rval;
+ char line[1024];
+
+ do {
+
+ char *sp;
+
+ rval = fgets(line, 1023, fh);
+ if ( rval == NULL ) break;
+ chomp(line);
+ if ( line[0] == '\0' ) continue;
+
+ if ( strcmp(line, "-----") == 0 ) break;
+
+ sp = strchr(line, ' ');
+ if ( sp == NULL ) {
+ ERROR("Unrecognised line in crystfel.project "
+ "file: '%s'\n", line);
+ continue;
+ }
+ sp[0] = '\0';
+ handle_var(line, sp+1, proj);
+
+ } while ( rval != NULL );
+}
+
+
+static void add_result(struct crystfelproject *proj,
+ char *results_name,
+ char **streams,
+ int n_streams,
+ int selected,
+ char *hkl, char *hkl1, char *hkl2)
+{
+ if ( (n_streams > 0) && (hkl == NULL) ) {
+ add_indexing_result(proj, results_name,
+ streams, n_streams);
+
+ if ( selected ) {
+ select_result(proj, results_name);
+ }
+
+ } else if ( (hkl != NULL) && (n_streams == 0) ) {
+ add_merge_result(proj,
+ results_name,
+ hkl, hkl1, hkl2);
+
+ } else {
+ ERROR("Bad results %s (%i %s)\n",
+ results_name, n_streams, hkl);
+ }
+
+}
+
+
+static void read_results(FILE *fh, struct crystfelproject *proj)
+{
+ char *rval;
+ char line[1024];
+ char **streams = NULL;
+ int n_streams = 0;
+ char *results_name = NULL;
+ char *hkl = NULL;
+ char *hkl1 = NULL;
+ char *hkl2 = NULL;
+ int selected = 0;
+ int first = 1;
+
+ do {
+
+ rval = fgets(line, 1023, fh);
+ if ( rval == NULL ) break;
+ chomp(line);
+ if ( line[0] == '\0' ) continue;
+
+ if ( strncmp(line, "Result ", 7) == 0 ) {
+
+ if ( !first ) {
+ add_result(proj, results_name,
+ streams, n_streams, selected,
+ hkl, hkl1, hkl2);
+ }
+ first = 0;
+
+ n_streams = 0;
+ selected = 0;
+ streams = NULL;
+ hkl = NULL;
+ hkl1 = NULL;
+ hkl2 = NULL;
+
+ results_name = strdup(line+7);
+ }
+
+ if ( strncmp(line, " Selected", 11) == 0 ) {
+ selected = 1;
+ }
+
+ if ( strncmp(line, " Stream ", 10) == 0 ) {
+ streams = add_stream(strdup(line+10),
+ streams,
+ &n_streams);
+ }
+
+ if ( strncmp(line, " HKL ", 7) == 0 ) {
+ hkl = strdup(line+7);
+ }
+
+ if ( strncmp(line, " HKL1 ", 7) == 0 ) {
+ hkl1 = strdup(line+8);
+ }
+
+ if ( strncmp(line, " HKL2 ", 7) == 0 ) {
+ hkl2 = strdup(line+8);
+ }
+
+ if ( strcmp(line, "-----") == 0 ) {
+ if ( !first ) {
+ add_result(proj, results_name,
+ streams, n_streams, selected,
+ hkl, hkl1, hkl2);
+ }
+ break;
+ }
+
+ } while ( rval != NULL );
+}
+
+
+static void read_frames(FILE *fh, struct crystfelproject *proj)
+{
+ char *rval;
+ char line[1024];
+
+ do {
+
+ rval = fgets(line, 1023, fh);
+ if ( rval == NULL ) break;
+
+ chomp(line);
+
+ if ( line[0] == '\0' ) continue;
+
+ char *ev = NULL;
+ size_t n = strlen(line)-1;
+ for ( ; n>0; n-- ) {
+ if ( line[n] == ' ' ) {
+ line[n] = '\0';
+ ev = &line[n+1];
+ break;
+ }
+ }
+ add_file_to_project(proj, line, ev);
+
+ } while ( rval != NULL );
+}
+
+
+int load_project(struct crystfelproject *proj)
+{
+ FILE *fh;
+
+ fh = fopen("crystfel.project", "r");
+ if ( fh == NULL ) return 1;
+
+ default_project(proj);
+
+ read_parameters(fh, proj);
+ read_results(fh, proj);
+ read_frames(fh, proj);
+
+ fclose(fh);
+
+ return 0;
+}
+
+
+int save_project(struct crystfelproject *proj)
+{
+ int i;
+ FILE *fh;
+
+ fh = fopen("crystfel.project", "w");
+ if ( fh == NULL ) {
+ STATUS("Couldn't save project.\n");
+ return 1;
+ }
+
+ if ( proj->geom_filename != NULL ) {
+ fprintf(fh, "geom %s\n", proj->geom_filename);
+ }
+ if ( proj->data_top_folder != NULL ) {
+ fprintf(fh, "data_folder %s\n", proj->data_top_folder);
+ }
+ fprintf(fh, "search_pattern %s\n",
+ str_matchtype(proj->data_search_pattern));
+ if ( proj->stream_filename != NULL ) {
+ fprintf(fh, "stream %s\n", proj->stream_filename);
+ }
+
+ fprintf(fh, "peak_search_params.method %s\n",
+ str_peaksearch(proj->peak_search_params.method));
+ fprintf(fh, "peak_search_params.threshold %f\n",
+ proj->peak_search_params.threshold);
+ fprintf(fh, "peak_search_params.min_sq_gradient %f\n",
+ proj->peak_search_params.min_sq_gradient);
+ fprintf(fh, "peak_search_params.min_snr %f\n",
+ proj->peak_search_params.min_snr);
+ fprintf(fh, "peak_search_params.min_pix_count %i\n",
+ proj->peak_search_params.min_pix_count);
+ fprintf(fh, "peak_search_params.max_pix_count %i\n",
+ proj->peak_search_params.max_pix_count);
+ fprintf(fh, "peak_search_params.local_bg_radius %i\n",
+ proj->peak_search_params.local_bg_radius);
+ fprintf(fh, "peak_search_params.min_res %i\n",
+ proj->peak_search_params.min_res);
+ fprintf(fh, "peak_search_params.max_res %i\n",
+ proj->peak_search_params.max_res);
+ fprintf(fh, "peak_search_params.min_snr_biggest_pix %f\n",
+ proj->peak_search_params.min_snr_biggest_pix);
+ fprintf(fh, "peak_search_params.min_snr_peak_pix %f\n",
+ proj->peak_search_params.min_snr_peak_pix);
+ fprintf(fh, "peak_search_params.min_peak_over_neighbour %f\n",
+ proj->peak_search_params.min_peak_over_neighbour);
+ fprintf(fh, "peak_search_params.pk_inn %f\n",
+ proj->peak_search_params.pk_inn);
+ fprintf(fh, "peak_search_params.pk_mid %f\n",
+ proj->peak_search_params.pk_mid);
+ fprintf(fh, "peak_search_params.pk_out %f\n",
+ proj->peak_search_params.pk_out);
+ fprintf(fh, "peak_search_params.half_pixel_shift %i\n",
+ proj->peak_search_params.half_pixel_shift);
+ fprintf(fh, "peak_search_params.revalidate %i\n",
+ proj->peak_search_params.revalidate);
+
+ if ( proj->indexing_params.cell_file != NULL ) {
+ fprintf(fh, "indexing.cell_file %s\n",
+ proj->indexing_params.cell_file);
+ }
+
+ if ( proj->indexing_params.indexing_methods != NULL ) {
+ fprintf(fh, "indexing.methods %s\n",
+ proj->indexing_params.indexing_methods);
+ }
+ fprintf(fh, "indexing.multi_lattice %i\n",
+ proj->indexing_params.multi);
+ fprintf(fh, "indexing.no_refine %i\n",
+ proj->indexing_params.no_refine);
+ fprintf(fh, "indexing.no_retry %i\n",
+ proj->indexing_params.no_retry);
+ fprintf(fh, "indexing.no_peak_check %i\n",
+ proj->indexing_params.no_peak_check);
+ fprintf(fh, "indexing.no_cell_check %i\n",
+ proj->indexing_params.no_cell_check);
+
+ /* Values in file are in percent and degrees */
+ /* Values in "tol" are in frac (not %) and radians */
+ fprintf(fh, "indexing.cell_tolerance %f,%f,%f,%f,%f,%f\n",
+ proj->indexing_params.tols[0]*100.0,
+ proj->indexing_params.tols[1]*100.0,
+ proj->indexing_params.tols[2]*100.0,
+ rad2deg(proj->indexing_params.tols[3]),
+ rad2deg(proj->indexing_params.tols[4]),
+ rad2deg(proj->indexing_params.tols[5]));
+ fprintf(fh, "indexing.min_peaks %i\n",
+ proj->indexing_params.min_peaks);
+
+ if ( proj->indexing_new_job_title != NULL ) {
+ fprintf(fh, "indexing.new_job_title %s\n",
+ proj->indexing_new_job_title);
+ }
+
+ fprintf(fh, "indexing.backend %s\n",
+ proj->backends[proj->indexing_backend_selected].name);
+ for ( i=0; i<proj->n_backends; i++ ) {
+ struct crystfel_backend *be;
+ be = &proj->backends[i];
+ be->write_indexing_opts(be->indexing_opts_priv, fh);
+ }
+
+ fprintf(fh, "integration.method %s\n",
+ proj->indexing_params.integration_method);
+ fprintf(fh, "integration.overpredict %i\n",
+ proj->indexing_params.overpredict);
+ fprintf(fh, "integration.push_res %f\n",
+ proj->indexing_params.push_res);
+ fprintf(fh, "integration.ir_inn %f\n",
+ proj->indexing_params.ir_inn);
+ fprintf(fh, "integration.ir_mid %f\n",
+ proj->indexing_params.ir_mid);
+ fprintf(fh, "integration.ir_out %f\n",
+ proj->indexing_params.ir_out);
+
+ fprintf(fh, "stream.exclude_blanks %i\n",
+ proj->indexing_params.exclude_nonhits);
+ fprintf(fh, "stream.exclude_peaks %i\n",
+ proj->indexing_params.exclude_peaks);
+ fprintf(fh, "stream.exclude_refls %i\n",
+ proj->indexing_params.exclude_refls);
+ if ( proj->indexing_params.metadata_to_copy != NULL ) {
+ int i;
+ for ( i=0; i<proj->indexing_params.n_metadata; i++ ) {
+ fprintf(fh, "stream.metadata %s\n",
+ proj->indexing_params.metadata_to_copy[i]);
+ }
+ }
+
+ fprintf(fh, "ambi.min_res_A %f\n", proj->ambi_params.res_min);
+ fprintf(fh, "ambi.max_res_A %f\n", proj->ambi_params.res_max);
+ fprintf(fh, "ambi.use_res %i\n", proj->ambi_params.use_res);
+ fprintf(fh, "ambi.niter %i\n", proj->ambi_params.niter);
+ fprintf(fh, "ambi.ncorr %i\n", proj->ambi_params.ncorr);
+ fprintf(fh, "ambi.use_ncorr %i\n", proj->ambi_params.use_ncorr);
+ fprintf(fh, "ambi.use_operator %i\n", proj->ambi_params.use_operator);
+ if ( proj->ambi_params.sym != NULL ) {
+ fprintf(fh, "ambi.sym %s\n", proj->ambi_params.sym);
+ }
+ if ( proj->ambi_params.source_sym != NULL ) {
+ fprintf(fh, "ambi.source_sym %s\n", proj->ambi_params.source_sym);
+ }
+ if ( proj->ambi_params.operator != NULL ) {
+ fprintf(fh, "ambi.operator %s\n", proj->ambi_params.operator);
+ }
+ if ( proj->ambi_new_job_title != NULL ) {
+ fprintf(fh, "ambi.new_job_title %s\n",
+ proj->ambi_new_job_title);
+ }
+
+ fprintf(fh, "merging.model %s\n",
+ proj->merging_params.model);
+ fprintf(fh, "merging.symmetry %s\n",
+ proj->merging_params.symmetry);
+ fprintf(fh, "merging.scale %i\n",
+ proj->merging_params.scale);
+ fprintf(fh, "merging.bscale %i\n",
+ proj->merging_params.bscale);
+ fprintf(fh, "merging.postref %i\n",
+ proj->merging_params.postref);
+ fprintf(fh, "merging.niter %i\n",
+ proj->merging_params.niter);
+ fprintf(fh, "merging.polarisation %s\n",
+ proj->merging_params.polarisation);
+ fprintf(fh, "merging.deltacchalf %i\n",
+ proj->merging_params.deltacchalf);
+ fprintf(fh, "merging.min_measurements %i\n",
+ proj->merging_params.min_measurements);
+ fprintf(fh, "merging.max_adu %f\n",
+ proj->merging_params.max_adu);
+ fprintf(fh, "merging.custom_split %s\n",
+ proj->merging_params.custom_split);
+ fprintf(fh, "merging.twin_sym %s\n",
+ proj->merging_params.twin_sym);
+ fprintf(fh, "merging.min_res %f\n",
+ proj->merging_params.min_res);
+ fprintf(fh, "merging.push_res %f\n",
+ proj->merging_params.push_res);
+
+ fprintf(fh, "merging.backend %s\n",
+ proj->backends[proj->merging_backend_selected].name);
+ for ( i=0; i<proj->n_backends; i++ ) {
+ struct crystfel_backend *be;
+ be = &proj->backends[i];
+ be->write_merging_opts(be->merging_opts_priv, fh);
+ }
+ if ( proj->merging_new_job_title != NULL ) {
+ fprintf(fh, "merging.new_job_title %s\n",
+ proj->merging_new_job_title);
+ }
+
+ fprintf(fh, "fom.min_res_A %f\n", proj->fom_res_min);
+ fprintf(fh, "fom.max_res_A %f\n", proj->fom_res_max);
+ fprintf(fh, "fom.num_bins %i\n", proj->fom_nbins);
+ fprintf(fh, "fom.min_snr %f\n", proj->fom_min_snr);
+ fprintf(fh, "fom.min_meas %i\n", proj->fom_min_meas);
+ fprintf(fh, "fom.cell_file %s\n", proj->fom_cell_filename);
+
+ fprintf(fh, "show_peaks %i\n", proj->show_peaks);
+ fprintf(fh, "show_refls %i\n", proj->show_refls);
+ fprintf(fh, "label_refls %i\n", proj->label_refls);
+
+ fprintf(fh, "-----\n");
+ for ( i=0; i<proj->n_results; i++ ) {
+ int j;
+ fprintf(fh, "Result %s\n", proj->results[i].name);
+ for ( j=0; j<proj->results[i].n_streams; j++ ) {
+ fprintf(fh, " Stream %s\n",
+ proj->results[i].streams[j]);
+ }
+ if ( strcmp(selected_result(proj),
+ proj->results[i].name) == 0 )
+ {
+ fprintf(fh, " Selected\n");
+ }
+ }
+ for ( i=0; i<proj->n_merge_results; i++ ) {
+ fprintf(fh, "Result %s\n", proj->merge_results[i].name);
+ fprintf(fh, " HKL %s\n", proj->merge_results[i].hkl);
+ fprintf(fh, " HKL1 %s\n", proj->merge_results[i].hkl1);
+ fprintf(fh, " HKL2 %s\n", proj->merge_results[i].hkl2);
+ }
+
+ fprintf(fh, "-----\n");
+ for ( i=0; i<proj->n_frames; i++ ) {
+ if ( proj->events[i] != NULL ) {
+ fprintf(fh, "%s %s\n",
+ proj->filenames[i], proj->events[i]);
+ } else {
+ fprintf(fh, "%s\n", proj->filenames[i]);
+ }
+ }
+
+ fclose(fh);
+
+ proj->unsaved = 0;
+ return 0;
+}
+
+
+void default_project(struct crystfelproject *proj)
+{
+ proj->unsaved = 0;
+ proj->geom_filename = NULL;
+ proj->n_frames = 0;
+ proj->max_frames = 0;
+ proj->n_random_history = 0;
+ memset(proj->random_history, 0, N_RANDOM_HISTORY*sizeof(int));
+ proj->filenames = NULL;
+ proj->events = NULL;
+ proj->peak_params = NULL;
+ proj->data_top_folder = NULL;
+ proj->data_search_pattern = 0;
+ proj->stream_filename = NULL;
+ proj->dtempl = NULL;
+ proj->cur_image = NULL;
+ proj->indexing_opts = NULL;
+ proj->merging_opts = NULL;
+ proj->ambi_opts = NULL;
+ proj->n_running_tasks = 0;
+ proj->indexing_new_job_title = NULL;
+ proj->merging_new_job_title = NULL;
+ proj->ambi_new_job_title = NULL;
+
+ proj->indexing_backend_selected = 0;
+ proj->merging_backend_selected = 0;
+ proj->n_backends = 0;
+ proj->backends = malloc(2*sizeof(struct crystfel_backend));
+ /* FIXME: Crappy error handling */
+ if ( proj->backends == NULL ) {
+ ERROR("Couldn't allocate space for backends\n");
+ }
+
+ if ( make_local_backend(&proj->backends[proj->n_backends++]) ) {
+ ERROR("Local backend setup failed\n");
+ }
+
+ #ifdef HAVE_SLURM
+ if ( make_slurm_backend(&proj->backends[proj->n_backends++]) ) {
+ ERROR("SLURM backend setup failed\n");
+ }
+ #endif
+
+ /* Default parameter values */
+ proj->show_peaks = 1;
+ proj->show_refls = 1;
+ proj->label_refls = 1;
+
+ proj->peak_search_params.method = PEAK_ZAEF;
+ proj->peak_search_params.threshold = 800.0;
+ proj->peak_search_params.min_sq_gradient = 100000;
+ proj->peak_search_params.min_snr = 5.0;
+ proj->peak_search_params.min_pix_count = 2;
+ proj->peak_search_params.max_pix_count = 200;
+ proj->peak_search_params.local_bg_radius = 3;
+ proj->peak_search_params.min_res = 0;
+ proj->peak_search_params.max_res = 1200;
+ proj->peak_search_params.min_snr_biggest_pix = 7.0;
+ proj->peak_search_params.min_snr_peak_pix = 6.0;
+ proj->peak_search_params.min_sig = 11.0;
+ proj->peak_search_params.min_peak_over_neighbour = -INFINITY;
+ proj->peak_search_params.pk_inn = 4.0;
+ proj->peak_search_params.pk_mid = 5.0;
+ proj->peak_search_params.pk_out = 7.0;
+ proj->peak_search_params.half_pixel_shift = 1;
+ proj->peak_search_params.revalidate = 1;
+
+ proj->indexing_params.cell_file = NULL;
+ proj->indexing_params.indexing_methods = NULL;
+ proj->indexing_params.multi = 1;
+ proj->indexing_params.no_refine = 0;
+ proj->indexing_params.no_retry = 0;
+ proj->indexing_params.no_peak_check = 0;
+ proj->indexing_params.no_cell_check = 0;
+ proj->indexing_params.tols[0] = 0.05; /* frac (not %) */
+ proj->indexing_params.tols[1] = 0.05; /* frac (not %) */
+ proj->indexing_params.tols[2] = 0.05; /* frac (not %) */
+ proj->indexing_params.tols[3] = deg2rad(1.5); /* rad */
+ proj->indexing_params.tols[4] = deg2rad(1.5); /* rad */
+ proj->indexing_params.tols[5] = deg2rad(1.5); /* rad */
+ proj->indexing_params.min_peaks = 0;
+ proj->indexing_params.integration_method = strdup("rings");
+ proj->indexing_params.overpredict = 0;
+ proj->indexing_params.push_res = INFINITY;
+ proj->indexing_params.ir_inn = 4.0;
+ proj->indexing_params.ir_mid = 5.0;
+ proj->indexing_params.ir_out = 7.0;
+ proj->indexing_params.exclude_nonhits = 0;
+ proj->indexing_params.exclude_peaks = 0;
+ proj->indexing_params.exclude_refls = 0;
+ proj->indexing_params.metadata_to_copy = NULL;
+ proj->indexing_params.n_metadata = 0;
+
+ proj->ambi_params.use_res = 1;
+ proj->ambi_params.res_min = 20; /* Angstroms */
+ proj->ambi_params.res_max = 4; /* Angstroms */
+ proj->ambi_params.niter = 4;
+ proj->ambi_params.use_ncorr = 0;
+ proj->ambi_params.ncorr = 1000;
+ proj->ambi_params.sym = NULL;
+ proj->ambi_params.source_sym = NULL;
+ proj->ambi_params.operator = NULL;
+ proj->ambi_params.use_operator = 1;
+
+ proj->merging_params.model = strdup("unity");
+ proj->merging_params.symmetry = strdup("1");
+ proj->merging_params.scale = 1;
+ proj->merging_params.bscale = 1;
+ proj->merging_params.postref = 0;
+ proj->merging_params.niter = 3;
+ proj->merging_params.polarisation = strdup("horiz");
+ proj->merging_params.deltacchalf = 1;
+ proj->merging_params.min_measurements = 2;
+ proj->merging_params.max_adu = INFINITY;
+ proj->merging_params.custom_split = NULL;
+ proj->merging_params.twin_sym = NULL;
+ proj->merging_params.min_res = INFINITY;
+ proj->merging_params.push_res = INFINITY;
+
+ proj->results = NULL;
+ proj->n_results = 0;
+
+ proj->merge_results = NULL;
+ proj->n_merge_results = 0;
+
+ proj->fom_res_min = 100.0; /* Angstroms */
+ proj->fom_res_max = 5.0; /* Angstroms */
+ proj->fom_nbins = 20;
+ proj->fom_min_snr = -INFINITY;
+ proj->fom_min_meas = 1;
+ proj->fom_cell_filename = NULL;
+
+ /* NB Export options are currently not saved (because I'm lazy) */
+ proj->export_res_min = INFINITY; /* Angstroms */
+ proj->export_res_max = 0.0; /* Angstroms */
+}
+
+
+/* Assumes ownership of "name" and "streams" */
+int add_indexing_result(struct crystfelproject *proj,
+ char *name,
+ char **streams,
+ int n_streams)
+{
+ int i;
+ struct gui_indexing_result *new_results;
+
+ new_results = realloc(proj->results,
+ (proj->n_results+1)*sizeof(struct gui_indexing_result));
+ if ( new_results == NULL ) return 1;
+
+ new_results[proj->n_results].name = name;
+ new_results[proj->n_results].streams = streams;
+ new_results[proj->n_results].n_streams = n_streams;
+ new_results[proj->n_results].indices = malloc(n_streams*sizeof(StreamIndex *));
+
+ for ( i=0; i<n_streams; i++ ) {
+ new_results[proj->n_results].indices[i] = NULL;
+ }
+
+ proj->results = new_results;
+ proj->n_results++;
+
+ gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(proj->results_combo),
+ name, name);
+
+ return 0;
+}
+
+
+int add_merge_result(struct crystfelproject *proj, char *name,
+ char *hkl, char *hkl1, char *hkl2)
+{
+ struct gui_merge_result *new_results;
+
+ new_results = realloc(proj->merge_results,
+ (proj->n_merge_results+1)*sizeof(struct gui_merge_result));
+ if ( new_results == NULL ) return 1;
+
+ new_results[proj->n_merge_results].name = name;
+ new_results[proj->n_merge_results].hkl = hkl;
+ new_results[proj->n_merge_results].hkl1 = hkl1;
+ new_results[proj->n_merge_results].hkl2 = hkl2;
+
+ proj->merge_results = new_results;
+ proj->n_merge_results++;
+
+ return 0;
+}
+
+
+struct gui_merge_result *find_merge_result_by_name(struct crystfelproject *proj,
+ const char *name)
+{
+ int i;
+
+ for ( i=0; i<proj->n_merge_results; i++ ) {
+ if ( strcmp(proj->merge_results[i].name, name) == 0 ) {
+ return &proj->merge_results[i];
+ }
+ }
+ return NULL;
+}
+
+
+void update_result_index(struct gui_indexing_result *result)
+{
+ int i;
+ for ( i=0; i<result->n_streams; i++ ) {
+ stream_index_free(result->indices[i]);
+ result->indices[i] = stream_make_index(result->streams[i]);
+ }
+}
+
+
+struct gui_indexing_result *find_indexing_result_by_name(struct crystfelproject *proj,
+ const char *name)
+{
+ int i;
+
+ for ( i=0; i<proj->n_results; i++ ) {
+ if ( strcmp(proj->results[i].name, name) == 0 ) {
+ return &proj->results[i];
+ }
+ }
+ return NULL;
+}
+
+
+static int ever_scanned(struct gui_indexing_result *result)
+{
+ return ( result->indices[0] != NULL );
+}
+
+
+struct image *find_indexed_image(struct crystfelproject *proj,
+ const char *results_name,
+ const char *filename,
+ const char *event,
+ int permit_rescan)
+{
+ Stream *st;
+ int i;
+ int found = 0;
+ struct image *image;
+ struct gui_indexing_result *result;
+
+ result = find_indexing_result_by_name(proj, results_name);
+ if ( result == NULL ) return NULL;
+
+ for ( i=0; i<result->n_streams; i++ ) {
+ if ( stream_select_chunk(NULL,
+ result->indices[i],
+ filename,
+ event) == 0 )
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ if ( !found && (permit_rescan || !ever_scanned(result)) ) {
+ /* Re-scan and try again */
+ update_result_index(result);
+ for ( i=0; i<result->n_streams; i++ ) {
+ if ( stream_select_chunk(NULL,
+ result->indices[i],
+ filename,
+ event) == 0 )
+ {
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ if ( !found ) return NULL;
+
+ st = stream_open_for_read(result->streams[i]);
+ if ( stream_select_chunk(st, result->indices[i],
+ filename, event) )
+ {
+ ERROR("Error selecting chunk.\n");
+ return NULL;
+ }
+
+ image = stream_read_chunk(st, STREAM_REFLECTIONS
+ | STREAM_PEAKS
+ | STREAM_DATA_DETGEOM);
+
+ stream_close(st);
+ return image;
+}
diff --git a/src/gui_project.h b/src/gui_project.h
new file mode 100644
index 00000000..1bb22d74
--- /dev/null
+++ b/src/gui_project.h
@@ -0,0 +1,373 @@
+/*
+ * gui_project.h
+ *
+ * GUI project persistence
+ *
+ * Copyright © 2020-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020-2021 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GUI_PROJECT_H
+#define GUI_PROJECT_H
+
+#include <gtk/gtk.h>
+
+#include <peaks.h>
+#include <stream.h>
+
+#define MAX_RUNNING_TASKS (16)
+
+enum match_type_id
+{
+ MATCH_EVERYTHING,
+ MATCH_H5,
+ MATCH_CHEETAH_LCLS_H5,
+ MATCH_CHEETAH_CXI,
+ MATCH_CBF,
+ MATCH_CBFGZ,
+};
+
+struct peak_params {
+ enum peak_search_method method;
+ float threshold; /* zaef, pf8 */
+ float min_sq_gradient; /* zaef */
+ float min_snr; /* zaef, pf8 */
+ int min_pix_count; /* pf8 */
+ int max_pix_count; /* pf8 */
+ int local_bg_radius; /* pf8 */
+ int min_res; /* pf8 */
+ int max_res; /* pf8 */
+ float min_snr_biggest_pix; /* pf9 */
+ float min_snr_peak_pix; /* pf9 */
+ float min_sig; /* pf9 */
+ float min_peak_over_neighbour; /* pf9 */
+ float pk_inn;
+ float pk_mid;
+ float pk_out;
+ int half_pixel_shift; /* cxi, hdf5 */
+ int revalidate;
+};
+
+struct index_params {
+
+ /* Indexing */
+ char *cell_file;
+ char *indexing_methods;
+ int multi;
+ int no_refine;
+ int no_retry;
+ int no_peak_check;
+ int no_cell_check;
+ float tols[6];
+ int min_peaks;
+
+ /* Integration */
+ char *integration_method;
+ int overpredict;
+ float push_res;
+ float ir_inn;
+ float ir_mid;
+ float ir_out;
+
+ /* Stream output */
+ int exclude_nonhits;
+ int exclude_peaks;
+ int exclude_refls;
+ char **metadata_to_copy;
+ int n_metadata;
+};
+
+struct merging_params {
+
+ char *model; /* "process_hkl" in addition to xsphere/unity etc */
+ char *symmetry;
+ int scale;
+ int bscale;
+ int postref;
+ int niter;
+ char *polarisation;
+ int deltacchalf;
+ int min_measurements;
+ float max_adu;
+ char *custom_split;
+ char *twin_sym;
+ float min_res;
+ float push_res;
+};
+
+struct ambi_params {
+ int use_res;
+ double res_min; /* Angstroms */
+ double res_max; /* Angstroms */
+ int niter;
+ int use_ncorr;
+ int ncorr;
+ char *sym;
+ char *source_sym;
+ int use_operator;
+ char *operator;
+};
+
+struct gui_indexing_result
+{
+ char *name;
+
+ int n_streams;
+ char **streams;
+ StreamIndex **indices;
+};
+
+struct gui_merge_result
+{
+ char *name;
+ char *hkl; /* Complete merged data */
+ char *hkl1; /* First half-split */
+ char *hkl2; /* Second half-split */
+};
+
+struct crystfelproject;
+
+struct crystfel_backend {
+
+ const char *name;
+ const char *friendly_name;
+
+ /* Called to ask the backend to cancel the job */
+ void (*cancel_task)(void *job_priv);
+
+ /* Called to get the status of a task */
+ int (*task_status)(void *job_priv,
+ int *running,
+ float *fraction_complete);
+
+ /* ....................... Indexing ........................ */
+
+ /* Backend should provide a GTK widget to set options */
+ GtkWidget *(*make_indexing_parameters_widget)(void *opts_priv);
+
+ /* Called to ask the backend to start indexing frames.
+ * It should return a void pointer representing this job */
+ void *(*run_indexing)(const char *job_title,
+ const char *job_notes,
+ struct crystfelproject *proj,
+ void *opts_priv);
+
+ /* Called to ask the backend to write its indexing options */
+ void (*write_indexing_opts)(void *opts_priv, FILE *fh);
+
+ /* Called when reading a project from file */
+ void (*read_indexing_opt)(void *opts_priv,
+ const char *key,
+ const char *val);
+
+ /* Backend should store options for indexing here */
+ void *indexing_opts_priv;
+
+ /* ....................... Merging ........................ */
+
+ /* Backend should provide a GTK widget to set options */
+ GtkWidget *(*make_merging_parameters_widget)(void *opts_priv);
+
+ /* Called to ask the backend to start merging data.
+ * It should return a void pointer representing this job */
+ void *(*run_merging)(const char *job_title,
+ const char *job_notes,
+ struct crystfelproject *proj,
+ struct gui_indexing_result *input,
+ void *opts_priv);
+
+ /* Called to ask the backend to write its merging options */
+ void (*write_merging_opts)(void *opts_priv, FILE *fh);
+
+ /* Called when reading a project from file */
+ void (*read_merging_opt)(void *opts_priv,
+ const char *key,
+ const char *val);
+
+ /* Backend should store options for merging here */
+ void *merging_opts_priv;
+
+ /* .................. Indexing ambiguity .................. */
+
+ /* Backend should provide a GTK widget to set options */
+ GtkWidget *(*make_ambi_parameters_widget)(void *opts_priv);
+
+ /* Called to ask the backend to start resolving indexing ambiguity.
+ * It should return a void pointer representing this job */
+ void *(*run_ambi)(const char *job_title,
+ const char *job_notes,
+ struct crystfelproject *proj,
+ struct gui_indexing_result *input,
+ void *opts_priv);
+
+ /* Called to ask the backend to write its ambigator options */
+ void (*write_ambi_opts)(void *opts_priv, FILE *fh);
+
+ /* Called when reading a project from file */
+ void (*read_ambi_opt)(void *opts_priv,
+ const char *key,
+ const char *val);
+
+ /* Backend should store options for ambigator here */
+ void *ambi_opts_priv;
+};
+
+struct gui_task
+{
+ GtkWidget *info_bar;
+ GtkWidget *cancel_button;
+ GtkWidget *progress_bar;
+ int running;
+ struct crystfel_backend *backend;
+ void *job_priv;
+};
+
+
+#define N_RANDOM_HISTORY (16)
+
+struct crystfelproject {
+
+ GtkWidget *window;
+ GtkUIManager *ui;
+ GtkActionGroup *action_group;
+
+ GtkWidget *imageview;
+ GtkWidget *icons; /* Drawing area for task icons */
+ GtkWidget *report; /* Text view at the bottom for messages */
+ GtkWidget *main_vbox;
+ GtkWidget *image_info;
+ GtkWidget *results_combo;
+ GtkWidget *next_button;
+ GtkWidget *prev_button;
+ GtkWidget *first_button;
+ GtkWidget *last_button;
+
+ int unsaved;
+
+ int cur_frame;
+ struct image *cur_image;
+ int random_history[N_RANDOM_HISTORY];
+ int n_random_history;
+
+ char *geom_filename;
+ char *stream_filename;
+ char *data_top_folder; /* For convenience only. Filenames in
+ * 'filenames' list should be complete */
+ enum match_type_id data_search_pattern;
+
+ DataTemplate *dtempl;
+ int n_frames;
+ int max_frames;
+ char **filenames;
+ char **events;
+
+ int show_peaks;
+ struct peak_params peak_search_params;
+
+ int show_refls;
+ int label_refls;
+ struct index_params indexing_params;
+ int indexing_backend_selected;
+ GtkWidget *indexing_opts;
+ char *indexing_new_job_title;
+
+ struct merging_params merging_params;
+ int merging_backend_selected;
+ GtkWidget *merging_opts;
+ char *merging_new_job_title;
+
+ GtkWidget *type_combo;
+ GtkWidget *peak_vbox; /* Box for peak search parameter widgets */
+ GtkWidget *peak_params; /* Peak search parameter widgets */
+ struct peak_params original_params;
+
+ /* All the backends available in this project */
+ struct crystfel_backend *backends;
+ int n_backends;
+
+ struct gui_task tasks[MAX_RUNNING_TASKS];
+ int n_running_tasks;
+
+ struct gui_indexing_result *results;
+ int n_results;
+
+ struct gui_merge_result *merge_results;
+ int n_merge_results;
+
+ double fom_res_min; /* Angstroms */
+ double fom_res_max; /* Angstroms */
+ int fom_nbins;
+ double fom_min_snr;
+ int fom_min_meas;
+ char *fom_cell_filename;
+
+ double export_res_min; /* Angstroms */
+ double export_res_max; /* Angstroms */
+
+ char *ambi_new_job_title;
+ int ambi_backend_selected;
+ GtkWidget *ambi_opts;
+ struct ambi_params ambi_params;
+};
+
+extern enum match_type_id decode_matchtype(const char *type_id);
+
+extern int match_filename(const char *fn, enum match_type_id mt);
+
+extern int load_project(struct crystfelproject *proj);
+
+extern void default_project(struct crystfelproject *proj);
+
+extern int save_project(struct crystfelproject *proj);
+
+extern void add_file_to_project(struct crystfelproject *proj,
+ const char *filename,
+ const char *event);
+
+extern void clear_project_files(struct crystfelproject *proj);
+extern void clear_indexing_results(struct crystfelproject *proj);
+
+extern int add_indexing_result(struct crystfelproject *proj,
+ char *name,
+ char **streams,
+ int n_streams);
+
+extern struct image *find_indexed_image(struct crystfelproject *proj,
+ const char *result_name,
+ const char *filename,
+ const char *event,
+ int permit_rescan);
+
+extern void update_result_index(struct gui_indexing_result *result);
+
+extern struct gui_indexing_result *find_indexing_result_by_name(struct crystfelproject *proj,
+ const char *name);
+
+extern int add_merge_result(struct crystfelproject *proj, char *name,
+ char *hkl, char *hkl1, char *hkl2);
+
+extern struct gui_merge_result *find_merge_result_by_name(struct crystfelproject *proj,
+ const char *name);
+
+extern const char *selected_result(struct crystfelproject *proj);
+
+#endif
diff --git a/src/hdfsee-render.c b/src/hdfsee-render.c
deleted file mode 100644
index 38f6ddfc..00000000
--- a/src/hdfsee-render.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * hdfsee-render.c
- *
- * Rendering bits for hdfsee
- *
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
- * a research centre of the Helmholtz Association.
- *
- * Authors:
- * 2011-2012,2015 Thomas White <taw@physics.org>
- *
- * This file is part of CrystFEL.
- *
- * CrystFEL is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * CrystFEL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <math.h>
-#include <stdint.h>
-#include <assert.h>
-
-
-#ifdef HAVE_GDKPIXBUF
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#endif
-
-#ifdef HAVE_TIFF
-#include <tiffio.h>
-#endif
-
-#include <render.h>
-#include <image.h>
-
-static float *get_binned_panel(struct image *image, int binning,
- int pi, double *max, int *pw, int *ph)
-{
- float *data;
- int x, y;
- int w, h;
- struct panel *p = &image->det->panels[pi];
-
- /* Some pixels might get discarded */
- w = p->w / binning;
- h = p->h / binning;
- *pw = w;
- *ph = h;
-
- data = malloc(w*h*sizeof(float));
-
- *max = 0.0;
- for ( x=0; x<w; x++ ) {
- for ( y=0; y<h; y++ ) {
-
- double total;
- size_t xb, yb;
- int bad = 0;
- double val;
-
- total = 0;
- for ( xb=0; xb<binning; xb++ ) {
- for ( yb=0; yb<binning; yb++ ) {
-
- double v;
- int fs, ss;
-
- fs = binning*x+xb;
- ss = binning*y+yb;
- v = image->dp[pi][fs+ss*p->w];
- total += v;
-
- if ( (image->bad != NULL)
- && (image->bad[pi][fs+ss*p->w]) ) bad = 1;
-
- }
- }
-
- val = total / ((double)binning * (double)binning);
-
- if ( bad ) {
- data[x+w*y] = -INFINITY;
- } else {
- data[x+w*y] = val;
- if ( val > *max ) *max = val;
- }
-
- }
- }
-
- return data;
-}
-
-
-#ifdef HAVE_GDKPIXBUF
-
-/* NB This function is shared between render_get_image() and
- * render_get_colour_scale() */
-static void render_free_data(guchar *data, gpointer p)
-{
- free(data);
-}
-
-
-static GdkPixbuf *render_panel(float *hdr, int scale, double max, int w, int h)
-{
- guchar *data;
- int x, y;
-
- /* Rendered (colourful) version */
- data = malloc(3*w*h);
- if ( data == NULL ) return NULL;
-
- /* These x,y coordinates are measured relative to the bottom-left
- * corner */
- for ( y=0; y<h; y++ ) {
- for ( x=0; x<w; x++ ) {
-
- double val;
- double r, g, b;
-
- val = hdr[x+w*y];
-
- if ( val > -INFINITY ) {
-
- render_scale(val, max, scale, &r, &g, &b);
-
- /* Stuff inside square brackets makes this pixel go to
- * the expected location in the pixbuf (which measures
- * from the top-left corner */
- data[3*( x+w*y )+0] = 255*r;
- data[3*( x+w*y )+1] = 255*g;
- data[3*( x+w*y )+2] = 255*b;
-
- } else {
-
- data[3*( x+w*y )+0] = 30;
- data[3*( x+w*y )+1] = 20;
- data[3*( x+w*y )+2] = 0;
-
- }
-
- }
- }
-
- /* Create the pixbuf from the 8-bit display data */
- return gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, FALSE, 8,
- w, h, w*3, render_free_data, NULL);
-
-}
-
-
-/* Render an image into multiple pixbufs according to geometry */
-GdkPixbuf **render_panels(struct image *image,
- int binning, int scale, double boost,
- int *n_pixbufs)
-{
- int i;
- int np = image->det->n_panels;
- GdkPixbuf **pixbufs;
- float **hdrs;
- double max;
- int *ws, *hs;
-
- hdrs = calloc(np, sizeof(float *));
- ws = calloc(np, sizeof(int));
- hs = calloc(np, sizeof(int));
- if ( (hdrs == NULL) || (ws == NULL) || (hs == NULL) ) {
- *n_pixbufs = 0;
- return NULL;
- }
-
- /* Find overall max value for whole image */
- max = 0.0;
- for ( i=0; i<np; i++ ) {
- double this_max = 0.0;
- hdrs[i] = get_binned_panel(image, binning, i, &this_max,
- &ws[i], &hs[i]);
- if ( this_max > max ) max = this_max;
- }
-
- max /= boost;
- if ( max <= 6 ) { max = 10; }
-
- pixbufs = calloc(np, sizeof(GdkPixbuf*));
- if ( pixbufs == NULL ) {
- *n_pixbufs = 0;
- return NULL;
- }
-
- for ( i=0; i<np; i++ ) {
-
- pixbufs[i] = render_panel(hdrs[i], scale, max, ws[i], hs[i]);
-
- free(hdrs[i]);
-
- }
-
- free(hdrs);
- free(ws);
- free(hs);
- *n_pixbufs = np;
-
- return pixbufs;
-}
-
-
-GdkPixbuf *render_get_colour_scale(size_t w, size_t h, int scale)
-{
- guchar *data;
- size_t x, y;
- int max;
-
- data = malloc(3*w*h);
- if ( data == NULL ) return NULL;
-
- max = h-(h/6);
-
- for ( y=0; y<h; y++ ) {
-
- double r, g, b;
- int val;
-
- val = y-(h/6);
-
- render_scale(val, max, scale, &r, &g, &b);
-
- data[3*( 0+w*(h-1-y) )+0] = 0;
- data[3*( 0+w*(h-1-y) )+1] = 0;
- data[3*( 0+w*(h-1-y) )+2] = 0;
- for ( x=1; x<w; x++ ) {
- data[3*( x+w*(h-1-y) )+0] = 255*r;
- data[3*( x+w*(h-1-y) )+1] = 255*g;
- data[3*( x+w*(h-1-y) )+2] = 255*b;
- }
-
- }
-
- y = h/6;
- for ( x=1; x<w; x++ ) {
- data[3*( x+w*(h-1-y) )+0] = 255;
- data[3*( x+w*(h-1-y) )+1] = 255;
- data[3*( x+w*(h-1-y) )+2] = 255;
- }
-
- return gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, FALSE, 8,
- w, h, w*3, render_free_data, NULL);
-}
-
-#endif /* HAVE_GDKPIXBUF */
-
-int render_tiff_fp(struct image *image, const char *filename, int min_x, int max_x,
- int min_y, int max_y)
-{
-#ifdef HAVE_TIFF
- TIFF *th;
- int16_t *line;
- int x, y;
- int width = max_x - min_x;
- int height = max_y - min_y;
- float *buf;
-
- if ( image == NULL ) return 1;
- if ( image->det == NULL ) return 1;
- if ( image->det->n_panels == 0 ) return 1;
-
- buf = calloc(width * height, sizeof(float));
- if ( buf == NULL ) return 1;
-
- /* Prepare image data */
- for ( y=min_y; y<max_y; y++ ) {
- for ( x=min_x; x<max_x; x++ ) {
-
- int invalid;
- float val;
- signed int pn;
- struct panel *p;
- double dfs, dss;
- int fs, ss;
-
- invalid = reverse_2d_mapping(x, y, image->det, &p, &dfs, &dss);
- if ( invalid ) continue;
-
- fs = dfs;
- ss = dss; /* Explicit rounding */
-
- pn = panel_number(image->det, p);
- assert(pn != -1);
- p = &image->det->panels[pn];
- val = image->dp[pn][fs + p->w* ss];
-
- buf[(x - min_x) + (y - min_y) * width] = val;
-
- }
- }
-
- th = TIFFOpen(filename, "w");
- if ( th == NULL ) return 1;
-
- TIFFSetField(th, TIFFTAG_IMAGEWIDTH, width);
- TIFFSetField(th, TIFFTAG_IMAGELENGTH, height);
- TIFFSetField(th, TIFFTAG_SAMPLESPERPIXEL, 1);
- TIFFSetField(th, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
- TIFFSetField(th, TIFFTAG_BITSPERSAMPLE, 32);
- TIFFSetField(th, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
- TIFFSetField(th, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
- TIFFSetField(th, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
- TIFFSetField(th, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(th, 0));
-
- line = _TIFFmalloc(TIFFScanlineSize(th));
-
- for ( y=0; y<height; y++ ) {
- TIFFWriteScanline(th, &buf[y*width], y, 0);
- }
- _TIFFfree(line);
-
- TIFFClose(th);
- free(buf);
-#else /* HAVE_TIFF */
- STATUS("No TIFF support.\n");
-#endif /* HAVE_TIFF */
- return 0;
-}
-
-
-int render_tiff_int16(struct image *image, const char *filename, double boost,
- int min_x, int max_x, int min_y, int max_y)
-{
-#ifdef HAVE_TIFF
- TIFF *th;
- int16_t *line;
- int x, y;
- int width = max_x - min_x;
- int height = max_y - min_y;
- int16_t *buf;
-
- if ( image == NULL ) return 1;
- if ( image->det == NULL ) return 1;
- if ( image->det->n_panels == 0 ) return 1;
-
- buf = calloc(width * height, sizeof(int16_t));
- if ( buf == NULL ) return 1;
-
- /* Prepare image data */
- for ( y=min_y; y<max_y; y++ ) {
- for ( x=min_x; x<max_x; x++ ) {
-
- int val, invalid;
- unsigned short out;
- signed int pn;
- struct panel *p;
- double dfs, dss;
- int fs, ss;
-
- invalid = reverse_2d_mapping(x, y, image->det, &p, &dfs, &dss);
- if ( invalid ) continue;
-
- fs = dfs;
- ss = dss; /* Explicit rounding */
-
- pn = panel_number(image->det, p);
- assert(pn != -1);
- p = &image->det->panels[pn];
- val = image->dp[pn][fs + p->w* ss];
-
- if ( val < -32767 ) {
- out = -32767;
- } else if ( val > 32767 ) {
- out = 32767;
- } else {
- out = val;
- }
-
- buf[(x - min_x) + (y - min_y) * width] = out;
-
- }
- }
-
- th = TIFFOpen(filename, "w");
- if ( th == NULL ) return 1;
-
- TIFFSetField(th, TIFFTAG_IMAGEWIDTH, width);
- TIFFSetField(th, TIFFTAG_IMAGELENGTH, height);
- TIFFSetField(th, TIFFTAG_SAMPLESPERPIXEL, 1);
- TIFFSetField(th, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT); /* (signed) */
- TIFFSetField(th, TIFFTAG_BITSPERSAMPLE, 16);
- TIFFSetField(th, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
- TIFFSetField(th, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
- TIFFSetField(th, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
- TIFFSetField(th, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(th, 0));
-
- line = _TIFFmalloc(TIFFScanlineSize(th));
-
- for ( y=0; y<height; y++ ) {
- TIFFWriteScanline(th, &buf[y*width], y, 0);
- }
- _TIFFfree(line);
-
- TIFFClose(th);
- free(buf);
-#else /* HAVE_TIFF */
- STATUS("No TIFF support.\n");
-#endif /* HAVE_TIFF */
- return 0;
-}
diff --git a/src/hdfsee-render.h b/src/hdfsee-render.h
deleted file mode 100644
index b60e2247..00000000
--- a/src/hdfsee-render.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * hdfsee-render.h
- *
- * Rendering bits for hdfsee
- *
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
- * a research centre of the Helmholtz Association.
- *
- * Authors:
- * 2011-2015 Thomas White <taw@physics.org>
- *
- * This file is part of CrystFEL.
- *
- * CrystFEL is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * CrystFEL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef HDFSEE_RENDER_H
-#define HDFSEE_RENDER_H
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_GDKPIXBUF
-#include <gdk-pixbuf/gdk-pixbuf.h>
-
-extern GdkPixbuf **render_panels(struct image *image,
- int binning, int scale, double boost,
- int *n_pixbufs);
-
-extern GdkPixbuf *render_get_colour_scale(size_t w, size_t h, int scale);
-
-#endif /* HAVE_GDKPIXBUF */
-
-extern int render_tiff_fp(struct image *image, const char *filename, int min_x,
- int max_x, int min_y, int max_y);
-
-extern int render_tiff_int16(struct image *image, const char *filename, double boost,
- int min_x, int max_x, int min_y, int max_y);
-
-#endif /* HDFSEE_RENDER_H */
diff --git a/src/hdfsee.c b/src/hdfsee.c
deleted file mode 100644
index 3e26f7ab..00000000
--- a/src/hdfsee.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * hdfsee.c
- *
- * Quick yet non-crappy HDF viewer
- *
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
- * a research centre of the Helmholtz Association.
- * Copyright © 2012 Richard Kirian
- *
- * Authors:
- * 2009-2014 Thomas White <taw@physics.org>
- * 2014 Valerio Mariani
- * 2012 Richard Kirian
- *
- * This file is part of CrystFEL.
- *
- * CrystFEL is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * CrystFEL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gtk/gtk.h>
-#include <getopt.h>
-
-#include "dw-hdfsee.h"
-#include "utils.h"
-#include "render.h"
-
-
-/* Global program state */
-DisplayWindow *main_window_list[64];
-size_t main_n_windows = 0;
-
-
-static void show_help(const char *s)
-{
- printf("Syntax: %s [options] image.h5\n\n", s);
- printf(
-"Quick HDF5 image viewer.\n"
-"\n"
-" -h, --help Display this help message.\n"
-" --version Print CrystFEL version number and exit.\n"
-"\n"
-" -p, --peak-overlay=<filename> Draw circles in positions listed in file.\n"
-" --ring-size=<n> Set the size for those circles.\n"
-" -i, --int-boost=<n> Multiply intensity by <n>.\n"
-" -b, --binning=<n> Set display binning to <n>.\n"
-" --filter-noise Apply an aggressive noise filter to the\n"
-" image data.\n"
-" --median-filter=<n> Apply a median filter to the image data.\n"
-" --calibration-mode Start in calibration mode\n"
-" --show-rings Overlay rings that indicate resolution.\n"
-" --simple-rings=XX,YY,... Overlay rings at specified radii XX, YY, ...\n"
-" in pixel units.\n"
-" -c, --colscale=<scale> Use the given colour scale. Choose from:\n"
-" mono : Greyscale, black is zero.\n"
-" invmono : Greyscale, white is zero.\n"
-" colour : Colour scale:\n"
-" black-blue-pink-red-orange-\n"
-" -yellow-white.\n"
-" -e, --image=<element> Start up displaying this image from the\n"
-" HDF5 file. When this option is used,\n"
-" information about the data layout\n"
-" from the geometry file is ignored (See\n"
-" manual page).\n"
-" Example: /data/data0.\n"
-" --event=<event code> Event to show from multi-event file.\n"
-" -g, --geometry=<filename> Use geometry from file for display.\n"
-" (When this option is used, the value of\n"
-" of the -e parameter is ignored)\n"
-" -o, --rigid-groups=<coll> Use rigid group collection <coll>.\n"
-"\n");
-}
-
-
-/* Called to notify that an image display window has been closed */
-void hdfsee_window_closed(DisplayWindow *dw)
-{
- size_t i;
-
- for ( i=0; i<main_n_windows; i++ ) {
-
- if ( main_window_list[i] == dw ) {
-
- size_t j;
-
- for ( j=i+1; j<main_n_windows; j++ ) {
- main_window_list[j] = main_window_list[j+1];
- }
-
- }
-
- }
-
- main_n_windows--;
-
- if ( main_n_windows == 0 ) gtk_main_quit();
-
-}
-
-
-int main(int argc, char *argv[])
-{
- int c;
- size_t i;
- int nfiles;
- char *peaks = NULL;
- char *geom_filename = NULL;
- double boost = 1.0;
- int binning = 2;
- int config_noisefilter = 0;
- int config_showrings = 0;
- int config_calibmode =0;
- int colscale = SCALE_COLOUR;
- char *cscale = NULL;
- char *element = NULL;
- char *event = NULL;
- char *rgcoll_name = NULL;
- double ring_size = 5.0;
- char *reslist = NULL;
- double ring_radii[128];
- int n_rings = -1;
- int median_filter = 0;
- struct detector *det_geom = NULL;
- struct beam_params cbeam;
- struct beam_params *beam = NULL;
-
- /* Long options */
- const struct option longopts[] = {
- {"help", 0, NULL, 'h'},
- {"version", 0, NULL, 4 },
- {"peak-overlay", 1, NULL, 'p'},
- {"int-boost", 1, NULL, 'i'},
- {"binning", 1, NULL, 'b'},
- {"filter-noise", 0, &config_noisefilter, 1},
- {"colscale", 1, NULL, 'c'},
- {"image", 1, NULL, 'e'},
- {"geometry", 1, NULL, 'g'},
- {"show-rings", 0, &config_showrings, 1},
- {"ring-size", 1, NULL, 2},
- {"simple-rings", 1, NULL, 'r'},
- {"median-filter", 1, NULL, 3},
- {"calibration-mode", 0, &config_calibmode, 1},
- {"event", 1, NULL, 5},
- {"rigid-groups", 1, NULL, 'o'},
- {0, 0, NULL, 0}
- };
-
- /* Default beam parameters */
- cbeam.photon_energy = 0.0;
- cbeam.photon_energy_from = NULL;
-
- /* This isn't great, but necessary to make the command-line UI and file
- * formats consistent with the other programs, which all use the C
- * locale. Better would be to have all the programs call
- * setlocale(LC_ALL, "") and use the C locale temporarily when reading
- * or writing a stream, reflection file, geometry file etc. */
- gtk_disable_setlocale();
-
- gtk_init(&argc, &argv);
-
- /* Short options */
- while ((c = getopt_long(argc, argv, "hp:b:i:c:e:g:2:r:m:o:",
- longopts, NULL)) != -1) {
-
- char *test;
-
- switch (c) {
-
- case 'h' :
- show_help(argv[0]);
- return 0;
-
- case 4 :
- printf("CrystFEL: " CRYSTFEL_VERSIONSTRING "\n");
- printf(CRYSTFEL_BOILERPLATE"\n");
- return 0;
-
- case 'p' :
- peaks = strdup(optarg);
- break;
-
- case 'i' :
- boost = atof(optarg);
- if ( boost <= 0 ) {
- ERROR("Intensity boost must be a positive"
- " number.\n");
- return 1;
- }
- break;
-
- case 'b' :
- binning = atoi(optarg);
- if ( binning < 1 ) {
- ERROR("Binning must be a positive integer.\n");
- return 1;
- }
- break;
-
- case 'c' :
- cscale = strdup(optarg);
- break;
-
- case 'e' :
- element = strdup(optarg);
- break;
-
- case 'g' :
- geom_filename = strdup(optarg);
- det_geom = get_detector_geometry(geom_filename, &cbeam);
- if ( det_geom == NULL ) {
- ERROR("Failed to read detector geometry "
- "from '%s'\n", optarg);
- return 1;
- }
- beam = &cbeam;
- break;
-
- case 'o' :
- rgcoll_name = strdup(optarg);
- break;
-
- case 2 :
- ring_size = strtod(optarg, &test);
- if ( test == optarg ) {
- ERROR("Ring size must be numerical.\n");
- return 1;
- }
- break;
-
- case 3 :
- median_filter = atoi(optarg);
- break;
-
- case 'r' :
- config_showrings = 1;
- reslist = strdup(optarg);
- int nchar = strlen(reslist);
- char thisvalue[128];
- int i;
- int j = 0;
- n_rings = 0;
- for ( i=0; i<=nchar; i++ ) {
- if ( ( reslist[i] != ',' )
- && ( reslist[i] != '\0' ) )
- {
- thisvalue[j] = reslist[i];
- j++;
- } else {
- thisvalue[j] = '\0';
- ring_radii[n_rings] = atof(thisvalue);
- n_rings++;
- j = 0;
- }
- }
- break;
-
- case 5 :
- event = strdup(optarg);
- break;
-
- case 0 :
- break;
-
- case '?' :
- break;
-
- default :
- ERROR("Unhandled option '%c'\n", c);
- break;
- }
-
- }
-
- nfiles = argc-optind;
-
- if ( nfiles < 1 ) {
- ERROR("You need to give me a file to open!\n");
- return -1;
- }
-
- if ( (element != NULL) && (event != NULL) ) {
- ERROR("The options --event and --element are "
- "mutually exclusive\n");
- return 1;
- }
-
- if ( event != NULL && geom_filename == NULL) {
- ERROR("The '--event' option requires geometry file\n");
- return 1;
- }
-
- if ( cscale == NULL ) cscale = strdup("colour");
- if ( strcmp(cscale, "mono") == 0 ) {
- colscale = SCALE_MONO;
- } else if ( strcmp(cscale, "invmono") == 0 ) {
- colscale = SCALE_INVMONO;
- } else if ( strcmp(cscale, "colour") == 0 ) {
- colscale = SCALE_COLOUR;
- } else if ( strcmp(cscale, "color") == 0 ) {
- colscale = SCALE_COLOUR;
- } else {
- ERROR("Unrecognised colour scale '%s'\n", cscale);
- return 1;
- }
- free(cscale);
-
- for ( i=0; i<nfiles; i++ ) {
- main_window_list[i] = displaywindow_open(argv[optind+i],
- geom_filename,
- peaks, boost, binning,
- config_noisefilter,
- config_calibmode,
- colscale, element,
- event, det_geom, beam,
- rgcoll_name,
- config_showrings,
- ring_radii,
- n_rings,
- ring_size,
- median_filter);
- if ( main_window_list[i] != NULL ) main_n_windows++;
- }
-
- if ( main_n_windows == 0 ) return 0;
- gtk_main();
-
- return 0;
-}
diff --git a/src/im-sandbox.c b/src/im-sandbox.c
index d7481f34..955e21e2 100644
--- a/src/im-sandbox.c
+++ b/src/im-sandbox.c
@@ -3,13 +3,13 @@
*
* Sandbox for indexing
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2012 Richard Kirian
* Copyright © 2012 Lorenzo Galli
*
* Authors:
- * 2010-2019 Thomas White <taw@physics.org>
+ * 2010-2020 Thomas White <taw@physics.org>
* 2014 Valerio Mariani
* 2011 Richard Kirian
* 2012 Lorenzo Galli
@@ -58,10 +58,6 @@
#include <sys/time.h>
#endif
-#include <events.h>
-#include <hdf5-file.h>
-#include <detector.h>
-
#include "im-sandbox.h"
#include "process_image.h"
#include "time-accounts.h"
@@ -113,10 +109,11 @@ struct get_pattern_ctx
{
FILE *fh;
int use_basename;
- struct detector *det;
+ const DataTemplate *dtempl;
const char *prefix;
char *filename;
- struct event_list *events;
+ char **events;
+ int n_events;
int event_index;
};
@@ -188,11 +185,12 @@ static void check_hung_workers(struct sandbox *sb)
}
-static char *read_prefixed_filename(struct get_pattern_ctx *gpctx, char **event)
+static char *read_prefixed_filename(struct get_pattern_ctx *gpctx,
+ char **event)
{
char* line;
- if ( event != NULL ) *event = NULL;
+ *event = NULL;
line = malloc(1024);
if ( line == NULL ) return NULL;
@@ -210,20 +208,18 @@ static char *read_prefixed_filename(struct get_pattern_ctx *gpctx, char **event)
} while ( line[0] == '\0' );
- /* Chop off event ID if requested */
- if ( event != NULL ) {
- size_t n = strlen(line);
- while ( line[n] != ' ' && n > 2 ) n--;
- if ( n != 2 ) {
- /* Event descriptor must contain "//".
- * If it doesn't, assume the filename just contains a
- * space. */
- if ( strstr(&line[n], "//") != NULL ) {
- line[n] = '\0';
- *event = strdup(&line[n+1]);
- }
- } /* else no spaces at all */
- }
+ /* Chop off event ID */
+ size_t n = strlen(line);
+ while ( line[n] != ' ' && n > 2 ) n--;
+ if ( n != 2 ) {
+ /* Event descriptor must contain "//".
+ * If it doesn't, assume the filename just contains a
+ * space. */
+ if ( strstr(&line[n], "//") != NULL ) {
+ line[n] = '\0';
+ *event = strdup(&line[n+1]);
+ }
+ } /* else no spaces at all */
if ( gpctx->use_basename ) {
char *tmp;
@@ -251,107 +247,59 @@ static char *read_prefixed_filename(struct get_pattern_ctx *gpctx, char **event)
}
-static struct filename_plus_event *get_pattern(struct get_pattern_ctx *gpctx)
+/* Return 0 for "no more" */
+static int get_pattern(struct get_pattern_ctx *gpctx,
+ char **pfilename, char **pevent)
{
char *filename;
char *evstr;
- /* If single-event geometry, just return next filename */
- if ( !multi_event_geometry(gpctx->det) )
- {
- struct filename_plus_event *fne;
- fne = malloc(sizeof(struct filename_plus_event));
- if ( fne == NULL ) return NULL;
- fne->filename = read_prefixed_filename(gpctx, NULL);
- if ( fne->filename == NULL ) {
- free(fne);
- return NULL;
- }
- fne->ev = NULL;
- return fne;
- }
-
- /* Ok, multi-event geometry. Is an event available already? */
+ /* Is an event available already? */
if ( (gpctx->events != NULL)
- && (gpctx->event_index < gpctx->events->num_events) )
+ && (gpctx->event_index < gpctx->n_events) )
{
- struct filename_plus_event *fne;
- fne = malloc(sizeof(struct filename_plus_event));
- fne->filename = strdup(gpctx->filename);
- fne->ev = copy_event(gpctx->events->events[gpctx->event_index++]);
-
- return fne;
- }
-
- /* No events in list. Time to top it up */
- filename = read_prefixed_filename(gpctx, &evstr);
-
- /* Nothing left in file -> we're done */
- if ( filename == NULL ) return NULL;
-
- /* Muppet check */
- if ( is_cbf_file(filename) == 1 ) {
- ERROR("Your geometry file is for a multi-event format, but "
- "this file is in CBF format.\n");
- ERROR("Your geometry file probably needs to be changed.\n");
- return NULL;
+ *pfilename = gpctx->filename;
+ *pevent = gpctx->events[gpctx->event_index++];
+ return 1;
}
- /* Does the line from the input file contain an event ID?
- * If so, just parse it and sent it straight back. */
- if ( evstr != NULL ) {
-
- /* Make an event list with only one item */
- struct event *ev = get_event_from_event_string(evstr);
- if ( ev == NULL ) {
- ERROR("Bad event descriptor: '%s'\n", evstr);
- return NULL;
- } else {
- struct filename_plus_event *fne;
- fne = malloc(sizeof(struct filename_plus_event));
- fne->filename = filename;
- fne->ev = ev;
- return fne;
- }
-
- } else {
+ do {
- /* Enumerate all the events in the file and then send the
- * first one back */
- struct hdfile *hdfile;
- struct filename_plus_event *fne;
+ /* No events in list. Time to top it up */
+ filename = read_prefixed_filename(gpctx, &evstr);
- hdfile = hdfile_open(filename);
- if ( hdfile == NULL ) {
- ERROR("Failed to open %s\n", filename);
- return NULL;
- }
+ /* Nothing left in file -> we're done */
+ if ( filename == NULL ) return 0;
- if ( gpctx->events != NULL ) {
- free_event_list(gpctx->events);
+ /* Does the line from the input file contain an event ID?
+ * If so, just send it straight back. */
+ if ( evstr != NULL ) {
+ *pfilename = filename;
+ *pevent = evstr;
+ return 1;
}
- gpctx->events = fill_event_list(hdfile, gpctx->det);
+ /* We got a filename, but no event. Attempt to expand... */
+ free(gpctx->events); /* Free the old list.
+ * NB The actual strings were freed
+ * by fill_queue */
+ gpctx->events = image_expand_frames(gpctx->dtempl, filename,
+ &gpctx->n_events);
if ( gpctx->events == NULL ) {
- ERROR("Failed to get event list.\n");
- return NULL;
+ ERROR("Failed to get event list from %s.\n",
+ filename);
}
- hdfile_close(hdfile);
+ } while ( gpctx->events == NULL );
- /* Save filename for next time */
- if ( gpctx->filename != NULL ) {
- free(gpctx->filename);
- }
- gpctx->filename = filename;
+ /* Save filename for next time */
+ free(gpctx->filename);
+ gpctx->filename = filename;
- gpctx->event_index = 0;
- fne = malloc(sizeof(struct filename_plus_event));
- fne->filename = strdup(gpctx->filename);
- fne->ev = copy_event(gpctx->events->events[gpctx->event_index++]);
- return fne;
-
- }
+ gpctx->event_index = 0;
+ *pfilename = gpctx->filename;
+ *pevent = gpctx->events[gpctx->event_index++];
+ return 1;
}
@@ -398,7 +346,6 @@ static int run_work(const struct index_args *iargs, Stream *st,
char filename[MAX_EV_LEN];
char event_str[MAX_EV_LEN];
int ser;
- struct event *ev;
int r;
if ( !sb->zmq ) {
@@ -444,31 +391,16 @@ static int run_work(const struct index_args *iargs, Stream *st,
if ( r != 3 ) continue;
- pargs.filename_p_e = initialize_filename_plus_event();
- pargs.filename_p_e->filename = strdup(filename);
+ pargs.filename = strdup(filename);
+ pargs.event = strdup(event_str);
- if ( strcmp(event_str, "(none)") != 0 ) {
-
- ev = get_event_from_event_string(event_str);
- if ( ev == NULL ) {
- ERROR("Bad event string '%s'\n", event_str);
- continue;
- }
- pargs.filename_p_e->ev = ev;
-
- } else {
-
- pargs.filename_p_e->ev = NULL;
-
- }
pargs.msgpack_obj = NULL;
} else {
pargs.msgpack_obj = im_zmq_fetch(zmqstuff);
- pargs.filename_p_e = initialize_filename_plus_event();
- pargs.filename_p_e->filename = strdup("(from ZMQ)");
- pargs.filename_p_e->ev = NULL;
+ pargs.filename = strdup("(from ZMQ)");
+ pargs.event = NULL;
ser = 0; /* FIXME */
}
@@ -477,9 +409,7 @@ static int run_work(const struct index_args *iargs, Stream *st,
process_image(iargs, &pargs, st, cookie, tmpdir, ser,
sb->shared, taccs, sb->shared->last_task[cookie]);
- if ( !sb->zmq ) {
- free_filename_plus_event(pargs.filename_p_e);
- } else {
+ if ( sb->zmq ) {
im_zmq_clean(zmqstuff);
}
@@ -489,9 +419,6 @@ static int run_work(const struct index_args *iargs, Stream *st,
time_accounts_set(taccs, TACC_FINALCLEANUP);
cleanup_indexing(iargs->ipriv);
- free_detector_geometry(iargs->det);
- free(iargs->hdf5_peak_path);
- free_imagefile_field_list(iargs->copyme);
cell_free(iargs->cell);
if ( sb->profile ) time_accounts_print(taccs);
time_accounts_free(taccs);
@@ -523,7 +450,7 @@ static int pump_chunk(FILE *fh, int ofd)
if ( chunk_started ) {
ERROR("EOF during chunk!\n");
lwrite(ofd, "Unfinished chunk!\n");
- lwrite(ofd, CHUNK_END_MARKER"\n");
+ lwrite(ofd, STREAM_CHUNK_END_MARKER"\n");
} /* else normal end of output */
return 1;
}
@@ -536,7 +463,7 @@ static int pump_chunk(FILE *fh, int ofd)
if ( strcmp(line, "FLUSH\n") == 0 ) break;
lwrite(ofd, line);
- if ( strcmp(line, CHUNK_END_MARKER"\n") == 0 ) break;
+ if ( strcmp(line, STREAM_CHUNK_END_MARKER"\n") == 0 ) break;
} while ( 1 );
return 0;
@@ -603,7 +530,7 @@ static void try_read(struct sandbox *sb, TimeAccounts *taccs)
struct timeval tv;
fd_set fds;
int fdmax;
- const int ofd = get_stream_fd(sb->stream);
+ const int ofd = stream_get_fd(sb->stream);
time_accounts_set(taccs, TACC_SELECT);
@@ -738,12 +665,11 @@ static void start_worker_process(struct sandbox *sb, int slot)
* prefix
*/
- st = open_stream_fd_for_write(stream_pipe[1]);
+ st = stream_open_fd_for_write(stream_pipe[1], sb->iargs->dtempl);
r = run_work(sb->iargs, st, slot, tmp, sb);
- close_stream(st);
+ stream_close(st);
free(tmp);
- free(sb->iargs->beam->photon_energy_from);
munmap(sb->shared, sizeof(struct sb_shm));
@@ -861,19 +787,16 @@ static int fill_queue(struct get_pattern_ctx *gpctx, struct sandbox *sb)
while ( sb->shared->n_events < QUEUE_SIZE ) {
- struct filename_plus_event *ne;
+ char *filename;
char *evstr;
- ne = get_pattern(gpctx);
- if ( ne == NULL ) return 1; /* No more */
+ if ( !get_pattern(gpctx, &filename, &evstr) ) return 1;
memset(sb->shared->queue[sb->shared->n_events], 0, MAX_EV_LEN);
- evstr = get_event_string(ne->ev),
snprintf(sb->shared->queue[sb->shared->n_events++], MAX_EV_LEN,
- "%s %s %i", ne->filename, evstr, sb->serial++);
- free(evstr);
+ "%s %s %i", filename, evstr, sb->serial++);
sem_post(sb->queue_sem);
- free_filename_plus_event(ne);
+ free(evstr);
}
return 0;
@@ -1100,7 +1023,7 @@ int create_sandbox(struct index_args *iargs, int n_proc, char *prefix,
gpctx.fh = fh;
gpctx.use_basename = config_basename;
- gpctx.det = iargs->det;
+ gpctx.dtempl = iargs->dtempl;
gpctx.prefix = prefix;
gpctx.filename = NULL;
gpctx.events = NULL;
diff --git a/src/im-sandbox.h b/src/im-sandbox.h
index 362856f4..2e006be4 100644
--- a/src/im-sandbox.h
+++ b/src/im-sandbox.h
@@ -3,7 +3,7 @@
*
* Sandbox for indexing
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2012 Richard Kirian
* Copyright © 2012 Lorenzo Galli
diff --git a/src/im-zmq.c b/src/im-zmq.c
index fa0306d3..dea8515b 100644
--- a/src/im-zmq.c
+++ b/src/im-zmq.c
@@ -3,13 +3,13 @@
*
* ZMQ data interface
*
- * Copyright © 2017-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2017-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2018 Thomas White <taw@physics.org>
- * 2014 Valerio Mariani
- * 2017 Stijn de Graaf
+ * 2018-2020 Thomas White <taw@physics.org>
+ * 2014 Valerio Mariani
+ * 2017 Stijn de Graaf
*
* This file is part of CrystFEL.
*
@@ -35,16 +35,17 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
-#include <hdf5.h>
#include <assert.h>
#include <unistd.h>
#include <zmq.h>
#include <msgpack.h>
-#include "events.h"
-#include "image.h"
-#include "hdf5-file.h"
-#include "utils.h"
+#include <image.h>
+#include <utils.h>
+
+#include "im-zmq.h"
+
+#include "datatemplate_priv.h"
struct im_zmq
@@ -134,357 +135,3 @@ void im_zmq_shutdown(struct im_zmq *z)
zmq_close(z->socket);
zmq_ctx_destroy(z->ctx);
}
-
-
-static msgpack_object *find_msgpack_kv(msgpack_object *obj, const char *key)
-{
- int i;
-
- if ( obj == NULL ) return NULL;
- if ( obj->type != MSGPACK_OBJECT_MAP ) return NULL;
-
- for ( i=0; i<obj->via.map.size; i++ ) {
- const char *kstr;
- size_t klen;
- assert(obj->via.map.ptr[i].key.type == MSGPACK_OBJECT_STR);
- kstr = obj->via.map.ptr[i].key.via.str.ptr;
- klen = obj->via.map.ptr[i].key.via.str.size;
- if ( strncmp(kstr, key, klen) == 0 ) {
- return &obj->via.map.ptr[i].val;
- }
- }
- return NULL;
-}
-
-
-/**
- * get_peaks_msgpack:
- * @obj: A %msgpack_object containing data in OnDA format
- * @image: An %image structure
- * @half_pixel_shift: Non-zero if 0.5 should be added to all peak coordinates
- *
- * Get peaks from msgpack_object. The data should be in a map, with the value
- * given by "peak_list" as an array of arrays. The first of these should contain
- * the list of fs positions of the peaks, the second the ss positions, and the
- * third the intensities of the peaks.
- *
- * http://c.msgpack.org/c/ provides documentation on msgpack objects
- *
- * CrystFEL considers all peak locations to be distances from the corner of the
- * detector panel, in pixel units, consistent with its description of detector
- * geometry (see 'man crystfel_geometry'). The software which generates the
- * CXI files, including Cheetah, may instead consider the peak locations to be
- * pixel indices in the data array. In this case, the peak coordinates should
- * have 0.5 added to them. This will be done if @half_pixel_shift is non-zero.
- *
- * Returns: non-zero on error, zero otherwise.
- *
- */
-int get_peaks_msgpack(msgpack_object *obj, struct image *image,
- int half_pixel_shift)
-{
-
- int num_peaks;
- int pk;
- msgpack_object *peak_list;
- msgpack_object *peak_x;
- msgpack_object *peak_y;
- msgpack_object *peak_i;
- double peak_offset = half_pixel_shift ? 0.5 : 0.0;
-
- if ( obj == NULL ) {
- ERROR("No MessagePack object to get peaks from.\n");
- return 1;
- }
-
- /* Object has structure:
- * {
- * "peak_list": [[peak_x], [peak_y], [peak_i]]
- * "key2":val2,
- * ...
- * }
- */
- peak_list = find_msgpack_kv(obj, "peak_list");
- peak_x = &peak_list->via.array.ptr[0];
- peak_y = &peak_list->via.array.ptr[1];
- peak_i = &peak_list->via.array.ptr[2];
-
- /* Length of peak_x array gives number of peaks */
- num_peaks = peak_x->via.array.size;
-
- if ( image->features != NULL ) {
- image_feature_list_free(image->features);
- }
- image->features = image_feature_list_new();
-
- for ( pk=0; pk<num_peaks; pk++ ) {
-
- float fs, ss, val;
- struct panel *p;
-
- /* Retrieve data from peak_list and apply half_pixel_shift,
- * if appropriate */
- fs = peak_x->via.array.ptr[pk].via.f64 + peak_offset;
- ss = peak_y->via.array.ptr[pk].via.f64 + peak_offset;
- val = peak_i->via.array.ptr[pk].via.f64;
-
- p = find_orig_panel(image->det, fs, ss);
- if ( p == NULL ) continue;
- if ( p->no_index ) continue;
-
- /* Convert coordinates to panel-relative */
- fs = fs - p->orig_min_fs;
- ss = ss - p->orig_min_ss;
-
- image_add_feature(image->features, fs, ss, p, image, val, NULL);
- }
-
- return 0;
-}
-
-
-static void im_zmq_fill_in_clen(struct detector *det)
-{
- int i = 0;
- for ( i=0; i<det->n_panels; i++) {
- struct panel *p = &det->panels[i];
- if ( p->clen_from != NULL ) {
- ERROR("Can't get clen over ZMQ yet.\n");
- }
- adjust_centering_for_rail(p);
- }
-}
-
-
-static void im_zmq_fill_in_beam_parameters(struct beam_params *beam,
- struct image *image)
-{
- double eV;
- if ( beam->photon_energy_from == NULL ) {
- /* Explicit value given */
- eV = beam->photon_energy;
- } else {
- ERROR("Can't get photon energy over ZMQ yet.\n");
- eV = 0.0;
- }
- image->lambda = ph_en_to_lambda(eV_to_J(eV))*beam->photon_energy_scale;
-}
-
-
-static int unpack_slab(struct image *image, double *data,
- int data_width, int data_height)
-{
- uint16_t *flags = NULL;
- float *sat = NULL;
- int pi;
-
- image->dp = malloc(image->det->n_panels*sizeof(float *));
- image->bad = malloc(image->det->n_panels*sizeof(int *));
- image->sat = malloc(image->det->n_panels*sizeof(float *));
- if ( (image->dp == NULL) || (image->bad == NULL) || (image->sat == NULL) ) {
- ERROR("Failed to allocate data arrays.\n");
- return 1;
- }
-
- for ( pi=0; pi<image->det->n_panels; pi++ ) {
-
- struct panel *p;
- int fs, ss;
-
- p = &image->det->panels[pi];
- image->dp[pi] = malloc(p->w*p->h*sizeof(float));
- image->bad[pi] = malloc(p->w*p->h*sizeof(int));
- image->sat[pi] = malloc(p->w*p->h*sizeof(float));
- if ( (image->dp[pi] == NULL) || (image->bad[pi] == NULL)
- || (image->sat[pi] == NULL) )
- {
- ERROR("Failed to allocate panel\n");
- return 1;
- }
-
- if ( (p->orig_min_fs + p->w > data_width)
- || (p->orig_min_ss + p->h > data_height) )
- {
- ERROR("Panel %s is outside range of data provided\n",
- p->name);
- return 1;
- }
-
- for ( ss=0; ss<p->h; ss++) {
- for ( fs=0; fs<p->w; fs++) {
-
- int idx;
- int cfs, css;
- int bad = 0;
-
- cfs = fs+p->orig_min_fs;
- css = ss+p->orig_min_ss;
- idx = cfs + css*data_width;
-
- image->dp[pi][fs+p->w*ss] = data[idx];
-
- if ( sat != NULL ) {
- image->sat[pi][fs+p->w*ss] = sat[idx];
- } else {
- image->sat[pi][fs+p->w*ss] = INFINITY;
- }
-
- if ( p->no_index ) bad = 1;
-
- if ( in_bad_region(image->det, p, cfs, css) ) {
- bad = 1;
- }
-
- if ( isnan(data[idx]) || isinf(data[idx]) ) bad = 1;
-
- if ( flags != NULL ) {
-
- int f;
-
- f = flags[idx];
-
- if ( (f & image->det->mask_good)
- != image->det->mask_good ) bad = 1;
-
- if ( f & image->det->mask_bad ) bad = 1;
-
- }
- image->bad[pi][fs+p->w*ss] = bad;
- }
- }
-
- }
-
- return 0;
-}
-
-
-static double *find_msgpack_data(msgpack_object *obj, int *width, int *height)
-{
- msgpack_object *corr_data_obj;
- msgpack_object *data_obj;
- msgpack_object *shape_obj;
- double *data;
-
- corr_data_obj = find_msgpack_kv(obj, "corr_data");
- if ( corr_data_obj == NULL ) {
- ERROR("No corr_data MessagePack object found.\n");
- return NULL;
- }
-
- data_obj = find_msgpack_kv(corr_data_obj, "data");
- if ( data_obj == NULL ) {
- ERROR("No data MessagePack object found inside corr_data.\n");
- return NULL;
- }
- if ( data_obj->type != MSGPACK_OBJECT_STR ) {
- ERROR("corr_data.data isn't a binary object.\n");
- return NULL;
- }
- data = (double *)data_obj->via.str.ptr;
-
- shape_obj = find_msgpack_kv(corr_data_obj, "shape");
- if ( shape_obj == NULL ) {
- ERROR("No shape MessagePack object found inside corr_data.\n");
- return NULL;
- }
- if ( shape_obj->type != MSGPACK_OBJECT_ARRAY ) {
- ERROR("corr_data.shape isn't an array object.\n");
- return NULL;
- }
- if ( shape_obj->via.array.size != 2 ) {
- ERROR("corr_data.shape is wrong size (%i, should be 2)\n",
- shape_obj->via.array.size);
- return NULL;
- }
- if ( shape_obj->via.array.ptr[0].type != MSGPACK_OBJECT_POSITIVE_INTEGER ) {
- ERROR("corr_data.shape contains wrong type of element.\n");
- return NULL;
- }
- *height = shape_obj->via.array.ptr[0].via.i64;
- *width = shape_obj->via.array.ptr[1].via.i64;
- return data;
-}
-
-
-static double *zero_array(struct detector *det, int *dw, int *dh)
-{
- int max_fs = 0;
- int max_ss = 0;
- int pi;
- double *data;
-
- for ( pi=0; pi<det->n_panels; pi++ ) {
- if ( det->panels[pi].orig_max_fs > max_fs ) {
- max_fs = det->panels[pi].orig_max_fs;
- }
- if ( det->panels[pi].orig_max_ss > max_ss ) {
- max_ss = det->panels[pi].orig_max_ss;
- }
- }
-
- data = calloc((max_fs+1)*(max_ss+1), sizeof(double));
- *dw = max_fs+1;
- *dh = max_ss+1;
- return data;
-}
-
-
-/* Unpacks the raw panel data from a msgpack_object, applies panel geometry,
- * and stores the resulting data in an image struct. Object has structure
- * {
- * "corr_data":
- * {
- * "data": binary_data,
- * "shape": [data_height, data_width],
- * ...
- * ...
- * },
- * "key2": val2,
- * ...
- * ...
- * }
- */
-int unpack_msgpack_data(msgpack_object *obj, struct image *image,
- int no_image_data)
-{
- int data_width, data_height;
- double *data;
-
- if ( image->det == NULL ) {
- ERROR("Geometry not available.\n");
- return 1;
- }
-
- if ( obj == NULL ) {
- ERROR("No MessagePack object!\n");
- return 1;
- }
-
- if ( !no_image_data ) {
- data = find_msgpack_data(obj, &data_width, &data_height);
- if ( data == NULL ) {
- ERROR("No image data in MessagePack object.\n");
- return 1;
- }
- } else {
- data = zero_array(image->det, &data_width, &data_height);
- }
-
- if ( unpack_slab(image, data, data_width, data_height) ) {
- ERROR("Failed to unpack data slab.\n");
- return 1;
- }
-
- if ( image->beam != NULL ) {
- im_zmq_fill_in_beam_parameters(image->beam, image);
- if ( image->lambda > 1000 ) {
- ERROR("Warning: Missing or nonsensical wavelength "
- "(%e m).\n", image->lambda);
- }
- }
- im_zmq_fill_in_clen(image->det);
- fill_in_adu(image);
-
- return 0;
-}
diff --git a/src/im-zmq.h b/src/im-zmq.h
index 50a9dde3..87128895 100644
--- a/src/im-zmq.h
+++ b/src/im-zmq.h
@@ -3,7 +3,7 @@
*
* ZMQ data interface
*
- * Copyright © 2017-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2017-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
@@ -36,8 +36,6 @@
#include <config.h>
#endif
-#include "image.h"
-
#if defined(HAVE_MSGPACK) && defined(HAVE_ZMQ)
#include <msgpack.h>
@@ -50,12 +48,6 @@ extern void im_zmq_shutdown(struct im_zmq *z);
extern msgpack_object *im_zmq_fetch(struct im_zmq *z);
-extern int get_peaks_msgpack(msgpack_object *obj, struct image *image,
- int half_pixel_shift);
-
-extern int unpack_msgpack_data(msgpack_object *obj, struct image *image,
- int no_image_data);
-
#else /* defined(HAVE_MSGPACK) && defined(HAVE_ZMQ) */
static UNUSED struct im_zmq *im_zmq_connect(const char *zmq_address) { return NULL; }
@@ -66,12 +58,6 @@ static UNUSED void im_zmq_shutdown(struct im_zmq *z) { return; }
static UNUSED void *im_zmq_fetch(struct im_zmq *z) { return NULL; }
-static UNUSED int get_peaks_msgpack(void *obj, struct image *image,
- int half_pixel_shift) { return 0; }
-
-static UNUSED int unpack_msgpack_data(void *obj, struct image *image,
- int no_image_data) { return 1; }
-
#endif /* defined(HAVE_MSGPACK) && defined(HAVE_ZMQ) */
#endif /* CRYSTFEL_ZMQ_H */
diff --git a/src/indexamajig.c b/src/indexamajig.c
index bfeb2960..4b12194c 100644
--- a/src/indexamajig.c
+++ b/src/indexamajig.c
@@ -3,13 +3,13 @@
*
* Index patterns, output hkl+intensity etc.
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2012 Richard Kirian
* Copyright © 2012 Lorenzo Galli
*
* Authors:
- * 2010-2019 Thomas White <taw@physics.org>
+ * 2010-2021 Thomas White <taw@physics.org>
* 2011 Richard Kirian
* 2012 Lorenzo Galli
* 2012 Chunhong Yoon
@@ -44,48 +44,26 @@
#include <string.h>
#include <unistd.h>
#include <argp.h>
-#include <hdf5.h>
#include <gsl/gsl_errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
-#include "utils.h"
-#include "hdf5-file.h"
-#include "index.h"
-#include "peaks.h"
-#include "detector.h"
-#include "filters.h"
-#include "thread-pool.h"
-#include "geometry.h"
-#include "stream.h"
-#include "reflist-utils.h"
-#include "cell-utils.h"
-#include "integration.h"
-#include "taketwo.h"
-#include "im-sandbox.h"
-#include "image.h"
-
-
-static void add_geom_beam_stuff_to_field_list(struct imagefile_field_list *copyme,
- struct detector *det,
- struct beam_params *beam)
-{
- int i;
-
- for ( i=0; i<det->n_panels; i++ ) {
-
- struct panel *p = &det->panels[i];
+#include <utils.h>
+#include <index.h>
+#include <peaks.h>
+#include <filters.h>
+#include <thread-pool.h>
+#include <geometry.h>
+#include <stream.h>
+#include <reflist-utils.h>
+#include <cell-utils.h>
+#include <integration.h>
+#include <image.h>
+#include <datatemplate.h>
- if ( p->clen_from != NULL ) {
- add_imagefile_field(copyme, p->clen_from);
- }
- }
-
- if ( beam->photon_energy_from != NULL ) {
- add_imagefile_field(copyme, beam->photon_energy_from);
- }
-}
+#include "im-sandbox.h"
+#include "version.h"
struct indexamajig_arguments
@@ -99,20 +77,21 @@ struct indexamajig_arguments
int check_prefix;
int n_proc;
char *cellfile;
- char *spectrum_fn;
char *indm_str;
int basename;
int zmq;
int no_image_data;
+ int no_mask_data;
int serial_start;
char *temp_location;
- char *command_line_peak_path;
int if_refine;
int if_checkcell;
int if_peaks;
int if_multi;
int if_retry;
int profile; /* Whether to do wall-clock time profiling */
+ char **copy_headers;
+ int n_copy_headers;
TakeTwoOptions **taketwo_opts_ptr;
FelixOptions **felix_opts_ptr;
@@ -123,8 +102,23 @@ struct indexamajig_arguments
static void show_version(FILE *fh, struct argp_state *state)
{
- printf("CrystFEL: " CRYSTFEL_VERSIONSTRING "\n");
- printf(CRYSTFEL_BOILERPLATE"\n");
+ printf("CrystFEL: %s\n", crystfel_version_string());
+ printf("%s\n", crystfel_licence_string());
+}
+
+
+static void add_copy_header(struct indexamajig_arguments *args,
+ const char *header)
+{
+ char **new_copy_headers = realloc(args->copy_headers,
+ (args->n_copy_headers+1)*sizeof(char *));
+ if ( new_copy_headers == NULL ) {
+ ERROR("Failed to add copy header '%s'\n", header);
+ return;
+ }
+
+ args->copy_headers = new_copy_headers;
+ args->copy_headers[args->n_copy_headers++] = strdup(header);
}
@@ -212,9 +206,11 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
break;
case 209 :
- args->spectrum_fn = strdup(arg);
- ERROR("WARNING: Prediction using arbitrary spectrum does not "
- "yet work in a useful way.\n");
+ ERROR("--spectrum-filename is no longer used.\n");
+ return 1;
+
+ case 210 :
+ args->no_mask_data = 1;
break;
/* ---------- Peak search ---------- */
@@ -224,21 +220,8 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
break;
case 301 :
- if ( strcmp(arg, "zaef") == 0 ) {
- args->iargs.peaks = PEAK_ZAEF;
- } else if ( strcmp(arg, "peakfinder8") == 0 ) {
- args->iargs.peaks = PEAK_PEAKFINDER8;
- } else if ( strcmp(arg, "hdf5") == 0 ) {
- args->iargs.peaks = PEAK_HDF5;
- } else if ( strcmp(arg, "cxi") == 0 ) {
- args->iargs.peaks = PEAK_CXI;
- } else if ( strcmp(arg, "peakfinder9") == 0 ) {
- args->iargs.peaks = PEAK_PEAKFINDER9;
- } else if ( strcmp(arg, "msgpack") == 0 ) {
- args->iargs.peaks = PEAK_MSGPACK;
- } else if ( strcmp(arg, "none") == 0 ) {
- args->iargs.peaks = PEAK_NONE;
- } else {
+ args->iargs.peaks = parse_peaksearch(arg);
+ if ( args->iargs.peaks == PEAK_ERROR ) {
ERROR("Unrecognised peak detection method '%s'\n", arg);
return EINVAL;
}
@@ -259,12 +242,11 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
ERROR("Invalid value for --min-peaks\n");
return EINVAL;
}
- (*(args->pinkindexer_opts_ptr))->min_peaks = args->iargs.min_peaks;
break;
case 304 :
- free(args->command_line_peak_path);
- args->command_line_peak_path = strdup(arg);
+ ERROR("The option --hdf5-peak-path is no longer used.\n");
+ ERROR("Set the peak path in the geometry file.\n");
break;
case 305 :
@@ -395,6 +377,8 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
break;
case 401 :
+ /* Values in 'tols' are in frac (not %) and rad
+ * Conversion happens a few lines below */
r = sscanf(arg, "%f,%f,%f,%f,%f,%f",
&args->iargs.tols[0], &args->iargs.tols[1], &args->iargs.tols[2],
&args->iargs.tols[3], &args->iargs.tols[4], &args->iargs.tols[5]);
@@ -466,6 +450,21 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
* better than the user expected. */
break;
+ case 413 :
+ if (sscanf(arg, "%f", &args->iargs.wavelength_estimate) != 1)
+ {
+ ERROR("Invalid value for --wavelength-estimate\n");
+ return EINVAL;
+ }
+ break;
+
+ case 414 :
+ if (sscanf(arg, "%d", &args->iargs.n_threads) != 1)
+ {
+ ERROR("Invalid value for --max-indexer-threads\n");
+ return EINVAL;
+ }
+ break;
/* ---------- Integration ---------- */
case 501 :
@@ -559,15 +558,17 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
break;
case 602 :
- add_imagefile_field(args->iargs.copyme, arg);
+ add_copy_header(args, arg);
break;
case 603 :
- args->iargs.stream_peaks = 0;
+ args->iargs.stream_flags = CLEAR_BIT(args->iargs.stream_flags,
+ STREAM_PEAKS);
break;
case 604 :
- args->iargs.stream_refls = 0;
+ args->iargs.stream_flags = CLEAR_BIT(args->iargs.stream_flags,
+ STREAM_REFLECTIONS);
break;
case 605 :
@@ -594,13 +595,13 @@ int main(int argc, char *argv[])
char *tmpdir; /* e.g. /tmp/indexamajig.12345 */
char *rn; /* e.g. /home/taw/indexing */
int r;
- struct beam_params beam;
char *zmq_address = NULL;
int timeout = 240;
TakeTwoOptions *taketwo_opts = NULL;
FelixOptions *felix_opts = NULL;
XGandalfOptions *xgandalf_opts = NULL;
PinkIndexerOptions *pinkindexer_opts = NULL;
+ double wl_from_dt;
/* Defaults for "top level" arguments */
args.filename = NULL;
@@ -611,18 +612,18 @@ int main(int argc, char *argv[])
args.check_prefix = 1;
args.n_proc = 1;
args.cellfile = NULL;
- args.spectrum_fn = NULL;
args.indm_str = NULL;
args.basename = 0;
args.zmq = 0;
args.serial_start = 1;
- args.command_line_peak_path = NULL;
args.if_peaks = 1;
args.if_multi = 0;
args.if_retry = 1;
args.if_refine = 1;
args.if_checkcell = 1;
args.profile = 0;
+ args.copy_headers = NULL;
+ args.n_copy_headers = 0;
args.taketwo_opts_ptr = &taketwo_opts;
args.felix_opts_ptr = &felix_opts;
args.xgandalf_opts_ptr = &xgandalf_opts;
@@ -632,12 +633,12 @@ int main(int argc, char *argv[])
args.iargs.cell = NULL;
args.iargs.noisefilter = 0;
args.iargs.median_filter = 0;
- args.iargs.tols[0] = 0.05;
- args.iargs.tols[1] = 0.05;
- args.iargs.tols[2] = 0.05;
- args.iargs.tols[3] = deg2rad(1.5);
- args.iargs.tols[4] = deg2rad(1.5);
- args.iargs.tols[5] = deg2rad(1.5);
+ args.iargs.tols[0] = 0.05; /* frac (not %) */
+ args.iargs.tols[1] = 0.05; /* frac (not %) */
+ args.iargs.tols[2] = 0.05; /* frac (not %) */
+ args.iargs.tols[3] = deg2rad(1.5); /* radians */
+ args.iargs.tols[4] = deg2rad(1.5); /* radians */
+ args.iargs.tols[5] = deg2rad(1.5); /* radians */
args.iargs.threshold = 800.0;
args.iargs.min_sq_gradient = 100000.0;
args.iargs.min_snr = 5.0;
@@ -651,12 +652,9 @@ int main(int argc, char *argv[])
args.iargs.min_sig = 11.0;
args.iargs.min_peak_over_neighbour = -INFINITY;
args.iargs.check_hdf5_snr = 0;
- args.iargs.det = NULL;
+ args.iargs.dtempl = NULL;
args.iargs.peaks = PEAK_ZAEF;
- args.iargs.beam = &beam;
- args.iargs.hdf5_peak_path = NULL;
args.iargs.half_pixel_shift = 1;
- args.iargs.copyme = NULL;
args.iargs.pk_inn = -1.0;
args.iargs.pk_mid = -1.0;
args.iargs.pk_out = -1.0;
@@ -665,18 +663,12 @@ int main(int argc, char *argv[])
args.iargs.ir_out = -1.0;
args.iargs.use_saturated = 1;
args.iargs.no_revalidate = 0;
- args.iargs.stream_peaks = 1;
- args.iargs.stream_refls = 1;
+ args.iargs.stream_flags = STREAM_PEAKS | STREAM_REFLECTIONS;
args.iargs.stream_nonhits = 1;
args.iargs.int_diag = INTDIAG_NONE;
args.iargs.min_peaks = 0;
args.iargs.overpredict = 0;
args.iargs.wait_for_file = 0;
- args.iargs.copyme = new_imagefile_field_list();
- if ( args.iargs.copyme == NULL ) {
- ERROR("Couldn't allocate HDF5 field list.\n");
- return 1;
- }
args.iargs.ipriv = NULL; /* No default */
args.iargs.int_meth = integration_method("rings-nocen-nosat-nograd", NULL);
args.iargs.push_res = +INFINITY;
@@ -684,6 +676,9 @@ int main(int argc, char *argv[])
args.iargs.fix_profile_r = -1.0;
args.iargs.fix_divergence = -1.0;
args.iargs.no_image_data = 0;
+ args.iargs.no_mask_data = 0;
+ args.iargs.wavelength_estimate = NAN;
+ args.iargs.n_threads = 1;
argp_program_version_hook = show_version;
@@ -716,15 +711,16 @@ int main(int argc, char *argv[])
"processing"},
{"zmq-msgpack", 207, NULL, OPTION_NO_USAGE, "Receive data in MessagePack format "
"over ZMQ"},
- {"no-image-data", 208, NULL, OPTION_NO_USAGE, "Do not load image data (from ZMQ)"},
+ {"no-image-data", 208, NULL, OPTION_NO_USAGE, "Do not load image data"},
{"spectrum-file", 209, "fn", OPTION_NO_USAGE | OPTION_HIDDEN,
"File containing radiation spectrum"},
+ {"no-mask-data", 210, NULL, OPTION_NO_USAGE, "Do not load mask data"},
{NULL, 0, 0, OPTION_DOC, "Peak search options:", 3},
{"peaks", 301, "method", 0, "Peak search method. Default: zaef"},
{"peak-radius", 302, "r1,r2,r3", OPTION_NO_USAGE, "Radii for peak search"},
{"min-peaks", 303, "n", OPTION_NO_USAGE, "Minimum number of peaks for indexing"},
- {"hdf5-peaks", 304, "p", OPTION_NO_USAGE, "Location of peak table in HDF5 file"},
+ {"hdf5-peaks", 304, "p", OPTION_HIDDEN, "Location of peak table in HDF5 file"},
{"median-filter", 305, "n", OPTION_NO_USAGE, "Apply median filter to image data"},
{"filter-noise", 306, NULL, OPTION_NO_USAGE, "Apply noise filter to image data"},
{"threshold", 't', "adu", OPTION_NO_USAGE, "Threshold for peak detection "
@@ -780,6 +776,10 @@ int main(int argc, char *argv[])
"accounted for by the indexing solution"},
{"check-peaks", 411, NULL, OPTION_HIDDEN, NULL},
{"no-cell-combinations", 412, NULL, OPTION_HIDDEN, NULL},
+ {"wavelength-estimate", 413, "metres", 0,
+ "Estimate of the incident radiation wavelength, in metres."},
+ {"max-indexer-threads", 414, "n", 0,
+ "Maximum number of threads allowed for indexing engines."},
{NULL, 0, 0, OPTION_DOC, "Integration options:", 5},
{"integration", 501, "method", OPTION_NO_USAGE, "Integration method"},
@@ -797,8 +797,9 @@ int main(int argc, char *argv[])
{NULL, 0, 0, OPTION_DOC, "Output options:", 6},
{"no-non-hits-in-stream", 601, NULL, OPTION_NO_USAGE, "Don't include non-hits in "
"stream (see --min-peaks)"},
- {"copy-hdf5-field", 602, "f", OPTION_NO_USAGE, "Put the value of this HDF5 field "
- "into the stream"},
+ {"copy-hdf5-field", 602, "f", OPTION_HIDDEN, NULL},
+ {"copy-header", 602, "f", OPTION_NO_USAGE, "Put the value of this image header "
+ "field into the stream"},
{"no-peaks-in-stream", 603, NULL, OPTION_NO_USAGE, "Don't put peak search results "
"in stream"},
{"no-refls-in-stream", 604, NULL, OPTION_NO_USAGE, "Don't put integration results "
@@ -861,31 +862,18 @@ int main(int argc, char *argv[])
return 1;
}
- /* Load detector geometry */
- args.iargs.det = get_detector_geometry_2(args.geom_filename,
- args.iargs.beam,
- &args.iargs.hdf5_peak_path);
- if ( args.iargs.det == NULL ) {
- ERROR("Failed to read detector geometry from '%s'\n",
- args.geom_filename);
+ /* Load data template (new API) */
+ args.iargs.dtempl = data_template_new_from_file(args.geom_filename);
+ if ( args.iargs.dtempl == NULL ) {
+ ERROR("Failed to read detector geometry from '%s'"
+ " (for new API)\n", args.geom_filename);
return 1;
}
- add_geom_beam_stuff_to_field_list(args.iargs.copyme, args.iargs.det,
- args.iargs.beam);
-
- /* If no peak path from geometry file, use these (but see later) */
- if ( args.iargs.hdf5_peak_path == NULL ) {
- if ( args.iargs.peaks == PEAK_HDF5 ) {
- args.iargs.hdf5_peak_path = strdup("/processing/hitfinder/peakinfo");
- } else if ( args.iargs.peaks == PEAK_CXI ) {
- args.iargs.hdf5_peak_path = strdup("/entry_1/result_1");
- }
- }
- /* If an HDF5 peak path was given on the command line, use it */
- if ( args.command_line_peak_path != NULL ) {
- free(args.iargs.hdf5_peak_path);
- args.iargs.hdf5_peak_path = args.command_line_peak_path;
+ /* Add any headers we need to copy */
+ for ( r=0; r<args.n_copy_headers; r++ ) {
+ data_template_add_copy_header(args.iargs.dtempl,
+ args.copy_headers[r]);
}
/* If no integration radii were given, apply the defaults */
@@ -917,18 +905,6 @@ int main(int argc, char *argv[])
args.iargs.cell = NULL;
}
- /* Load spectrum from file if given */
- if ( args.spectrum_fn != NULL ) {
- args.iargs.spectrum = spectrum_load(args.spectrum_fn);
- if ( args.iargs.spectrum == NULL ) {
- ERROR("Couldn't read spectrum (from %s)\n", args.spectrum_fn);
- return 1;
- }
- free(args.spectrum_fn);
- } else {
- args.iargs.spectrum = NULL;
- }
-
tmpdir = create_tempdir(args.temp_location);
if ( tmpdir == NULL ) return 1;
@@ -955,6 +931,16 @@ int main(int argc, char *argv[])
}
+ wl_from_dt = data_template_get_wavelength_if_possible(args.iargs.dtempl);
+ if ( !isnan(wl_from_dt) ) {
+ if ( !isnan(args.iargs.wavelength_estimate) ) {
+ ERROR("WARNING: Ignoring your value for "
+ "--wavelength-estimate because the geometry file "
+ "already contains a static value.\n");
+ }
+ args.iargs.wavelength_estimate = wl_from_dt;
+ }
+
/* Prepare the indexing system */
if ( args.indm_str == NULL ) {
@@ -1001,9 +987,12 @@ int main(int argc, char *argv[])
flags |= INDEXING_RETRY;
}
- args.iargs.ipriv = setup_indexing(args.indm_str, args.iargs.cell,
- args.iargs.det, args.iargs.beam,
- args.iargs.tols, flags,
+ args.iargs.ipriv = setup_indexing(args.indm_str,
+ args.iargs.cell,
+ args.iargs.tols,
+ flags,
+ args.iargs.wavelength_estimate,
+ args.iargs.n_threads,
taketwo_opts,
xgandalf_opts,
pinkindexer_opts,
@@ -1039,13 +1028,18 @@ int main(int argc, char *argv[])
free(rn);
/* Open output stream */
- st = open_stream_for_write_4(args.outfile, args.geom_filename,
- args.iargs.cell, argc, argv,
- args.indm_str);
+ st = stream_open_for_write(args.outfile, args.iargs.dtempl);
if ( st == NULL ) {
ERROR("Failed to open stream '%s'\n", args.outfile);
return 1;
}
+
+ /* Write audit info */
+ stream_write_commandline_args(st, argc, argv);
+ stream_write_geometry_file(st, args.geom_filename);
+ stream_write_target_cell(st, args.iargs.cell);
+ stream_write_indexing_methods(st, args.indm_str);
+
free(args.outfile);
free(args.indm_str);
@@ -1069,15 +1063,12 @@ int main(int argc, char *argv[])
fh, st, tmpdir, args.serial_start, zmq_address,
timeout, args.profile);
- free_imagefile_field_list(args.iargs.copyme);
cell_free(args.iargs.cell);
- free(args.iargs.beam->photon_energy_from);
free(args.prefix);
free(args.temp_location);
free(tmpdir);
- free_detector_geometry(args.iargs.det);
- free(args.iargs.hdf5_peak_path);
- close_stream(st);
+ data_template_free(args.iargs.dtempl);
+ stream_close(st);
cleanup_indexing(args.iargs.ipriv);
return r;
diff --git a/src/list_events.c b/src/list_events.c
index 095cc715..960c8929 100644
--- a/src/list_events.c
+++ b/src/list_events.c
@@ -3,11 +3,11 @@
*
* Generate event lists
*
- * Copyright © 2015-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2015-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2015 Thomas White <taw@physics.org>
+ * 2015-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -38,9 +38,11 @@
#include <unistd.h>
#include <getopt.h>
-#include "utils.h"
-#include "detector.h"
-#include "hdf5-file.h"
+#include <utils.h>
+#include <image.h>
+#include <datatemplate.h>
+
+#include "version.h"
static void show_help(const char *s)
@@ -69,7 +71,7 @@ int main(int argc, char *argv[])
char *rval;
FILE *ifh;
FILE *ofh;
- struct detector *det;
+ DataTemplate *dtempl;
/* Long options */
const struct option longopts[] = {
@@ -92,8 +94,10 @@ int main(int argc, char *argv[])
return 0;
case 2 :
- printf("CrystFEL: " CRYSTFEL_VERSIONSTRING "\n");
- printf(CRYSTFEL_BOILERPLATE"\n");
+ printf("CrystFEL: %s\n",
+ crystfel_version_string());
+ printf("%s\n",
+ crystfel_licence_string());
return 0;
case 'o' :
@@ -140,19 +144,12 @@ int main(int argc, char *argv[])
return 1;
}
- det = get_detector_geometry(geom, NULL);
- if ( det == NULL ) {
+ dtempl = data_template_new_from_file(geom);
+ if ( dtempl == NULL ) {
ERROR("Failed to read '%s'\n", geom);
return 1;
}
- if ( !multi_event_geometry(det) ) {
- ERROR("This does not look like a multi-event geometry file.\n");
- ERROR("Are you sure you need to use list_events instead of "
- "just 'find' or 'ls'?\n");
- return 1;
- }
-
do {
char filename[1024];
@@ -161,40 +158,34 @@ int main(int argc, char *argv[])
rval = fgets(filename, 1024, ifh);
if ( rval != NULL ) {
- struct event_list *evlist;
- struct hdfile *hdfile;
+ char **evlist;
+ int num_events;
chomp(filename);
- hdfile = hdfile_open(filename);
- if ( hdfile == NULL ) {
- ERROR("Failed to open '%s'\n", filename);
- ERROR("Aborting creation of event list.\n");
- return 1;
- }
-
- evlist = fill_event_list(hdfile, det);
+ evlist = image_expand_frames(dtempl, filename,
+ &num_events);
if ( evlist == NULL ) {
ERROR("Failed to read %s\n", filename);
- hdfile_close(hdfile);
- ERROR("Aborting creation of event list.\n");
return 1;
}
- for ( i=0; i<evlist->num_events; i++ ) {
- char *str = get_event_string(evlist->events[i]);
- fprintf(ofh, "%s %s\n", filename, str);
- free(str);
+ for ( i=0; i<num_events; i++ ) {
+ fprintf(ofh, "%s %s\n",
+ filename, evlist[i]);
+ free(evlist[i]);
}
- STATUS("%i events found in %s\n", evlist->num_events,
- filename);
+ STATUS("%i events found in %s\n",
+ num_events, filename);
+
+ free(evlist);
- free_event_list(evlist);
- hdfile_close(hdfile);
}
} while ( rval != NULL );
+ data_template_free(dtempl);
+
return 0;
}
diff --git a/src/list_tmp.h b/src/list_tmp.h
index 99ba6ffd..0c1a84e4 100644
--- a/src/list_tmp.h
+++ b/src/list_tmp.h
@@ -19,11 +19,11 @@
*/
/*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2009-2010,2012 Thomas White <taw@physics.org>
+ * 2009-2012 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
diff --git a/src/make_pixelmap.c b/src/make_pixelmap.c
index 1a1ed5f3..903f17e2 100644
--- a/src/make_pixelmap.c
+++ b/src/make_pixelmap.c
@@ -3,11 +3,11 @@
*
* Create a pixel map file from a CrystFEL geometry description
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2012-2018 Thomas White <taw@physics.org>
+ * 2012-2021 Thomas White <taw@physics.org>
* 2016-2016 Omri Mor <omor1@asu.edu>
*
* This file is part of CrystFEL.
@@ -41,8 +41,14 @@
#include <unistd.h>
#include <getopt.h>
#include <assert.h>
+#include <hdf5.h>
-#include "detector.h"
+#include <utils.h>
+#include <datatemplate.h>
+#include <detgeom.h>
+#include <image.h>
+
+#include "version.h"
static void show_help(const char *s)
@@ -126,7 +132,7 @@ static void create_scalar(hid_t gh, const char *name, float val)
static void write_pixelmap_hdf5(const char *filename,
float *x, float *y, float *z,
- int width, int height, float res, float coffset)
+ int width, int height, float res)
{
hid_t fh;
@@ -141,7 +147,6 @@ static void write_pixelmap_hdf5(const char *filename,
create_array(fh, "z", z, H5T_NATIVE_FLOAT, width, height);
create_scalar(fh, "res", res);
- create_scalar(fh, "coffset", coffset);
H5Fclose(fh);
}
@@ -171,12 +176,13 @@ int main(int argc, char *argv[])
int c;
char *input_file = NULL;
char *output_file = NULL;
- struct detector *det = NULL;
+ DataTemplate *dtempl;
+ struct detgeom *detgeom;
int fs, ss, w, h;
float *x, *y, *z;
uint16_t *b;
- int i;
- float res, coffset;
+ float res;
+ struct image *image;
int badmap = 0;
int good_pixel_val = 1;
int bad_pixel_val = 0;
@@ -188,6 +194,7 @@ int main(int argc, char *argv[])
{"badmap", 0, &badmap, 1},
{"good-pixel", 1, NULL, 301},
{"bad-pixel", 1, NULL, 302},
+ {"version", 0, NULL, 2},
{0, 0, NULL, 0}
};
@@ -205,6 +212,13 @@ int main(int argc, char *argv[])
output_file = strdup(optarg);
break;
+ case 2 :
+ printf("CrystFEL: %s\n",
+ crystfel_version_string());
+ printf("%s\n",
+ crystfel_licence_string());
+ return 0;
+
case 301:
if (sscanf(optarg, "%d", &good_pixel_val) != 1)
{
@@ -248,24 +262,28 @@ int main(int argc, char *argv[])
}
/* Load geometry */
- det = get_detector_geometry(input_file, NULL);
- if ( det == NULL ) {
- ERROR("Failed to read geometry from '%s'\n", input_file);
+ dtempl = data_template_new_from_file(input_file);
+ if ( dtempl == NULL ) {
+ ERROR("Failed to read geometry from '%s'\n",
+ input_file);
return 1;
}
free(input_file);
+ image = image_create_for_simulation(dtempl);
+ if ( image == NULL ) {
+ ERROR("Geometry file seems to contain references to "
+ "image header values.\n");
+ return 1;
+ }
+ detgeom = image->detgeom;
+
/* Determine max orig fs and ss */
- w = 0; h = 0;
- for ( i=0; i<det->n_panels; i++ ) {
- if ( det->panels[i].orig_max_fs > w ) {
- w = det->panels[i].orig_max_fs;
- }
- if ( det->panels[i].orig_max_ss > h ) {
- h = det->panels[i].orig_max_ss;
- }
+ if ( data_template_get_slab_extents(dtempl, &w, &h) ) {
+ ERROR("Pixel map can only be created if all panels "
+ "have their data in one \"slab\".\n");
+ return 1;
}
- w += 1; h += 1; /* Inclusive -> Exclusive */
STATUS("Data slab size: %i x %i\n", w, h);
x = malloc(w*h*sizeof(float));
@@ -277,66 +295,60 @@ int main(int argc, char *argv[])
return 1;
}
+ /* For every pixel in the slab ... */
for ( ss=0; ss<h; ss++ ) {
- for ( fs=0; fs<w; fs++ ) {
-
- double rx, ry;
- struct panel *p;
- double xs, ys;
- double cfs, css;
- int nfs, nss;
-
- p = find_orig_panel(det, fs, ss);
-
- /* Add half a pixel to fs and ss to get the fs,ss
- * coordinates of the CENTRE of the pixel */
- cfs = fs + 0.5;
- css = ss + 0.5;
- xs = (cfs - p->orig_min_fs)*p->fsx
- + (css - p->orig_min_ss)*p->ssx;
- ys = (cfs - p->orig_min_fs)*p->fsy
- + (css - p->orig_min_ss)*p->ssy;
-
- rx = (xs + p->cnx) / p->res;
- ry = (ys + p->cny) / p->res;
-
- x[fs + w*ss] = rx;
- y[fs + w*ss] = ry;
- z[fs + w*ss] = 0.0; /* FIXME */
-
- nfs = fs - p->orig_min_fs;
- nss = ss - p->orig_min_ss;
- if ( in_bad_region(det, p, nfs, nss) ) {
- b[fs + w*ss] = bad_pixel_val;
- } else {
- b[fs + w*ss] = good_pixel_val;
- }
+ for ( fs=0; fs<w; fs++ ) {
+
+ double rx, ry;
+ double xs, ys;
+ float cfs, css;
+ int pn;
+ struct detgeom_panel *p;
+
+ /* Add half a pixel to fs and ss to get the fs,ss
+ * coordinates of the CENTRE of the pixel */
+ cfs = fs + 0.5;
+ css = ss + 0.5;
+
+ if ( data_template_file_to_panel_coords(dtempl,
+ &cfs, &css,
+ &pn) )
+ {
+ ERROR("Couldn't convert coordinates\n");
+ return 1;
+ }
+
+ p = &detgeom->panels[pn];
+
+ xs = cfs*p->fsx + css*p->ssx;
+ ys = cfs*p->fsy + css*p->ssy;
+
+ rx = (xs + p->cnx) * p->pixel_pitch;
+ ry = (ys + p->cny) * p->pixel_pitch;
+ x[fs + w*ss] = rx;
+ y[fs + w*ss] = ry;
+ z[fs + w*ss] = 0.0; /* 2D part only */
+
+ if ( image->bad[pn][fs + w*ss] ) {
+ b[fs + w*ss] = bad_pixel_val;
+ } else {
+ b[fs + w*ss] = good_pixel_val;
}
- progress_bar(ss, h, "Converting");
}
- STATUS("\n");
-
- res = det->defaults.res;
- /* use the res of the first panel if not in global definitions
- * assumes one of these exist */
- if ( res == -1.0 ) {
- res = det->panels[0].res;
}
- coffset = det->defaults.coffset;
- /* use the coffset of the first panel if not in global definitions
- * assumes one of these exist*/
- if ( coffset == 0.0 ) {
- coffset = det->panels[0].coffset;
- }
+ res = 1.0 / detgeom->panels[0].pixel_pitch;
if ( badmap ) {
write_badmap_hdf5(output_file, b, w, h);
} else {
- write_pixelmap_hdf5(output_file, x, y, z, w, h, res, coffset);
+ write_pixelmap_hdf5(output_file, x, y, z, w, h, res);
}
+ data_template_free(dtempl);
+ image_free(image);
+
return 0;
}
diff --git a/src/merge.c b/src/merge.c
index d0d5b7d6..20981ff8 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -3,11 +3,11 @@
*
* Parallel weighted merging of intensities
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2018 Thomas White <taw@physics.org>
+ * 2010-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
diff --git a/src/merge.h b/src/merge.h
index e6684ac6..1e193b62 100644
--- a/src/merge.h
+++ b/src/merge.h
@@ -3,11 +3,11 @@
*
* Parallel weighted merging of intensities
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2015 Thomas White <taw@physics.org>
+ * 2010-2019 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
diff --git a/src/multihistogram.c b/src/multihistogram.c
index dabaf633..f0245583 100644
--- a/src/multihistogram.c
+++ b/src/multihistogram.c
@@ -3,11 +3,11 @@
*
* MultiHistogram with categories
*
- * Copyright © 2013-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2013-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2013-2014 Thomas White <taw@physics.org>
+ * 2013-2018 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
diff --git a/src/multihistogram.h b/src/multihistogram.h
index 232ac18f..effe557f 100644
--- a/src/multihistogram.h
+++ b/src/multihistogram.h
@@ -3,11 +3,11 @@
*
* Histogram with categories
*
- * Copyright © 2013-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2013-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2013-2014 Thomas White <taw@physics.org>
+ * 2013-2018 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
diff --git a/src/partial_sim.c b/src/partial_sim.c
index 884032b5..63851b9c 100644
--- a/src/partial_sim.c
+++ b/src/partial_sim.c
@@ -3,11 +3,11 @@
*
* Generate partials for testing scaling
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2011-2017 Thomas White <taw@physics.org>
+ * 2011-2020 Thomas White <taw@physics.org>
* 2014 Valerio Mariani
*
* This file is part of CrystFEL.
@@ -42,14 +42,17 @@
#include <pthread.h>
#include <gsl/gsl_rng.h>
-#include "image.h"
-#include "utils.h"
-#include "reflist-utils.h"
-#include "symmetry.h"
-#include "geometry.h"
-#include "stream.h"
-#include "thread-pool.h"
-#include "cell-utils.h"
+#include <image.h>
+#include <utils.h>
+#include <reflist-utils.h>
+#include <symmetry.h>
+#include <geometry.h>
+#include <stream.h>
+#include <thread-pool.h>
+#include <cell-utils.h>
+
+#include "version.h"
+
/* Number of bins for partiality graph */
#define NBINS 50
@@ -170,22 +173,24 @@ static void calculate_partials(Crystal *cr,
}
-static void draw_and_write_image(struct image *image, RefList *reflections,
+static void draw_and_write_image(struct image *image,
+ const DataTemplate *dtempl,
+ RefList *reflections,
gsl_rng *rng, double background)
{
Reflection *refl;
RefListIterator *iter;
int i;
- image->dp = malloc(image->det->n_panels*sizeof(float *));
+ image->dp = malloc(image->detgeom->n_panels*sizeof(float *));
if ( image->dp == NULL ) {
ERROR("Failed to allocate data\n");
return;
}
- for ( i=0; i<image->det->n_panels; i++ ) {
+ for ( i=0; i<image->detgeom->n_panels; i++ ) {
int j;
- struct panel *p = &image->det->panels[i];
+ struct detgeom_panel *p = &image->detgeom->panels[i];
image->dp[i] = calloc(p->w * p->h, sizeof(float));
if ( image->dp[i] == NULL ) {
@@ -205,15 +210,15 @@ static void draw_and_write_image(struct image *image, RefList *reflections,
double Ip;
double dfs, dss;
int fs, ss;
- struct panel *p;
+ struct detgeom_panel *p;
signed int pn;
Ip = get_intensity(refl);
get_detector_pos(refl, &dfs, &dss);
- p = get_panel(refl);
- pn = panel_number(image->det, p);
- assert(pn != image->det->n_panels);
+ pn = get_panel_number(refl);
+ assert(pn < image->detgeom->n_panels);
+ p = &image->detgeom->panels[pn];
/* Explicit rounding, downwards */
fs = dfs; ss = dss;
@@ -223,12 +228,11 @@ static void draw_and_write_image(struct image *image, RefList *reflections,
assert(ss < p->h);
image->dp[pn][fs + p->w*ss] += Ip;
-
}
- hdf5_write_image(image->filename, image, NULL);
+ image_write(image, dtempl, image->filename);
- for ( i=0; i<image->det->n_panels; i++ ) {
+ for ( i=0; i<image->detgeom->n_panels; i++ ) {
free(image->dp[i]);
}
free(image->dp);
@@ -273,10 +277,11 @@ static void show_help(const char *s)
}
-struct queue_args
+struct partial_sim_queue_args
{
RefList *full;
pthread_rwlock_t full_lock;
+ const DataTemplate *dtempl;
int n_done;
int n_started;
@@ -292,7 +297,6 @@ struct queue_args
double background;
double profile_radius;
- struct image *template_image;
double max_q;
char *image_prefix;
@@ -308,11 +312,10 @@ struct queue_args
};
-struct worker_args
+struct partial_sim_worker_args
{
- struct queue_args *qargs;
- Crystal *crystal;
- struct image image;
+ struct partial_sim_queue_args *qargs;
+ struct image *image;
UnitCell *template_cell;
RefList *template_reflist;
@@ -328,41 +331,36 @@ struct worker_args
static void *create_job(void *vqargs)
{
- struct worker_args *wargs;
- struct queue_args *qargs = vqargs;
+ struct partial_sim_worker_args *wargs;
+ struct partial_sim_queue_args *qargs = vqargs;
/* All done already? */
if ( qargs->n_started == qargs->n_to_do ) return NULL;
- wargs = malloc(sizeof(struct worker_args));
+ wargs = malloc(sizeof(struct partial_sim_worker_args));
wargs->qargs = qargs;
- wargs->image = *qargs->template_image;
if ( qargs->template_stream != NULL ) {
- struct image im;
- int r;
+ struct image *image;
- im.det = wargs->image.det;
- r = read_chunk_2(qargs->template_stream, &im,
- STREAM_READ_UNITCELL | STREAM_READ_REFLECTIONS);
- if ( r ) {
+ image = stream_read_chunk(qargs->template_stream,
+ STREAM_REFLECTIONS);
+ if ( image == NULL ) {
ERROR("Failed to read template chunk!\n");
return NULL;
}
- if ( im.n_crystals != 1 ) {
+ if ( image->n_crystals != 1 ) {
ERROR("Template stream must have exactly one crystal "
"per frame.\n");
return NULL;
}
- wargs->template_cell = crystal_get_cell(im.crystals[0]);
- wargs->template_reflist = crystal_get_reflections(im.crystals[0]);
+ wargs->template_cell = crystal_get_cell(image->crystals[0]);
+ wargs->template_reflist = crystal_get_reflections(image->crystals[0]);
- crystal_free(im.crystals[0]);
- free(im.filename);
- free_event(im.event);
+ image_free(image);
} else {
wargs->template_cell = NULL;
@@ -378,19 +376,26 @@ static void *create_job(void *vqargs)
static void run_job(void *vwargs, int cookie)
{
- struct worker_args *wargs = vwargs;
- struct queue_args *qargs = wargs->qargs;
+ struct partial_sim_worker_args *wargs = vwargs;
+ struct partial_sim_queue_args *qargs = wargs->qargs;
int i;
Crystal *cr;
double osf;
+ struct image *image;
+
+ image = image_create_for_simulation(qargs->dtempl);
+ if ( image == NULL ) {
+ ERROR("Failed to create image.\n");
+ return;
+ }
cr = crystal_new();
if ( cr == NULL ) {
ERROR("Failed to create crystal.\n");
return;
}
- wargs->crystal = cr;
- crystal_set_image(cr, &wargs->image);
+ crystal_set_image(cr, image);
+ image_add_crystal(image, cr);
do {
osf = gaussian_noise(qargs->rngs[cookie], 1.0,
@@ -409,21 +414,21 @@ static void run_job(void *vwargs, int cookie)
crystal_set_cell(cr, wargs->template_cell);
}
- wargs->image.filename = malloc(256);
- if ( wargs->image.filename == NULL ) {
+ image->filename = malloc(256);
+ if ( image->filename == NULL ) {
ERROR("Failed to allocate filename.\n");
return;
}
if ( qargs->image_prefix != NULL ) {
- snprintf(wargs->image.filename, 255, "%s%i.h5",
+ snprintf(image->filename, 255, "%s%i.h5",
qargs->image_prefix, wargs->n);
} else {
- snprintf(wargs->image.filename, 255, "dummy.h5");
+ snprintf(image->filename, 255, "dummy.h5");
}
if ( wargs->template_reflist == NULL ) {
RefList *reflections;
- reflections = predict_to_res(cr, largest_q(&wargs->image));
+ reflections = predict_to_res(cr, qargs->max_q);
crystal_set_reflections(cr, reflections);
calculate_partialities(cr, PMODEL_XSPHERE);
} else {
@@ -447,26 +452,29 @@ static void run_job(void *vwargs, int cookie)
wargs->template_cell, wargs->template_reflist);
if ( qargs->image_prefix != NULL ) {
- draw_and_write_image(&wargs->image, crystal_get_reflections(cr),
- qargs->rngs[cookie], qargs->background);
+ draw_and_write_image(image, qargs->dtempl,
+ crystal_get_reflections(cr),
+ qargs->rngs[cookie],
+ qargs->background);
}
/* Give a slightly incorrect cell in the stream */
mess_up_cell(cr, qargs->cnoise, qargs->rngs[cookie]);
- image_add_crystal(&wargs->image, cr);
+ wargs->image = image;
}
static void finalise_job(void *vqargs, void *vwargs)
{
- struct worker_args *wargs = vwargs;
- struct queue_args *qargs = vqargs;
+ struct partial_sim_worker_args *wargs = vwargs;
+ struct partial_sim_queue_args *qargs = vqargs;
int i;
int ret;
- ret = write_chunk(qargs->stream, &wargs->image, NULL, 0, 1, NULL);
- if ( ret != 0) {
+ ret = stream_write_chunk(qargs->stream, wargs->image,
+ STREAM_REFLECTIONS);
+ if ( ret != 0 ) {
ERROR("WARNING: error writing stream file.\n");
}
@@ -481,30 +489,7 @@ static void finalise_job(void *vqargs, void *vwargs)
qargs->n_done++;
progress_bar(qargs->n_done, qargs->n_to_do, "Simulating");
- free_all_crystals(&wargs->image);
- free(wargs->image.filename);
- free(wargs);
-}
-
-
-static void fixup_geom(struct detector *det)
-{
- int i;
-
- for ( i=0; i<det->n_panels; i++ ) {
- det->panels[i].clen += det->panels[i].coffset;
- }
-}
-
-
-static int geom_contains_references(struct detector *det)
-{
- int i;
-
- for ( i=0; i<det->n_panels; i++ ) {
- if ( det->panels[i].clen_from != NULL ) return 1;
- }
- return 0;
+ image_free(wargs->image);
}
@@ -515,8 +500,7 @@ int main(int argc, char *argv[])
char *output_file = NULL;
char *geomfile = NULL;
char *cellfile = NULL;
- struct detector *det = NULL;
- struct beam_params beam;
+ DataTemplate *dtempl;
RefList *full = NULL;
char *sym_str = NULL;
SymOpList *sym;
@@ -525,8 +509,7 @@ int main(int argc, char *argv[])
int n = 2;
int random_intensities = 0;
char *save_file = NULL;
- struct queue_args qargs;
- struct image image;
+ struct partial_sim_queue_args qargs;
int n_threads = 1;
char *rval;
int i;
@@ -537,6 +520,7 @@ int main(int argc, char *argv[])
char *image_prefix = NULL;
Stream *template_stream = NULL;
char *template = NULL;
+ struct image *test_image;
/* Default simulation parameters */
double divergence = 0.001;
@@ -590,8 +574,10 @@ int main(int argc, char *argv[])
return 0;
case 'v' :
- printf("CrystFEL: " CRYSTFEL_VERSIONSTRING "\n");
- printf(CRYSTFEL_BOILERPLATE"\n");
+ printf("CrystFEL: %s\n",
+ crystfel_version_string());
+ printf("%s\n",
+ crystfel_licence_string());
return 0;
case 'b' :
@@ -797,24 +783,11 @@ int main(int argc, char *argv[])
ERROR("You need to give a geometry file.\n");
return 1;
}
- det = get_detector_geometry(geomfile, &beam);
- if ( det == NULL ) {
+ dtempl = data_template_new_from_file(geomfile);
+ if ( dtempl == NULL ) {
ERROR("Failed to read geometry from '%s'\n", geomfile);
return 1;
}
- if ( (beam.photon_energy > 0.0) && (beam.photon_energy_from == NULL) ) {
- ERROR("WARNING: An explicit photon energy was found in the "
- "geometry file. It will be ignored!\n");
- ERROR("The value given on the command line "
- "(with --photon-energy) will be used instead.\n");
- }
- if ( geom_contains_references(det) ) {
- ERROR("Geometry file contains a reference to an HDF5 location"
- " for the camera length. Change it to a numerical value "
- " and try again.\n");
- return 1;
- }
- fixup_geom(det);
if ( save_file == NULL ) save_file = strdup("partial_sim.hkl");
@@ -876,46 +849,41 @@ int main(int argc, char *argv[])
ERROR("You must give a filename for the output.\n");
return 1;
}
- stream = open_stream_for_write_2(output_file, geomfile, argc, argv);
+ stream = stream_open_for_write(output_file, dtempl);
if ( stream == NULL ) {
ERROR("Couldn't open output file '%s'\n", output_file);
return 1;
}
free(output_file);
+ stream_write_geometry_file(stream, geomfile);
+ stream_write_commandline_args(stream, argc, argv);
+
if ( template != NULL ) {
- template_stream = open_stream_for_read(template);
+ template_stream = stream_open_for_read(template);
if ( template_stream == NULL ) {
ERROR("Couldn't open template stream '%s'\n", template);
return 1;
}
}
- image.det = det;
- image.beam = &beam;
-
- image.lambda = ph_en_to_lambda(eV_to_J(photon_energy));
- image.div = divergence;
- image.bw = bandwidth;
- image.spectrum = spectrum_generate_gaussian(image.lambda, image.bw);
- image.filename = "dummy.h5";
- image.copyme = NULL;
- image.crystals = NULL;
- image.n_crystals = 0;
- image.indexed_by = INDEXING_SIMULATION;
- image.serial = 0;
- image.event = NULL;
- image.hit = 0;
- image.n_indexing_tries = 1;
- image.features = NULL;
- image.peak_resolution = 0.0;
+ test_image = image_create_for_simulation(dtempl);
+ if ( test_image == NULL ) {
+ ERROR("Could not create image structure.\n");
+ ERROR("Does the geometry file contain references?\n");
+ return 1;
+ }
STATUS("Simulation parameters:\n");
- STATUS(" Photon energy: %.2f eV (wavelength %.5f A)\n",
- photon_energy, image.lambda*1e10);
- STATUS(" Beam divergence: %.5f mrad\n", image.div*1e3);
- STATUS(" Beam bandwidth: %.5f %%\n", image.bw*100.0);
- STATUS("Reciprocal space profile radius: %e m^-1\n", profile_radius);
+ STATUS(" Wavelength: %.5f A (photon energy %.2f eV)\n",
+ test_image->lambda*1e10,
+ ph_lambda_to_eV(test_image->lambda));
+ STATUS(" Beam divergence: %.5f mrad\n",
+ test_image->div*1e3);
+ STATUS(" Beam bandwidth: %.5f %%\n",
+ test_image->bw*100.0);
+ STATUS("Reciprocal space profile radius: %e m^-1\n",
+ profile_radius);
if ( image_prefix != NULL ) {
STATUS(" Background: %.2f detector units\n",
background);
@@ -953,14 +921,14 @@ int main(int argc, char *argv[])
qargs.sym = sym;
qargs.random_intensities = random_intensities;
qargs.cell = cell;
- qargs.template_image = &image;
qargs.stream = stream;
qargs.cnoise = cnoise;
qargs.osf_stddev = osf_stddev;
qargs.full_stddev = full_stddev;
qargs.noise_stddev = noise_stddev;
qargs.background = background;
- qargs.max_q = largest_q(&image);
+ qargs.max_q = detgeom_max_resolution(test_image->detgeom,
+ test_image->lambda);
qargs.image_prefix = image_prefix;
qargs.profile_radius = profile_radius;
qargs.template_stream = template_stream;
@@ -1054,7 +1022,8 @@ int main(int argc, char *argv[])
overall_mean /= overall_total;
- STATUS("Overall max partiality = %.2f\n", overall_max);
+ STATUS("Overall max partiality = %.2f\n",
+ overall_max);
STATUS("Overall mean partiality = %.2f\n", overall_mean);
STATUS("Total number of reflections = %lli\n",
overall_total);
@@ -1071,9 +1040,9 @@ int main(int argc, char *argv[])
}
free(qargs.rngs);
pthread_rwlock_destroy(&qargs.full_lock);
- close_stream(stream);
+ stream_close(stream);
cell_free(cell);
- free_detector_geometry(det);
+ data_template_free(dtempl);
free_symoplist(sym);
reflist_free(full);
free(save_file);
diff --git a/src/partialator.c b/src/partialator.c
index 246880da..90467d9d 100644
--- a/src/partialator.c
+++ b/src/partialator.c
@@ -3,11 +3,11 @@
*
* Scaling and post refinement for coherent nanocrystallography
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2018 Thomas White <taw@physics.org>
+ * 2010-2021 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -58,6 +58,7 @@
#include "post-refinement.h"
#include "merge.h"
#include "rejection.h"
+#include "version.h"
struct csplit_hash_entry
@@ -254,14 +255,12 @@ static void write_custom_split(struct custom_split *csplit, int dsn,
for ( i=0; i<n_crystals; i++ ) {
const char *fn;
- struct event *ev;
char *evs;
char *id;
int dsn_crystal;
fn = crystal_get_image(crystals[i])->filename;
- ev = crystal_get_image(crystals[i])->event;
- evs = get_event_string(ev);
+ evs = crystal_get_image(crystals[i])->ev;
id = malloc(strlen(evs)+strlen(fn)+2);
if ( id == NULL ) {
@@ -349,14 +348,12 @@ static signed int find_first_crystal(Crystal **crystals, int n_crystals,
for ( i=0; i<n_crystals; i++ ) {
const char *fn;
- struct event *ev;
char *evs;
char *id;
int dsn_crystal;
fn = crystal_get_image(crystals[i])->filename;
- ev = crystal_get_image(crystals[i])->event;
- evs = get_event_string(ev);
+ evs = crystal_get_image(crystals[i])->ev;
id = malloc(strlen(evs)+strlen(fn)+2);
if ( id == NULL ) {
@@ -389,14 +386,12 @@ static void check_csplit(Crystal **crystals, int n_crystals,
for ( i=0; i<n_crystals; i++ ) {
const char *fn;
- struct event *ev;
char *evs;
char *id;
int dsn_crystal;
fn = crystal_get_image(crystals[i])->filename;
- ev = crystal_get_image(crystals[i])->event;
- evs = get_event_string(ev);
+ evs = crystal_get_image(crystals[i])->ev;
id = malloc(strlen(evs)+strlen(fn)+2);
if ( id == NULL ) {
@@ -490,7 +485,7 @@ static struct custom_split *load_custom_split(const char *filename)
ds = bits[2];
} else {
fn = bits[0];
- evs = get_event_string(NULL);
+ evs = strdup("(none)");
ds = bits[1];
}
free(bits);
@@ -554,10 +549,13 @@ static RefList *apply_max_adu(RefList *list, double max_adu)
signed int h, k, l;
get_indices(refl, &h, &k, &l);
Reflection *nrefl = add_refl(nlist, h, k, l);
+ if ( nrefl == NULL ) {
+ ERROR("Failed to add reflection\n");
+ return NULL;
+ }
copy_data(nrefl, refl);
}
}
- reflist_free(list);
return nlist;
}
@@ -609,6 +607,7 @@ static int set_initial_params(Crystal *cr, FILE *fh, double force_bandwidth,
if ( force_lambda > 0.0 ) {
image->lambda = force_lambda;
}
+ spectrum_free(image->spectrum);
image->spectrum = spectrum_generate_gaussian(image->lambda, image->bw);
return 0;
@@ -926,10 +925,42 @@ static void write_logs_parallel(Crystal **crystals, int n_crystals,
}
+struct stream_list
+{
+ int n;
+ int max_n;
+ const char **filenames;
+ Stream **streams;
+};
+
+
+static int add_stream(const char *filename, struct stream_list *list)
+{
+ if ( list->n == list->max_n ) {
+ const char **new_filenames = realloc(list->filenames,
+ (list->n+16)*sizeof(const char *));
+ Stream **new_streams = realloc(list->streams,
+ (list->n+16)*sizeof(Stream *));
+ if ( (new_filenames == NULL) || (new_streams == NULL) ) return 1;
+ list->max_n += 16;
+ list->filenames = new_filenames;
+ list->streams = new_streams;
+ }
+
+ list->filenames[list->n] = filename;
+ list->streams[list->n] = NULL;
+ list->n++;
+ return 0;
+}
+
+
int main(int argc, char *argv[])
{
int c;
- char *infile = NULL;
+ struct stream_list stream_list = {.n = 0,
+ .max_n = 0,
+ .filenames = NULL,
+ .streams = NULL};
char *outfile = NULL;
char *sym_str = NULL;
SymOpList *sym;
@@ -946,7 +977,6 @@ int main(int argc, char *argv[])
int no_scale = 0;
int no_Bscale = 0;
int no_pr = 0;
- Stream *st;
Crystal **crystals;
char *pmodel_str = NULL;
PartialityModel pmodel = PMODEL_XSPHERE;
@@ -1042,12 +1072,14 @@ int main(int argc, char *argv[])
return 0;
case 'v' :
- printf("CrystFEL: " CRYSTFEL_VERSIONSTRING "\n");
- printf(CRYSTFEL_BOILERPLATE"\n");
+ printf("CrystFEL: %s\n",
+ crystfel_version_string());
+ printf("%s\n",
+ crystfel_licence_string());
return 0;
case 'i' :
- infile = strdup(optarg);
+ add_stream(optarg, &stream_list);
break;
case 'j' :
@@ -1209,18 +1241,17 @@ int main(int argc, char *argv[])
}
+ while ( optind < argc ) {
+ add_stream(argv[optind++], &stream_list);
+ }
+
if ( nthreads < 1 ) {
ERROR("Invalid number of threads.\n");
return 1;
}
- if ( infile == NULL ) {
- ERROR("Please give the input filename (with -i)\n");
- return 1;
- }
- st = open_stream_for_read(infile);
- if ( st == NULL ) {
- ERROR("Failed to open input stream '%s'\n", infile);
+ if ( stream_list.n == 0 ) {
+ ERROR("Please give at least one input filename\n");
return 1;
}
@@ -1376,105 +1407,139 @@ int main(int argc, char *argv[])
sparams_fh = NULL;
}
- do {
-
- RefList *as;
- int i;
- struct image cur;
-
- cur.div = NAN;
- cur.bw = NAN;
- cur.det = NULL;
- if ( read_chunk_2(st, &cur, STREAM_READ_REFLECTIONS
- | STREAM_READ_UNITCELL) != 0 ) {
- break;
- }
+ audit_info = NULL;
+ for ( i=0; i<stream_list.n; i++ ) {
- if ( isnan(cur.div) || isnan(cur.bw) ) {
- ERROR("Chunk doesn't contain beam parameters.\n");
+ Stream *st = stream_open_for_read(stream_list.filenames[i]);
+ if ( st == NULL ) {
+ ERROR("Couldn't open %s\n", stream_list.filenames[i]);
return 1;
}
- free_stuff_from_stream(cur.stuff_from_stream);
- cur.stuff_from_stream = NULL;
+ if ( audit_info == NULL ) {
+ audit_info = stream_audit_info(st);
+ }
- for ( i=0; i<cur.n_crystals; i++ ) {
+ do {
- Crystal *cr;
- Crystal **crystals_new;
- RefList *cr_refl;
struct image *image;
+ RefList *as;
+ int i;
- n_crystals_seen++;
- if ( n_crystals_seen <= start_after ) continue;
-
- if ( crystal_get_resolution_limit(cur.crystals[i]) < min_res ) continue;
+ image = stream_read_chunk(st, STREAM_REFLECTIONS);
+ if ( image == NULL ) break;
- crystals_new = realloc(crystals,
- (n_crystals+1)*sizeof(Crystal *));
- if ( crystals_new == NULL ) {
- ERROR("Failed to allocate memory for crystal "
- "list.\n");
+ if ( isnan(image->div) || isnan(image->bw) ) {
+ ERROR("Chunk doesn't contain beam parameters.\n");
return 1;
}
- crystals = crystals_new;
- crystals[n_crystals] = cur.crystals[i];
- cr = crystals[n_crystals];
- image = malloc(sizeof(struct image));
- if ( image == NULL ) {
- ERROR("Failed to allocate memory for image.\n");
- return 1;
- }
+ for ( i=0; i<image->n_crystals; i++ ) {
- crystal_set_image(cr, image);
- *image = cur;
- image->n_crystals = 1;
- image->crystals = &crystals[n_crystals];
+ Crystal *cr;
+ Crystal **crystals_new;
+ RefList *cr_refl;
+ RefList *cr_refl_raw;
+ struct image *image_for_crystal;
+ double lowest_r;
- image->filename = strdup(image->filename);
+ n_crystals_seen++;
+ if ( n_crystals_seen <= start_after ) continue;
- /* This is the raw list of reflections */
- cr_refl = crystal_get_reflections(cr);
+ if ( crystal_get_resolution_limit(image->crystals[i]) < min_res ) continue;
- cr_refl = apply_max_adu(cr_refl, max_adu);
+ lowest_r = lowest_reflection(crystal_get_cell(image->crystals[i]));
+ if ( crystal_get_profile_radius(image->crystals[i]) > 0.2*lowest_r ) {
+ ERROR("Rejecting %s %s crystal %i because "
+ "profile radius is obviously too big (%e %e).\n",
+ image->filename, image->ev, i,
+ crystal_get_profile_radius(image->crystals[i]),
+ lowest_r);
+ continue;
+ }
- if ( !no_free ) select_free_reflections(cr_refl, rng);
+ crystals_new = realloc(crystals,
+ (n_crystals+1)*sizeof(Crystal *));
+ if ( crystals_new == NULL ) {
+ ERROR("Failed to allocate memory for crystal "
+ "list.\n");
+ return 1;
+ }
+ crystals = crystals_new;
+ crystals[n_crystals] = crystal_copy_deep(image->crystals[i]);
+ cr = crystals[n_crystals];
+
+ /* Create a completely new, separate image
+ * structure for this crystal. */
+ image_for_crystal = image_new();
+ if ( image_for_crystal == NULL ) {
+ ERROR("Failed to allocate memory for image.\n");
+ return 1;
+ }
- as = asymmetric_indices(cr_refl, sym);
- crystal_set_reflections(cr, as);
- crystal_set_user_flag(cr, PRFLAG_OK);
- reflist_free(cr_refl);
+ crystal_set_image(cr, image_for_crystal);
+ *image_for_crystal = *image;
+ image_for_crystal->n_crystals = 1;
+ image_for_crystal->crystals = &crystals[n_crystals];
+
+ image_for_crystal->filename = strdup(image->filename);
+ image_for_crystal->ev = safe_strdup(image->ev);
+ image_for_crystal->detgeom = NULL;
+ image_for_crystal->features = NULL;
+ image_for_crystal->spectrum = NULL;
+ image_for_crystal->copied_headers = NULL;
+ image_for_crystal->dp = NULL;
+ image_for_crystal->bad = NULL;
+ image_for_crystal->sat = NULL;
+
+ /* This is the raw list of reflections */
+ cr_refl_raw = crystal_get_reflections(cr);
+
+ cr_refl = apply_max_adu(cr_refl_raw, max_adu);
+ reflist_free(cr_refl_raw);
+
+ if ( !no_free ) select_free_reflections(cr_refl, rng);
+
+ as = asymmetric_indices(cr_refl, sym);
+ crystal_set_reflections(cr, as);
+ crystal_set_user_flag(cr, PRFLAG_OK);
+ reflist_free(cr_refl);
+
+ if ( set_initial_params(cr, sparams_fh, force_bandwidth,
+ force_radius, force_lambda) )
+ {
+ ERROR("Failed to set initial parameters\n");
+ return 1;
+ }
+
+ n_crystals++;
+
+ if ( n_crystals == stop_after ) break;
- if ( set_initial_params(cr, sparams_fh, force_bandwidth,
- force_radius, force_lambda) )
- {
- ERROR("Failed to set initial parameters\n");
- return 1;
}
- n_crystals++;
+ image_free(image);
- if ( n_crystals == stop_after ) break;
+ n_images++;
- }
- free(cur.crystals);
- free(cur.filename);
+ if ( n_images % 100 == 0 ) {
+ display_progress(n_images, n_crystals);
+ }
- n_images++;
+ if ( (stop_after>0) && (n_crystals == stop_after) ) break;
- if ( n_images % 100 == 0 ) {
- display_progress(n_images, n_crystals);
- }
+ } while ( 1 );
- if ( (stop_after>0) && (n_crystals == stop_after) ) break;
+ stream_close(st);
+
+ }
+
+ free(stream_list.filenames);
+ free(stream_list.streams);
- } while ( 1 );
display_progress(n_images, n_crystals);
fprintf(stderr, "\n");
if ( sparams_fh != NULL ) fclose(sparams_fh);
- audit_info = stream_audit_info(st);
- close_stream(st);
STATUS("Initial partiality calculation...\n");
for ( i=0; i<n_crystals; i++ ) {
@@ -1628,8 +1693,10 @@ int main(int argc, char *argv[])
gsl_rng_free(rng);
for ( i=0; i<n_crystals; i++ ) {
struct image *image = crystal_get_image(crystals[i]);
+ spectrum_free(image->spectrum);
reflist_free(crystal_get_reflections(crystals[i]));
free(image->filename);
+ free(image->ev);
free(image);
cell_free(crystal_get_cell(crystals[i]));
crystal_free(crystals[i]);
@@ -1639,7 +1706,6 @@ int main(int argc, char *argv[])
free_symoplist(sym);
free(outfile);
free(crystals);
- free(infile);
return 0;
}
diff --git a/src/pattern_sim.c b/src/pattern_sim.c
index 1fce0f60..f0f24ac9 100644
--- a/src/pattern_sim.c
+++ b/src/pattern_sim.c
@@ -3,11 +3,11 @@
*
* Simulate diffraction patterns from small crystals
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2009-2017 Thomas White <taw@physics.org>
+ * 2009-2020 Thomas White <taw@physics.org>
* 2013-2014 Chun Hong Yoon <chun.hong.yoon@desy.de>
* 2014 Valerio Mariani
* 2013 Alexandra Tolstikova
@@ -42,20 +42,21 @@
#include <getopt.h>
#include <hdf5.h>
-#include "image.h"
+#include <image.h>
+#include <cell.h>
+#include <cell-utils.h>
+#include <utils.h>
+#include <peaks.h>
+#include <symmetry.h>
+#include <reflist.h>
+#include <reflist-utils.h>
+#include <stream.h>
+#include <datatemplate.h>
+
#include "diffraction.h"
#include "diffraction-gpu.h"
-#include "cell.h"
-#include "cell-utils.h"
-#include "utils.h"
-#include "hdf5-file.h"
-#include "detector.h"
-#include "peaks.h"
-#include "symmetry.h"
-#include "reflist.h"
-#include "reflist-utils.h"
#include "pattern_sim.h"
-#include "stream.h"
+#include "version.h"
enum spectrum_type {
@@ -116,6 +117,131 @@ static void show_help(const char *s)
}
+static void record_panel(struct detgeom_panel *p, float *dp,
+ int do_poisson,
+ gsl_rng *rng, double ph_per_e, double background,
+ double lambda,
+ int *n_neg1, int *n_inf1, int *n_nan1,
+ int *n_neg2, int *n_inf2, int *n_nan2,
+ double *max_tt)
+{
+ int fs, ss;
+
+ for ( ss=0; ss<p->h; ss++ ) {
+ for ( fs=0; fs<p->w; fs++ ) {
+
+ double counts;
+ double cf;
+ double intensity, sa;
+ double pix_area, Lsq;
+ double xs, ys, rx, ry;
+ double dsq, proj_area;
+ float dval;
+ double twotheta;
+
+ intensity = (double)dp[fs + p->w*ss];
+ if ( isinf(intensity) ) (*n_inf1)++;
+ if ( intensity < 0.0 ) (*n_neg1)++;
+ if ( isnan(intensity) ) (*n_nan1)++;
+
+ /* Area of one pixel */
+ pix_area = pow(p->pixel_pitch, 2.0);
+ Lsq = pow(p->cnz*p->pixel_pitch, 2.0);
+
+ /* Calculate distance from crystal to pixel */
+ xs = fs*p->fsx + ss*p->ssx;
+ ys = ss*p->fsy + ss*p->ssy;
+ rx = (xs + p->cnx) * p->pixel_pitch;
+ ry = (ys + p->cny) * p->pixel_pitch;
+ dsq = pow(rx, 2.0) + pow(ry, 2.0);
+ twotheta = atan2(sqrt(dsq), p->cnz*p->pixel_pitch);
+
+ /* Area of pixel as seen from crystal (approximate) */
+ proj_area = pix_area * cos(twotheta);
+
+ /* Projected area of pixel divided by distance squared */
+ sa = proj_area / (dsq + Lsq);
+
+ if ( do_poisson ) {
+ counts = poisson_noise(rng, intensity * ph_per_e * sa);
+ } else {
+ cf = intensity * ph_per_e * sa;
+ counts = cf;
+ }
+
+ /* Number of photons in pixel */
+ dval = counts + poisson_noise(rng, background);
+
+ /* Convert to ADU */
+ dval *= p->adu_per_photon;
+
+ /* Saturation */
+ if ( dval > p->max_adu ) dval = p->max_adu;
+
+ dp[fs + p->w*ss] = dval;
+
+ /* Sanity checks */
+ if ( isinf(dp[fs + p->w*ss]) ) n_inf2++;
+ if ( isnan(dp[fs + p->w*ss]) ) n_nan2++;
+ if ( dp[fs + p->w*ss] < 0.0 ) n_neg2++;
+
+ if ( twotheta > *max_tt ) *max_tt = twotheta;
+
+ }
+ }
+}
+
+
+void record_image(struct image *image, int do_poisson, double background,
+ gsl_rng *rng, double beam_radius, double nphotons)
+{
+ double total_energy, energy_density;
+ double ph_per_e;
+ double area;
+ double max_tt = 0.0;
+ int n_inf1 = 0;
+ int n_neg1 = 0;
+ int n_nan1 = 0;
+ int n_inf2 = 0;
+ int n_neg2 = 0;
+ int n_nan2 = 0;
+ int pn;
+
+ /* How many photons are scattered per electron? */
+ area = M_PI*pow(beam_radius, 2.0);
+ total_energy = nphotons * ph_lambda_to_en(image->lambda);
+ energy_density = total_energy / area;
+ ph_per_e = (nphotons /area) * pow(THOMSON_LENGTH, 2.0);
+ STATUS("Fluence = %8.2e photons, "
+ "Energy density = %5.3f kJ/cm^2, "
+ "Total energy = %5.3f microJ\n",
+ nphotons, energy_density/1e7, total_energy*1e6);
+
+ for ( pn=0; pn<image->detgeom->n_panels; pn++ ) {
+
+ record_panel(&image->detgeom->panels[pn], image->dp[pn],
+ do_poisson, rng, ph_per_e, background,
+ image->lambda,
+ &n_neg1, &n_inf1, &n_nan1,
+ &n_neg2, &n_inf2, &n_nan2, &max_tt);
+ }
+
+ STATUS("Max 2theta = %.2f deg, min d = %.2f nm\n",
+ rad2deg(max_tt), (image->lambda/(2.0*sin(max_tt/2.0)))/1e-9);
+
+ STATUS("Halve the d values to get the voxel size for a synthesis.\n");
+
+ if ( n_neg1 + n_inf1 + n_nan1 + n_neg2 + n_inf2 + n_nan2 ) {
+ ERROR("WARNING: The raw calculation produced %i negative"
+ " values, %i infinities and %i NaNs.\n",
+ n_neg1, n_inf1, n_nan1);
+ ERROR("WARNING: After processing, there were %i negative"
+ " values, %i infinities and %i NaNs.\n",
+ n_neg2, n_inf2, n_nan2);
+ }
+}
+
+
static double *intensities_from_list(RefList *list, SymOpList *sym)
{
Reflection *refl;
@@ -237,28 +363,8 @@ static int random_ncells(double len, double min_m, double max_m)
}
-static void fixup_geom(struct detector *det)
-{
- int i;
-
- for ( i=0; i<det->n_panels; i++ ) {
- det->panels[i].clen += det->panels[i].coffset;
- }
-}
-
-
-static int geom_contains_references(struct detector *det)
-{
- int i;
-
- for ( i=0; i<det->n_panels; i++ ) {
- if ( det->panels[i].clen_from != NULL ) return 1;
- }
- return 0;
-}
-
-
-static void add_metadata(const char *filename, struct quaternion q,
+static void add_metadata(const char *filename,
+ struct quaternion q,
UnitCell *cell)
{
hid_t fh, gh, sh, dh;
@@ -361,9 +467,10 @@ static void add_metadata(const char *filename, struct quaternion q,
int main(int argc, char *argv[])
{
int c;
- struct image image;
+ struct image *image;
+ DataTemplate *dtempl;
struct gpu_context *gctx = NULL;
- struct image powder;
+ struct image *powder;
char *intfile = NULL;
double *intensities;
char *rval;
@@ -409,8 +516,6 @@ int main(int argc, char *argv[])
double photon_energy = 9000.0;
double sase_spike_width = 2e6; /* m^-1 */
double twocol_sep = 8e6; /* m^-1 */
- struct beam_params beam;
- int i;
/* Long options */
const struct option longopts[] = {
@@ -463,8 +568,10 @@ int main(int argc, char *argv[])
return 0;
case 'v' :
- printf("CrystFEL: " CRYSTFEL_VERSIONSTRING "\n");
- printf(CRYSTFEL_BOILERPLATE"\n");
+ printf("CrystFEL: %s\n",
+ crystfel_version_string());
+ printf("%s\n",
+ crystfel_licence_string());
return 0;
case 'b' :
@@ -673,7 +780,7 @@ int main(int argc, char *argv[])
ERROR("You cannot use -r and --template together.\n");
return 1;
}
- st = open_stream_for_read(template_file);
+ st = stream_open_for_read(template_file);
if ( st == NULL ) {
ERROR("Failed to open stream.\n");
return 1;
@@ -707,26 +814,13 @@ int main(int argc, char *argv[])
ERROR("You need to specify a geometry file with --geometry\n");
return 1;
}
- image.beam = &beam;
- image.det = get_detector_geometry(geometry, image.beam);
- if ( image.det == NULL ) {
- ERROR("Failed to read detector geometry from '%s'\n", geometry);
+ dtempl = data_template_new_from_file(geometry);
+ if ( dtempl == NULL ) {
+ ERROR("Failed to read detector geometry from '%s'\n",
+ geometry);
return 1;
}
free(geometry);
- if ( (beam.photon_energy > 0.0) && (beam.photon_energy_from == NULL) ) {
- ERROR("WARNING: An explicit photon energy was found in the "
- "geometry file. It will be ignored!\n");
- ERROR("The value given on the command line "
- "(with --photon-energy) will be used instead.\n");
- }
- if ( geom_contains_references(image.det) ) {
- ERROR("Geometry file contains a reference to an HDF5 location"
- " for the camera length. Change it to a numerical value "
- " and try again.\n");
- return 1;
- }
- fixup_geom(image.det);
if ( spectrum_str == NULL ) {
STATUS("You didn't specify a spectrum type, so"
@@ -823,28 +917,6 @@ int main(int argc, char *argv[])
}
- image.lambda = ph_en_to_lambda(eV_to_J(photon_energy));
- image.bw = bandwidth;
-
- /* Initialise stuff */
- image.filename = NULL;
- image.features = NULL;
- image.bad = NULL;
- image.dp = malloc(image.det->n_panels*sizeof(float *));
- if ( image.dp == NULL ) {
- ERROR("Failed to allocate data\n");
- return 1;
- }
- for ( i=0; i<image.det->n_panels; i++ ) {
- image.dp[i] = calloc(image.det->panels[i].w *
- image.det->panels[i].h,
- sizeof(float));
- if ( image.dp[i] == NULL ) {
- ERROR("Failed to allocate data\n");
- return 1;
- }
- }
-
rng = gsl_rng_alloc(gsl_rng_mt19937);
if ( config_random ) {
FILE *fh;
@@ -858,30 +930,16 @@ int main(int argc, char *argv[])
fclose(fh);
}
- powder.det = image.det;
- powder.beam = NULL;
- powder.lambda = 0.0;
- powder.spectrum = NULL;
- powder.dp = malloc(image.det->n_panels*sizeof(float *));
- if ( powder.dp == NULL ) {
- ERROR("Failed to allocate powder data\n");
- return 1;
- }
- for ( i=0; i<image.det->n_panels; i++ ) {
- powder.dp[i] = calloc(image.det->panels[i].w *
- image.det->panels[i].h,
- sizeof(float));
- if ( powder.dp[i] == NULL ) {
- ERROR("Failed to allocate powder data\n");
- return 1;
- }
- }
+ image = image_create_for_simulation(dtempl);
+ powder = image_create_for_simulation(dtempl);
/* Splurge a few useful numbers */
STATUS("Simulation parameters:\n");
- STATUS(" Photon energy: %.2f eV (wavelength %.5f A)\n",
- photon_energy, image.lambda*1e10);
- STATUS(" Number of photons: %.0f (%.2f mJ)\n", nphotons,
+ STATUS(" Wavelength: %.5f A (photon energy %.2f eV)\n",
+ image->lambda*1e10,
+ ph_lambda_to_eV(image->lambda));
+ STATUS(" Number of photons: %.0f (%.2f mJ)\n",
+ nphotons,
eV_to_J(photon_energy)*nphotons*1e3);
STATUS(" Beam divergence: not simulated\n");
STATUS(" Beam radius: %.2f microns\n",
@@ -892,22 +950,22 @@ int main(int argc, char *argv[])
case SPECTRUM_TOPHAT:
STATUS(" X-ray spectrum: top hat, "
- "width %.5f %%\n", image.bw*100.0);
+ "width %.5f %%\n", image->bw*100.0);
break;
case SPECTRUM_GAUSSIAN:
STATUS(" X-ray spectrum: Gaussian, "
- "bandwidth %.5f %%\n", image.bw*100.0);
+ "bandwidth %.5f %%\n", image->bw*100.0);
break;
case SPECTRUM_SASE:
STATUS(" X-ray spectrum: SASE, "
- "bandwidth %.5f %%\n", image.bw*100.0);
+ "bandwidth %.5f %%\n", image->bw*100.0);
break;
case SPECTRUM_TWOCOLOUR:
STATUS(" X-ray spectrum: two colour, "
- "separation %.5f %%\n", image.bw*100.0);
+ "separation %.5f %%\n", image->bw*100.0);
break;
case SPECTRUM_FROMFILE:
@@ -937,12 +995,13 @@ int main(int argc, char *argv[])
int err = 0;
int pi;
- for ( pi=0; pi<image.det->n_panels; pi++ ) {
+ /* Reset image data to zero for new pattern */
+ for ( pi=0; pi<image->detgeom->n_panels; pi++ ) {
long j;
- long np = image.det->panels[pi].w
- * image.det->panels[pi].h;
+ long np = image->detgeom->panels[pi].w
+ * image->detgeom->panels[pi].h;
for ( j=0; j<np; j++ ) {
- image.dp[pi][j] = 0.0;
+ image->dp[pi][j] = 0.0;
}
}
@@ -986,70 +1045,53 @@ int main(int argc, char *argv[])
} else {
- struct image image;
- int i;
+ struct image *templ_image;
Crystal *cr;
- image.det = NULL;
-
/* Get data from next chunk */
- if ( read_chunk(st, &image) ) break;
-
- free(image.filename);
- image_feature_list_free(image.features);
-
- if ( image.n_crystals == 0 ) continue;
+ templ_image = stream_read_chunk(st, 0);
+ if ( templ_image == NULL ) break;
+ if ( templ_image->n_crystals == 0 ) continue;
- cr = image.crystals[0];
- cell = crystal_get_cell(cr);
+ cr = templ_image->crystals[0];
+ cell = cell_new_from_cell(crystal_get_cell(cr));
- if ( image.n_crystals > 1 ) {
+ if ( templ_image->n_crystals > 1 ) {
ERROR("Using the first crystal only.\n");
}
- for ( i=1; i<image.n_crystals; i++ ) {
-
- Crystal *cr = image.crystals[i];
- cell = crystal_get_cell(cr);
-
- reflist_free(crystal_get_reflections(cr));
- cell_free(crystal_get_cell(cr));
- crystal_free(cr);
-
- }
-
- free(image.crystals);
+ image_free(templ_image);
}
switch ( spectrum_type ) {
case SPECTRUM_TOPHAT :
- image.spectrum = spectrum_generate_tophat(image.lambda,
- image.bw);
+ image->spectrum = spectrum_generate_tophat(image->lambda,
+ image->bw);
break;
case SPECTRUM_GAUSSIAN :
- image.spectrum = spectrum_generate_gaussian(image.lambda,
- image.bw);
+ image->spectrum = spectrum_generate_gaussian(image->lambda,
+ image->bw);
break;
case SPECTRUM_SASE :
- image.spectrum = spectrum_generate_sase(image.lambda,
- image.bw,
- sase_spike_width,
- rng);
+ image->spectrum = spectrum_generate_sase(image->lambda,
+ image->bw,
+ sase_spike_width,
+ rng);
break;
- case SPECTRUM_TWOCOLOUR :
- image.spectrum = spectrum_generate_twocolour(image.lambda,
- image.bw,
- twocol_sep);
+ case SPECTRUM_TWOCOLOUR :
+ image->spectrum = spectrum_generate_twocolour(image->lambda,
+ image->bw,
+ twocol_sep);
break;
- case SPECTRUM_FROMFILE :
- image.spectrum = spectrum_load(spectrum_fn);
+ case SPECTRUM_FROMFILE :
+ image->spectrum = spectrum_load(spectrum_fn);
break;
}
@@ -1066,12 +1108,12 @@ int main(int argc, char *argv[])
intensities, flags, sym_str,
gpu_dev);
}
- err = get_diffraction_gpu(gctx, &image, na, nb, nc,
+ err = get_diffraction_gpu(gctx, image, na, nb, nc,
cell, no_fringes, flat,
nsamples);
} else {
- get_diffraction(&image, na, nb, nc, intensities, phases,
+ get_diffraction(image, na, nb, nc, intensities, phases,
flags, cell, grad, sym, no_fringes, flat,
nsamples);
}
@@ -1081,28 +1123,28 @@ int main(int argc, char *argv[])
goto skip;
}
- record_image(&image, !config_nonoise, background, rng,
+ record_image(image, !config_nonoise, background, rng,
beam_radius, nphotons);
if ( powder_fn != NULL ) {
int pn;
- for ( pn=0; pn<image.det->n_panels; pn++ ) {
+ for ( pn=0; pn<image->detgeom->n_panels; pn++ ) {
size_t w, i;
- w = image.det->panels[pn].w
- * image.det->panels[pn].h;
+ w = image->detgeom->panels[pn].w
+ * image->detgeom->panels[pn].h;
for ( i=0; i<w; i++ ) {
- powder.dp[pn][i] += (double)image.dp[pn][i];
+ powder->dp[pn][i] += (double)image->dp[pn][i];
}
}
if ( !(ndone % 10) ) {
- hdf5_write_image(powder_fn, &powder, NULL);
+ image_write(powder, dtempl, powder_fn);
}
}
@@ -1120,7 +1162,9 @@ int main(int argc, char *argv[])
number++;
/* Write the output file */
- hdf5_write_image(filename, &image, NULL);
+ image_write(image, dtempl, filename);
+
+ /* Add some pattern_sim-specific metadata */
add_metadata(filename, orientation, cell);
}
@@ -1135,21 +1179,16 @@ skip:
} while ( !done );
if ( powder_fn != NULL ) {
- hdf5_write_image(powder_fn, &powder, NULL);
+ image_write(powder, dtempl, powder_fn);
}
if ( gctx != NULL ) {
cleanup_gpu(gctx);
}
- for ( i=0; i<image.det->n_panels; i++ ) {
- free(image.dp[i]);
- free(powder.dp[i]);
- }
- free(image.dp);
- free(powder.dp);
+ image_free(image);
+ image_free(powder);
free(intfile);
- free(image.det);
cell_free(input_cell);
free(intensities);
free(outfile);
diff --git a/src/pattern_sim.h b/src/pattern_sim.h
index 15a33530..f013c0fb 100644
--- a/src/pattern_sim.h
+++ b/src/pattern_sim.h
@@ -3,11 +3,11 @@
*
* Simulate diffraction patterns from small crystals
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2011-2012 Thomas White <taw@physics.org>
+ * 2011-2021 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -48,7 +48,7 @@
#define TYPE double
#include "list_tmp.h"
-/* CAs above, but for phase values */
+/* As above, but for phase values */
#define LABEL(x) x##_phase
#define TYPE double
#include "list_tmp.h"
diff --git a/src/post-refinement.c b/src/post-refinement.c
index 16ab41ce..d4aeecef 100644
--- a/src/post-refinement.c
+++ b/src/post-refinement.c
@@ -3,11 +3,11 @@
*
* Post refinement
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2018 Thomas White <taw@physics.org>
+ * 2010-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -56,7 +56,7 @@ struct rf_alteration
struct rf_priv
{
- const Crystal *cr; /**< Original crystal (before any refinement) */
+ Crystal *cr; /**< Original crystal (before any refinement) */
const RefList *full;
int serial;
int scaleflags;
@@ -98,7 +98,7 @@ const char *str_prflag(enum prflag flag)
}
-static void rotate_cell_xy(const UnitCell *source, UnitCell *tgt,
+static void rotate_cell_xy(UnitCell *source, UnitCell *tgt,
double ang1, double ang2)
{
double asx, asy, asz;
@@ -150,7 +150,7 @@ static void rotate_cell_xy(const UnitCell *source, UnitCell *tgt,
}
-static void apply_parameters(const Crystal *cr_orig, Crystal *cr_tgt,
+static void apply_parameters(Crystal *cr_orig, Crystal *cr_tgt,
struct rf_alteration alter)
{
double R, lambda;
@@ -161,7 +161,7 @@ static void apply_parameters(const Crystal *cr_orig, Crystal *cr_tgt,
R = crystal_get_profile_radius(cr_orig);
lambda = crystal_get_image_const(cr_orig)->lambda;
- rotate_cell_xy(crystal_get_cell_const(cr_orig), crystal_get_cell(cr_tgt),
+ rotate_cell_xy(crystal_get_cell(cr_orig), crystal_get_cell(cr_tgt),
alter.rot_x, alter.rot_y);
crystal_set_profile_radius(cr_tgt, R+alter.delta_R);
image->lambda = lambda+alter.delta_wave;
@@ -336,9 +336,7 @@ void write_test_logs(Crystal *crystal, const RefList *full,
}
if ( cycle == 0 ) {
- char *evstr = get_event_string(image->event);
- fprintf(fh, "Image: %s %s\n", image->filename, evstr);
- free(evstr);
+ fprintf(fh, "Image: %s %s\n", image->filename, image->ev);
}
if ( cycle >= 0 ) {
@@ -393,10 +391,8 @@ void write_specgraph(Crystal *crystal, const RefList *full,
}
if ( cycle == 0 ) {
- char *evstr = get_event_string(image->event);
- fprintf(fh, "Image: %s %s\n", image->filename, evstr);
+ fprintf(fh, "Image: %s %s\n", image->filename, image->ev);
fprintf(fh, "khalf/m 1/d(m) pcalc pobs iteration h k l\n");
- free(evstr);
}
cell = crystal_get_cell(crystal);
@@ -757,7 +753,7 @@ struct refine_args
};
-struct queue_args
+struct pr_queue_args
{
int n_started;
int n_done;
@@ -784,7 +780,7 @@ static void refine_image(void *task, int id)
static void *get_image(void *vqargs)
{
struct refine_args *task;
- struct queue_args *qargs = vqargs;
+ struct pr_queue_args *qargs = vqargs;
task = malloc(sizeof(struct refine_args));
memcpy(task, &qargs->task_defaults, sizeof(struct refine_args));
@@ -800,7 +796,7 @@ static void *get_image(void *vqargs)
static void done_image(void *vqargs, void *task)
{
- struct queue_args *qa = vqargs;
+ struct pr_queue_args *qa = vqargs;
qa->n_done++;
@@ -815,7 +811,7 @@ void refine_all(Crystal **crystals, int n_crystals,
SymOpList *sym, SymOpList *amb, int scaleflags)
{
struct refine_args task_defaults;
- struct queue_args qargs;
+ struct pr_queue_args qargs;
task_defaults.full = full;
task_defaults.crystal = NULL;
diff --git a/src/post-refinement.h b/src/post-refinement.h
index 29e8aa7f..a15d0396 100644
--- a/src/post-refinement.h
+++ b/src/post-refinement.h
@@ -3,11 +3,11 @@
*
* Post refinement
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2018 Thomas White <taw@physics.org>
+ * 2010-2019 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
diff --git a/src/process_hkl.c b/src/process_hkl.c
index 53379243..ed384a4a 100644
--- a/src/process_hkl.c
+++ b/src/process_hkl.c
@@ -3,13 +3,13 @@
*
* Assemble and process FEL Bragg intensities
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
* Copyright © 2012 Lorenzo Galli
*
* Authors:
* 2015 Keitaro Yamashita <k.yamashita@spring8.or.jp>
- * 2009-2016 Thomas White <taw@physics.org>
+ * 2009-2020 Thomas White <taw@physics.org>
* 2011 Andrew Martin <andrew.martin@desy.de>
* 2012 Lorenzo Galli <lorenzo.galli@desy.de>
* 2014 Chunhong Yoon <chun.hong.yoon@desy.de>
@@ -43,16 +43,18 @@
#include <unistd.h>
#include <getopt.h>
-#include "utils.h"
-#include "reflist-utils.h"
-#include "symmetry.h"
-#include "stream.h"
-#include "reflist.h"
-#include "image.h"
-#include "crystal.h"
-#include "thread-pool.h"
-#include "geometry.h"
-#include "cell-utils.h"
+#include <utils.h>
+#include <reflist-utils.h>
+#include <symmetry.h>
+#include <stream.h>
+#include <reflist.h>
+#include <image.h>
+#include <crystal.h>
+#include <thread-pool.h>
+#include <geometry.h>
+#include <cell-utils.h>
+
+#include "version.h"
static void show_help(const char *s)
@@ -300,7 +302,7 @@ static int merge_crystal(RefList *model, struct image *image, Crystal *cr,
if ( scale <= 0.0 ) return 1;
if ( stat != NULL ) {
fprintf(stat, "%s %s %f %f\n", image->filename,
- get_event_string(image->event), scale, cc);
+ image->ev, scale, cc);
}
} else {
@@ -395,50 +397,42 @@ static void display_progress(int n_images, int n_crystals, int n_crystals_used)
}
-static int merge_all(Stream *st, RefList *model, RefList *reference,
- const SymOpList *sym,
- double **hist_vals, signed int hist_h,
- signed int hist_k, signed int hist_l,
- int *hist_i, struct polarisation p, int min_measurements,
- double min_snr, double max_adu,
- int start_after, int stop_after, double min_res,
- double push_res, double min_cc, int do_scale, int flag_even_odd, char *stat_output)
+static int merge_stream(Stream *st,
+ RefList *model, RefList *reference,
+ const SymOpList *sym,
+ double **hist_vals, signed int hist_h,
+ signed int hist_k, signed int hist_l,
+ int *hist_i, struct polarisation p,
+ int min_measurements,
+ double min_snr, double max_adu,
+ int start_after, int stop_after, double min_res,
+ double push_res, double min_cc, int do_scale,
+ int flag_even_odd, char *stat_output,
+ int *pn_images, int *pn_crystals,
+ int *pn_crystals_used, int *pn_crystals_seen,
+ FILE *stat)
{
- int rval;
- int n_images = 0;
- int n_crystals = 0;
- int n_crystals_used = 0;
- Reflection *refl;
- RefListIterator *iter;
- int n_crystals_seen = 0;
- FILE *stat = NULL;
-
- if ( stat_output != NULL ) {
- stat = fopen(stat_output, "w");
- if ( stat == NULL ) {
- ERROR("Failed to open statistics output file %s\n",
- stat_output);
- }
- }
+ int n_images = *pn_images;
+ int n_crystals = *pn_crystals;
+ int n_crystals_used = *pn_crystals_used;
+ int n_crystals_seen = *pn_crystals_seen;
do {
- struct image image;
+ struct image *image;
int i;
- image.det = NULL;
-
/* Get data from next chunk */
- rval = read_chunk_2(st, &image, STREAM_READ_REFLECTIONS |
- STREAM_READ_UNITCELL);
- if ( rval ) break;
+ image = stream_read_chunk(st,
+ STREAM_REFLECTIONS);
+ if ( image == NULL ) break;
n_images++;
- for ( i=0; i<image.n_crystals; i++ ) {
+ for ( i=0; i<image->n_crystals; i++ ) {
int r;
- Crystal *cr = image.crystals[i];
+ Crystal *cr = image->crystals[i];
n_crystals_seen++;
if ( (n_crystals_seen > start_after)
@@ -446,7 +440,7 @@ static int merge_all(Stream *st, RefList *model, RefList *reference,
&& (flag_even_odd == 2 || n_crystals_seen%2 == flag_even_odd) )
{
n_crystals++;
- r = merge_crystal(model, &image, cr, reference,
+ r = merge_crystal(model, image, cr, reference,
sym, hist_vals,
hist_h, hist_k, hist_l,
hist_i, p,
@@ -455,23 +449,76 @@ static int merge_all(Stream *st, RefList *model, RefList *reference,
if ( r == 0 ) n_crystals_used++;
}
- reflist_free(crystal_get_reflections(cr));
- cell_free(crystal_get_cell(cr));
- crystal_free(cr);
-
if ( n_crystals_used == stop_after ) break;
}
- free(image.filename);
- image_feature_list_free(image.features);
- free(image.crystals);
+ image_free(image);
display_progress(n_images, n_crystals_seen, n_crystals_used);
if ( (stop_after>0) && (n_crystals_used == stop_after) ) break;
- } while ( rval == 0 );
+ } while ( 1 );
+
+ *pn_images = n_images;
+ *pn_crystals = n_crystals;
+ *pn_crystals_seen = n_crystals_seen;
+ *pn_crystals_used = n_crystals_used;
+ return 0;
+}
+
+
+struct stream_list
+{
+ int n;
+ int max_n;
+ const char **filenames;
+ Stream **streams;
+};
+
+
+static int merge_all(struct stream_list *streams,
+ RefList *model, RefList *reference,
+ const SymOpList *sym,
+ double **hist_vals, signed int hist_h,
+ signed int hist_k, signed int hist_l,
+ int *hist_i, struct polarisation p,
+ int min_measurements,
+ double min_snr, double max_adu,
+ int start_after, int stop_after, double min_res,
+ double push_res, double min_cc, int do_scale,
+ int flag_even_odd, char *stat_output)
+{
+ Reflection *refl;
+ RefListIterator *iter;
+ int i;
+ int n_images = 0;
+ int n_crystals = 0;
+ int n_crystals_used = 0;
+ int n_crystals_seen = 0;
+ FILE *stat = NULL;
+
+ if ( stat_output != NULL ) {
+ stat = fopen(stat_output, "w");
+ if ( stat == NULL ) {
+ ERROR("Failed to open statistics output file %s\n",
+ stat_output);
+ }
+ }
+
+ for ( i=0; i<streams->n; i++ ) {
+ if ( merge_stream(streams->streams[i],
+ model, reference, sym,
+ hist_vals, hist_h, hist_k, hist_l, hist_i,
+ p, min_measurements, min_snr, max_adu,
+ start_after, stop_after, min_res,
+ push_res, min_cc, do_scale,
+ flag_even_odd, stat_output,
+ &n_images, &n_crystals, &n_crystals_used,
+ &n_crystals_seen, stat) ) return 1;
+ }
+
for ( refl = first_refl(model, &iter);
refl != NULL;
@@ -498,13 +545,45 @@ static int merge_all(Stream *st, RefList *model, RefList *reference,
}
+static int add_stream(const char *filename, struct stream_list *list)
+{
+ if ( list->n == list->max_n ) {
+ const char **new_filenames = realloc(list->filenames,
+ (list->n+16)*sizeof(const char *));
+ Stream **new_streams = realloc(list->streams,
+ (list->n+16)*sizeof(Stream *));
+ if ( (new_filenames == NULL) || (new_streams == NULL) ) return 1;
+ list->max_n += 16;
+ list->filenames = new_filenames;
+ list->streams = new_streams;
+ }
+
+ list->filenames[list->n] = filename;
+ list->streams[list->n] = NULL;
+ list->n++;
+ return 0;
+}
+
+
+static int rewind_all_streams(struct stream_list *stream_list)
+{
+ int i;
+
+ for ( i=0; i<stream_list->n; i++ ) {
+ if ( stream_rewind(stream_list->streams[i]) ) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
int main(int argc, char *argv[])
{
int c;
- char *filename = NULL;
+ int i;
char *output = NULL;
char *stat_output = NULL;
- Stream *st;
RefList *model;
int config_scale = 0;
int config_evenonly = 0;
@@ -535,6 +614,10 @@ int main(int argc, char *argv[])
double min_cc = -INFINITY;
int twopass = 0;
char *audit_info;
+ struct stream_list stream_list = {.n = 0,
+ .max_n = 0,
+ .filenames = NULL,
+ .streams = NULL};
/* Long options */
const struct option longopts[] = {
@@ -576,7 +659,7 @@ int main(int argc, char *argv[])
return 0;
case 'i' :
- filename = strdup(optarg);
+ add_stream(optarg, &stream_list);
break;
case 'o' :
@@ -667,8 +750,10 @@ int main(int argc, char *argv[])
break;
case 7 :
- printf("CrystFEL: " CRYSTFEL_VERSIONSTRING "\n");
- printf(CRYSTFEL_BOILERPLATE"\n");
+ printf("CrystFEL: %s\n",
+ crystfel_version_string());
+ printf("%s\n",
+ crystfel_licence_string());
return 0;
case '?' :
@@ -708,8 +793,12 @@ int main(int argc, char *argv[])
}
- if ( filename == NULL ) {
- ERROR("Please specify filename using the -i option\n");
+ while ( optind < argc ) {
+ add_stream(argv[optind++], &stream_list);
+ }
+
+ if ( stream_list.n == 0 ) {
+ ERROR("Please give at least one input stream filename.\n");
return 1;
}
@@ -722,11 +811,13 @@ int main(int argc, char *argv[])
sym = get_pointgroup(sym_str);
free(sym_str);
- /* Open the data stream */
- st = open_stream_for_read(filename);
- if ( st == NULL ) {
- ERROR("Failed to open stream.\n");
- return 1;
+ /* Open all the data streams */
+ for ( i=0; i<stream_list.n; i++ ) {
+ stream_list.streams[i] = stream_open_for_read(stream_list.filenames[i]);
+ if ( stream_list.streams[i] == NULL ) {
+ ERROR("Failed to open stream.\n");
+ return 1;
+ }
}
model = reflist_new();
@@ -774,7 +865,7 @@ int main(int argc, char *argv[])
}
if ( config_evenonly && config_oddonly ) {
- ERROR("Don't specify both --even-only and --odd-only\n")
+ ERROR("Don't specify both --even-only and --odd-only\n");
return 1;
}
@@ -785,7 +876,8 @@ int main(int argc, char *argv[])
if ( config_scale ) twopass = 1;
hist_i = 0;
- r = merge_all(st, model, NULL, sym, &hist_vals, hist_h, hist_k, hist_l,
+ r = merge_all(&stream_list, model, NULL, sym,
+ &hist_vals, hist_h, hist_k, hist_l,
&hist_i, polarisation, min_measurements, min_snr,
max_adu, start_after, stop_after, min_res, push_res,
min_cc, config_scale, flag_even_odd, stat_output);
@@ -799,7 +891,7 @@ int main(int argc, char *argv[])
RefList *reference;
- if ( rewind_stream(st) ) {
+ if ( rewind_all_streams(&stream_list) ) {
ERROR("Couldn't rewind stream - scaling cannot be "
"performed.\n");
@@ -819,8 +911,8 @@ int main(int argc, char *argv[])
hist_i = 0;
}
- r = merge_all(st, model, reference, sym, &hist_vals,
- hist_h, hist_k, hist_l, &hist_i,
+ r = merge_all(&stream_list, model, reference, sym,
+ &hist_vals, hist_h, hist_k, hist_l, &hist_i,
polarisation, min_measurements, min_snr,
max_adu, start_after, stop_after, min_res,
push_res, min_cc, config_scale,
@@ -848,8 +940,10 @@ int main(int argc, char *argv[])
hist_nbins);
}
- audit_info = stream_audit_info(st);
- close_stream(st);
+ audit_info = stream_audit_info(stream_list.streams[0]);
+ for ( i=0; i<stream_list.n; i++ ) {
+ stream_close(stream_list.streams[i]);
+ }
reflist_add_command_and_version(model, argc, argv);
reflist_add_notes(model, "Audit information from stream:");
@@ -859,7 +953,6 @@ int main(int argc, char *argv[])
free_symoplist(sym);
reflist_free(model);
free(output);
- free(filename);
free(stat_output);
return 0;
diff --git a/src/process_image.c b/src/process_image.c
index b785705a..d3355f38 100644
--- a/src/process_image.c
+++ b/src/process_image.c
@@ -3,11 +3,11 @@
*
* The processing pipeline for one image
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2019 Thomas White <taw@physics.org>
+ * 2010-2020 Thomas White <taw@physics.org>
* 2014-2017 Valerio Mariani <valerio.mariani@desy.de>
* 2017 Stijn de Graaf
*
@@ -33,32 +33,31 @@
#endif
#include <stdlib.h>
-#include <hdf5.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_statistics_double.h>
#include <gsl/gsl_sort.h>
#include <unistd.h>
#include <sys/stat.h>
-#include "utils.h"
-#include "hdf5-file.h"
-#include "index.h"
-#include "peaks.h"
-#include "detector.h"
-#include "filters.h"
-#include "thread-pool.h"
-#include "geometry.h"
-#include "stream.h"
-#include "reflist-utils.h"
+#include <utils.h>
+#include <index.h>
+#include <peaks.h>
+#include <filters.h>
+#include <thread-pool.h>
+#include <geometry.h>
+#include <stream.h>
+#include <reflist-utils.h>
+#include <integration.h>
+#include <detgeom.h>
+#include <image-msgpack.h>
+
#include "process_image.h"
-#include "integration.h"
#include "predict-refine.h"
#include "im-sandbox.h"
-#include "time-accounts.h"
#include "im-zmq.h"
+#include "time-accounts.h"
-
-static float **backup_image_data(float **dp, struct detector *det)
+static float **backup_image_data(float **dp, struct detgeom *det)
{
float **bu;
int i;
@@ -86,7 +85,7 @@ static float **backup_image_data(float **dp, struct detector *det)
}
-static void restore_image_data(float **dp, struct detector *det, float **bu)
+static void restore_image_data(float **dp, struct detgeom *det, float **bu)
{
int i;
@@ -100,16 +99,22 @@ static void restore_image_data(float **dp, struct detector *det, float **bu)
}
-static int file_wait_open_read(struct sb_shm *sb_shared, struct image *image,
- TimeAccounts *taccs, char *last_task,
- signed int wait_for_file, int cookie,
- struct imagefile **pimfile)
+static struct image *file_wait_open_read(const char *filename,
+ const char *event,
+ DataTemplate *dtempl,
+ struct sb_shm *sb_shared,
+ TimeAccounts *taccs,
+ char *last_task,
+ signed int wait_for_file,
+ int cookie,
+ int no_image_data,
+ int no_mask_data)
{
signed int file_wait_time = wait_for_file;
int wait_message_done = 0;
int read_retry_done = 0;
int r;
- struct imagefile *imfile;
+ struct image *image;
time_accounts_set(taccs, TACC_WAITFILE);
set_last_task(last_task, "wait for file");
@@ -119,14 +124,14 @@ static int file_wait_open_read(struct sb_shm *sb_shared, struct image *image,
struct stat statbuf;
sb_shared->pings[cookie]++;
- r = stat(image->filename, &statbuf);
+ r = stat(filename, &statbuf);
if ( r ) {
if ( (wait_for_file != 0) && (file_wait_time != 0) ) {
if ( !wait_message_done ) {
STATUS("Waiting for '%s'\n",
- image->filename);
+ filename);
wait_message_done = 1;
}
@@ -138,8 +143,8 @@ static int file_wait_open_read(struct sb_shm *sb_shared, struct image *image,
}
- ERROR("File %s not found\n", image->filename);
- return 1;
+ ERROR("File %s not found\n", filename);
+ return NULL;
}
} while ( r );
@@ -149,44 +154,29 @@ static int file_wait_open_read(struct sb_shm *sb_shared, struct image *image,
sb_shared->pings[cookie]++;
do {
- imfile = imagefile_open(image->filename);
- if ( imfile == NULL ) {
- if ( wait_for_file && !read_retry_done ) {
- read_retry_done = 1;
- r = 1;
- STATUS("File '%s' exists but could not be opened."
- " Trying again after 10 seconds.\n",
- image->filename);
- sleep(10);
- continue;
- }
- ERROR("Couldn't open file: %s\n", image->filename);
- return 1;
- }
time_accounts_set(taccs, TACC_HDF5READ);
set_last_task(last_task, "read file");
sb_shared->pings[cookie]++;
- r = imagefile_read(imfile, image, image->event);
- if ( r ) {
+ image = image_read(dtempl, filename, event,
+ no_image_data, no_mask_data);
+ if ( image == NULL ) {
if ( wait_for_file && !read_retry_done ) {
read_retry_done = 1;
- imagefile_close(imfile);
STATUS("File '%s' exists but could not be read."
" Trying again after 10 seconds.\n",
- image->filename);
+ filename);
sleep(10);
continue;
}
- ERROR("Couldn't open file: %s\n", image->filename);
- return 1;
+ ERROR("Couldn't open file: %s\n", filename);
+ return NULL;
}
} while ( r );
- *pimfile = imfile;
- return 0;
+ return image;
}
@@ -195,8 +185,7 @@ void process_image(const struct index_args *iargs, struct pattern_args *pargs,
int serial, struct sb_shm *sb_shared, TimeAccounts *taccs,
char *last_task)
{
- struct imagefile *imfile = NULL;
- struct image image;
+ struct image *image;
int i;
int r;
int ret;
@@ -204,27 +193,21 @@ void process_image(const struct index_args *iargs, struct pattern_args *pargs,
float **prefilter;
int any_crystals;
- image.features = NULL;
- image.copyme = iargs->copyme;
- image.id = cookie;
- image.beam = iargs->beam;
- image.det = copy_geom(iargs->det);
- image.crystals = NULL;
- image.n_crystals = 0;
- image.serial = serial;
- image.indexed_by = INDEXING_NONE;
-
- image.filename = pargs->filename_p_e->filename;
- image.event = pargs->filename_p_e->ev;
if ( pargs->msgpack_obj != NULL ) {
set_last_task(last_task, "unpacking messagepack object");
- if ( unpack_msgpack_data(pargs->msgpack_obj, &image,
- iargs->no_image_data) ) return;
+ image = image_msgpack_read(iargs->dtempl,
+ pargs->msgpack_obj,
+ iargs->no_image_data);
+ if ( image == NULL ) return;
} else {
- if ( file_wait_open_read(sb_shared, &image, taccs, last_task,
- iargs->wait_for_file, cookie,
- &imfile) )
- {
+ image = file_wait_open_read(pargs->filename, pargs->event,
+ iargs->dtempl,
+ sb_shared, taccs, last_task,
+ iargs->wait_for_file,
+ cookie,
+ iargs->no_image_data,
+ iargs->no_mask_data);
+ if ( image == NULL ) {
if ( iargs->wait_for_file != 0 ) {
pthread_mutex_lock(&sb_shared->totals_lock);
sb_shared->should_shutdown = 1;
@@ -234,62 +217,43 @@ void process_image(const struct index_args *iargs, struct pattern_args *pargs,
}
}
- image.bw = iargs->beam->bandwidth;
+ image->serial = serial;
/* Take snapshot of image before applying horrible noise filters */
time_accounts_set(taccs, TACC_FILTER);
set_last_task(last_task, "image filter");
sb_shared->pings[cookie]++;
- prefilter = backup_image_data(image.dp, image.det);
+ prefilter = backup_image_data(image->dp, image->detgeom);
if ( iargs->median_filter > 0 ) {
- filter_median(&image, iargs->median_filter);
+ filter_median(image, iargs->median_filter);
}
if ( iargs->noisefilter ) {
- filter_noise(&image);
+ filter_noise(image);
}
time_accounts_set(taccs, TACC_RESRANGE);
set_last_task(last_task, "resolution range");
sb_shared->pings[cookie]++;
- mark_resolution_range_as_bad(&image, iargs->highres, +INFINITY);
+ mark_resolution_range_as_bad(image, iargs->highres, +INFINITY);
time_accounts_set(taccs, TACC_PEAKSEARCH);
sb_shared->pings[cookie]++;
switch ( iargs->peaks ) {
- struct hdfile *hdfile;
-
case PEAK_HDF5:
- set_last_task(last_task, "peaksearch:hdf5");
- hdfile = imagefile_get_hdfile(imfile);
- if ( (hdfile == NULL)
- || (get_peaks_2(&image, hdfile, iargs->hdf5_peak_path,
- iargs->half_pixel_shift)) )
- {
- ERROR("Failed to get peaks from HDF5 file.\n");
- }
- if ( !iargs->no_revalidate ) {
- validate_peaks(&image, iargs->min_snr,
- iargs->pk_inn, iargs->pk_mid,
- iargs->pk_out, iargs->use_saturated,
- iargs->check_hdf5_snr);
- }
- break;
-
case PEAK_CXI:
- set_last_task(last_task, "peaksearch:cxi");
- hdfile = imagefile_get_hdfile(imfile);
- if ( (hdfile == NULL)
- || (get_peaks_cxi_2(&image, hdfile, iargs->hdf5_peak_path,
- pargs->filename_p_e,
- iargs->half_pixel_shift)) )
- {
- ERROR("Failed to get peaks from CXI file.\n");
+ set_last_task(last_task, "peaksearch:hdf5orcxi");
+ image->features = image_read_peaks(iargs->dtempl,
+ pargs->filename,
+ pargs->event,
+ iargs->half_pixel_shift);
+ if ( image->features == NULL ) {
+ ERROR("Failed to get peaks from HDF5 file.\n");
}
if ( !iargs->no_revalidate ) {
- validate_peaks(&image, iargs->min_snr,
+ validate_peaks(image, iargs->min_snr,
iargs->pk_inn, iargs->pk_mid,
iargs->pk_out, iargs->use_saturated,
iargs->check_hdf5_snr);
@@ -298,7 +262,7 @@ void process_image(const struct index_args *iargs, struct pattern_args *pargs,
case PEAK_ZAEF:
set_last_task(last_task, "peaksearch:zaef");
- search_peaks(&image, iargs->threshold,
+ search_peaks(image, iargs->threshold,
iargs->min_sq_gradient, iargs->min_snr,
iargs->pk_inn, iargs->pk_mid, iargs->pk_out,
iargs->use_saturated);
@@ -306,30 +270,24 @@ void process_image(const struct index_args *iargs, struct pattern_args *pargs,
case PEAK_PEAKFINDER8:
set_last_task(last_task, "peaksearch:pf8");
- if ( search_peaks_peakfinder8(&image, 2048,
- iargs->threshold,
- iargs->min_snr,
- iargs->min_pix_count,
- iargs->max_pix_count,
- iargs->local_bg_radius,
- iargs->min_res,
- iargs->max_res,
- iargs->use_saturated) ) {
- if ( image.event != NULL ) {
- ERROR("Failed to find peaks in image %s"
- "(event %s).\n", image.filename,
- get_event_string(image.event));
- } else {
- ERROR("Failed to find peaks in image %s.",
- image.filename);
- }
-
+ if ( search_peaks_peakfinder8(image, 2048,
+ iargs->threshold,
+ iargs->min_snr,
+ iargs->min_pix_count,
+ iargs->max_pix_count,
+ iargs->local_bg_radius,
+ iargs->min_res,
+ iargs->max_res,
+ iargs->use_saturated) ) {
+ ERROR("Failed to find peaks in image %s"
+ "(event %s).\n",
+ image->filename, image->ev);
}
break;
case PEAK_PEAKFINDER9:
set_last_task(last_task, "peaksearch:pf9");
- if ( search_peaks_peakfinder9(&image,
+ if ( search_peaks_peakfinder9(image,
iargs->min_snr_biggest_pix,
iargs->min_snr_peak_pix,
iargs->min_snr,
@@ -337,31 +295,29 @@ void process_image(const struct index_args *iargs, struct pattern_args *pargs,
iargs->min_peak_over_neighbour,
iargs->local_bg_radius) )
{
- if ( image.event != NULL ) {
- ERROR("Failed to find peaks in image %s"
- "(event %s).\n", image.filename,
- get_event_string(image.event));
- } else {
- ERROR("Failed to find peaks in image %s.",
- image.filename);
- }
+ ERROR("Failed to find peaks in image %s"
+ "(event %s).\n",
+ image->filename, image->ev);
}
break;
case PEAK_MSGPACK:
- get_peaks_msgpack(pargs->msgpack_obj, &image,
- iargs->half_pixel_shift);
+ image->features = image_msgpack_read_peaks(iargs->dtempl,
+ pargs->msgpack_obj,
+ iargs->half_pixel_shift);
break;
case PEAK_NONE:
+ case PEAK_ERROR:
break;
}
- image.peak_resolution = estimate_peak_resolution(image.features,
- image.lambda);
+ image->peak_resolution = estimate_peak_resolution(image->features,
+ image->lambda,
+ image->detgeom);
- restore_image_data(image.dp, image.det, prefilter);
+ restore_image_data(image->dp, image->detgeom, prefilter);
rn = getcwd(NULL, 0);
@@ -369,33 +325,24 @@ void process_image(const struct index_args *iargs, struct pattern_args *pargs,
if ( r ) {
ERROR("Failed to chdir to temporary folder: %s\n",
strerror(errno));
- imagefile_close(imfile);
return;
}
/* Set beam parameters */
if ( iargs->fix_divergence >= 0.0 ) {
- image.div = iargs->fix_divergence;
+ image->div = iargs->fix_divergence;
} else {
- image.div = 0.0;
- }
- /* Set beam spectrum */
- if ( iargs->spectrum != NULL ) {
- image.spectrum = iargs->spectrum;
- } else {
- image.spectrum = spectrum_generate_gaussian(image.lambda,
- image.bw);
+ image->div = 0.0;
}
- if ( image_feature_count(image.features) < iargs->min_peaks ) {
+ if ( image_feature_count(image->features) < iargs->min_peaks ) {
r = chdir(rn);
if ( r ) {
ERROR("Failed to chdir: %s\n", strerror(errno));
- imagefile_close(imfile);
return;
}
free(rn);
- image.hit = 0;
+ image->hit = 0;
if ( iargs->stream_nonhits ) {
goto streamwrite;
@@ -403,18 +350,17 @@ void process_image(const struct index_args *iargs, struct pattern_args *pargs,
goto out;
}
}
- image.hit = 1;
+ image->hit = 1;
/* Index the pattern */
time_accounts_set(taccs, TACC_INDEXING);
set_last_task(last_task, "indexing");
- index_pattern_3(&image, iargs->ipriv, &sb_shared->pings[cookie],
+ index_pattern_3(image, iargs->ipriv, &sb_shared->pings[cookie],
last_task);
r = chdir(rn);
if ( r ) {
ERROR("Failed to chdir: %s\n", strerror(errno));
- imagefile_close(imfile);
return;
}
free(rn);
@@ -423,22 +369,22 @@ void process_image(const struct index_args *iargs, struct pattern_args *pargs,
time_accounts_set(taccs, TACC_PREDPARAMS);
set_last_task(last_task, "prediction params");
if ( iargs->fix_profile_r >= 0.0 ) {
- for ( i=0; i<image.n_crystals; i++ ) {
- crystal_set_profile_radius(image.crystals[i],
+ for ( i=0; i<image->n_crystals; i++ ) {
+ crystal_set_profile_radius(image->crystals[i],
iargs->fix_profile_r);
- crystal_set_mosaicity(image.crystals[i], 0.0);
+ crystal_set_mosaicity(image->crystals[i], 0.0);
}
} else {
- for ( i=0; i<image.n_crystals; i++ ) {
- crystal_set_profile_radius(image.crystals[i], 0.02e9);
- crystal_set_mosaicity(image.crystals[i], 0.0);
+ for ( i=0; i<image->n_crystals; i++ ) {
+ crystal_set_profile_radius(image->crystals[i], 0.02e9);
+ crystal_set_mosaicity(image->crystals[i], 0.0);
}
}
if ( iargs->fix_profile_r < 0.0 ) {
- for ( i=0; i<image.n_crystals; i++ ) {
- if ( refine_radius(image.crystals[i], &image) ) {
+ for ( i=0; i<image->n_crystals; i++ ) {
+ if ( refine_radius(image->crystals[i], image) ) {
ERROR("WARNING: Radius determination failed\n");
}
}
@@ -448,7 +394,7 @@ void process_image(const struct index_args *iargs, struct pattern_args *pargs,
time_accounts_set(taccs, TACC_INTEGRATION);
set_last_task(last_task, "integration");
sb_shared->pings[cookie]++;
- integrate_all_5(&image, iargs->int_meth, PMODEL_XSPHERE,
+ integrate_all_5(image, iargs->int_meth, PMODEL_XSPHERE,
iargs->push_res,
iargs->ir_inn, iargs->ir_mid, iargs->ir_out,
iargs->int_diag, iargs->int_diag_h,
@@ -459,21 +405,18 @@ streamwrite:
time_accounts_set(taccs, TACC_WRITESTREAM);
set_last_task(last_task, "stream write");
sb_shared->pings[cookie]++;
- ret = write_chunk(st, &image, imfile,
- iargs->stream_peaks, iargs->stream_refls,
- pargs->filename_p_e->ev);
+ ret = stream_write_chunk(st, image, iargs->stream_flags);
if ( ret != 0 ) {
ERROR("Error writing stream file.\n");
}
int n = 0;
- for ( i=0; i<image.n_crystals; i++ ) {
- n += crystal_get_num_implausible_reflections(image.crystals[i]);
+ for ( i=0; i<image->n_crystals; i++ ) {
+ n += crystal_get_num_implausible_reflections(image->crystals[i]);
}
if ( n > 0 ) {
STATUS("WARNING: %i implausibly negative reflection%s in %s "
- "%s\n", n, n>1?"s":"", image.filename,
- get_event_string(image.event));
+ "%s\n", n, n>1?"s":"", image->filename, image->ev);
}
out:
@@ -483,40 +426,19 @@ out:
sb_shared->pings[cookie]++;
pthread_mutex_lock(&sb_shared->totals_lock);
any_crystals = 0;
- for ( i=0; i<image.n_crystals; i++ ) {
- if ( crystal_get_user_flag(image.crystals[i]) == 0 ) {
+ for ( i=0; i<image->n_crystals; i++ ) {
+ if ( crystal_get_user_flag(image->crystals[i]) == 0 ) {
sb_shared->n_crystals++;
any_crystals = 1;
}
}
sb_shared->n_processed++;
- sb_shared->n_hits += image.hit;
+ sb_shared->n_hits += image->hit;
sb_shared->n_hadcrystals += any_crystals;
pthread_mutex_unlock(&sb_shared->totals_lock);
- for ( i=0; i<image.n_crystals; i++ ) {
- cell_free(crystal_get_cell(image.crystals[i]));
- reflist_free(crystal_get_reflections(image.crystals[i]));
- crystal_free(image.crystals[i]);
- }
- free(image.crystals);
-
- /* Free spectrum only if we generated it for this image */
- if ( iargs->spectrum == NULL ) {
- spectrum_free(image.spectrum);
- }
-
- for ( i=0; i<image.det->n_panels; i++ ) {
- free(image.dp[i]);
- free(image.bad[i]);
- free(image.sat[i]);
- }
- free(image.dp);
- free(image.bad);
- free(image.sat);
+ /* Free image (including detgeom) */
+ image_free(image);
- image_feature_list_free(image.features);
- free_detector_geometry(image.det);
- if ( imfile != NULL ) imagefile_close(imfile);
set_last_task(last_task, "sandbox");
}
diff --git a/src/process_image.h b/src/process_image.h
index 7c2d4781..703f0cde 100644
--- a/src/process_image.h
+++ b/src/process_image.h
@@ -3,11 +3,11 @@
*
* The processing pipeline for one image
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2019 Thomas White <taw@physics.org>
+ * 2010-2020 Thomas White <taw@physics.org>
* 2014-2017 Valerio Mariani <valerio.mariani@desy.de>
* 2017-2018 Yaroslav Gevorkov <yaroslav.gevorkov@desy.de>
*
@@ -44,17 +44,7 @@ struct index_args;
#include "integration.h"
#include "im-sandbox.h"
#include "time-accounts.h"
-
-
-enum {
- PEAK_PEAKFINDER9,
- PEAK_PEAKFINDER8,
- PEAK_ZAEF,
- PEAK_HDF5,
- PEAK_CXI,
- PEAK_MSGPACK,
- PEAK_NONE,
-};
+#include "peaks.h"
/* Information about the indexing process which is common to all patterns */
@@ -68,12 +58,10 @@ struct index_args
float min_sq_gradient;
float min_snr;
int check_hdf5_snr;
- struct detector *det;
+ DataTemplate *dtempl;
IndexingPrivate *ipriv;
- int peaks; /* Peak detection method */
+ enum peak_search_method peaks;
float tols[6];
- struct beam_params *beam;
- char *hdf5_peak_path;
int half_pixel_shift;
float pk_inn;
float pk_mid;
@@ -92,12 +80,10 @@ struct index_args
float min_snr_peak_pix;
float min_sig;
float min_peak_over_neighbour;
- struct imagefile_field_list *copyme;
int integrate_saturated;
int use_saturated;
int no_revalidate;
- int stream_peaks;
- int stream_refls;
+ int stream_flags;
int stream_nonhits;
IntegrationMethod int_meth;
IntDiag int_diag;
@@ -109,9 +95,11 @@ struct index_args
float fix_profile_r;
float fix_divergence;
int overpredict;
- Spectrum *spectrum;
signed int wait_for_file; /* -1 means wait forever */
int no_image_data;
+ int no_mask_data;
+ float wavelength_estimate;
+ int n_threads;
};
@@ -119,7 +107,8 @@ struct index_args
struct pattern_args
{
/* "Input" */
- struct filename_plus_event *filename_p_e;
+ char *filename;
+ char *event;
#ifdef HAVE_MSGPACK
msgpack_object *msgpack_obj;
#else
diff --git a/src/rejection.c b/src/rejection.c
index f1b3cd84..346d2c30 100644
--- a/src/rejection.c
+++ b/src/rejection.c
@@ -3,7 +3,7 @@
*
* Crystal rejection for scaling
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
diff --git a/src/rejection.h b/src/rejection.h
index badbe1bc..7dc2c92b 100644
--- a/src/rejection.h
+++ b/src/rejection.h
@@ -3,7 +3,7 @@
*
* Crystal rejection for scaling
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
diff --git a/src/render_hkl.c b/src/render_hkl.c
index 5f39766c..94d6202a 100644
--- a/src/render_hkl.c
+++ b/src/render_hkl.c
@@ -3,11 +3,11 @@
*
* Draw pretty renderings of reflection lists
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2017 Thomas White <taw@physics.org>
+ * 2010-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -45,13 +45,22 @@
#include <gsl/gsl_linalg.h>
#include <gsl/gsl_blas.h>
-#include "utils.h"
-#include "symmetry.h"
-#include "render.h"
+#include <utils.h>
+#include <symmetry.h>
+#include <colscale.h>
+#include <reflist.h>
+#include <reflist-utils.h>
+#include <cell-utils.h>
+
#include "render_hkl.h"
-#include "reflist.h"
-#include "reflist-utils.h"
-#include "cell-utils.h"
+#include "version.h"
+
+
+struct resrings
+{
+ double res[100];
+ int n_rings;
+};
#define KEY_FILENAME "key.pdf"
@@ -332,8 +341,8 @@ static void draw_circles(double xh, double xk, double xl,
((double)cy)+v*scale,
radius, 0.0, 2.0*M_PI);
- render_scale(val, max_val/boost, colscale,
- &r, &g, &b);
+ colscale_lookup(val, max_val/boost, colscale,
+ &r, &g, &b);
cairo_set_source_rgb(dctx, r, g, b);
cairo_fill(dctx);
@@ -399,13 +408,6 @@ static void render_overlined_indices(cairo_t *dctx,
}
-struct resrings
-{
- double res[100];
- int n_rings;
-};
-
-
static void render_za(UnitCell *cell, RefList *list,
double boost, const SymOpList *sym, int wght,
int colscale,
@@ -658,7 +660,7 @@ static int render_key(int colscale, double scale_top)
val = v/ht;
}
- render_scale(val, top, colscale, &r, &g, &b);
+ colscale_lookup(val, top, colscale, &r, &g, &b);
cairo_set_source_rgb(dctx, r, g, b);
cairo_stroke_preserve(dctx);
@@ -717,10 +719,12 @@ static int render_key(int colscale, double scale_top)
static void render_za(UnitCell *cell, RefList *list,
- double boost, const char *sym, int wght, int colscale,
+ double boost, const SymOpList *sym, int wght,
+ int colscale,
signed int xh, signed int xk, signed int xl,
signed int yh, signed int yk, signed int yl,
- const char *outfile, double scale_top)
+ const char *outfile, double scale_top, signed int zone,
+ struct resrings *rings, int noaxes)
{
ERROR("This version of CrystFEL was compiled without Cairo");
ERROR(" support, which is required to plot a zone axis");
@@ -811,8 +815,10 @@ int main(int argc, char *argv[])
return 0;
case 5 :
- printf("CrystFEL: " CRYSTFEL_VERSIONSTRING "\n");
- printf(CRYSTFEL_BOILERPLATE"\n");
+ printf("CrystFEL: %s\n",
+ crystfel_version_string());
+ printf("%s\n",
+ crystfel_licence_string());
return 0;
case 'p' :
diff --git a/src/render_hkl.h b/src/render_hkl.h
index 3e132fbd..67ab3f8f 100644
--- a/src/render_hkl.h
+++ b/src/render_hkl.h
@@ -3,11 +3,11 @@
*
* Draw pretty renderings of reflection lists
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010,2012 Thomas White <taw@physics.org>
+ * 2010-2012 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
diff --git a/src/scaling.c b/src/scaling.c
index 368c3ab5..3be8712b 100644
--- a/src/scaling.c
+++ b/src/scaling.c
@@ -3,11 +3,11 @@
*
* Scaling
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2010-2017 Thomas White <taw@physics.org>
+ * 2010-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -57,7 +57,7 @@ struct scale_args
};
-struct queue_args
+struct scale_queue_args
{
int n_started;
int n_done;
@@ -77,7 +77,7 @@ static void scale_crystal(void *task, int id)
static void *get_crystal(void *vqargs)
{
struct scale_args *task;
- struct queue_args *qargs = vqargs;
+ struct scale_queue_args *qargs = vqargs;
task = malloc(sizeof(struct scale_args));
memcpy(task, &qargs->task_defaults, sizeof(struct scale_args));
@@ -92,7 +92,7 @@ static void *get_crystal(void *vqargs)
static void done_crystal(void *vqargs, void *task)
{
- struct queue_args *qa = vqargs;
+ struct scale_queue_args *qa = vqargs;
qa->n_done++;
progress_bar(qa->n_done, qa->n_crystals, "Scaling");
free(task);
@@ -124,7 +124,7 @@ static double total_log_r(Crystal **crystals, int n_crystals, RefList *full,
void scale_all(Crystal **crystals, int n_crystals, int nthreads, int scaleflags)
{
struct scale_args task_defaults;
- struct queue_args qargs;
+ struct scale_queue_args qargs;
double old_res, new_res;
int niter = 0;
diff --git a/src/scaling.h b/src/scaling.h
index da02d8a1..e47a845d 100644
--- a/src/scaling.h
+++ b/src/scaling.h
@@ -3,7 +3,7 @@
*
* Scaling
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
diff --git a/src/time-accounts.c b/src/time-accounts.c
index 8093c789..679eb5f1 100644
--- a/src/time-accounts.c
+++ b/src/time-accounts.c
@@ -3,7 +3,7 @@
*
* Simple profiling according to wall clock time
*
- * Copyright © 2016-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2016-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
diff --git a/src/time-accounts.h b/src/time-accounts.h
index 53e88f65..41990e7f 100644
--- a/src/time-accounts.h
+++ b/src/time-accounts.h
@@ -3,7 +3,7 @@
*
* Simple profiling according to wall clock time
*
- * Copyright © 2016-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2016-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
diff --git a/src/version.c.cmake.in b/src/version.c.cmake.in
new file mode 100644
index 00000000..a22b4143
--- /dev/null
+++ b/src/version.c.cmake.in
@@ -0,0 +1,13 @@
+const char *crystfel_version_string()
+{
+ return "${CRYSTFEL_VERSION}";
+}
+
+const char *crystfel_licence_string()
+{
+ return "License GPLv3+: GNU GPL version 3 or later" \
+ " <http://gnu.org/licenses/gpl.html>.\n" \
+ "This is free software: you are free to change and redistribute it.\n" \
+ "There is NO WARRANTY, to the extent permitted by law.\n\n" \
+ "Written by Thomas White and others.";
+}
diff --git a/src/version.c.in b/src/version.c.in
new file mode 100644
index 00000000..86315801
--- /dev/null
+++ b/src/version.c.in
@@ -0,0 +1,17 @@
+/* Prevent subsequent inclusion of version.h
+ * (e.g. in the case of Meson unity build mode) */
+#define CRYSTFEL_VERSION_H
+
+const char *crystfel_version_string()
+{
+ return "@VCS_TAG@";
+}
+
+const char *crystfel_licence_string()
+{
+ return "License GPLv3+: GNU GPL version 3 or later" \
+ " <http://gnu.org/licenses/gpl.html>.\n" \
+ "This is free software: you are free to change and redistribute it.\n" \
+ "There is NO WARRANTY, to the extent permitted by law.\n\n" \
+ "Written by Thomas White and others.";
+}
diff --git a/src/version.h b/src/version.h
new file mode 100644
index 00000000..e31c4c17
--- /dev/null
+++ b/src/version.h
@@ -0,0 +1,5 @@
+#ifndef CRYSTFEL_VERSION_H
+#define CRYSTFEL_VERSION_H
+extern const char *crystfel_version_string(void);
+extern const char *crystfel_licence_string(void);
+#endif
diff --git a/src/whirligig.c b/src/whirligig.c
index 199ad0f3..d964557f 100644
--- a/src/whirligig.c
+++ b/src/whirligig.c
@@ -3,11 +3,11 @@
*
* Find and combine rotation series
*
- * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY,
+ * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2012-2014 Thomas White <taw@physics.org>
+ * 2012-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -42,11 +42,13 @@
#include <image.h>
#include <utils.h>
#include <stream.h>
+#include <cell-utils.h>
+#include <integer_matrix.h>
+#include <reflist.h>
+#include <reflist-utils.h>
+
+#include "version.h"
-#include "cell-utils.h"
-#include "integer_matrix.h"
-#include "reflist.h"
-#include "reflist-utils.h"
/* Maximum number of series which can overlap at once */
#define MAX_SER 8
@@ -173,7 +175,7 @@ static void process_series(struct image *images, signed int *ser,
Crystal *cr = images[i].crystals[ser[i]];
fprintf(fh, "%4i %5i %s %s %i\n", i, images[i].serial,
images[i].filename,
- get_event_string(images[i].event),
+ images[i].ev,
ser[i]);
p[i] = transform_reflections(crystal_get_reflections(cr),
mat[i]);
@@ -634,8 +636,10 @@ int main(int argc, char *argv[])
break;
case 3 :
- printf("CrystFEL: " CRYSTFEL_VERSIONSTRING "\n");
- printf(CRYSTFEL_BOILERPLATE"\n");
+ printf("CrystFEL: %s\n",
+ crystfel_version_string());
+ printf("%s\n",
+ crystfel_licence_string());
return 0;
case 4 :
@@ -670,7 +674,7 @@ int main(int argc, char *argv[])
return 1;
}
- st = open_stream_for_read(argv[optind++]);
+ st = stream_open_for_read(argv[optind++]);
if ( st == NULL ) {
ERROR("Failed to open input stream '%s'\n", argv[optind-1]);
return 1;
@@ -714,29 +718,25 @@ int main(int argc, char *argv[])
win.join_ptr = 0;
do {
- struct image cur;
+ struct image *image;
- cur.div = NAN;
- cur.bw = NAN;
- cur.det = NULL;
- if ( read_chunk_2(st, &cur, STREAM_READ_REFLECTIONS
- | STREAM_READ_UNITCELL) != 0 ) {
- break;
- }
+ image = stream_read_chunk(st, STREAM_REFLECTIONS);
+
+ if ( image == NULL ) break;
- if ( verbose ) printf("\n\nIncoming serial %i\n", cur.serial);
+ if ( verbose ) printf("\n\nIncoming serial %i\n", image->serial);
- if ( isnan(cur.div) || isnan(cur.bw) ) {
+ if ( isnan(image->div) || isnan(image->bw) ) {
ERROR("Chunk doesn't contain beam parameters.\n");
return 1;
}
- if ( cur.serial < 1 ) {
+ if ( image->serial < 1 ) {
ERROR("Serial numbers must be greater than zero.\n");
return 1;
}
- add_to_window(&cur, &win, &ss);
+ add_to_window(image, &win, &ss);
connect_series(&win);
if ( verbose ) {
@@ -764,7 +764,7 @@ int main(int argc, char *argv[])
display_progress(n_images);
printf("\n");
- close_stream(st);
+ stream_close(st);
find_and_process_series(&win, 1, &ss, outdir);
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index f8de368c..38520004 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -31,10 +31,6 @@ add_test(centering_check centering_check)
add_executable(integration_check integration_check.c histogram.c)
target_include_directories(integration_check PRIVATE ${COMMON_INCLUDES})
target_link_libraries(integration_check PRIVATE ${COMMON_LIBRARIES})
-if (CURSES_FOUND)
- target_include_directories(integration_check PRIVATE ${CURSES_INCLUDE_DIRS})
- target_link_libraries(integration_check PRIVATE ${CURSES_LIBRARIES})
-endif (CURSES_FOUND)
add_test(integration_check integration_check)
add_executable(list_check list_check.c)
@@ -50,19 +46,11 @@ add_test(prediction_gradient_check prediction_gradient_check)
add_executable(prof2d_check prof2d_check.c histogram.c)
target_include_directories(prof2d_check PRIVATE ${COMMON_INCLUDES})
target_link_libraries(prof2d_check PRIVATE ${COMMON_LIBRARIES})
-if (CURSES_FOUND)
- target_include_directories(prof2d_check PRIVATE ${CURSES_INCLUDE_DIRS})
- target_link_libraries(prof2d_check PRIVATE ${CURSES_LIBRARIES})
-endif (CURSES_FOUND)
add_test(prof2d_check prof2d_check)
add_executable(ring_check ring_check.c)
target_include_directories(ring_check PRIVATE ${COMMON_INCLUDES})
target_link_libraries(ring_check PRIVATE ${COMMON_LIBRARIES})
-if (FDIP_FOUND)
- target_include_directories(ring_check PRIVATE ${FDIP_INCLUDES})
- target_link_libraries(ring_check PRIVATE ${FDIP_LIBRARIES})
-endif (FDIP_FOUND)
add_test(ring_check ring_check)
add_executable(symmetry_check symmetry_check.c)
@@ -80,7 +68,8 @@ if (HAVE_OPENCL)
../src/diffraction-gpu.c ../src/cl-utils.c)
target_include_directories(gpu_sim_check PRIVATE ${COMMON_INCLUDES} ${OpenCL_INCLUDE_DIRS})
target_link_libraries(gpu_sim_check ${COMMON_LIBRARIES} ${OpenCL_LIBRARIES})
- add_test(gpu_sim_check gpu_sim_check)
+ add_test(NAME gpu_sim_check
+ COMMAND gpu_sim_check ${CMAKE_CURRENT_SOURCE_DIR}/gpu_sim_check.geom)
endif (HAVE_OPENCL)
add_executable(rational_check rational_check.c)
@@ -98,6 +87,104 @@ target_include_directories(cellcompare_check PRIVATE ${COMMON_INCLUDES})
target_link_libraries(cellcompare_check ${COMMON_LIBRARIES})
add_test(cellcompare_check cellcompare_check)
-add_executable(polarisation_check polarisation_check.c)
-target_include_directories(polarisation_check PRIVATE ${COMMON_INCLUDES})
-target_link_libraries(polarisation_check ${COMMON_LIBRARIES})
+add_executable(evparse1 evparse1.c)
+target_include_directories(evparse1 PRIVATE ${COMMON_INCLUDES})
+target_link_libraries(evparse1 ${COMMON_LIBRARIES} ${HDF5_C_LIBRARIES})
+add_test(evparse1 evparse1)
+
+add_executable(evparse2 evparse2.c)
+target_include_directories(evparse2 PRIVATE ${COMMON_INCLUDES})
+target_link_libraries(evparse2 ${COMMON_LIBRARIES} ${HDF5_C_LIBRARIES})
+add_test(evparse2 evparse2)
+
+add_executable(evparse3 evparse3.c)
+target_include_directories(evparse3 PRIVATE ${COMMON_INCLUDES})
+target_link_libraries(evparse3 ${COMMON_LIBRARIES} ${HDF5_C_LIBRARIES})
+add_test(evparse3 evparse3)
+
+add_executable(evparse4 evparse4.c)
+target_include_directories(evparse4 PRIVATE ${COMMON_INCLUDES})
+target_link_libraries(evparse4 ${COMMON_LIBRARIES} ${HDF5_C_LIBRARIES})
+add_test(evparse4 evparse4)
+
+add_executable(evparse5 evparse5.c)
+target_include_directories(evparse5 PRIVATE ${COMMON_INCLUDES})
+target_link_libraries(evparse5 ${COMMON_LIBRARIES} ${HDF5_C_LIBRARIES})
+add_test(evparse5 evparse5)
+
+add_executable(evparse6 evparse6.c)
+target_include_directories(evparse6 PRIVATE ${COMMON_INCLUDES})
+target_link_libraries(evparse6 ${COMMON_LIBRARIES} ${HDF5_C_LIBRARIES})
+add_test(evparse6 evparse6)
+
+add_executable(evparse7 evparse7.c)
+target_include_directories(evparse7 PRIVATE ${COMMON_INCLUDES})
+target_link_libraries(evparse7 ${COMMON_LIBRARIES} ${HDF5_C_LIBRARIES})
+add_test(evparse7 evparse7)
+
+add_executable(ev_enum1 ev_enum1.c)
+target_include_directories(ev_enum1 PRIVATE ${COMMON_INCLUDES})
+target_link_libraries(ev_enum1 ${COMMON_LIBRARIES})
+add_test(NAME ev_enum1
+ COMMAND ev_enum1 ${CMAKE_CURRENT_SOURCE_DIR}/ev_enum1.h5
+ ${CMAKE_CURRENT_SOURCE_DIR}/ev_enum1.geom)
+
+add_executable(ev_enum2 ev_enum2.c)
+target_include_directories(ev_enum2 PRIVATE ${COMMON_INCLUDES})
+target_link_libraries(ev_enum2 ${COMMON_LIBRARIES})
+add_test(NAME ev_enum2
+ COMMAND ev_enum2 ${CMAKE_CURRENT_SOURCE_DIR}/ev_enum2.h5
+ ${CMAKE_CURRENT_SOURCE_DIR}/ev_enum2.geom)
+
+add_executable(ev_enum3 ev_enum3.c)
+target_include_directories(ev_enum3 PRIVATE ${COMMON_INCLUDES})
+target_link_libraries(ev_enum3 ${COMMON_LIBRARIES})
+add_test(NAME ev_enum3
+ COMMAND ev_enum3 ${CMAKE_CURRENT_SOURCE_DIR}/ev_enum3.h5
+ ${CMAKE_CURRENT_SOURCE_DIR}/ev_enum3.geom)
+
+add_executable(wavelength_geom wavelength_geom.c)
+target_include_directories(wavelength_geom PRIVATE ${COMMON_INCLUDES})
+target_link_libraries(wavelength_geom ${COMMON_LIBRARIES})
+add_test(NAME wavelength_geom1
+ COMMAND wavelength_geom ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom.h5
+ ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom1.geom 1e-10)
+add_test(NAME wavelength_geom2
+ COMMAND wavelength_geom ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom.h5
+ ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom2.geom 1.3776e-10)
+add_test(NAME wavelength_geom3
+ COMMAND wavelength_geom ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom.h5
+ ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom3.geom 1.3776e-10)
+add_test(NAME wavelength_geom4
+ COMMAND wavelength_geom ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom.h5
+ ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom4.geom 1.9687e-12)
+add_test(NAME wavelength_geom5
+ COMMAND wavelength_geom ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom.h5
+ ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom5.geom 1.9687e-12)
+add_test(NAME wavelength_geom6
+ COMMAND wavelength_geom ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom.h5
+ ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom6.geom 1.3776e-10)
+add_test(NAME wavelength_geom7
+ COMMAND wavelength_geom ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom.h5
+ ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom7.geom 1.3776e-10)
+add_test(NAME wavelength_geom8
+ COMMAND wavelength_geom ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom.h5
+ ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom8.geom 1.9687e-12)
+add_test(NAME wavelength_geom9
+ COMMAND wavelength_geom ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom.h5
+ ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom9.geom 1.3776e-10)
+add_test(NAME wavelength_geom10
+ COMMAND wavelength_geom ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom.h5
+ ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom10.geom 1.3776e-10)
+add_test(NAME wavelength_geom11
+ COMMAND wavelength_geom ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom.h5
+ ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom11.geom 1.125e-10)
+add_test(NAME wavelength_geom12
+ COMMAND wavelength_geom ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom.h5
+ ${CMAKE_CURRENT_SOURCE_DIR}/wavelength_geom12.geom 1.125e-10)
+
+add_executable(stream_read stream_read.c)
+target_include_directories(stream_read PRIVATE ${COMMON_INCLUDES})
+target_link_libraries(stream_read ${COMMON_LIBRARIES})
+add_test(NAME stream_read
+ COMMAND stream_read ${CMAKE_CURRENT_SOURCE_DIR}/test.stream)
diff --git a/tests/ambi_check.c b/tests/ambi_check.c
index 03224ce6..5f13053a 100644
--- a/tests/ambi_check.c
+++ b/tests/ambi_check.c
@@ -26,11 +26,6 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
diff --git a/tests/cell_check.c b/tests/cell_check.c
index 23f7245f..ec83680a 100644
--- a/tests/cell_check.c
+++ b/tests/cell_check.c
@@ -26,11 +26,6 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
diff --git a/tests/cellcompare_check.c b/tests/cellcompare_check.c
index beb1d844..fa9bf869 100644
--- a/tests/cellcompare_check.c
+++ b/tests/cellcompare_check.c
@@ -26,11 +26,6 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
@@ -212,192 +207,168 @@ static int check_crcp(UnitCell *cell, UnitCell *cref, double *tols,
}
-static void yaro_test()
+static int test_plain_rotation(UnitCell *cref, gsl_rng *rng,
+ double *tols)
{
UnitCell *cell;
- UnitCell *reference;
- UnitCell *cmatch;
- //float tols[] = {5, 5, 5, 1.5};
- double dtols[] = {0.05, 0.05, 0.05, deg2rad(5.0), deg2rad(5.0), deg2rad(5.0)};
-
- cell = cell_new_from_parameters(63.24e-10, 63.94e-10, 64.61e-10,
- deg2rad(89.98), deg2rad(89.82), deg2rad(119.87));
- cell_set_unique_axis(cell, 'c');
- cell_set_lattice_type(cell, L_HEXAGONAL);
- cell_set_centering(cell, 'P');
-
- reference = cell_new_from_parameters(64.7e-10, 64.7e-10, 65.2e-10,
- deg2rad(90.0), deg2rad(90.0), deg2rad(120.0));
- cell_set_unique_axis(reference, 'c');
- cell_set_lattice_type(reference, L_HEXAGONAL);
- cell_set_centering(reference, 'P');
-
- STATUS("The cell:\n");
- cell_print(cell);
- STATUS("The reference:\n");
- cell_print(reference);
- //cmatch = match_cell(cell, reference, 0, tols, 1);
- //STATUS("The match:\n");
- //cell_print(cmatch);
- //cell_free(cmatch);
- RationalMatrix *m = NULL;
- cmatch = compare_reindexed_cell_parameters(cell, reference, dtols, &m);
- STATUS("The new match:\n")
- cell_print(cmatch);
- STATUS("The matrix:\n");
- rtnl_mtx_print(m);
- cell_free(cmatch);
- rtnl_mtx_free(m);
+ cell = cell_rotate(cref, random_quaternion(rng));
+ if ( cell == NULL ) return 1;
+
+ if ( check_ccp(cell, cref, tols, 1) ) return 1;
+ if ( check_ccpao(cell, cref, tols, 0) ) return 1;
+ if ( check_cpcpao(cell, cref, tols, 0) ) return 1;
+ if ( check_cdcp(cell, cref, tols, NULL, 1) ) return 1;
+ if ( check_crcp(cell, cref, tols, NULL, 1) ) return 1;
cell_free(cell);
- cell_free(reference);
+
+ return 0;
}
-extern IntegerMatrix *reduce_g6(struct g6 g, double epsrel);
-
-int main(int argc, char *argv[])
+static int test_permutation_no_rotation(UnitCell *cref, gsl_rng *rng,
+ double *tols)
{
- UnitCell *cell, *cref;
- gsl_rng *rng;
- int i;
- const int ntrial = 10;
- double tols[] = { 0.01, 0.01, 0.01,
- deg2rad(1.0), deg2rad(1.0), deg2rad(1.0) };
+ IntegerMatrix *tr;
+ UnitCell *cell;
- rng = gsl_rng_alloc(gsl_rng_mt19937);
+ tr = random_permutation(rng);
+ cell = cell_transform_intmat(cref, tr);
- yaro_test();
+ if ( check_ccp(cell, cref, tols, intmat_is_identity(tr)) ) return 1;
+ if ( check_ccpao(cell, cref, tols, intmat_is_identity(tr)) ) return 1;
+ if ( check_cpcpao(cell, cref, tols, 1) ) return 1;
+ if ( check_cdcp(cell, cref, tols, NULL, 1) ) return 1;
+ if ( check_crcp(cell, cref, tols, NULL, 1) ) return 1;
- cref = cell_new_from_parameters(3e-10, 5.196e-10, 2e-10,
- deg2rad(103.9166666),
- deg2rad(109.4666666),
- deg2rad(134.8833333));
- cell_set_centering(cref, 'P');
- if ( cref == NULL ) return 1;
+ cell_free(cell);
+ intmat_free(tr);
- /* Just rotate cell */
- for ( i=0; i<ntrial; i++ ) {
+ return 0;
+}
- cell = cell_rotate(cref, random_quaternion(rng));
- if ( cell == NULL ) return 1;
- if ( check_ccp(cell, cref, tols, 1) ) return 1;
- if ( check_ccpao(cell, cref, tols, 0) ) return 1;
- if ( check_cpcpao(cell, cref, tols, 0) ) return 1;
- if ( check_cdcp(cell, cref, tols, NULL, 1) ) return 1;
- if ( check_crcp(cell, cref, tols, NULL, 1) ) return 1;
+static int test_rotation_and_permutation(UnitCell *cref, gsl_rng *rng,
+ double *tols)
+{
+ IntegerMatrix *tr;
+ UnitCell *cell;
+ UnitCell *cell2;
- cell_free(cell);
- progress_bar(i+1, ntrial, "Plain rotation");
- }
+ cell2 = cell_rotate(cref, random_quaternion(rng));
+ if ( cell2 == NULL ) return 1;
- /* Permute axes but don't rotate */
- for ( i=0; i<ntrial; i++ ) {
+ tr = random_permutation(rng);
+ cell = cell_transform_intmat(cell2, tr);
+ cell_free(cell2);
- IntegerMatrix *tr;
+ if ( check_ccp(cell, cref, tols, intmat_is_identity(tr)) ) return 1;
+ if ( check_ccpao(cell, cref, tols, 0) ) return 1;
+ if ( check_cpcpao(cell, cref, tols, 0) ) return 1;
+ if ( check_cdcp(cell, cref, tols, NULL, 1) ) return 1;
+ if ( check_crcp(cell, cref, tols, NULL, 1) ) return 1;
- tr = random_permutation(rng);
- cell = cell_transform_intmat(cref, tr);
+ cell_free(cell);
+ intmat_free(tr);
- if ( check_ccp(cell, cref, tols, intmat_is_identity(tr)) ) return 1;
- if ( check_ccpao(cell, cref, tols, intmat_is_identity(tr)) ) return 1;
- if ( check_cpcpao(cell, cref, tols, 1) ) return 1;
- if ( check_cdcp(cell, cref, tols, NULL, 1) ) return 1;
- if ( check_crcp(cell, cref, tols, NULL, 1) ) return 1;
+ return 0;
+}
- cell_free(cell);
- intmat_free(tr);
- progress_bar(i+1, ntrial, "Axis permutation");
- }
- /* Rotate cell and permute axes */
- for ( i=0; i<ntrial; i++ ) {
+static int test_derivative_lattice(UnitCell *cref, gsl_rng *rng,
+ double *tols)
+{
+ RationalMatrix *tr;
+ UnitCell *cell;
- IntegerMatrix *tr;
- UnitCell *cell2;
+ cell = NULL;
+ tr = NULL;
+ do {
+ cell_free(cell);
+ rtnl_mtx_free(tr);
+ tr = random_derivative(rng);
+ cell = cell_transform_rational(cref, tr);
+ } while ( (cell_get_centering(cell) == '?')
+ || (cell_get_centering(cell) == 'H' ) );
+ /* H centering is no good because it needs a unique axis to
+ * be specified in order for uncentering in c_r_c_p to work.
+ * cell_transform_rational doesn't set the unique axis (yet?) */
+
+ if ( check_ccp(cell, cref, tols, rtnl_mtx_is_identity(tr)) ) return 1;
+ if ( check_ccpao(cell, cref, tols, rtnl_mtx_is_identity(tr)) ) return 1;
+ if ( check_cpcpao(cell, cref, tols, rtnl_mtx_is_perm(tr)) ) return 1;
+ if ( check_cdcp(cell, cref, tols, tr, 1) ) return 1;
+ /* check_crcp: Sometimes yes, hard to tell */
- cell2 = cell_rotate(cref, random_quaternion(rng));
- if ( cell2 == NULL ) return 1;
+ cell_free(cell);
+ rtnl_mtx_free(tr);
- tr = random_permutation(rng);
- cell = cell_transform_intmat(cell2, tr);
- cell_free(cell2);
+ return 0;
+}
- if ( check_ccp(cell, cref, tols, intmat_is_identity(tr)) ) return 1;
- if ( check_ccpao(cell, cref, tols, 0) ) return 1;
- if ( check_cpcpao(cell, cref, tols, 0) ) return 1;
- if ( check_cdcp(cell, cref, tols, NULL, 1) ) return 1;
- if ( check_crcp(cell, cref, tols, NULL, 1) ) return 1;
- cell_free(cell);
- intmat_free(tr);
- progress_bar(i+1, ntrial, "Rotation with axis permutation");
- }
+static int test_derivative_lattice_rotation(UnitCell *cref, gsl_rng *rng,
+ double *tols)
+{
+ RationalMatrix *tr;
+ UnitCell *cell;
+ UnitCell *cell2;
- /* Derivative lattice */
- for ( i=0; i<ntrial; i++ ) {
-
- RationalMatrix *tr;
-
- cell = NULL;
- tr = NULL;
- do {
- cell_free(cell);
- rtnl_mtx_free(tr);
- tr = random_derivative(rng);
- cell = cell_transform_rational(cref, tr);
- } while ( (cell_get_centering(cell) == '?')
- || (cell_get_centering(cell) == 'H' ) );
- /* H centering is no good because it needs a unique axis to
- * be specified in order for uncentering in c_r_c_p to work.
- * cell_transform_rational doesn't set the unique axis (yet?) */
-
- if ( check_ccp(cell, cref, tols, rtnl_mtx_is_identity(tr)) ) return 1;
- if ( check_ccpao(cell, cref, tols, rtnl_mtx_is_identity(tr)) ) return 1;
- if ( check_cpcpao(cell, cref, tols, rtnl_mtx_is_perm(tr)) ) return 1;
- if ( check_cdcp(cell, cref, tols, tr, 1) ) return 1;
- /* check_crcp: Sometimes yes, hard to tell */
+ cell2 = cell_rotate(cref, random_quaternion(rng));
+ if ( cell2 == NULL ) return 1;
+ cell = NULL;
+ tr = NULL;
+ do {
cell_free(cell);
rtnl_mtx_free(tr);
- progress_bar(i+1, ntrial, "Derivative lattice");
- }
+ tr = random_derivative(rng);
+ cell = cell_transform_rational(cell2, tr);
+ } while ( (cell_get_centering(cell) == '?')
+ || (cell_get_centering(cell) == 'H' ) ); /* See above */
+ cell_free(cell2);
+
+ if ( check_ccp(cell, cref, tols, rtnl_mtx_is_identity(tr)) ) return 1;
+ if ( check_ccpao(cell, cref, tols, 0) ) return 1;
+ if ( check_cpcpao(cell, cref, tols, 0) ) return 1;
+ if ( check_cdcp(cell, cref, tols, tr, 1) ) return 1;
+ /* check_crcp: Sometimes yes, hard to tell */
- /* Derivative lattice and rotate */
- for ( i=0; i<ntrial; i++ ) {
+ cell_free(cell);
+ rtnl_mtx_free(tr);
- RationalMatrix *tr;
- UnitCell *cell2;
+ return 0;
+}
- cell2 = cell_rotate(cref, random_quaternion(rng));
- if ( cell2 == NULL ) return 1;
- cell = NULL;
- tr = NULL;
- do {
- cell_free(cell);
- rtnl_mtx_free(tr);
- tr = random_derivative(rng);
- cell = cell_transform_rational(cell2, tr);
- } while ( (cell_get_centering(cell) == '?')
- || (cell_get_centering(cell) == 'H' ) ); /* See above */
- cell_free(cell2);
+extern IntegerMatrix *reduce_g6(struct g6 g, double epsrel);
- if ( check_ccp(cell, cref, tols, rtnl_mtx_is_identity(tr)) ) return 1;
- if ( check_ccpao(cell, cref, tols, 0) ) return 1;
- if ( check_cpcpao(cell, cref, tols, 0) ) return 1;
- if ( check_cdcp(cell, cref, tols, tr, 1) ) return 1;
- /* check_crcp: Sometimes yes, hard to tell */
+int main(int argc, char *argv[])
+{
+ UnitCell *cref;
+ gsl_rng *rng;
+ int fail = 0;
+ double tols[] = { 0.01, 0.01, 0.01,
+ deg2rad(1.0), deg2rad(1.0), deg2rad(1.0) };
- cell_free(cell);
- rtnl_mtx_free(tr);
- progress_bar(i+1, ntrial, "Derivative lattice with rotation");
- }
+ rng = gsl_rng_alloc(gsl_rng_mt19937);
+
+ cref = cell_new_from_parameters(3e-10, 5.196e-10, 2e-10,
+ deg2rad(103.9166666),
+ deg2rad(109.4666666),
+ deg2rad(134.8833333));
+ cell_set_centering(cref, 'P');
+ if ( cref == NULL ) return 1;
+
+ fail += test_plain_rotation(cref, rng, tols);
+ fail += test_permutation_no_rotation(cref, rng, tols);
+ fail += test_rotation_and_permutation(cref, rng, tols);
+ fail += test_derivative_lattice(cref, rng, tols);
+ fail += test_derivative_lattice_rotation(cref, rng, tols);
cell_free(cref);
gsl_rng_free(rng);
- return 0;
+ return fail;
}
diff --git a/tests/centering_check.c b/tests/centering_check.c
index f418da50..4f6a9841 100644
--- a/tests/centering_check.c
+++ b/tests/centering_check.c
@@ -26,11 +26,6 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
diff --git a/tests/ev_enum1.c b/tests/ev_enum1.c
new file mode 100644
index 00000000..ce9a9d61
--- /dev/null
+++ b/tests/ev_enum1.c
@@ -0,0 +1,89 @@
+/*
+ * ev_enum1.c
+ *
+ * Check that event enumeration works
+ *
+ * Copyright © 2020 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <image.h>
+
+int main(int argc, char *argv[])
+{
+ char **event_ids;
+ int n_event_ids;
+ int i;
+ DataTemplate *dtempl;
+
+ dtempl = data_template_new_from_file(argv[2]);
+ if ( dtempl == NULL ) {
+ ERROR("Failed to load data template\n");
+ return 1;
+ }
+
+ event_ids = image_expand_frames(dtempl, argv[1], &n_event_ids);
+
+ if ( event_ids == NULL ) {
+ printf("event_ids = NULL\n");
+ return 1;
+ }
+
+ if ( n_event_ids != 4 ) {
+ printf("Number of event IDs = %i\n", n_event_ids);
+ return 1;
+ }
+
+ if ( strcmp(event_ids[0], "ev_1/dataABCset//") != 0 ) {
+ printf("Wrong event id '%s'\n", event_ids[0]);
+ return 1;
+ }
+
+ if ( strcmp(event_ids[1], "ev_2/dataDEFset//") != 0 ) {
+ printf("Wrong event id '%s'\n", event_ids[1]);
+ return 1;
+ }
+
+ if ( strcmp(event_ids[2], "ev_3/dataGHIset//") != 0 ) {
+ printf("Wrong event id '%s'\n", event_ids[2]);
+ return 1;
+ }
+
+ if ( strcmp(event_ids[3], "ev_5/dataNOPset//") != 0 ) {
+ printf("Wrong event id '%s'\n", event_ids[3]);
+ return 1;
+ }
+
+ for ( i=0; i<n_event_ids; i++ ) {
+ free(event_ids[i]);
+ }
+ free(event_ids);
+
+ data_template_free(dtempl);
+
+ return 0;
+}
diff --git a/tests/ev_enum1.geom b/tests/ev_enum1.geom
new file mode 100644
index 00000000..6c763e09
--- /dev/null
+++ b/tests/ev_enum1.geom
@@ -0,0 +1,12 @@
+panel/min_fs = 0
+panel/min_ss = 1
+panel/max_fs = 0
+panel/max_ss = 1
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/dim0 = ss
+panel/dim1 = fs
+panel/data = /data/panelA/%/panel_data1t/%/array \ No newline at end of file
diff --git a/tests/ev_enum1.h5 b/tests/ev_enum1.h5
new file mode 100644
index 00000000..448fa539
--- /dev/null
+++ b/tests/ev_enum1.h5
Binary files differ
diff --git a/tests/ev_enum2.c b/tests/ev_enum2.c
new file mode 100644
index 00000000..1c1dd55a
--- /dev/null
+++ b/tests/ev_enum2.c
@@ -0,0 +1,73 @@
+/*
+ * ev_enum2.c
+ *
+ * Check that event enumeration works
+ *
+ * Copyright © 2020 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <image.h>
+
+int main(int argc, char *argv[])
+{
+ char **event_ids;
+ int n_event_ids;
+ int i;
+ DataTemplate *dtempl;
+
+ dtempl = data_template_new_from_file(argv[2]);
+ if ( dtempl == NULL ) {
+ ERROR("Failed to load data template\n");
+ return 1;
+ }
+
+ event_ids = image_expand_frames(dtempl, argv[1], &n_event_ids);
+
+ if ( event_ids == NULL ) {
+ printf("event_ids = NULL\n");
+ return 1;
+ }
+
+ for ( i=0; i<n_event_ids; i++ ) {
+ char tmp[64];
+ char c = i < 100 ? 'a' : 'b';
+ int n = i < 100 ? i : (i-100);
+ snprintf(tmp, 64, "%c//%i", c, n);
+ if ( strcmp(tmp, event_ids[i]) != 0 ) {
+ printf("Event ID %i is wrong '%s'\n",
+ i, event_ids[i]);
+ return 1;
+ }
+ free(event_ids[i]);
+ }
+ free(event_ids);
+
+ data_template_free(dtempl);
+
+ return 0;
+}
diff --git a/tests/ev_enum2.geom b/tests/ev_enum2.geom
new file mode 100644
index 00000000..6afe53b4
--- /dev/null
+++ b/tests/ev_enum2.geom
@@ -0,0 +1,14 @@
+panel/min_fs = 0
+panel/min_ss = 1
+panel/max_fs = 0
+panel/max_ss = 1
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/dim0 = %
+panel/dim1 = ss
+panel/dim2 = fs
+panel/dim3 = 1
+panel/data = /data/%/data_array \ No newline at end of file
diff --git a/tests/ev_enum2.h5 b/tests/ev_enum2.h5
new file mode 100644
index 00000000..660ffece
--- /dev/null
+++ b/tests/ev_enum2.h5
Binary files differ
diff --git a/tests/ev_enum3.c b/tests/ev_enum3.c
new file mode 100644
index 00000000..c6407ec7
--- /dev/null
+++ b/tests/ev_enum3.c
@@ -0,0 +1,68 @@
+/*
+ * ev_enum3.c
+ *
+ * Check that event enumeration works
+ *
+ * Copyright © 2020 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <image.h>
+
+int main(int argc, char *argv[])
+{
+ char **event_ids;
+ int n_event_ids;
+ DataTemplate *dtempl;
+
+ dtempl = data_template_new_from_file(argv[2]);
+ if ( dtempl == NULL ) {
+ ERROR("Failed to load data template\n");
+ return 1;
+ }
+
+ event_ids = image_expand_frames(dtempl, argv[1], &n_event_ids);
+
+ if ( n_event_ids != 1 ) {
+ printf("n_event_ids = %i\n", n_event_ids);
+ return 1;
+ }
+
+ if ( event_ids == NULL ) {
+ printf("event_ids not NULL\n");
+ return 1;
+ }
+
+ if ( strcmp(event_ids[0], "//") != 0 ) {
+ printf("Event is not '//' ('%s')\n", event_ids[0]);
+ return 1;
+ }
+
+ data_template_free(dtempl);
+
+ return 0;
+}
diff --git a/tests/ev_enum3.geom b/tests/ev_enum3.geom
new file mode 100644
index 00000000..67424606
--- /dev/null
+++ b/tests/ev_enum3.geom
@@ -0,0 +1,12 @@
+panel/min_fs = 0
+panel/min_ss = 1
+panel/max_fs = 0
+panel/max_ss = 1
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/dim0 = ss
+panel/dim1 = fs
+panel/data = /data/data_array
diff --git a/tests/ev_enum3.h5 b/tests/ev_enum3.h5
new file mode 100644
index 00000000..59238c8c
--- /dev/null
+++ b/tests/ev_enum3.h5
Binary files differ
diff --git a/tests/evparse1.c b/tests/evparse1.c
new file mode 100644
index 00000000..2768b3cf
--- /dev/null
+++ b/tests/evparse1.c
@@ -0,0 +1,69 @@
+/*
+ * evparse1.c
+ *
+ * Check that event string parsing works
+ *
+ * Copyright © 2020 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+extern char **read_path_parts(const char *ev_orig, int *pn_plvals);
+
+int main(int argc, char *argv[])
+{
+ char **plvals;
+ int n_plvals;
+ int r = 0;
+
+ plvals = read_path_parts("cc/data123/bb//234/59", &n_plvals);
+
+ if ( plvals == NULL ) {
+ printf("read_path_parts failed\n");
+ r++;
+ }
+
+ if ( n_plvals != 3 ) {
+ printf("Wrong number of path parts\n");
+ r++;
+ }
+
+ if ( plvals == NULL ) return r;
+
+ if ( strcmp(plvals[0], "cc") != 0 ) {
+ printf("First path part is wrong\n");
+ r++;
+ }
+ if ( strcmp(plvals[1], "data123") != 0 ) {
+ printf("Second path part is wrong\n");
+ r++;
+ }
+ if ( strcmp(plvals[2], "bb") != 0 ) {
+ printf("Third path part is wrong\n");
+ r++;
+ }
+
+ return r;
+}
diff --git a/tests/evparse2.c b/tests/evparse2.c
new file mode 100644
index 00000000..034b1672
--- /dev/null
+++ b/tests/evparse2.c
@@ -0,0 +1,61 @@
+/*
+ * evparse2.c
+ *
+ * Check that event string parsing works
+ *
+ * Copyright © 2020 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+extern char **read_path_parts(const char *ev_orig, int *pn_plvals);
+
+int main(int argc, char *argv[])
+{
+ char **plvals;
+ int n_plvals;
+ int r = 0;
+
+ plvals = read_path_parts("bb//234/59", &n_plvals);
+
+ if ( plvals == NULL ) {
+ printf("read_path_parts failed\n");
+ r++;
+ }
+
+ if ( n_plvals != 1 ) {
+ printf("Wrong number of path parts\n");
+ r++;
+ }
+
+ if ( plvals == NULL ) return r;
+
+ if ( strcmp(plvals[0], "bb") != 0 ) {
+ printf("First path part is wrong\n");
+ r++;
+ }
+
+ return r;
+}
diff --git a/tests/evparse3.c b/tests/evparse3.c
new file mode 100644
index 00000000..5db1de8c
--- /dev/null
+++ b/tests/evparse3.c
@@ -0,0 +1,53 @@
+/*
+ * evparse3.c
+ *
+ * Check that event string parsing works
+ *
+ * Copyright © 2020 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+extern char **read_path_parts(const char *ev_orig, int *pn_plvals);
+
+int main(int argc, char *argv[])
+{
+ char **plvals;
+ int n_plvals;
+ int r = 0;
+
+ plvals = read_path_parts("//234/59", &n_plvals);
+
+ if ( plvals == NULL ) {
+ printf("read_path_parts failed\n");
+ r++;
+ }
+
+ if ( n_plvals != 0 ) {
+ printf("Wrong number of path parts\n");
+ r++;
+ }
+
+ return r;
+}
diff --git a/tests/evparse4.c b/tests/evparse4.c
new file mode 100644
index 00000000..13f096cf
--- /dev/null
+++ b/tests/evparse4.c
@@ -0,0 +1,63 @@
+/*
+ * evparse4.c
+ *
+ * Check that event string parsing works
+ *
+ * Copyright © 2020 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+extern int *read_dim_parts(const char *ev_orig, int *pn_dvals);
+
+int main(int argc, char *argv[])
+{
+ int *dvals;
+ int n_dvals = 99;
+ int r = 0;
+
+ dvals = read_dim_parts("cc/data123/bb//234/59", &n_dvals);
+
+ if ( n_dvals != 2 ) {
+ printf("Wrong number of dimension parts\n");
+ r++;
+ }
+
+ if ( dvals == NULL ) {
+ printf("read_dim_parts failed\n");
+ return 1;
+ }
+
+ if ( dvals[0] != 234 ) {
+ printf("First dimension part is wrong\n");
+ r++;
+ }
+ if ( dvals[1] != 59 ) {
+ printf("Second dimension part is wrong "
+ "(%i, should be %i)\n", dvals[1], 59);
+ r++;
+ }
+
+ return r;
+}
diff --git a/tests/evparse5.c b/tests/evparse5.c
new file mode 100644
index 00000000..7f81f47e
--- /dev/null
+++ b/tests/evparse5.c
@@ -0,0 +1,59 @@
+/*
+ * evparse5.c
+ *
+ * Check that event string parsing works
+ *
+ * Copyright © 2020 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+extern int *read_dim_parts(const char *ev_orig, int *pn_dvals);
+
+int main(int argc, char *argv[])
+{
+ int *dvals;
+ int n_dvals = 99;
+ int r = 0;
+
+ dvals = read_dim_parts("cc/data123/bb//59", &n_dvals);
+
+ if ( n_dvals != 1 ) {
+ printf("Wrong number of dimension parts\n");
+ r++;
+ }
+
+ if ( dvals == NULL ) {
+ printf("read_dim_parts failed\n");
+ return 1;
+ }
+
+ if ( dvals[0] != 59 ) {
+ printf("First dimension part is wrong "
+ "(%i, should be %i)\n", dvals[0], 59);
+ r++;
+ }
+
+ return r;
+}
diff --git a/tests/evparse6.c b/tests/evparse6.c
new file mode 100644
index 00000000..631db686
--- /dev/null
+++ b/tests/evparse6.c
@@ -0,0 +1,54 @@
+/*
+ * evparse6.c
+ *
+ * Check that event string parsing works
+ *
+ * Copyright © 2020 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+extern int *read_dim_parts(const char *ev_orig, int *pn_dvals);
+
+int main(int argc, char *argv[])
+{
+ int *dvals;
+ int n_dvals = 99;
+ int r = 0;
+
+ dvals = read_dim_parts("cc/data123/bb//", &n_dvals);
+
+ if ( n_dvals != 0 ) {
+ printf("Wrong number of dimension parts (got %i)\n",
+ n_dvals);
+ r++;
+ }
+
+ if ( dvals == NULL ) {
+ printf("read_dim_parts failed\n");
+ return 1;
+ }
+
+ return r;
+}
diff --git a/tests/evparse7.c b/tests/evparse7.c
new file mode 100644
index 00000000..26f2dc41
--- /dev/null
+++ b/tests/evparse7.c
@@ -0,0 +1,53 @@
+/*
+ * evparse7.c
+ *
+ * Check that event string parsing works
+ *
+ * Copyright © 2020 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+extern char *substitute_path(const char *ev, const char *pattern);
+
+int main(int argc, char *argv[])
+{
+ char *subs;
+
+ subs = substitute_path("cc/data123/bb//234/59",
+ "/data/%/test/%/%");
+
+ if ( subs == NULL ) {
+ printf("substitute_path() failed\n");
+ return 1;
+ }
+
+ if ( strcmp(subs, "/data/cc/test/data123/bb") != 0 ) {
+ printf("Wrong substitution: got '%s'\n", subs);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/tests/gen-ev-test.py b/tests/gen-ev-test.py
new file mode 100644
index 00000000..e3cb9924
--- /dev/null
+++ b/tests/gen-ev-test.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+
+import h5py
+import numpy
+
+blank = numpy.zeros((1,1), dtype=float)
+
+with h5py.File('tests/ev_enum1.h5', 'w') as fh:
+ fh.create_dataset('/data/panelA/ev_1/panel_data1t/dataABCset/array', data=blank)
+ fh.create_dataset('/data/panelA/ev_2/panel_data1t/dataDEFset/array', data=blank)
+ fh.create_dataset('/data/panelA/ev_3/panel_data1t/dataGHIset/array', data=blank)
+ fh.create_dataset('/data/panelA/ev_4/panel_data1t/dataKLMset/nomatch', data=blank)
+ fh.create_dataset('/data/panelA/ev_5/panel_data1t/dataNOPset/array', data=blank)
+ fh.create_dataset('/data/panelB/ev_1/panel_data1t/dataABCset/array', data=blank)
+ fh.create_dataset('/data/panelB/ev_2/panel_data1t/dataDEFset/array', data=blank)
+ fh.create_dataset('/data/panelB/ev_3/panel_data1t/dataGHIset/array', data=blank)
+ fh.create_dataset('/data/panelB/ev_4/panel_data1t/dataKLMset/array', data=blank)
+ fh.create_dataset('/data/panelB/ev_5/panel_data1t/dataNOPset/array', data=blank)
+ fh.create_dataset('/data/panelB/ev_1/dataABCset/array', data=blank)
+ fh.create_dataset('/data/panelB/ev_2/dataDEFset/array', data=blank)
+ fh.create_dataset('/data/panelB/ev_3/dataGHIset/array', data=blank)
+ fh.create_dataset('/data/panelB/ev_4/dataKLMset/array', data=blank)
+ fh.create_dataset('/data/panelB/ev_5/dataNOPset/array', data=blank)
+
+array = numpy.zeros((100,1,1,2), dtype=float)
+
+with h5py.File('tests/ev_enum2.h5', 'w') as fh:
+ fh.create_dataset('/data/a/data_array', data=array)
+ fh.create_dataset('/data/b/data_array', data=array)
+
+array = numpy.zeros((1,1), dtype=float)
+
+with h5py.File('tests/ev_enum3.h5', 'w') as fh:
+ fh.create_dataset('/data/data_array', data=array)
+
+array = numpy.zeros((2,2), dtype=float)
+with h5py.File('tests/wavelength_geom.h5', 'w') as fh:
+ fh.create_dataset('/data/data_array', data=array)
+ dh = fh.create_dataset('/LCLS/photon_energy', (), 'f')
+ dh[()] = 9000.0
+ dh = fh.create_dataset('/LCLS/photon_energyK', (), 'f')
+ dh[()] = 9.0
+ dh = fh.create_dataset('/LCLS/electron_energy', (), 'f')
+ dh[()] = 300000
+ dh = fh.create_dataset('/LCLS/electron_energy2', (), 'f')
+ dh[()] = 300
+ dh = fh.create_dataset('/LCLS/wavelength', (), 'f')
+ dh[()] = 1e-10
diff --git a/tests/gpu_sim_check.c b/tests/gpu_sim_check.c
index 4424b68e..f0b3193e 100644
--- a/tests/gpu_sim_check.c
+++ b/tests/gpu_sim_check.c
@@ -26,11 +26,6 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include <stdlib.h>
#include <stdio.h>
@@ -40,11 +35,15 @@
#include <sys/time.h>
#endif
+#define CL_TARGET_OPENCL_VERSION 220
+
#include "../src/diffraction.h"
#include "../src/diffraction-gpu.h"
#include "../src/cl-utils.h"
-#include <detector.h>
+
+#include <datatemplate.h>
#include <utils.h>
+#include <image.h>
#include <symmetry.h>
#include <cell-utils.h>
@@ -76,16 +75,15 @@ static double get_hires_seconds()
int main(int argc, char *argv[])
{
struct gpu_context *gctx;
- struct image gpu_image;
- struct image cpu_image;
+ struct image *gpu_image;
+ struct image *cpu_image;
+ DataTemplate *dtempl;
UnitCell *cell;
UnitCell *cell_raw;
- struct detector *det;
int i;
double gpu_min, gpu_max, gpu_tot;
double cpu_min, cpu_max, cpu_tot;
double dev, perc;
- const double sep = 20.0;
double start, end;
double gpu_time, cpu_time;
SymOpList *sym;
@@ -109,73 +107,14 @@ int main(int argc, char *argv[])
cell = cell_rotate(cell_raw, random_quaternion(rng));
- det = calloc(1, sizeof(struct detector));
- det->n_panels = 2;
- det->panels = calloc(2, sizeof(struct panel));
-
- det->panels[0].orig_min_fs = 0;
- det->panels[0].orig_max_fs = 1023;
- det->panels[0].orig_min_ss = 0;
- det->panels[0].orig_max_ss = 511;
- det->panels[0].w = 1024;
- det->panels[0].h = 512;
- det->panels[0].fsx = 1.0;
- det->panels[0].fsy = 0.0;
- det->panels[0].fsz = 0.4;
- det->panels[0].ssx = 0.0;
- det->panels[0].ssy = 1.0;
- det->panels[0].ssz = 0.0;
- det->panels[0].xfs = 1.0;
- det->panels[0].yfs = 0.0;
- det->panels[0].xss = 0.0;
- det->panels[0].yss = 1.0;
- det->panels[0].cnx = -512.0;
- det->panels[0].cny = -512.0-sep;
- det->panels[0].clen = 100.0e-3;
- det->panels[0].res = 9090.91;
- det->panels[0].adu_per_eV = 1.0;
- det->panels[0].data = NULL;
-
- det->panels[1].orig_min_fs = 0;
- det->panels[1].orig_max_fs = 1023;
- det->panels[1].orig_min_ss = 512;
- det->panels[1].orig_max_ss = 1023;
- det->panels[1].w = 1024;
- det->panels[1].h = 512;
- det->panels[1].fsx = 1.0;
- det->panels[1].fsy = 0.0;
- det->panels[1].fsz = 0.0;
- det->panels[1].ssx = 0.0;
- det->panels[1].ssy = 1.0;
- det->panels[1].ssz = 1.4;
- det->panels[1].xfs = 1.0;
- det->panels[1].yfs = 0.0;
- det->panels[1].xss = 0.0;
- det->panels[1].yss = 1.0;
- det->panels[1].cnx = -512.0;
- det->panels[1].cny = sep;
- det->panels[1].clen = 100.0e-3;
- det->panels[1].res = 9090.91;
- det->panels[1].adu_per_eV = 1.0;
- det->panels[1].data = NULL;
-
- cpu_image.det = det;
- gpu_image.det = det;
- cpu_image.beam = NULL;
- gpu_image.beam = NULL;
-
- cpu_image.lambda = ph_en_to_lambda(eV_to_J(6000));
- gpu_image.lambda = ph_en_to_lambda(eV_to_J(6000));
- cpu_image.bw = 1.0 / 100.0;
- gpu_image.bw = 1.0 / 100.0;
-
- cpu_image.spectrum = spectrum_generate_tophat(cpu_image.lambda,
- cpu_image.bw);
- gpu_image.spectrum = spectrum_generate_tophat(gpu_image.lambda,
- gpu_image.bw);
+ dtempl = data_template_new_from_file(argv[1]);
+ if ( dtempl == NULL ) return 1;
+
+ cpu_image = image_create_for_simulation(dtempl);
+ gpu_image = image_create_for_simulation(dtempl);
start = get_hires_seconds();
- if ( get_diffraction_gpu(gctx, &gpu_image, 8, 8, 8, cell, 0, 0, 10) ) {
+ if ( get_diffraction_gpu(gctx, gpu_image, 8, 8, 8, cell, 0, 0, 10) ) {
return 1;
}
end = get_hires_seconds();
@@ -183,22 +122,22 @@ int main(int argc, char *argv[])
sym = get_pointgroup("1");
- cpu_image.dp = malloc(det->n_panels * sizeof(float *));
- if ( cpu_image.dp == NULL ) {
+ cpu_image->dp = malloc(cpu_image->detgeom->n_panels * sizeof(float *));
+ if ( cpu_image->dp == NULL ) {
ERROR("Couldn't allocate memory for result.\n");
return 1;
}
- for ( i=0; i<det->n_panels; i++ ) {
- struct panel *p = &det->panels[i];
- cpu_image.dp[i] = calloc(p->w * p->h, sizeof(float));
- if ( cpu_image.dp[i] == NULL ) {
+ for ( i=0; i<cpu_image->detgeom->n_panels; i++ ) {
+ struct detgeom_panel *p = &cpu_image->detgeom->panels[i];
+ cpu_image->dp[i] = calloc(p->w * p->h, sizeof(float));
+ if ( cpu_image->dp[i] == NULL ) {
ERROR("Couldn't allocate memory for panel %i\n", i);
return 1;
}
}
start = get_hires_seconds();
- get_diffraction(&cpu_image, 8, 8, 8, NULL, NULL, NULL, cell,
+ get_diffraction(cpu_image, 8, 8, 8, NULL, NULL, NULL, cell,
GRADIENT_MOSAIC, sym, 0, 0, 10);
end = get_hires_seconds();
cpu_time = end - start;
@@ -210,15 +149,15 @@ int main(int argc, char *argv[])
gpu_min = +INFINITY; gpu_max = -INFINITY; gpu_tot = 0.0;
cpu_min = +INFINITY; cpu_max = -INFINITY; cpu_tot = 0.0;
dev = 0.0;
- for ( i=0; i<det->n_panels; i++ ) {
+ for ( i=0; i<cpu_image->detgeom->n_panels; i++ ) {
int j;
- struct panel *p = &det->panels[i];
+ struct detgeom_panel *p = &cpu_image->detgeom->panels[i];
for ( j=0; j<p->w*p->h; j++ ) {
- const double cpu = cpu_image.dp[i][j];
- const double gpu = gpu_image.dp[i][j];
+ const double cpu = cpu_image->dp[i][j];
+ const double gpu = gpu_image->dp[i][j];
if ( cpu > cpu_max ) cpu_max = cpu;
if ( cpu < cpu_min ) cpu_min = cpu;
@@ -242,8 +181,8 @@ int main(int argc, char *argv[])
STATUS("Test failed! I'm writing cpu-sim.h5 and gpu-sim.h5"
" for you to inspect.\n");
- hdf5_write_image("cpu-sim.h5", &cpu_image, NULL);
- hdf5_write_image("gpu-sim.h5", &gpu_image, NULL);
+ image_write(cpu_image, dtempl, "cpu-sim.h5");
+ image_write(gpu_image, dtempl, "gpu-sim.h5");
return 1;
@@ -251,8 +190,9 @@ int main(int argc, char *argv[])
gsl_rng_free(rng);
cell_free(cell);
- free_detector_geometry(det);
-
+ image_free(cpu_image);
+ image_free(gpu_image);
+ data_template_free(dtempl);
return 0;
}
diff --git a/tests/gpu_sim_check.geom b/tests/gpu_sim_check.geom
new file mode 100644
index 00000000..57064e58
--- /dev/null
+++ b/tests/gpu_sim_check.geom
@@ -0,0 +1,28 @@
+photon_energy = 6 keV
+bandwidth = 0.01
+
+panel0/min_fs = 0
+panel0/max_fs = 1023
+panel0/min_ss = 0
+panel0/max_ss = 511
+panel0/corner_x = -512.0
+panel0/corner_y = -532.0
+panel0/clen = 100 mm
+panel0/res = 9090.91
+panel0/adu_per_eV = 1
+panel0/data = /data/panel0
+panel0/fs = x
+panel0/ss = y
+
+panel1/min_fs = 0
+panel1/max_fs = 1023
+panel1/min_ss = 0
+panel1/max_ss = 511
+panel1/corner_x = -512.0
+panel1/corner_y = 20.0
+panel1/clen = 100 mm
+panel1/res = 9090.91
+panel1/adu_per_eV = 1
+panel1/data = /data/panel1
+panel1/fs = x
+panel1/ss = y \ No newline at end of file
diff --git a/tests/histogram.c b/tests/histogram.c
index 3cccfaea..dfd59fee 100644
--- a/tests/histogram.c
+++ b/tests/histogram.c
@@ -26,10 +26,6 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
diff --git a/tests/histogram.h b/tests/histogram.h
index f0091bd7..7b295caa 100644
--- a/tests/histogram.h
+++ b/tests/histogram.h
@@ -29,10 +29,6 @@
#ifndef HISTOGRAM_H
#define HISTOGRAM_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/tests/integration_check.c b/tests/integration_check.c
index da808cce..5fb544b7 100644
--- a/tests/integration_check.c
+++ b/tests/integration_check.c
@@ -7,7 +7,7 @@
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2013-2016 Thomas White <taw@physics.org>
+ * 2013-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -26,22 +26,17 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include <stdlib.h>
#include <stdio.h>
#include <image.h>
#include <utils.h>
+#include <cell.h>
+#include <cell-utils.h>
+#include <integration.h>
#include "histogram.h"
-#include "../libcrystfel/src/integration.c"
-
-
int main(int argc, char *argv[])
{
struct image image;
@@ -54,7 +49,7 @@ int main(int argc, char *argv[])
RefList *list;
Reflection *refl;
UnitCell *cell;
- struct intcontext ic;
+ struct intcontext *ic;
const int ir_inn = 2;
const int ir_mid = 4;
const int ir_out = 6;
@@ -73,30 +68,24 @@ int main(int argc, char *argv[])
}
fclose(fh);
- image.beam = NULL;
image.lambda = ph_eV_to_lambda(9000.0);
- image.det = calloc(1, sizeof(struct detector));
- image.det->n_panels = 1;
- image.det->panels = calloc(1, sizeof(struct panel));
-
- image.det->panels[0].w = w;
- image.det->panels[0].h = h;
- image.det->panels[0].fsx = 1.0;
- image.det->panels[0].fsy = 0.0;
- image.det->panels[0].ssx = 0.0;
- image.det->panels[0].ssy = 1.0;
- image.det->panels[0].xfs = 1.0;
- image.det->panels[0].yfs = 0.0;
- image.det->panels[0].xss = 0.0;
- image.det->panels[0].yss = 1.0;
- image.det->panels[0].cnx = -w/2;
- image.det->panels[0].cny = -h/2;
- image.det->panels[0].clen = 60.0e-3;
- image.det->panels[0].res = 100000; /* 10 px per mm */
- image.det->panels[0].adu_per_eV = NAN;
- image.det->panels[0].adu_per_photon = 10;
- image.det->panels[0].max_adu = +INFINITY; /* No cutoff */
+ image.detgeom = calloc(1, sizeof(struct detgeom));
+ image.detgeom->n_panels = 1;
+ image.detgeom->panels = calloc(1, sizeof(struct detgeom_panel));
+
+ image.detgeom->panels[0].w = w;
+ image.detgeom->panels[0].h = h;
+ image.detgeom->panels[0].fsx = 1.0;
+ image.detgeom->panels[0].fsy = 0.0;
+ image.detgeom->panels[0].ssx = 0.0;
+ image.detgeom->panels[0].ssy = 1.0;
+ image.detgeom->panels[0].cnx = -w/2;
+ image.detgeom->panels[0].cny = -h/2;
+ image.detgeom->panels[0].cnz = 60.0e-3 / 100e-6;
+ image.detgeom->panels[0].pixel_pitch = 100e-6; /* 10 px per mm */
+ image.detgeom->panels[0].adu_per_photon = 10;
+ image.detgeom->panels[0].max_adu = +INFINITY; /* No cutoff */
image.dp = malloc(sizeof(float *));
image.dp[0] = malloc(w*h*sizeof(float));
@@ -124,7 +113,7 @@ int main(int argc, char *argv[])
list = reflist_new();
refl = add_refl(list, 0, 0, 0);
set_detector_pos(refl, 64, 64);
- set_panel(refl, &image.det->panels[0]);
+ set_panel_number(refl, 0);
cell = cell_new();
cell_set_lattice_type(cell, L_CUBIC);
cell_set_centering(cell, 'P');
@@ -132,25 +121,14 @@ int main(int argc, char *argv[])
deg2rad(90.0), deg2rad(90.0), deg2rad(90.0));
cell = cell_rotate(cell, random_quaternion(rng));
- ic.halfw = ir_out;
- ic.image = &image;
- ic.k = 1.0/image.lambda;
- ic.n_saturated = 0;
- ic.n_implausible = 0;
- ic.cell = cell;
- ic.ir_inn = ir_inn;
- ic.ir_mid = ir_mid;
- ic.ir_out = ir_out;
- ic.meth = INTEGRATION_RINGS;
- ic.int_diag = INTDIAG_NONE;
- ic.masks = NULL;
- if ( init_intcontext(&ic) ) {
+ ic = intcontext_new(&image, cell, INTEGRATION_RINGS,
+ ir_inn, ir_mid, ir_out, NULL);
+ if ( ic == NULL ) {
ERROR("Failed to initialise integration.\n");
return 1;
}
- setup_ring_masks(&ic, ir_inn, ir_mid, ir_out);
- integrate_rings_once(refl, &image, &ic, cell, 0);
+ integrate_rings_once(refl, ic, 0);
cell_free(cell);
@@ -163,9 +141,7 @@ int main(int argc, char *argv[])
histogram_show(hi);
histogram_free(hi);
- free(image.beam);
- free(image.det->panels);
- free(image.det);
+ detgeom_free(image.detgeom);
free(image.dp[0]);
free(image.dp);
diff --git a/tests/list_check.c b/tests/list_check.c
index 4a98e20d..4eac2650 100644
--- a/tests/list_check.c
+++ b/tests/list_check.c
@@ -26,11 +26,6 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include <stdlib.h>
#include <stdio.h>
diff --git a/tests/meson.build b/tests/meson.build
new file mode 100644
index 00000000..5ad19672
--- /dev/null
+++ b/tests/meson.build
@@ -0,0 +1,123 @@
+# CrystFEL unit tests
+
+# Test wrapper scripts for process_hkl
+process_hkl_tests = ['process_hkl_check_1',
+ 'process_hkl_check_2',
+ 'process_hkl_check_3',
+ 'process_hkl_check_4']
+
+foreach name : process_hkl_tests
+ exe = find_program(name)
+ test(name, exe, args : [process_hkl.full_path()])
+endforeach
+
+
+# Test wrapper scripts for partialator
+partialator_tests = ['partialator_merge_check_1',
+ 'partialator_merge_check_2',
+ 'partialator_merge_check_3']
+
+foreach name : partialator_tests
+ exe = find_program(name)
+ test(name, exe, args : [partialator.full_path()])
+endforeach
+
+
+# Easy unit tests of libcrystfel functions
+simple_tests = ['ambi_check',
+ 'cell_check',
+ 'centering_check',
+ 'list_check',
+ 'prediction_gradient_check',
+ 'ring_check',
+ 'symmetry_check',
+ 'transformation_check',
+ 'rational_check',
+ 'spectrum_check',
+ 'cellcompare_check',
+ 'evparse1',
+ 'evparse2',
+ 'evparse3',
+ 'evparse4',
+ 'evparse5',
+ 'evparse6',
+ 'evparse7']
+
+foreach name : simple_tests
+ exe = executable(name, ''.join([name, '.c']),
+ dependencies : [libcrystfeldep, mdep, gsldep, hdf5dep],
+ include_directories: conf_inc)
+
+ test(name, exe, timeout : 60)
+endforeach
+
+
+# Less easy unit tests for libcrystfel functions
+exe = executable('stream_read',
+ ['stream_read.c'],
+ dependencies : [libcrystfeldep])
+test_stream = files('test.stream')
+test('stream_read',
+ exe,
+ args: [test_stream])
+
+exe = executable('integration_check',
+ ['integration_check.c',
+ 'histogram.c'],
+ dependencies : [libcrystfeldep, mdep, gsldep])
+test('integration_check', exe)
+
+exe = executable('prof2d_check',
+ ['prof2d_check.c',
+ 'histogram.c'],
+ dependencies : [libcrystfeldep, mdep, gsldep])
+test('prof2d_check', exe)
+
+if opencldep.found()
+ exe = executable('gpu_sim_check',
+ ['gpu_sim_check.c',
+ simulation_bits],
+ dependencies : [libcrystfeldep, mdep, gsldep, opencldep],
+ include_directories: conf_inc)
+ geom = files('gpu_sim_check.geom')
+ test('gpu_sim_check', exe, args: [geom])
+endif
+
+# Event enumeration tests
+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
+
+
+# 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
diff --git a/tests/partialator_merge_check_1 b/tests/partialator_merge_check_1
index 616ccf31..137f6128 100755
--- a/tests/partialator_merge_check_1
+++ b/tests/partialator_merge_check_1
@@ -5,6 +5,19 @@ PARTIALATOR=$1
cat > partialator_merge_check_1.stream << EOF
CrystFEL stream format 2.1
Command line: indexamajig -i dummy.lst -o dummy.stream --kraken=prawn
+----- Begin geometry file -----
+photon_energy = 9000 eV
+panel/min_fs = 0
+panel/min_ss = 0
+panel/max_fs = 1023
+panel/max_ss = 1023
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
+----- End geometry file -----
----- Begin chunk -----
Image filename: dummy.h5
photon_energy_eV = 6000.0
@@ -15,7 +28,7 @@ Cell parameters 27.74398 27.84377 16.90346 nm, 88.53688 91.11774 118.75944 deg
astar = -0.0283891 +0.0149254 -0.0257273 nm^-1
bstar = -0.0068281 +0.0403989 -0.0005196 nm^-1
cstar = +0.0406926 +0.0052233 -0.0426520 nm^-1
-profile_radius = 0.005 nm^-1
+profile_radius = 0.0005 nm^-1
Reflections measured after indexing
h k l I phase sigma(I) counts fs/px ss/px
1 0 0 100.00 - 1.00 1 938.0 629.0
@@ -26,7 +39,7 @@ Cell parameters 27.74398 27.84377 16.90346 nm, 88.53688 91.11774 118.75944 deg
astar = -0.0283891 +0.0149254 -0.0257273 nm^-1
bstar = -0.0068281 +0.0403989 -0.0005196 nm^-1
cstar = +0.0406926 +0.0052233 -0.0426520 nm^-1
-profile_radius = 0.005 nm^-1
+profile_radius = 0.0005 nm^-1
Reflections measured after indexing
h k l I phase sigma(I) counts fs/px ss/px
1 0 0 200.00 - 1.00 1 938.0 629.0
diff --git a/tests/partialator_merge_check_2 b/tests/partialator_merge_check_2
index 9938f64f..05881426 100755
--- a/tests/partialator_merge_check_2
+++ b/tests/partialator_merge_check_2
@@ -5,6 +5,19 @@ PARTIALATOR=$1
cat > partialator_merge_check_2.stream << EOF
CrystFEL stream format 2.1
Command line: indexamajig -i dummy.lst -o dummy.stream --kraken=prawn
+----- Begin geometry file -----
+photon_energy = 9000 eV
+panel/min_fs = 0
+panel/min_ss = 0
+panel/max_fs = 1023
+panel/max_ss = 1023
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
+----- End geometry file -----
----- Begin chunk -----
Image filename: dummy.h5
photon_energy_eV = 6000.0
@@ -15,7 +28,7 @@ Cell parameters 27.74398 27.84377 16.90346 nm, 88.53688 91.11774 118.75944 deg
astar = -0.0283891 +0.0149254 -0.0257273 nm^-1
bstar = -0.0068281 +0.0403989 -0.0005196 nm^-1
cstar = +0.0406926 +0.0052233 -0.0426520 nm^-1
-profile_radius = 0.005 nm^-1
+profile_radius = 0.0005 nm^-1
Reflections measured after indexing
h k l I phase sigma(I) counts fs/px ss/px
1 0 0 100.00 - 1.00 1 938.0 629.0
@@ -27,7 +40,7 @@ Cell parameters 27.74398 27.84377 16.90346 nm, 88.53688 91.11774 118.75944 deg
astar = -0.0283891 +0.0149254 -0.0257273 nm^-1
bstar = -0.0068281 +0.0403989 -0.0005196 nm^-1
cstar = +0.0406926 +0.0052233 -0.0426520 nm^-1
-profile_radius = 0.005 nm^-1
+profile_radius = 0.0005 nm^-1
Reflections measured after indexing
h k l I phase sigma(I) counts fs/px ss/px
1 0 0 200.00 - 1.00 1 938.0 629.0
diff --git a/tests/partialator_merge_check_3 b/tests/partialator_merge_check_3
index 2d237b02..ece2ad3f 100755
--- a/tests/partialator_merge_check_3
+++ b/tests/partialator_merge_check_3
@@ -5,6 +5,19 @@ PARTIALATOR=$1
cat > partialator_merge_check_3.stream << EOF
CrystFEL stream format 2.1
Command line: indexamajig -i dummy.lst -o dummy.stream --kraken=prawn
+----- Begin geometry file -----
+photon_energy = 9000 eV
+panel/min_fs = 0
+panel/min_ss = 0
+panel/max_fs = 1023
+panel/max_ss = 1023
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
+----- End geometry file -----
----- Begin chunk -----
Image filename: dummy.h5
photon_energy_eV = 6000.0
@@ -15,7 +28,7 @@ Cell parameters 27.74398 27.84377 16.90346 nm, 88.53688 91.11774 118.75944 deg
astar = -0.0283891 +0.0149254 -0.0257273 nm^-1
bstar = -0.0068281 +0.0403989 -0.0005196 nm^-1
cstar = +0.0406926 +0.0052233 -0.0426520 nm^-1
-profile_radius = 0.005 nm^-1
+profile_radius = 0.0005 nm^-1
Reflections measured after indexing
h k l I phase sigma(I) counts fs/px ss/px
0 1 0 100.00 - 1.00 1 938.0 629.0
@@ -28,7 +41,7 @@ Cell parameters 27.74398 27.84377 16.90346 nm, 88.53688 91.11774 118.75944 deg
astar = -0.0283891 +0.0149254 -0.0257273 nm^-1
bstar = -0.0068281 +0.0403989 -0.0005196 nm^-1
cstar = +0.0406926 +0.0052233 -0.0426520 nm^-1
-profile_radius = 0.005 nm^-1
+profile_radius = 0.0005 nm^-1
Reflections measured after indexing
h k l I phase sigma(I) counts fs/px ss/px
1 0 0 50.00 - 1.00 1 938.0 629.0
diff --git a/tests/polarisation_check.c b/tests/polarisation_check.c
deleted file mode 100644
index f8660e32..00000000
--- a/tests/polarisation_check.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * polarisation_check.c
- *
- * Check polarisation correction
- *
- * Copyright © 2019-2020 Deutsches Elektronen-Synchrotron DESY,
- * a research centre of the Helmholtz Association.
- *
- * Authors:
- * 2019 Thomas White <taw@physics.org>
- *
- * This file is part of CrystFEL.
- *
- * CrystFEL is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * CrystFEL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <image.h>
-#include <utils.h>
-#include <cell.h>
-#include <cell-utils.h>
-#include <geometry.h>
-
-
-int main(int argc, char *argv[])
-{
- struct image image;
- FILE *fh;
- unsigned long int seed;
- int fail = 0;
- const int w = 1024;
- const int h = 1024;
- RefList *list;
- RefListIterator *iter;
- Reflection *refl;
- UnitCell *cell;
- Crystal *cr;
- gsl_rng *rng;
- struct polarisation p;
- int i;
- double *map;
- double *nmap;
- const int ntrial = 1000;
-
- rng = gsl_rng_alloc(gsl_rng_mt19937);
-
- fh = fopen("/dev/urandom", "r");
- if ( fread(&seed, sizeof(seed), 1, fh) == 1 ) {
- gsl_rng_set(rng, seed);
- } else {
- ERROR("Failed to seed RNG\n");
- }
- fclose(fh);
-
- image.beam = NULL;
- image.lambda = ph_eV_to_lambda(9000.0);
- image.bw = 0.000001;
- image.div = 0.0;
- image.spectrum = spectrum_generate_gaussian(image.lambda, image.bw);
-
- image.det = calloc(1, sizeof(struct detector));
- image.det->n_panels = 1;
- image.det->panels = calloc(1, sizeof(struct panel));
-
- image.dp = calloc(1, sizeof(float *));
- image.bad = calloc(1, sizeof(int *));
-
- image.det->panels[0].w = w;
- image.det->panels[0].h = h;
- image.det->panels[0].fsx = 1.0;
- image.det->panels[0].fsy = 0.0;
- image.det->panels[0].ssx = 0.0;
- image.det->panels[0].ssy = 1.0;
- image.det->panels[0].xfs = 1.0;
- image.det->panels[0].yfs = 0.0;
- image.det->panels[0].xss = 0.0;
- image.det->panels[0].yss = 1.0;
- image.det->panels[0].cnx = -w/2;
- image.det->panels[0].cny = -h/2;
- image.det->panels[0].clen = 50.0e-3;
- image.det->panels[0].res = 10000; /* 10 micron pixels */
- image.det->panels[0].adu_per_eV = 10.0/9000.0; /* 10 adu/ph */
- image.det->panels[0].max_adu = +INFINITY; /* No cutoff */
- image.det->panels[0].orig_min_fs = 0;
- image.det->panels[0].orig_min_ss = 0;
- image.det->panels[0].orig_max_fs = w-1;
- image.det->panels[0].orig_max_ss = h-1;
-
- image.det->furthest_out_panel = &image.det->panels[0];
- image.det->furthest_out_fs = 0;
- image.det->furthest_out_ss = 0;
-
- image.dp[0] = malloc(w*h*sizeof(float));
- memset(image.dp[0], 0, w*h*sizeof(float));
- image.bad[0] = malloc(w*h*sizeof(int));
- memset(image.bad[0], 0, w*h*sizeof(int));
- image.sat = NULL;
-
- cell = cell_new();
- cell_set_lattice_type(cell, L_CUBIC);
- cell_set_centering(cell, 'P');
- cell_set_parameters(cell, 50.0e-10, 50.0e-10, 50.0e-10,
- deg2rad(90.0), deg2rad(90.0), deg2rad(90.0));
-
- cr = crystal_new();
- crystal_set_profile_radius(cr, 0.001e9);
- crystal_set_mosaicity(cr, 0.0); /* radians */
- crystal_set_image(cr, &image);
- crystal_set_cell(cr, cell);
-
- image.n_crystals = 1;
- image.crystals = &cr;
-
- map = malloc(w*h*sizeof(double));
- nmap = malloc(w*h*sizeof(double));
- for ( i=0; i<w*h; i++ ) {
- map[i] = 0.0;
- nmap[i] = 0.0;
- }
- for ( i=0; i<ntrial; i++ ) {
-
- UnitCell *ncell;
-
- ncell = cell_rotate(cell, random_quaternion(rng));
- crystal_set_cell(cr, ncell);
-
- list = predict_to_res(cr, largest_q(&image));
- crystal_set_reflections(cr, list);
-
- for ( refl = first_refl(list, &iter);
- refl != NULL;
- refl = next_refl(refl, iter) )
- {
- set_intensity(refl, 1.0);
- }
-
- p.angle = deg2rad(105.0);
- p.fraction = 1.0;
- polarisation_correction(list, ncell, p);
-
- for ( refl = first_refl(list, &iter);
- refl != NULL;
- refl = next_refl(refl, iter) )
- {
- double fs, ss;
- int nfs, nss;
- get_detector_pos(refl, &fs, &ss);
- nfs = fs; nss = ss; /* Explicit truncation */
-
- /* Intensity in reflist is corrected,
- * but we want "un-correction" */
- map[nfs + nss*w] += 1.0/get_intensity(refl);
- nmap[nfs + nss*w] += 1.0;
- }
-
- cell_free(ncell);
- reflist_free(list);
-
- progress_bar(i+1, ntrial, "Calculating");
-
- }
-
- for ( i=0; i<w*h; i++ ) {
- image.dp[0][i] = 1000.0 * map[i] / nmap[i];
- if ( isnan(image.dp[0][i]) ) image.dp[0][i] = 0.0;
- }
- hdf5_write_image("test.h5", &image, "/data/data");
-
- free(image.beam);
- free(image.det->panels);
- free(image.det);
- free(image.dp[0]);
- free(image.dp);
- gsl_rng_free(rng);
-
- if ( fail ) return 1;
-
- return 0;
-}
diff --git a/tests/prediction_gradient_check.c b/tests/prediction_gradient_check.c
index 8c5cb1e4..6d8e596a 100644
--- a/tests/prediction_gradient_check.c
+++ b/tests/prediction_gradient_check.c
@@ -7,7 +7,7 @@
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2012-2016 Thomas White <taw@physics.org>
+ * 2012-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -26,11 +26,6 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include <stdlib.h>
#include <stdio.h>
#include <gsl/gsl_statistics.h>
@@ -47,20 +42,21 @@ int checkrxy;
static void twod_mapping(double fs, double ss, double *px, double *py,
- struct panel *p)
+ struct detgeom_panel *p)
{
double xs, ys;
xs = fs*p->fsx + ss*p->ssx;
ys = fs*p->fsy + ss*p->ssy;
- *px = (xs + p->cnx) / p->res;
- *py = (ys + p->cny) / p->res;
+ *px = (xs + p->cnx) * p->pixel_pitch;
+ *py = (ys + p->cny) * p->pixel_pitch;
}
static void scan(RefList *reflections, RefList *compare,
- int *valid, long double *vals[3], int idx)
+ int *valid, long double *vals[3], int idx,
+ struct detgeom *det)
{
int i;
Reflection *refl;
@@ -74,7 +70,7 @@ static void scan(RefList *reflections, RefList *compare,
signed int h, k, l;
Reflection *refl2;
double fs, ss, xh, yh;
- struct panel *panel;
+ int pn;
get_indices(refl, &h, &k, &l);
refl2 = find_refl(compare, h, k, l);
@@ -85,8 +81,8 @@ static void scan(RefList *reflections, RefList *compare,
}
get_detector_pos(refl2, &fs, &ss);
- panel = get_panel(refl2);
- twod_mapping(fs, ss, &xh, &yh, panel);
+ pn = get_panel_number(refl2);
+ twod_mapping(fs, ss, &xh, &yh, &det->panels[pn]);
switch ( checkrxy ) {
@@ -176,31 +172,41 @@ static Crystal *new_shifted_crystal(Crystal *cr, int refine, double incr_val)
static void calc_either_side(Crystal *cr, double incr_val,
- int *valid, long double *vals[3], int refine)
+ int *valid, long double *vals[3],
+ int refine, struct detgeom *det)
{
RefList *compare;
struct image *image = crystal_get_image(cr);
Crystal *cr_new;
cr_new = new_shifted_crystal(cr, refine, -incr_val);
- compare = predict_to_res(cr_new, largest_q(image));
- scan(crystal_get_reflections(cr), compare, valid, vals, 0);
+ compare = predict_to_res(cr_new, detgeom_max_resolution(image->detgeom,
+ image->lambda));
+ scan(crystal_get_reflections(cr), compare, valid, vals, 0, det);
cell_free(crystal_get_cell(cr_new));
crystal_free(cr_new);
reflist_free(compare);
cr_new = new_shifted_crystal(cr, refine, +incr_val);
- compare = predict_to_res(cr_new, largest_q(image));
- scan(crystal_get_reflections(cr), compare, valid, vals, 2);
+ compare = predict_to_res(cr_new, detgeom_max_resolution(image->detgeom,
+ image->lambda));
+ scan(crystal_get_reflections(cr), compare, valid, vals, 2, det);
cell_free(crystal_get_cell(cr_new));
crystal_free(cr_new);
reflist_free(compare);
}
+static double max_resolution(const struct image *image)
+{
+ return detgeom_max_resolution(image->detgeom,
+ image->lambda);
+}
+
+
static double test_gradients(Crystal *cr, double incr_val, int refine,
const char *str, const char *file,
- int quiet, int plot)
+ int quiet, int plot, struct detgeom *det)
{
Reflection *refl;
RefListIterator *iter;
@@ -219,7 +225,7 @@ static double test_gradients(Crystal *cr, double incr_val, int refine,
int n_line;
double cc;
- reflections = predict_to_res(cr, largest_q(crystal_get_image(cr)));
+ reflections = predict_to_res(cr, max_resolution(crystal_get_image(cr)));
crystal_set_reflections(cr, reflections);
nref = num_reflections(reflections);
@@ -243,9 +249,9 @@ static double test_gradients(Crystal *cr, double incr_val, int refine,
}
for ( i=0; i<nref; i++ ) valid[i] = 1;
- scan(reflections, reflections, valid, vals, 1);
+ scan(reflections, reflections, valid, vals, 1, det);
- calc_either_side(cr, incr_val, valid, vals, refine);
+ calc_either_side(cr, incr_val, valid, vals, refine, det);
if ( plot ) {
snprintf(tmp, 32, "gradient-test-%s.dat", file);
@@ -296,11 +302,11 @@ static double test_gradients(Crystal *cr, double incr_val, int refine,
if ( checkrxy == 1 ) {
cgrad = x_gradient(refine, refl,
crystal_get_cell(cr),
- &image->det->panels[0]);
+ &image->detgeom->panels[0]);
} else {
cgrad = y_gradient(refine, refl,
crystal_get_cell(cr),
- &image->det->panels[0]);
+ &image->detgeom->panels[0]);
}
}
@@ -409,10 +415,24 @@ int main(int argc, char *argv[])
}
- image.det = simple_geometry(&image, 1024, 1024);
- image.det->panels[0].res = 13333.3;
- image.det->panels[0].clen = 80e-3;
- image.det->panels[0].coffset = 0.0;
+ image.detgeom = malloc(sizeof(struct detgeom));
+ image.detgeom->n_panels = 1;
+ image.detgeom->panels = malloc(sizeof(struct detgeom_panel));
+ image.detgeom->panels[0].name = "panel";
+ image.detgeom->panels[0].adu_per_photon = 1.0;
+ image.detgeom->panels[0].max_adu = INFINITY;
+ image.detgeom->panels[0].fsx = 1.0;
+ image.detgeom->panels[0].fsy = 0.0;
+ image.detgeom->panels[0].fsz = 0.0;
+ image.detgeom->panels[0].ssx = 0.0;
+ image.detgeom->panels[0].ssy = 1.0;
+ image.detgeom->panels[0].ssz = 0.0;
+ image.detgeom->panels[0].cnx = -500.0;
+ image.detgeom->panels[0].cny = -500.0;
+ image.detgeom->panels[0].cnz = 1000.0; /* pixels */
+ image.detgeom->panels[0].w = 1000;
+ image.detgeom->panels[0].h = 1000;
+ image.detgeom->panels[0].pixel_pitch = 75e-6;
image.lambda = ph_en_to_lambda(eV_to_J(8000.0));
image.div = 1e-3;
@@ -465,15 +485,18 @@ int main(int argc, char *argv[])
incr_val = incr_frac * ax;
val = test_gradients(cr, incr_val, GPARAM_ASX,
- "ax*", "ax", quiet, plot);
+ "ax*", "ax", quiet, plot,
+ image.detgeom);
if ( val < 0.99 ) fail = 1;
incr_val = incr_frac * bx;
val = test_gradients(cr, incr_val, GPARAM_BSX,
- "bx*", "bx", quiet, plot);
+ "bx*", "bx", quiet, plot,
+ image.detgeom);
if ( val < 0.99 ) fail = 1;
incr_val = incr_frac * cx;
val = test_gradients(cr, incr_val, GPARAM_CSX,
- "cx*", "cx", quiet, plot);
+ "cx*", "cx", quiet, plot,
+ image.detgeom);
if ( val < 0.99 ) fail = 1;
}
@@ -482,30 +505,33 @@ int main(int argc, char *argv[])
incr_val = incr_frac * ay;
val = test_gradients(cr, incr_val, GPARAM_ASY,
- "ay*", "ay", quiet, plot);
+ "ay*", "ay", quiet, plot,
+ image.detgeom);
if ( val < 0.99 ) fail = 1;
incr_val = incr_frac * by;
val = test_gradients(cr, incr_val, GPARAM_BSY,
- "by*", "by", quiet, plot);
+ "by*", "by", quiet, plot,
+ image.detgeom);
if ( val < 0.99 ) fail = 1;
incr_val = incr_frac * cy;
val = test_gradients(cr, incr_val, GPARAM_CSY,
- "cy*", "cy", quiet, plot);
+ "cy*", "cy", quiet, plot,
+ image.detgeom);
if ( val < 0.99 ) fail = 1;
}
incr_val = incr_frac * az;
val = test_gradients(cr, incr_val, GPARAM_ASZ, "az*", "az",
- quiet, plot);
+ quiet, plot, image.detgeom);
if ( val < 0.99 ) fail = 1;
incr_val = incr_frac * bz;
val = test_gradients(cr, incr_val, GPARAM_BSZ, "bz*", "bz",
- quiet, plot);
+ quiet, plot, image.detgeom);
if ( val < 0.99 ) fail = 1;
incr_val = incr_frac * cz;
val = test_gradients(cr, incr_val, GPARAM_CSZ, "cz*", "cz",
- quiet, plot);
+ quiet, plot, image.detgeom);
if ( val < 0.99 ) fail = 1;
}
diff --git a/tests/process_hkl_check_1 b/tests/process_hkl_check_1
index 2d65c0a9..8496041d 100755
--- a/tests/process_hkl_check_1
+++ b/tests/process_hkl_check_1
@@ -5,6 +5,19 @@ PROCESS_HKL=$1
cat > process_hkl_check_1.stream << EOF
CrystFEL stream format 2.1
Command line: indexamajig -i dummy.lst -o dummy.stream --kraken=prawn
+----- Begin geometry file -----
+photon_energy = 9000 eV
+panel/min_fs = 0
+panel/min_ss = 0
+panel/max_fs = 1023
+panel/max_ss = 1023
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
+----- End geometry file -----
----- Begin chunk -----
Image filename: dummy.h5
photon_energy_eV = 2000.0
diff --git a/tests/process_hkl_check_2 b/tests/process_hkl_check_2
index b4d85fb4..2dec8840 100755
--- a/tests/process_hkl_check_2
+++ b/tests/process_hkl_check_2
@@ -5,6 +5,19 @@ PROCESS_HKL=$1
cat > process_hkl_check_2.stream << EOF
CrystFEL stream format 2.1
Command line: indexamajig -i dummy.lst -o dummy.stream --kraken=prawn
+----- Begin geometry file -----
+photon_energy = 9000 eV
+panel/min_fs = 0
+panel/min_ss = 0
+panel/max_fs = 1023
+panel/max_ss = 1023
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
+----- End geometry file -----
----- Begin chunk -----
Image filename: dummy.h5
photon_energy_eV = 2000.0
diff --git a/tests/process_hkl_check_3 b/tests/process_hkl_check_3
index cef7996c..763f6e87 100755
--- a/tests/process_hkl_check_3
+++ b/tests/process_hkl_check_3
@@ -5,6 +5,19 @@ PROCESS_HKL=$1
cat > process_hkl_check_3.stream << EOF
CrystFEL stream format 2.1
Command line: indexamajig -i dummy.lst -o dummy.stream --kraken=prawn
+----- Begin geometry file -----
+photon_energy = 9000 eV
+panel/min_fs = 0
+panel/min_ss = 0
+panel/max_fs = 1023
+panel/max_ss = 1023
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
+----- End geometry file -----
----- Begin chunk -----
Image filename: dummy.h5
photon_energy_eV = 2000.0
diff --git a/tests/process_hkl_check_4 b/tests/process_hkl_check_4
index aa36f112..1b267cf9 100755
--- a/tests/process_hkl_check_4
+++ b/tests/process_hkl_check_4
@@ -5,6 +5,19 @@ PROCESS_HKL=$1
cat > process_hkl_check_4.stream << EOF
CrystFEL stream format 2.1
Command line: indexamajig -i dummy.lst -o dummy.stream --kraken=prawn
+----- Begin geometry file -----
+photon_energy = 9000 eV
+panel/min_fs = 0
+panel/min_ss = 0
+panel/max_fs = 1023
+panel/max_ss = 1023
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
+----- End geometry file -----
----- Begin chunk -----
Image filename: dummy.h5
photon_energy_eV = 2000.0
diff --git a/tests/prof2d_check.c b/tests/prof2d_check.c
index d6b1d475..28ecd67c 100644
--- a/tests/prof2d_check.c
+++ b/tests/prof2d_check.c
@@ -7,7 +7,7 @@
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2013-2014,2016 Thomas White <taw@physics.org>
+ * 2013-2020 Thomas White <taw@physics.org>
*
* This file is part of CrystFEL.
*
@@ -26,20 +26,23 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include <stdlib.h>
#include <stdio.h>
#include <image.h>
#include <utils.h>
+#include <cell.h>
+#include <cell-utils.h>
+#include <geometry.h>
+#include <integration.h>
#include "histogram.h"
-#include "../libcrystfel/src/integration.c"
+extern void integrate_prof2d(IntegrationMethod meth,
+ Crystal *cr, struct image *image, IntDiag int_diag,
+ signed int idh, signed int idk, signed int idl,
+ double ir_inn, double ir_mid, double ir_out,
+ pthread_mutex_t *term_lock, int **masks);
#define ADD_PX(fs, ss, val) \
@@ -81,39 +84,30 @@ int main(int argc, char *argv[])
}
fclose(fh);
- image.beam = NULL;
image.lambda = ph_eV_to_lambda(9000.0);
image.bw = 0.000001;
image.div = 0.0;
image.spectrum = spectrum_generate_gaussian(image.lambda, image.bw);
- image.det = calloc(1, sizeof(struct detector));
- image.det->n_panels = 1;
- image.det->panels = calloc(1, sizeof(struct panel));
+ image.detgeom = calloc(1, sizeof(struct detgeom));
+ image.detgeom->n_panels = 1;
+ image.detgeom->panels = calloc(1, sizeof(struct detgeom_panel));
image.dp = calloc(1, sizeof(float *));
image.bad = calloc(1, sizeof(int *));
- image.det->panels[0].w = w;
- image.det->panels[0].h = h;
- image.det->panels[0].fsx = 1.0;
- image.det->panels[0].fsy = 0.0;
- image.det->panels[0].ssx = 0.0;
- image.det->panels[0].ssy = 1.0;
- image.det->panels[0].xfs = 1.0;
- image.det->panels[0].yfs = 0.0;
- image.det->panels[0].xss = 0.0;
- image.det->panels[0].yss = 1.0;
- image.det->panels[0].cnx = -w/2;
- image.det->panels[0].cny = -h/2;
- image.det->panels[0].clen = 60.0e-3;
- image.det->panels[0].res = 100000; /* 10 px per mm */
- image.det->panels[0].adu_per_eV = 10.0/9000.0; /* 10 adu/ph */
- image.det->panels[0].max_adu = +INFINITY; /* No cutoff */
-
- image.det->furthest_out_panel = &image.det->panels[0];
- image.det->furthest_out_fs = 0;
- image.det->furthest_out_ss = 0;
+ image.detgeom->panels[0].w = w;
+ image.detgeom->panels[0].h = h;
+ image.detgeom->panels[0].fsx = 1.0;
+ image.detgeom->panels[0].fsy = 0.0;
+ image.detgeom->panels[0].ssx = 0.0;
+ image.detgeom->panels[0].ssy = 1.0;
+ image.detgeom->panels[0].cnx = -w/2;
+ image.detgeom->panels[0].cny = -h/2;
+ image.detgeom->panels[0].cnz = 60.0e-3 / 100e-6;
+ image.detgeom->panels[0].pixel_pitch = 100e-6; /* 10 px per mm */
+ image.detgeom->panels[0].adu_per_photon = 10.0;
+ image.detgeom->panels[0].max_adu = +INFINITY; /* No cutoff */
image.dp[0] = malloc(w*h*sizeof(float));
memset(image.dp[0], 0, w*h*sizeof(float));
@@ -124,7 +118,7 @@ int main(int argc, char *argv[])
cell = cell_new();
cell_set_lattice_type(cell, L_CUBIC);
cell_set_centering(cell, 'P');
- cell_set_parameters(cell, 800.0e-10, 800.0e-10, 800.0e-10,
+ cell_set_parameters(cell, 200.0e-10, 200.0e-10, 200.0e-10,
deg2rad(90.0), deg2rad(90.0), deg2rad(90.0));
cell = cell_rotate(cell, random_quaternion(rng));
@@ -137,7 +131,8 @@ int main(int argc, char *argv[])
image.n_crystals = 1;
image.crystals = &cr;
- list = predict_to_res(cr, largest_q(&image));
+ list = predict_to_res(cr, detgeom_max_resolution(image.detgeom,
+ image.lambda));
crystal_set_reflections(cr, list);
for ( fs=0; fs<w; fs++ ) {
@@ -226,9 +221,7 @@ int main(int argc, char *argv[])
histogram_show(hi);
histogram_free(hi);
- free(image.beam);
- free(image.det->panels);
- free(image.det);
+ detgeom_free(image.detgeom);
free(image.dp[0]);
free(image.dp);
gsl_rng_free(rng);
diff --git a/tests/rational_check.c b/tests/rational_check.c
index fc48b709..6ad4df8f 100644
--- a/tests/rational_check.c
+++ b/tests/rational_check.c
@@ -26,11 +26,6 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
diff --git a/tests/ring_check.c b/tests/ring_check.c
index e0667e37..f4830068 100644
--- a/tests/ring_check.c
+++ b/tests/ring_check.c
@@ -7,7 +7,7 @@
* a research centre of the Helmholtz Association.
*
* Authors:
- * 2011-2016 Thomas White <taw@physics.org>
+ * 2011-2020 Thomas White <taw@physics.org>
* 2012 Andrew Martin <andrew.martin@desy.de>
*
* This file is part of CrystFEL.
@@ -27,19 +27,19 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include <stdlib.h>
#include <stdio.h>
#include <image.h>
#include <utils.h>
-#include "../libcrystfel/src/peaks.c"
+extern int integrate_peak(struct image *image,
+ int p_cfs, int p_css, int pn,
+ double *pfs, double *pss,
+ double *intensity, double *sigma,
+ double ir_inn, double ir_mid, double ir_out,
+ int *saturated);
/* The third integration check draws a Poisson background and checks that, on
* average, it gets subtracted by the background subtraction. */
@@ -60,14 +60,14 @@ static void third_integration_check(struct image *image, int n_trials,
double fsp, ssp;
int r;
- for ( fs=0; fs<image->det->panels[0].w; fs++ ) {
- for ( ss=0; ss<image->det->panels[0].h; ss++ ) {
- image->dp[0][fs+image->det->panels[0].w*ss]
+ for ( fs=0; fs<image->detgeom->panels[0].w; fs++ ) {
+ for ( ss=0; ss<image->detgeom->panels[0].h; ss++ ) {
+ image->dp[0][fs+image->detgeom->panels[0].w*ss]
= poisson_noise(rng, 1000.0);
}
}
- r = integrate_peak(image, 64, 64, &image->det->panels[0],
+ r = integrate_peak(image, 64, 64, 0,
&fsp, &ssp, &intensity, &sigma,
10.0, 15.0, 17.0, NULL);
@@ -119,9 +119,9 @@ static void fourth_integration_check(struct image *image, int n_trials,
double fsp, ssp;
int r;
- for ( fs=0; fs<image->det->panels[0].w; fs++ ) {
- for ( ss=0; ss<image->det->panels[0].h; ss++ ) {
- int idx = fs+image->det->panels[0].w*ss;
+ for ( fs=0; fs<image->detgeom->panels[0].w; fs++ ) {
+ for ( ss=0; ss<image->detgeom->panels[0].h; ss++ ) {
+ int idx = fs+image->detgeom->panels[0].w*ss;
image->dp[0][idx] = poisson_noise(rng, 1000.0);
if ( (fs-64)*(fs-64) + (ss-64)*(ss-64) > 9*9 ) continue;
image->dp[0][idx] += 1000.0;
@@ -129,7 +129,7 @@ static void fourth_integration_check(struct image *image, int n_trials,
}
}
- r = integrate_peak(image, 64, 64, &image->det->panels[0],
+ r = integrate_peak(image, 64, 64, 0,
&fsp, &ssp, &intensity, &sigma,
10.0, 15.0, 17.0, NULL);
@@ -188,30 +188,24 @@ int main(int argc, char *argv[])
image.dp[0] = malloc(128*128*sizeof(float));
image.bad = malloc(sizeof(uint16_t *));
image.bad[0] = calloc(128*128, sizeof(int));
- image.beam = NULL;
image.lambda = ph_eV_to_lambda(1000.0);
- image.det = calloc(1, sizeof(struct detector));
- image.det->n_panels = 1;
- image.det->panels = calloc(1, sizeof(struct panel));
-
- image.det->panels[0].fsx = 1.0;
- image.det->panels[0].fsy = 0.0;
- image.det->panels[0].ssx = 0.0;
- image.det->panels[0].ssy = 1.0;
- image.det->panels[0].xfs = 1.0;
- image.det->panels[0].yfs = 0.0;
- image.det->panels[0].xss = 0.0;
- image.det->panels[0].yss = 1.0;
- image.det->panels[0].cnx = -64.0;
- image.det->panels[0].cny = -64.0;
- image.det->panels[0].clen = 1.0;
- image.det->panels[0].res = 1.0;
- image.det->panels[0].w = 128;
- image.det->panels[0].h = 128;
- image.det->panels[0].adu_per_eV = NAN;
- image.det->panels[0].adu_per_photon = 1.0;
- image.det->panels[0].max_adu = +INFINITY; /* No cutoff */
+ image.detgeom = calloc(1, sizeof(struct detgeom));
+ image.detgeom->n_panels = 1;
+ image.detgeom->panels = calloc(1, sizeof(struct detgeom_panel));
+
+ image.detgeom->panels[0].fsx = 1.0;
+ image.detgeom->panels[0].fsy = 0.0;
+ image.detgeom->panels[0].ssx = 0.0;
+ image.detgeom->panels[0].ssy = 1.0;
+ image.detgeom->panels[0].cnx = -64.0;
+ image.detgeom->panels[0].cny = -64.0;
+ image.detgeom->panels[0].cnz = 1.0;
+ image.detgeom->panels[0].pixel_pitch = 1.0;
+ image.detgeom->panels[0].w = 128;
+ image.detgeom->panels[0].h = 128;
+ image.detgeom->panels[0].adu_per_photon = 1.0;
+ image.detgeom->panels[0].max_adu = +INFINITY; /* No cutoff */
memset(image.dp[0], 0, 128*128*sizeof(float));
@@ -219,7 +213,7 @@ int main(int argc, char *argv[])
image.crystals = NULL;
/* First check: no intensity -> no peak, or very low intensity */
- r = integrate_peak(&image, 64, 64, &image.det->panels[0],
+ r = integrate_peak(&image, 64, 64, 0,
&fsp, &ssp, &intensity, &sigma,
10.0, 15.0, 17.0, NULL);
STATUS(" First check: integrate_peak() returned %i", r);
@@ -238,15 +232,15 @@ int main(int argc, char *argv[])
/* Second check: uniform peak gives correct I and low sigma(I) */
npx = 0;
- for ( fs=0; fs<image.det->panels[0].w; fs++ ) {
- for ( ss=0; ss<image.det->panels[0].h; ss++ ) {
+ for ( fs=0; fs<image.detgeom->panels[0].w; fs++ ) {
+ for ( ss=0; ss<image.detgeom->panels[0].h; ss++ ) {
if ( (fs-64)*(fs-64) + (ss-64)*(ss-64) > 9*9 ) continue;
- image.dp[0][fs+image.det->panels[0].w*ss] = 1000.0;
+ image.dp[0][fs+image.detgeom->panels[0].w*ss] = 1000.0;
npx++;
}
}
- r = integrate_peak(&image, 64, 64, &image.det->panels[0],
+ r = integrate_peak(&image, 64, 64, 0,
&fsp, &ssp, &intensity, &sigma,
10.0, 15.0, 17.0, NULL);
if ( r ) {
@@ -280,16 +274,16 @@ int main(int argc, char *argv[])
/* Fifth check: uniform peak on uniform background */
npx = 0;
- for ( fs=0; fs<image.det->panels[0].w; fs++ ) {
- for ( ss=0; ss<image.det->panels[0].h; ss++ ) {
- image.dp[0][fs+image.det->panels[0].w*ss] = 1000.0;
+ for ( fs=0; fs<image.detgeom->panels[0].w; fs++ ) {
+ for ( ss=0; ss<image.detgeom->panels[0].h; ss++ ) {
+ image.dp[0][fs+image.detgeom->panels[0].w*ss] = 1000.0;
if ( (fs-64)*(fs-64) + (ss-64)*(ss-64) > 9*9 ) continue;
- image.dp[0][fs+image.det->panels[0].w*ss] += 1000.0;
+ image.dp[0][fs+image.detgeom->panels[0].w*ss] += 1000.0;
npx++;
}
}
- r = integrate_peak(&image, 64, 64, &image.det->panels[0],
+ r = integrate_peak(&image, 64, 64, 0,
&fsp, &ssp, &intensity, &sigma,
10.0, 15.0, 17.0, NULL);
if ( r ) {
@@ -315,9 +309,7 @@ int main(int argc, char *argv[])
}
- free(image.beam);
- free(image.det->panels);
- free(image.det);
+ detgeom_free(image.detgeom);
free(image.dp[0]);
free(image.dp);
gsl_rng_free(rng);
diff --git a/tests/scaling_check.c b/tests/scaling_check.c
index 5a60bf46..05887dde 100644
--- a/tests/scaling_check.c
+++ b/tests/scaling_check.c
@@ -26,11 +26,6 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include <stdlib.h>
#include <stdio.h>
diff --git a/tests/spectrum_check.c b/tests/spectrum_check.c
index b20aa06e..920a680a 100644
--- a/tests/spectrum_check.c
+++ b/tests/spectrum_check.c
@@ -26,11 +26,6 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
diff --git a/tests/stream_read.c b/tests/stream_read.c
new file mode 100644
index 00000000..786026ac
--- /dev/null
+++ b/tests/stream_read.c
@@ -0,0 +1,62 @@
+/*
+ * stream_read.c
+ *
+ * Simple test of stream reading
+ *
+ * Copyright © 2020 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include <stdio.h>
+
+#include "stream.h"
+#include "image.h"
+
+int main(int argc, char *argv[])
+{
+ Stream *st;
+ int n;
+ char *stream_filename = argv[1];
+
+ st = stream_open_for_read(stream_filename);
+ if ( st == NULL ) {
+ fprintf(stderr, "Failed to open '%s'\n",
+ stream_filename);
+ return 1;
+ }
+
+ n = 0;
+ do {
+
+ struct image *image = stream_read_chunk(st, 0);
+ if ( image == NULL ) break;
+ n++;
+
+ image_free(image);
+
+ } while ( 1 );
+
+ printf("Got %i chunks\n", n);
+
+ return (n != 70);
+}
diff --git a/tests/symmetry_check.c b/tests/symmetry_check.c
index 5309206c..be9312e1 100644
--- a/tests/symmetry_check.c
+++ b/tests/symmetry_check.c
@@ -26,11 +26,6 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
diff --git a/tests/test.stream b/tests/test.stream
new file mode 100644
index 00000000..542693d5
--- /dev/null
+++ b/tests/test.stream
@@ -0,0 +1,12642 @@
+CrystFEL stream format 2.3
+Generated by CrystFEL 0.9.1+2c51b20e
+/home/taw/crystfel-master/build/indexamajig -i files.lst -o test.stream -g 5HT2b-Liu-2013.geom -j 3 --peaks=hdf5 -p 5HT2B.cell --indexing=xgandalf
+Indexing methods selected: xgandalf
+----- Begin geometry file -----
+adu_per_eV = 0.00105
+clen = /LCLS/detector0-EncoderValue
+coffset = 582.00e-3
+photon_energy = /LCLS/photon_energy_eV
+res = 9097.525473
+data = /data/data
+peak_list = /processing/hitfinder/peakinfo-raw
+
+mask_file = /home/taw/experiments/5HT2B/r0092-ab/badpixelmap.h5
+mask = /data/data
+mask_good = 0x0001
+mask_bad = 0xfffe
+
+bad_test/min_fs = 0
+bad_test/min_ss = 0
+bad_test/max_fs = 100
+bad_test/max_ss = 100
+bad_test/panel = q2a0
+
+bad_thing/min_x = -390
+bad_thing/max_x = -270
+bad_thing/min_y = 820
+bad_thing/max_y = 890
+
+bad_sparkly/min_x = -220
+bad_sparkly/max_x = -180
+bad_sparkly/min_y = 30
+bad_sparkly/max_y = 235
+
+bad_squiggle/min_x = 80
+bad_squiggle/max_x = 180
+bad_squiggle/min_y = 595
+bad_squiggle/max_y = 640
+
+; The following lines define "rigid groups" which express the physical
+; construction of the detector. This is used when refining the detector
+; geometry.
+
+rigid_group_q0 = q0a0,q0a1,q0a2,q0a3,q0a4,q0a5,q0a6,q0a7,q0a8,q0a9,q0a10,q0a11,q0a12,q0a13,q0a14,q0a15
+rigid_group_q1 = q1a0,q1a1,q1a2,q1a3,q1a4,q1a5,q1a6,q1a7,q1a8,q1a9,q1a10,q1a11,q1a12,q1a13,q1a14,q1a15
+rigid_group_q2 = q2a0,q2a1,q2a2,q2a3,q2a4,q2a5,q2a6,q2a7,q2a8,q2a9,q2a10,q2a11,q2a12,q2a13,q2a14,q2a15
+rigid_group_q3 = q3a0,q3a1,q3a2,q3a3,q3a4,q3a5,q3a6,q3a7,q3a8,q3a9,q3a10,q3a11,q3a12,q3a13,q3a14,q3a15
+
+rigid_group_a0 = q0a0,q0a1
+rigid_group_a1 = q0a2,q0a3
+rigid_group_a2 = q0a4,q0a5
+rigid_group_a3 = q0a6,q0a7
+rigid_group_a4 = q0a8,q0a9
+rigid_group_a5 = q0a10,q0a11
+rigid_group_a6 = q0a12,q0a13
+rigid_group_a7 = q0a14,q0a15
+rigid_group_a8 = q1a0,q1a1
+rigid_group_a9 = q1a2,q1a3
+rigid_group_a10 = q1a4,q1a5
+rigid_group_a11 = q1a6,q1a7
+rigid_group_a12 = q1a8,q1a9
+rigid_group_a13 = q1a10,q1a11
+rigid_group_a14 = q1a12,q1a13
+rigid_group_a15 = q1a14,q1a15
+rigid_group_a16 = q2a0,q2a1
+rigid_group_a17 = q2a2,q2a3
+rigid_group_a18 = q2a4,q2a5
+rigid_group_a19 = q2a6,q2a7
+rigid_group_a20 = q2a8,q2a9
+rigid_group_a21 = q2a10,q2a11
+rigid_group_a22 = q2a12,q2a13
+rigid_group_a23 = q2a14,q2a15
+rigid_group_a24 = q3a0,q3a1
+rigid_group_a25 = q3a2,q3a3
+rigid_group_a26 = q3a4,q3a5
+rigid_group_a27 = q3a6,q3a7
+rigid_group_a28 = q3a8,q3a9
+rigid_group_a29 = q3a10,q3a11
+rigid_group_a30 = q3a12,q3a13
+rigid_group_a31 = q3a14,q3a15
+
+rigid_group_collection_quadrants = q0,q1,q2,q3
+rigid_group_collection_asics = a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31
+
+q0a0/min_fs = 0
+q0a0/min_ss = 0
+q0a0/max_fs = 193
+q0a0/max_ss = 184
+q0a0/fs = -0.005902x +0.999983y
+q0a0/ss = -0.999983x -0.005902y
+q0a0/corner_x = 449.314461
+q0a0/corner_y = -28.273254
+
+q0a1/min_fs = 194
+q0a1/min_ss = 0
+q0a1/max_fs = 387
+q0a1/max_ss = 184
+q0a1/fs = -0.005902x +0.999983y
+q0a1/ss = -0.999983x -0.005902y
+q0a1/corner_x = 448.152461
+q0a1/corner_y = 168.723346
+
+q0a2/min_fs = 0
+q0a2/min_ss = 185
+q0a2/max_fs = 193
+q0a2/max_ss = 369
+q0a2/fs = +0.000023x +1.000000y
+q0a2/ss = -1.000000x +0.000023y
+q0a2/corner_x = 235.021461
+q0a2/corner_y = -29.911754
+
+q0a3/min_fs = 194
+q0a3/min_ss = 185
+q0a3/max_fs = 387
+q0a3/max_ss = 369
+q0a3/fs = +0.000023x +1.000000y
+q0a3/ss = -1.000000x +0.000023y
+q0a3/corner_x = 235.025461
+q0a3/corner_y = 167.088346
+
+q0a4/min_fs = 0
+q0a4/min_ss = 370
+q0a4/max_fs = 193
+q0a4/max_ss = 554
+q0a4/fs = -0.999985x +0.005489y
+q0a4/ss = -0.005489x -0.999985y
+q0a4/corner_x = 869.017461
+q0a4/corner_y = 368.638346
+
+q0a5/min_fs = 194
+q0a5/min_ss = 370
+q0a5/max_fs = 387
+q0a5/max_ss = 554
+q0a5/fs = -0.999985x +0.005489y
+q0a5/ss = -0.005489x -0.999985y
+q0a5/corner_x = 672.020461
+q0a5/corner_y = 369.720346
+
+q0a6/min_fs = 0
+q0a6/min_ss = 555
+q0a6/max_fs = 193
+q0a6/max_ss = 739
+q0a6/fs = -1.000000x -0.000609y
+q0a6/ss = +0.000609x -1.000000y
+q0a6/corner_x = 868.559461
+q0a6/corner_y = 157.379346
+
+q0a7/min_fs = 194
+q0a7/min_ss = 555
+q0a7/max_fs = 387
+q0a7/max_ss = 739
+q0a7/fs = -1.000000x -0.000609y
+q0a7/ss = +0.000609x -1.000000y
+q0a7/corner_x = 671.559461
+q0a7/corner_y = 157.259346
+
+q0a8/min_fs = 0
+q0a8/min_ss = 740
+q0a8/max_fs = 193
+q0a8/max_ss = 924
+q0a8/fs = -0.002572x -0.999997y
+q0a8/ss = +0.999997x -0.002572y
+q0a8/corner_x = 471.437461
+q0a8/corner_y = 791.986346
+
+q0a9/min_fs = 194
+q0a9/min_ss = 740
+q0a9/max_fs = 387
+q0a9/max_ss = 924
+q0a9/fs = -0.002572x -0.999997y
+q0a9/ss = +0.999997x -0.002572y
+q0a9/corner_x = 470.930461
+q0a9/corner_y = 594.987346
+
+q0a10/min_fs = 0
+q0a10/min_ss = 925
+q0a10/max_fs = 193
+q0a10/max_ss = 1109
+q0a10/fs = -0.001378x -0.999999y
+q0a10/ss = +0.999999x -0.001378y
+q0a10/corner_x = 683.554461
+q0a10/corner_y = 791.847346
+
+q0a11/min_fs = 194
+q0a11/min_ss = 925
+q0a11/max_fs = 387
+q0a11/max_ss = 1109
+q0a11/fs = -0.001378x -0.999999y
+q0a11/ss = +0.999999x -0.001378y
+q0a11/corner_x = 683.282461
+q0a11/corner_y = 594.847346
+
+q0a12/min_fs = 0
+q0a12/min_ss = 1110
+q0a12/max_fs = 193
+q0a12/max_ss = 1294
+q0a12/fs = -0.999993x -0.003801y
+q0a12/ss = +0.003801x -0.999993y
+q0a12/corner_x = 441.094461
+q0a12/corner_y = 771.651346
+
+q0a13/min_fs = 194
+q0a13/min_ss = 1110
+q0a13/max_fs = 387
+q0a13/max_ss = 1294
+q0a13/fs = -0.999993x -0.003801y
+q0a13/ss = +0.003801x -0.999993y
+q0a13/corner_x = 244.095461
+q0a13/corner_y = 770.902346
+
+q0a14/min_fs = 0
+q0a14/min_ss = 1295
+q0a14/max_fs = 193
+q0a14/max_ss = 1479
+q0a14/fs = -0.999998x -0.001814y
+q0a14/ss = +0.001814x -0.999998y
+q0a14/corner_x = 442.048461
+q0a14/corner_y = 558.714346
+
+q0a15/min_fs = 194
+q0a15/min_ss = 1295
+q0a15/max_fs = 387
+q0a15/max_ss = 1479
+q0a15/fs = -0.999998x -0.001814y
+q0a15/ss = +0.001814x -0.999998y
+q0a15/corner_x = 245.048461
+q0a15/corner_y = 558.356346
+
+q1a0/min_fs = 388
+q1a0/min_ss = 0
+q1a0/max_fs = 581
+q1a0/max_ss = 184
+q1a0/fs = -0.999983x -0.005902y
+q1a0/ss = +0.005902x -0.999983y
+q1a0/corner_x = 31.029061
+q1a0/corner_y = 445.239346
+
+q1a1/min_fs = 582
+q1a1/min_ss = 0
+q1a1/max_fs = 775
+q1a1/max_ss = 184
+q1a1/fs = -0.999983x -0.005902y
+q1a1/ss = +0.005902x -0.999983y
+q1a1/corner_x = -165.967539
+q1a1/corner_y = 444.077346
+
+q1a2/min_fs = 388
+q1a2/min_ss = 185
+q1a2/max_fs = 581
+q1a2/max_ss = 369
+q1a2/fs = -1.000000x +0.000023y
+q1a2/ss = -0.000023x -1.000000y
+q1a2/corner_x = 32.667561
+q1a2/corner_y = 230.946346
+
+q1a3/min_fs = 582
+q1a3/min_ss = 185
+q1a3/max_fs = 775
+q1a3/max_ss = 369
+q1a3/fs = -1.000000x +0.000023y
+q1a3/ss = -0.000023x -1.000000y
+q1a3/corner_x = -164.332539
+q1a3/corner_y = 230.950346
+
+q1a4/min_fs = 388
+q1a4/min_ss = 370
+q1a4/max_fs = 581
+q1a4/max_ss = 554
+q1a4/fs = -0.005489x -0.999985y
+q1a4/ss = +0.999985x -0.005489y
+q1a4/corner_x = -365.882539
+q1a4/corner_y = 864.942346
+
+q1a5/min_fs = 582
+q1a5/min_ss = 370
+q1a5/max_fs = 775
+q1a5/max_ss = 554
+q1a5/fs = -0.005489x -0.999985y
+q1a5/ss = +0.999985x -0.005489y
+q1a5/corner_x = -366.964539
+q1a5/corner_y = 667.945346
+
+q1a6/min_fs = 388
+q1a6/min_ss = 555
+q1a6/max_fs = 581
+q1a6/max_ss = 739
+q1a6/fs = +0.000609x -1.000000y
+q1a6/ss = +1.000000x +0.000609y
+q1a6/corner_x = -154.623539
+q1a6/corner_y = 864.484346
+
+q1a7/min_fs = 582
+q1a7/min_ss = 555
+q1a7/max_fs = 775
+q1a7/max_ss = 739
+q1a7/fs = +0.000609x -1.000000y
+q1a7/ss = +1.000000x +0.000609y
+q1a7/corner_x = -154.503539
+q1a7/corner_y = 667.484346
+
+q1a8/min_fs = 388
+q1a8/min_ss = 740
+q1a8/max_fs = 581
+q1a8/max_ss = 924
+q1a8/fs = +0.999997x -0.002572y
+q1a8/ss = +0.002572x +0.999997y
+q1a8/corner_x = -789.230539
+q1a8/corner_y = 467.362346
+
+q1a9/min_fs = 582
+q1a9/min_ss = 740
+q1a9/max_fs = 775
+q1a9/max_ss = 924
+q1a9/fs = +0.999997x -0.002572y
+q1a9/ss = +0.002572x +0.999997y
+q1a9/corner_x = -592.231539
+q1a9/corner_y = 466.855346
+
+q1a10/min_fs = 388
+q1a10/min_ss = 925
+q1a10/max_fs = 581
+q1a10/max_ss = 1109
+q1a10/fs = +0.999999x -0.001378y
+q1a10/ss = +0.001378x +0.999999y
+q1a10/corner_x = -789.091539
+q1a10/corner_y = 679.479346
+
+q1a11/min_fs = 582
+q1a11/min_ss = 925
+q1a11/max_fs = 775
+q1a11/max_ss = 1109
+q1a11/fs = +0.999999x -0.001378y
+q1a11/ss = +0.001378x +0.999999y
+q1a11/corner_x = -592.091539
+q1a11/corner_y = 679.207346
+
+q1a12/min_fs = 388
+q1a12/min_ss = 1110
+q1a12/max_fs = 581
+q1a12/max_ss = 1294
+q1a12/fs = +0.003801x -0.999993y
+q1a12/ss = +0.999993x +0.003801y
+q1a12/corner_x = -768.895539
+q1a12/corner_y = 437.019346
+
+q1a13/min_fs = 582
+q1a13/min_ss = 1110
+q1a13/max_fs = 775
+q1a13/max_ss = 1294
+q1a13/fs = +0.003801x -0.999993y
+q1a13/ss = +0.999993x +0.003801y
+q1a13/corner_x = -768.146539
+q1a13/corner_y = 240.020346
+
+q1a14/min_fs = 388
+q1a14/min_ss = 1295
+q1a14/max_fs = 581
+q1a14/max_ss = 1479
+q1a14/fs = +0.001814x -0.999998y
+q1a14/ss = +0.999998x +0.001814y
+q1a14/corner_x = -555.958539
+q1a14/corner_y = 437.973346
+
+q1a15/min_fs = 582
+q1a15/min_ss = 1295
+q1a15/max_fs = 775
+q1a15/max_ss = 1479
+q1a15/fs = +0.001814x -0.999998y
+q1a15/ss = +0.999998x +0.001814y
+q1a15/corner_x = -555.600539
+q1a15/corner_y = 240.973346
+
+q2a0/min_fs = 776
+q2a0/min_ss = 0
+q2a0/max_fs = 969
+q2a0/max_ss = 184
+q2a0/fs = +0.005902x -0.999983y
+q2a0/ss = +0.999983x +0.005902y
+q2a0/corner_x = -441.683539
+q2a0/corner_y = 27.153946
+
+q2a1/min_fs = 970
+q2a1/min_ss = 0
+q2a1/max_fs = 1163
+q2a1/max_ss = 184
+q2a1/fs = +0.005902x -0.999983y
+q2a1/ss = +0.999983x +0.005902y
+q2a1/corner_x = -440.521539
+q2a1/corner_y = -169.842654
+
+q2a2/min_fs = 776
+q2a2/min_ss = 185
+q2a2/max_fs = 969
+q2a2/max_ss = 369
+q2a2/fs = -0.000023x -1.000000y
+q2a2/ss = +1.000000x -0.000023y
+q2a2/corner_x = -227.390539
+q2a2/corner_y = 28.792446
+
+q2a3/min_fs = 970
+q2a3/min_ss = 185
+q2a3/max_fs = 1163
+q2a3/max_ss = 369
+q2a3/fs = -0.000023x -1.000000y
+q2a3/ss = +1.000000x -0.000023y
+q2a3/corner_x = -227.394539
+q2a3/corner_y = -168.207654
+
+q2a4/min_fs = 776
+q2a4/min_ss = 370
+q2a4/max_fs = 969
+q2a4/max_ss = 554
+q2a4/fs = +0.999985x -0.005489y
+q2a4/ss = +0.005489x +0.999985y
+q2a4/corner_x = -861.386539
+q2a4/corner_y = -369.757654
+
+q2a5/min_fs = 970
+q2a5/min_ss = 370
+q2a5/max_fs = 1163
+q2a5/max_ss = 554
+q2a5/fs = +0.999985x -0.005489y
+q2a5/ss = +0.005489x +0.999985y
+q2a5/corner_x = -664.389539
+q2a5/corner_y = -370.839654
+
+q2a6/min_fs = 776
+q2a6/min_ss = 555
+q2a6/max_fs = 969
+q2a6/max_ss = 739
+q2a6/fs = +1.000000x +0.000609y
+q2a6/ss = -0.000609x +1.000000y
+q2a6/corner_x = -860.928539
+q2a6/corner_y = -158.498654
+
+q2a7/min_fs = 970
+q2a7/min_ss = 555
+q2a7/max_fs = 1163
+q2a7/max_ss = 739
+q2a7/fs = +1.000000x +0.000609y
+q2a7/ss = -0.000609x +1.000000y
+q2a7/corner_x = -663.928539
+q2a7/corner_y = -158.378654
+
+q2a8/min_fs = 776
+q2a8/min_ss = 740
+q2a8/max_fs = 969
+q2a8/max_ss = 924
+q2a8/fs = +0.002572x +0.999997y
+q2a8/ss = -0.999997x +0.002572y
+q2a8/corner_x = -463.806539
+q2a8/corner_y = -793.105654
+
+q2a9/min_fs = 970
+q2a9/min_ss = 740
+q2a9/max_fs = 1163
+q2a9/max_ss = 924
+q2a9/fs = +0.002572x +0.999997y
+q2a9/ss = -0.999997x +0.002572y
+q2a9/corner_x = -463.299539
+q2a9/corner_y = -596.106654
+
+q2a10/min_fs = 776
+q2a10/min_ss = 925
+q2a10/max_fs = 969
+q2a10/max_ss = 1109
+q2a10/fs = +0.001378x +0.999999y
+q2a10/ss = -0.999999x +0.001378y
+q2a10/corner_x = -675.923539
+q2a10/corner_y = -792.966654
+
+q2a11/min_fs = 970
+q2a11/min_ss = 925
+q2a11/max_fs = 1163
+q2a11/max_ss = 1109
+q2a11/fs = +0.001378x +0.999999y
+q2a11/ss = -0.999999x +0.001378y
+q2a11/corner_x = -675.651539
+q2a11/corner_y = -595.966654
+
+q2a12/min_fs = 776
+q2a12/min_ss = 1110
+q2a12/max_fs = 969
+q2a12/max_ss = 1294
+q2a12/fs = +0.999993x +0.003801y
+q2a12/ss = -0.003801x +0.999993y
+q2a12/corner_x = -433.463539
+q2a12/corner_y = -772.770654
+
+q2a13/min_fs = 970
+q2a13/min_ss = 1110
+q2a13/max_fs = 1163
+q2a13/max_ss = 1294
+q2a13/fs = +0.999993x +0.003801y
+q2a13/ss = -0.003801x +0.999993y
+q2a13/corner_x = -236.464539
+q2a13/corner_y = -772.021654
+
+q2a14/min_fs = 776
+q2a14/min_ss = 1295
+q2a14/max_fs = 969
+q2a14/max_ss = 1479
+q2a14/fs = +0.999998x +0.001814y
+q2a14/ss = -0.001814x +0.999998y
+q2a14/corner_x = -434.417539
+q2a14/corner_y = -559.833654
+
+q2a15/min_fs = 970
+q2a15/min_ss = 1295
+q2a15/max_fs = 1163
+q2a15/max_ss = 1479
+q2a15/fs = +0.999998x +0.001814y
+q2a15/ss = -0.001814x +0.999998y
+q2a15/corner_x = -237.417539
+q2a15/corner_y = -559.475654
+
+q3a0/min_fs = 1164
+q3a0/min_ss = 0
+q3a0/max_fs = 1357
+q3a0/max_ss = 184
+q3a0/fs = +0.999983x +0.005902y
+q3a0/ss = -0.005902x +0.999983y
+q3a0/corner_x = -28.098139
+q3a0/corner_y = -445.058654
+
+q3a1/min_fs = 1358
+q3a1/min_ss = 0
+q3a1/max_fs = 1551
+q3a1/max_ss = 184
+q3a1/fs = +0.999983x +0.005902y
+q3a1/ss = -0.005902x +0.999983y
+q3a1/corner_x = 168.898461
+q3a1/corner_y = -443.896654
+
+q3a2/min_fs = 1164
+q3a2/min_ss = 185
+q3a2/max_fs = 1357
+q3a2/max_ss = 369
+q3a2/fs = +1.000000x -0.000023y
+q3a2/ss = +0.000023x +1.000000y
+q3a2/corner_x = -29.736639
+q3a2/corner_y = -230.765654
+
+q3a3/min_fs = 1358
+q3a3/min_ss = 185
+q3a3/max_fs = 1551
+q3a3/max_ss = 369
+q3a3/fs = +1.000000x -0.000023y
+q3a3/ss = +0.000023x +1.000000y
+q3a3/corner_x = 167.263461
+q3a3/corner_y = -230.769654
+
+q3a4/min_fs = 1164
+q3a4/min_ss = 370
+q3a4/max_fs = 1357
+q3a4/max_ss = 554
+q3a4/fs = +0.005489x +0.999985y
+q3a4/ss = -0.999985x +0.005489y
+q3a4/corner_x = 368.813461
+q3a4/corner_y = -864.761654
+
+q3a5/min_fs = 1358
+q3a5/min_ss = 370
+q3a5/max_fs = 1551
+q3a5/max_ss = 554
+q3a5/fs = +0.005489x +0.999985y
+q3a5/ss = -0.999985x +0.005489y
+q3a5/corner_x = 369.895461
+q3a5/corner_y = -667.764654
+
+q3a6/min_fs = 1164
+q3a6/min_ss = 555
+q3a6/max_fs = 1357
+q3a6/max_ss = 739
+q3a6/fs = -0.000609x +1.000000y
+q3a6/ss = -1.000000x -0.000609y
+q3a6/corner_x = 157.554461
+q3a6/corner_y = -864.303654
+
+q3a7/min_fs = 1358
+q3a7/min_ss = 555
+q3a7/max_fs = 1551
+q3a7/max_ss = 739
+q3a7/fs = -0.000609x +1.000000y
+q3a7/ss = -1.000000x -0.000609y
+q3a7/corner_x = 157.434461
+q3a7/corner_y = -667.303654
+
+q3a8/min_fs = 1164
+q3a8/min_ss = 740
+q3a8/max_fs = 1357
+q3a8/max_ss = 924
+q3a8/fs = -0.999997x +0.002572y
+q3a8/ss = -0.002572x -0.999997y
+q3a8/corner_x = 792.161461
+q3a8/corner_y = -467.181654
+
+q3a9/min_fs = 1358
+q3a9/min_ss = 740
+q3a9/max_fs = 1551
+q3a9/max_ss = 924
+q3a9/fs = -0.999997x +0.002572y
+q3a9/ss = -0.002572x -0.999997y
+q3a9/corner_x = 595.162461
+q3a9/corner_y = -466.674654
+
+q3a10/min_fs = 1164
+q3a10/min_ss = 925
+q3a10/max_fs = 1357
+q3a10/max_ss = 1109
+q3a10/fs = -0.999999x +0.001378y
+q3a10/ss = -0.001378x -0.999999y
+q3a10/corner_x = 792.022461
+q3a10/corner_y = -679.298654
+
+q3a11/min_fs = 1358
+q3a11/min_ss = 925
+q3a11/max_fs = 1551
+q3a11/max_ss = 1109
+q3a11/fs = -0.999999x +0.001378y
+q3a11/ss = -0.001378x -0.999999y
+q3a11/corner_x = 595.022461
+q3a11/corner_y = -679.026654
+
+q3a12/min_fs = 1164
+q3a12/min_ss = 1110
+q3a12/max_fs = 1357
+q3a12/max_ss = 1294
+q3a12/fs = -0.003801x +0.999993y
+q3a12/ss = -0.999993x -0.003801y
+q3a12/corner_x = 771.826461
+q3a12/corner_y = -436.838654
+
+q3a13/min_fs = 1358
+q3a13/min_ss = 1110
+q3a13/max_fs = 1551
+q3a13/max_ss = 1294
+q3a13/fs = -0.003801x +0.999993y
+q3a13/ss = -0.999993x -0.003801y
+q3a13/corner_x = 771.077461
+q3a13/corner_y = -239.839654
+
+q3a14/min_fs = 1164
+q3a14/min_ss = 1295
+q3a14/max_fs = 1357
+q3a14/max_ss = 1479
+q3a14/fs = -0.001814x +0.999998y
+q3a14/ss = -0.999998x -0.001814y
+q3a14/corner_x = 558.889461
+q3a14/corner_y = -437.792654
+
+q3a15/min_fs = 1358
+q3a15/min_ss = 1295
+q3a15/max_fs = 1551
+q3a15/max_ss = 1479
+q3a15/fs = -0.001814x +0.999998y
+q3a15/ss = -0.999998x -0.001814y
+q3a15/corner_x = 558.531461
+q3a15/corner_y = -240.792654
+----- End geometry file -----
+----- Begin unit cell -----
+CrystFEL unit cell file version 1.0
+
+lattice_type = orthorhombic
+centering = C
+a = 61.40 A
+b = 122.60 A
+c = 168.00 A
+al = 90.00 deg
+be = 90.00 deg
+ga = 90.00 deg
+; Please note: this is the target unit cell.
+; The actual unit cells produced by indexing depend on many other factors.
+----- End unit cell -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035103_1824f.h5
+Image serial number: 1
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9511.868397
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9511.868397
+average_camera_length = 0.152001 m
+num_peaks = 20
+peak_resolution = 3.876811 nm^-1 or 2.579439 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 33.50 10.98 2.35 -78.50 q0a0
+ 87.50 47.17 2.18 835.72 q0a0
+ 466.50 134.06 1.71 1431.25 q1a0
+ 470.50 169.68 1.53 921.74 q1a0
+1030.81 68.07 2.34 5291.03 q2a1
+1346.50 135.11 1.87 1419.64 q3a0
+ 76.50 324.79 0.59 1051.96 q0a2
+ 256.98 282.92 1.47 7093.80 q0a3
+ 444.67 195.76 1.22 4856.40 q1a2
+ 508.71 260.07 0.99 1319.84 q1a2
+ 450.50 296.86 0.68 904.74 q1a2
+ 510.36 326.22 0.70 1985.59 q1a2
+ 738.69 340.50 1.79 4960.33 q1a3
+ 817.00 321.50 0.51 1153.11 q2a2
+ 909.28 329.19 0.74 1933.86 q2a2
+ 867.50 351.83 0.48 1321.29 q2a2
+1323.61 308.76 0.93 3077.91 q3a2
+1321.81 341.51 0.82 9320.04 q3a2
+1294.15 344.15 0.68 519.84 q3a2
+ 502.50 539.11 3.88 438.95 q1a4
+End of peak list
+--- Begin crystal
+Cell parameters 6.13532 12.19726 16.88163 nm, 90.54524 91.23016 90.53769 deg
+astar = +0.0706577 -0.1444151 +0.0270631 nm^-1
+bstar = -0.0612585 -0.0381529 -0.0389182 nm^-1
+cstar = +0.0296121 +0.0034501 -0.0512061 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00258 nm^-1
+predict_refine/final_residual = 3.289294e-07
+predict_refine/det_shift x = 0.022 y = -0.009 mm
+diffraction_resolution_limit = 1.80 nm^-1 or 5.56 A
+num_reflections = 257
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -28 10 5 185.09 155.78 217.00 64.71 634.8 1057.6 q1a11
+ -28 22 -1 13.96 89.69 105.00 52.84 417.2 970.2 q1a10
+ -27 11 3 -68.26 113.63 144.00 68.86 631.7 1004.8 q1a11
+ -27 21 -2 -8.75 129.56 115.00 55.34 454.3 932.2 q1a10
+ -26 14 0 -99.39 91.82 109.00 64.99 593.7 939.2 q1a11
+ -25 -1 9 -95.82 116.71 130.00 80.42 478.4 433.5 q1a4
+ -25 7 3 172.21 127.00 165.00 71.59 730.5 952.0 q1a11
+ -25 23 -5 13.80 97.62 128.00 67.80 453.7 863.7 q1a8
+ -24 0 7 103.09 147.49 150.00 86.71 528.3 427.6 q1a4
+ -24 10 0 77.90 108.24 170.00 76.90 692.3 916.5 q1a9
+ -24 20 -5 74.96 154.70 151.00 70.84 523.9 844.4 q1a8
+ -23 -9 14 389.80 126.92 133.00 82.80 484.1 573.0 q1a6
+ -22 -10 14 223.94 149.82 183.00 95.06 513.4 601.3 q1a6
+ -22 -8 12 60.64 120.07 146.00 95.76 533.0 564.6 q1a6
+ -22 10 -2 -194.15 139.85 167.00 85.35 720.4 841.5 q1a9
+ -21 -11 14 253.91 237.79 250.00 102.29 542.1 629.1 q1a6
+ -21 1 3 168.80 142.95 153.00 99.80 648.2 445.8 q1a5
+ -20 -8 10 -155.20 166.85 190.00 124.80 605.3 584.2 q1a7
+ -20 0 3 243.69 157.18 203.00 109.31 674.8 474.8 q1a5
+ -20 4 0 -141.77 173.70 186.00 113.97 707.3 408.7 q1a5
+ -20 24 -10 -155.69 144.20 164.00 77.69 425.9 1223.2 q1a12
+ -19 -1 3 130.41 417.97 390.00 144.79 700.9 503.3 q1a5
+ -19 3 0 -343.15 495.31 476.00 152.35 733.1 437.8 q1a5
+ -19 17 -8 -257.51 170.49 189.00 113.11 411.9 1325.9 q1a14
+ -19 25 -11 116.00 111.48 147.00 71.00 466.3 1222.7 q1a12
+ -18 -22 25 -3.41 139.32 142.00 95.21 271.5 1159.5 q0a13
+ -18 -2 3 1353.38 483.68 439.00 164.62 726.5 531.3 q1a5
+ -18 2 0 -100.56 367.11 350.00 149.56 758.4 466.4 q1a5
+ -18 26 -12 -184.23 175.71 208.00 79.03 506.3 1222.2 q1a12
+ -18 30 -13 331.51 146.53 231.00 71.89 533.3 1155.0 q1a12
+ -17 -19 20 157.00 295.28 412.00 116.00 328.0 1231.7 q0a13
+ -17 7 -4 525.51 216.65 369.00 175.89 754.8 22.1 q1a1
+ -16 -12 11 1266.48 436.26 477.00 174.72 706.2 695.7 q1a7
+ -16 -10 9 1389.96 486.21 464.00 182.84 724.0 660.7 q1a7
+ -16 -8 7 873.86 493.52 591.00 185.74 741.8 625.9 q1a7
+ -16 6 -4 560.58 225.27 334.00 189.82 726.5 46.5 q1a1
+ -16 20 -11 26.44 198.80 232.00 128.56 528.7 1322.6 q1a14
+ -16 26 -13 175.14 201.35 201.00 81.26 569.9 1254.4 q1a12
+ -15 -3 2 409.13 378.78 464.00 200.67 574.4 9.5 q1a0
+ -15 1 -1 -660.85 336.42 416.00 212.65 635.1 40.0 q1a1
+ -14 -30 35 3.93 113.76 159.00 88.67 50.7 1199.7 q0a12
+ -14 26 -14 -13.81 165.97 234.00 92.81 628.7 1285.7 q1a13
+ -14 30 -15 -31.85 99.56 119.00 78.65 656.8 1221.5 q1a13
+ -14 36 -16 144.59 103.05 114.00 74.21 699.8 1121.7 q1a13
+ -13 -37 49 -334.09 160.49 153.00 73.29 26.5 887.6 q0a8
+ -13 9 -7 82.28 633.23 563.00 270.52 733.6 158.2 q1a1
+ -13 17 -11 168.16 229.03 438.00 175.04 595.1 1412.7 q1a15
+ -13 29 -15 264.56 126.07 157.00 85.44 679.6 1253.8 q1a13
+ -12 -36 46 57.34 105.48 121.00 73.46 85.3 856.9 q0a8
+ -12 -30 34 10.61 141.51 174.00 93.99 34.3 1270.0 q0a12
+ -12 -18 16 32.17 271.88 347.00 209.43 300.0 1379.6 q0a15
+ -12 14 -10 -1600.60 634.77 528.00 247.40 603.1 1471.9 q1a15
+ -12 24 -14 180.79 216.44 216.00 145.41 673.8 1320.2 q1a15
+ -12 32 -16 115.45 246.50 307.00 89.95 731.1 1221.6 q1a13
+ -11 -39 53 127.39 112.21 106.00 57.01 62.2 953.4 q0a10
+ -11 -37 48 169.43 109.49 167.00 73.17 102.7 901.9 q0a8
+ -11 -19 17 95.59 359.42 484.00 213.21 269.5 1400.3 q0a15
+ -11 -13 10 855.41 727.34 629.00 319.75 380.4 1455.2 q0a15
+ -11 -9 6 852.81 255.98 400.00 191.19 428.7 80.9 q1a0
+ -11 -1 -1 -528.01 271.53 299.00 158.61 558.2 143.4 q1a0
+ -11 31 -16 629.15 378.40 400.00 104.65 753.1 1253.9 q1a13
+ -10 -32 37 475.18 133.02 168.00 77.42 216.9 750.1 q0a9
+ -10 -28 30 83.31 183.49 187.00 124.69 65.1 1333.4 q0a14
+ -10 -6 3 1269.84 215.47 832.00 153.96 466.3 133.5 q1a0
+ -10 6 -6 1360.00 252.57 499.00 107.00 649.4 194.9 q1a3
+ -10 20 -13 -833.92 490.58 504.00 220.32 702.4 1410.6 q1a15
+ -10 26 -15 -107.65 312.89 428.00 166.85 745.6 1320.1 q1a15
+ -10 36 -17 121.14 280.62 259.00 94.26 949.4 715.9 q2a6
+ -9 -35 43 161.40 143.47 167.00 75.40 204.4 852.7 q0a9
+ -9 -33 39 -210.62 126.27 144.00 80.62 234.2 792.1 q0a9
+ -9 -25 25 389.96 391.71 446.00 175.84 124.8 1399.0 q0a14
+ -9 -23 22 -1016.55 577.27 493.00 221.95 168.8 1420.4 q0a14
+ -9 -5 2 1010.98 178.98 1051.00 136.22 469.9 169.3 q1a0
+ -9 11 -9 928.60 333.77 453.00 130.60 710.0 258.5 q1a3
+ -9 13 -10 878.73 538.01 409.00 189.47 739.4 272.8 q1a3
+ -9 15 -11 -145.11 613.20 530.00 227.70 768.9 287.2 q1a3
+ -9 35 -17 68.96 236.11 298.00 105.84 979.3 694.7 q2a7
+ -8 -34 41 74.61 132.24 244.00 79.99 251.6 834.6 q0a9
+ -8 -32 37 126.12 124.34 134.00 78.88 280.1 775.1 q0a9
+ -8 -16 13 -785.10 665.26 514.00 241.90 364.8 271.0 q0a3
+ -8 0 -2 274.38 214.92 226.00 71.62 535.1 205.7 q1a2
+ -7 -35 43 139.61 104.57 116.00 76.99 269.2 877.5 q0a9
+ -7 -33 39 -144.75 136.87 179.00 79.75 297.5 816.9 q0a9
+ -7 -31 35 68.95 142.90 190.00 88.45 324.8 758.6 q0a9
+ -7 -25 25 43.06 408.86 456.00 189.94 100.0 1458.2 q0a14
+ -7 -5 2 4856.40 251.20 2586.00 62.40 444.4 195.2 q1a2
+ -7 11 -9 511.96 176.44 388.00 103.84 681.9 312.8 q1a3
+ -7 13 -10 325.59 246.42 292.00 120.21 710.9 327.2 q1a3
+ -7 15 -11 4115.71 435.87 2623.00 148.09 740.2 341.6 q1a3
+ -7 35 -17 89.31 181.64 222.00 111.69 1012.3 637.7 q2a7
+ -6 -34 41 -116.46 179.12 254.00 82.66 315.2 859.2 q0a9
+ -6 -32 37 -321.26 310.21 359.00 93.86 342.3 799.8 q0a9
+ -6 -28 30 -244.24 285.85 284.00 159.64 15.8 1454.5 q0a14
+ -6 -6 3 513.73 147.79 272.00 65.47 415.0 214.4 q1a2
+ -6 0 -2 1312.18 191.16 542.00 69.42 508.6 259.7 q1a2
+ -6 6 -6 341.16 267.72 190.00 67.68 594.6 303.4 q1a3
+ -6 20 -13 220.23 415.02 446.00 212.97 792.5 61.1 q2a0
+ -6 30 -16 356.86 420.44 496.00 152.74 1105.6 649.0 q2a7
+ -6 36 -17 -263.09 165.32 184.00 110.29 1013.0 601.4 q2a7
+ -5 -39 53 35.11 84.58 116.00 61.49 266.7 1027.9 q0a11
+ -5 -37 48 69.59 87.92 101.00 60.21 301.0 949.1 q0a11
+ -5 -13 10 6914.20 296.26 2355.00 104.20 257.0 284.5 q0a3
+ -5 -1 -1 1523.34 171.51 1181.00 61.46 479.2 278.7 q1a2
+ -5 3 -4 -84.48 192.06 226.00 70.28 539.7 308.2 q1a2
+ -5 23 -14 -1138.90 364.78 388.00 224.10 841.6 32.0 q2a0
+ -5 31 -16 -66.70 380.14 415.00 150.30 1106.5 613.6 q2a7
+ -5 37 -17 -1.38 148.71 183.00 106.38 1013.8 564.9 q2a7
+ -4 -38 51 -6.66 87.76 140.00 62.46 314.9 1006.2 q0a11
+ -4 -24 24 5.94 422.32 520.00 219.06 325.7 86.4 q0a1
+ -4 -2 0 853.62 162.47 406.00 62.38 449.8 297.5 q1a2
+ -4 2 -3 1985.59 200.54 1320.00 71.21 510.3 327.0 q1a2
+ -4 16 -11 189.21 178.77 219.00 144.59 817.0 148.5 q2a0
+ -4 24 -14 -929.33 597.22 629.00 254.93 876.0 32.9 q2a0
+ -4 32 -16 439.65 342.35 341.00 143.15 1107.4 578.1 q2a7
+ -4 50 -17 -230.35 121.48 126.00 70.15 816.5 444.1 q2a4
+ -3 -37 49 -215.46 174.51 160.00 64.66 361.6 985.1 q0a11
+ -3 -25 26 172.15 343.39 522.00 201.65 308.0 48.2 q0a1
+ -3 -23 23 -451.52 429.24 468.00 237.72 288.9 92.4 q0a1
+ -3 -3 1 -139.90 151.30 130.00 65.10 420.6 316.3 q1a2
+ -3 1 -2 971.76 151.85 1053.00 67.64 480.9 345.7 q1a2
+ -3 19 -12 292.64 205.17 285.00 156.76 865.5 120.3 q2a0
+ -3 43 -17 -79.40 181.11 197.00 80.60 954.2 482.9 q2a4
+ -3 45 -17 46.93 168.13 217.00 75.67 921.1 464.0 q2a4
+ -3 47 -17 -161.14 145.37 145.00 74.74 887.3 444.7 q2a4
+ -2 -26 28 43.09 226.22 235.00 173.71 290.1 9.5 q0a1
+ -2 -24 25 -168.96 408.37 537.00 210.16 271.1 54.4 q0a1
+ -2 -22 22 -0.12 564.20 545.00 248.12 252.6 98.3 q0a1
+ -2 -6 4 174.60 152.70 255.00 82.60 126.1 357.9 q0a2
+ -2 6 -5 298.00 177.79 200.00 77.00 797.0 293.3 q2a2
+ -2 20 -12 243.84 219.62 268.00 168.96 899.5 121.3 q2a0
+ -2 26 -14 -122.15 663.46 534.00 259.35 945.2 34.7 q2a0
+ -1 -25 27 667.73 267.42 310.00 176.47 253.2 16.0 q0a1
+ -1 -23 24 -1251.17 438.00 512.00 235.57 234.7 60.6 q0a1
+ -1 5 -4 1320.60 216.85 503.00 81.60 815.6 322.7 q2a2
+ -1 21 -12 -561.88 329.36 409.00 180.88 933.5 122.4 q2a0
+ -1 39 -16 -214.00 126.61 198.00 100.00 1049.7 462.9 q2a5
+ 0 -38 54 -152.31 124.02 140.00 70.31 18.8 384.4 q0a4
+ 0 -36 49 -44.55 103.91 106.00 69.95 98.7 414.1 q0a4
+ 0 -32 40 -38.96 138.49 199.00 95.10 232.6 466.3 q0a5
+ 0 -14 13 -56.16 121.04 154.00 87.23 136.0 192.7 q0a2
+ 0 -6 5 727.88 142.88 629.00 82.12 74.5 327.0 q0a2
+ 0 34 -15 -1004.79 590.96 479.00 170.59 1142.6 479.8 q2a5
+ 1 -33 43 119.96 254.46 294.00 77.84 182.3 482.0 q0a4
+ 1 -31 39 -20.98 183.31 267.00 99.78 240.0 505.1 q0a5
+ 1 -3 3 1618.50 1205.44 2219.00 556.50 26.5 358.3 q0a2
+ 1 5 -3 1300.86 224.49 1009.00 95.74 867.1 353.6 q2a2
+ 1 27 -13 5733.76 382.66 2319.00 220.64 1031.0 67.8 q2a1
+ 1 31 -14 -373.45 250.21 283.00 193.05 1064.0 9.6 q2a1
+ 1 51 -15 -47.90 126.04 278.00 62.10 1109.0 995.9 q2a11
+ 2 -36 51 -188.06 119.71 125.00 71.06 50.1 471.3 q0a4
+ 2 -30 38 47.64 131.12 156.00 94.76 247.4 543.5 q0a5
+ 2 -20 22 -839.97 690.41 609.00 262.77 131.9 70.5 q0a0
+ 2 6 -3 1419.61 206.56 874.00 81.99 900.2 355.2 q2a2
+ 3 -35 50 -313.59 152.67 184.00 74.79 59.0 512.2 q0a4
+ 3 -11 12 737.10 156.89 664.00 77.10 35.1 193.4 q0a2
+ 3 7 -3 -480.57 280.61 277.00 82.17 933.4 356.8 q2a2
+ 3 41 -14 38.06 200.02 186.00 86.94 1154.4 823.4 q2a9
+ 4 -26 33 -71.68 202.21 303.00 124.08 310.4 609.3 q0a7
+ 4 -18 21 7.19 229.88 345.00 204.81 62.7 74.3 q0a0
+ 4 -4 6 9164.74 360.69 5660.00 79.86 1321.4 342.6 q3a2
+ 4 10 -4 1235.45 223.88 741.00 99.95 978.8 330.6 q2a3
+ 4 18 -8 688.61 198.36 244.00 106.99 1040.3 217.0 q2a3
+ 4 52 -13 -63.97 105.47 124.00 59.77 1004.8 957.5 q2a11
+ 4 58 -12 -165.84 134.35 97.00 50.04 930.8 1066.4 q2a10
+ 5 -33 48 225.90 144.15 122.00 63.90 77.4 565.8 q0a6
+ 5 -27 36 128.62 135.17 252.00 110.38 259.9 626.9 q0a7
+ 5 -3 6 3072.98 257.48 1852.00 82.22 1323.3 309.3 q3a2
+ 5 35 -12 160.56 282.18 310.00 153.44 790.1 1443.8 q2a14
+ 5 59 -11 -2.65 64.65 85.00 49.85 883.4 1066.0 q2a10
+ 6 -30 43 -289.15 172.23 196.00 86.59 149.9 625.5 q0a6
+ 6 -22 29 430.66 491.35 423.00 171.54 361.0 698.1 q0a7
+ 6 2 3 678.62 133.87 659.00 81.38 1264.5 246.3 q3a2
+ 6 34 -11 -534.45 254.04 241.00 158.05 822.5 1424.5 q2a14
+ 6 60 -10 39.18 84.92 102.00 49.42 835.0 1065.5 q2a10
+ 7 -31 47 151.94 98.78 129.00 72.06 83.0 642.9 q0a6
+ 7 -23 32 -563.49 318.95 303.00 142.89 311.9 716.6 q0a7
+ 7 13 -3 565.89 217.79 380.00 118.51 1081.1 340.3 q2a3
+ 7 15 -4 -222.36 326.90 348.00 138.76 1096.9 311.9 q2a3
+ 7 17 -5 961.06 438.87 390.00 170.94 1112.7 283.3 q2a3
+ 7 33 -10 -41.33 211.72 265.00 152.93 854.8 1405.3 q2a14
+ 7 43 -11 74.91 104.40 122.00 76.29 1015.2 782.0 q2a9
+ 7 45 -11 -111.60 134.72 180.00 78.40 992.9 813.2 q2a9
+ 8 -32 51 76.00 125.53 138.00 72.00 13.2 661.1 q0a6
+ 8 -10 16 942.59 482.91 471.00 172.21 1496.8 282.6 q3a3
+ 8 -8 14 -356.24 295.90 327.00 132.64 1462.2 267.7 q3a3
+ 8 -6 12 433.25 162.05 199.00 107.75 1427.8 252.8 q3a3
+ 8 -4 10 -19.30 149.48 207.00 108.70 1393.7 238.1 q3a3
+ 8 2 5 74.14 150.58 223.00 91.26 1301.7 193.6 q3a2
+ 8 42 -10 38.48 111.01 121.00 75.95 995.5 747.8 q2a9
+ 8 46 -10 240.93 160.09 180.00 71.67 953.0 810.0 q2a8
+ 8 56 -9 26.96 95.55 84.00 51.84 824.2 951.3 q2a10
+ 9 -23 35 40.78 335.88 368.00 112.03 1539.1 1273.5 q3a13
+ 9 -17 26 -183.21 430.03 464.00 202.41 1491.9 1386.4 q3a15
+ 9 5 4 1078.14 198.71 851.00 150.26 1275.4 172.8 q3a0
+ 9 15 -2 -364.56 728.89 483.00 259.56 1151.2 348.6 q2a3
+ 9 25 -6 -1440.04 699.60 648.00 232.84 1002.7 1420.7 q2a15
+ 9 33 -8 329.29 229.56 259.00 141.91 891.6 1346.7 q2a14
+ 9 45 -9 -194.88 161.68 149.00 75.88 933.0 775.1 q2a8
+ 9 47 -9 -247.21 127.20 121.00 75.41 909.2 806.8 q2a8
+ 10 -22 35 189.45 313.23 349.00 107.95 1503.0 1270.7 q3a13
+ 10 -16 26 -24.53 256.04 390.00 183.58 1456.8 1383.9 q3a15
+ 10 -12 21 1831.23 429.48 516.00 219.97 1426.9 1464.5 q3a15
+ 10 4 6 -80.42 214.07 296.00 161.82 1311.0 152.9 q3a0
+ 10 10 2 246.66 224.38 253.00 167.54 1221.0 107.3 q3a0
+ 10 20 -3 749.54 643.50 588.00 272.66 1092.7 1435.3 q2a15
+ 10 34 -7 -264.50 213.31 248.00 139.50 896.4 1306.6 q2a14
+ 11 -3 13 -139.35 257.49 374.00 206.72 1440.8 177.2 q3a1
+ 11 3 8 1882.56 392.95 1179.00 185.44 1347.0 132.8 q3a0
+ 11 23 -3 -93.35 321.57 472.00 203.15 1069.5 1380.6 q2a15
+ 12 -22 39 -305.64 120.04 138.00 84.24 1445.2 1205.1 q3a13
+ 12 0 12 -577.12 439.06 501.00 243.12 1415.0 126.8 q3a1
+ 12 8 6 612.06 667.41 572.00 278.94 1292.7 66.2 q3a0
+ 12 24 -2 22.41 272.88 361.00 195.79 1075.8 1341.8 q2a15
+ 13 -23 43 119.31 121.00 119.00 72.69 1422.7 1139.7 q3a13
+ 13 -19 36 276.23 151.41 249.00 86.97 1393.0 1251.9 q3a13
+ 13 3 11 513.78 578.22 591.00 261.02 1389.1 75.9 q3a1
+ 13 7 8 331.89 725.37 577.00 305.51 1329.0 45.4 q3a0
+ 13 25 -1 -654.58 223.92 250.00 176.11 1082.1 1302.4 q2a15
+ 13 41 -4 518.18 128.41 148.00 82.42 852.6 1162.2 q2a12
+ 13 43 -4 52.88 132.81 137.00 81.12 822.5 1137.6 q2a12
+ 14 -12 28 666.89 235.58 278.00 151.51 1315.5 1355.4 q3a14
+ 14 -4 19 -277.73 361.90 376.00 206.71 1533.0 98.1 q3a1
+ 14 -2 17 9.77 322.88 452.00 214.03 1497.1 83.7 q3a1
+ 14 8 9 -525.68 593.22 541.00 247.18 1337.4 7.9 q3a0
+ 14 30 -1 -252.34 210.00 292.00 106.54 1031.7 1249.7 q2a13
+ 14 36 -2 362.10 258.41 396.00 88.10 948.4 1185.4 q2a12
+ 15 -21 44 -358.39 157.84 138.00 77.99 1348.4 1121.6 q3a12
+ 15 -7 24 -182.36 329.85 379.00 153.76 1249.4 1426.9 q3a14
+ 15 1 16 92.74 228.94 289.00 189.86 1471.1 31.7 q3a1
+ 15 25 2 123.11 389.28 403.00 128.49 1125.4 1266.7 q2a13
+ 15 33 0 -103.31 123.34 133.00 90.31 1010.8 1184.7 q2a13
+ 16 -14 35 -85.14 135.46 148.00 80.96 1267.6 1271.7 q3a12
+ 16 -6 25 -3.24 240.53 267.00 143.64 1211.1 1415.5 q3a14
+ 17 -15 39 -18.80 87.78 102.00 73.87 1241.5 1207.7 q3a12
+ 17 -13 36 60.36 94.24 127.00 76.24 1228.0 1258.3 q3a12
+ 17 -5 26 266.94 203.87 247.00 138.06 1172.2 1403.9 q3a14
+ 17 7 15 894.74 349.67 374.00 154.86 1504.4 503.7 q3a5
+ 17 13 11 -109.33 223.84 282.00 137.93 1455.0 569.5 q3a7
+ 17 15 10 -23.79 224.79 238.00 140.59 1437.2 598.9 q3a7
+ 17 21 7 450.89 242.71 292.00 133.51 1382.9 688.4 q3a7
+ 18 -2 25 -269.66 286.27 312.00 106.46 1529.0 758.1 q3a9
+ 18 10 15 75.99 202.75 272.00 124.61 1446.5 522.7 q3a5
+ 19 13 15 420.88 182.16 255.00 113.12 1387.1 542.1 q3a5
+ 19 23 10 -203.60 184.07 198.00 105.40 1296.8 665.8 q3a6
+ 20 -12 43 -22.75 109.80 114.00 68.75 1225.9 760.0 q3a8
+ 20 -10 40 231.07 94.46 139.00 72.33 1279.0 772.8 q3a8
+ 20 -2 30 -35.10 101.94 136.00 84.90 1456.9 828.0 q3a9
+ 20 2 26 91.80 291.14 270.00 95.80 1534.3 858.0 q3a9
+ 20 26 11 160.54 152.78 156.00 93.66 1228.0 682.3 q3a6
+ 21 7 24 8.90 130.50 180.00 102.41 1365.7 377.8 q3a5
+ 21 11 21 126.80 292.16 304.00 97.80 1334.6 446.0 q3a4
+ 22 -4 38 409.73 236.01 255.00 73.47 1331.5 890.9 q3a8
+ 24 -4 45 -117.57 93.96 113.00 58.17 1222.9 953.2 q3a10
+ 24 10 30 -190.68 203.76 224.00 74.08 1526.8 1055.6 q3a11
+ 24 14 27 267.48 131.11 145.00 83.72 1183.8 384.9 q3a4
+ 25 1 42 -89.32 144.02 142.00 67.92 1294.0 1032.5 q3a10
+ 25 9 34 188.34 90.75 169.00 71.46 1461.9 1093.9 q3a11
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035156_1cc9b.h5
+Image serial number: 2
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9520.057821
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9520.057821
+average_camera_length = 0.152001 m
+num_peaks = 28
+peak_resolution = 3.552281 nm^-1 or 2.815093 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 9.50 11.93 2.34 603.02 q0a0
+ 418.59 56.92 2.09 2604.19 q1a0
+ 490.50 113.94 1.84 1316.88 q1a0
+1208.26 26.88 2.25 7844.92 q3a0
+1192.62 123.14 1.75 2324.69 q3a0
+1380.84 113.78 2.06 7408.49 q3a1
+1389.31 158.84 1.89 1467.94 q3a1
+ 84.50 193.87 1.28 1459.93 q0a2
+ 100.72 265.64 0.94 1676.91 q0a2
+ 181.21 268.50 1.18 2437.61 q0a2
+ 117.10 350.50 0.62 935.44 q0a2
+ 266.86 239.14 1.64 680.03 q0a3
+ 425.47 263.56 0.84 2923.59 q1a2
+ 547.00 325.94 0.86 1990.04 q1a2
+ 868.00 200.50 1.22 832.91 q2a2
+ 929.99 230.28 1.22 2089.18 q2a2
+ 877.90 236.50 1.05 1929.60 q2a2
+ 958.87 245.13 1.25 772.85 q2a2
+ 788.90 285.50 0.71 1858.96 q2a2
+ 821.05 328.50 0.47 2173.99 q2a2
+1022.50 212.98 1.62 1269.84 q2a3
+1089.88 243.50 1.82 1113.86 q2a3
+1184.50 234.81 1.00 1056.12 q3a2
+1257.90 260.50 0.93 996.65 q3a2
+1127.16 628.16 2.72 845.35 q2a7
+1479.50 596.10 2.93 288.25 q3a7
+1536.97 833.03 3.55 763.55 q3a9
+ 280.14 1456.45 2.29 228.34 q0a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.16101 12.19772 16.86916 nm, 89.88707 90.62211 90.26872 deg
+astar = +0.1192907 -0.0042517 -0.1100008 nm^-1
+bstar = +0.0507546 +0.0364578 +0.0530670 nm^-1
+cstar = +0.0172602 -0.0531382 +0.0198227 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00253 nm^-1
+predict_refine/final_residual = 8.960599e-07
+predict_refine/det_shift x = 0.003 y = -0.006 mm
+diffraction_resolution_limit = 2.10 nm^-1 or 4.77 A
+num_reflections = 242
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -13 -41 -18 30.92 83.29 83.00 47.55 807.9 612.0 q2a6
+ -13 -39 -22 45.43 99.45 96.00 48.46 818.1 672.2 q2a6
+ -13 -37 -26 -151.99 99.23 99.00 49.35 828.2 731.9 q2a6
+ -12 -46 -3 120.72 93.25 92.00 43.43 824.5 428.0 q2a4
+ -12 -36 -14 167.70 107.46 117.00 49.11 926.2 608.4 q2a6
+ -12 -34 -17 162.58 145.47 110.00 53.27 941.1 655.9 q2a6
+ -12 -32 -22 165.53 153.55 151.00 51.40 944.9 724.2 q2a6
+ -12 -30 -28 57.78 94.63 160.00 54.66 732.4 1183.8 q1a13
+ -12 -28 -45 -22.65 77.45 81.00 47.12 528.1 1120.3 q1a12
+ -12 -28 -44 -2.82 84.38 88.00 47.22 540.1 1126.1 q1a12
+ -12 -28 -43 40.41 87.07 97.00 48.15 552.0 1131.9 q1a12
+ -12 -28 -42 -59.04 102.33 100.00 46.12 563.8 1137.6 q1a12
+ -11 -51 7 -63.39 91.00 89.00 40.62 1087.9 1076.5 q2a11
+ -11 -49 6 182.23 96.79 88.00 36.08 1121.6 1047.2 q2a11
+ -11 -47 5 -181.91 109.03 77.00 39.04 1154.4 1018.7 q2a11
+ -11 -41 1 -53.97 111.30 139.00 48.90 943.6 432.4 q2a4
+ -11 -37 -3 -48.24 141.81 168.00 60.66 980.6 510.8 q2a5
+ -11 -33 -8 247.35 139.89 148.00 69.32 1014.7 568.5 q2a7
+ -11 -25 -59 96.59 92.43 84.00 40.64 398.5 763.9 q1a8
+ -11 -25 -27 99.80 185.66 197.00 63.37 710.4 1278.0 q1a13
+ -10 -40 7 -155.25 98.54 96.00 58.25 1002.9 377.2 q2a5
+ -10 -34 1 203.75 107.79 160.00 64.74 1060.0 494.2 q2a5
+ -10 -28 -7 -0.38 204.27 214.00 91.03 1105.3 596.2 q2a7
+ -10 -26 -11 -63.21 247.82 309.00 94.13 1113.5 651.6 q2a7
+ -10 -22 -65 45.66 74.51 77.00 42.54 426.4 862.1 q1a8
+ -10 -20 -56 65.59 78.04 94.00 44.21 512.7 752.1 q1a8
+ -10 -20 -31 -316.43 136.29 136.00 90.48 635.9 1316.4 q1a15
+ -10 -20 -30 448.90 174.17 163.00 84.47 646.8 1321.2 q1a15
+ -9 -55 19 -11.26 63.93 63.00 32.86 897.0 1047.7 q2a10
+ -9 -29 2 161.96 355.40 299.00 92.12 1149.2 524.8 q2a5
+ -9 -21 -74 -145.60 87.58 83.00 33.40 400.8 973.7 q1a10
+ -9 -19 -18 361.80 319.03 369.00 136.80 765.9 1405.5 q1a15
+ -9 -17 -61 255.60 120.64 99.00 47.60 546.5 834.1 q1a8
+ -9 -17 -26 -193.29 252.25 311.00 113.35 670.5 1395.5 q1a15
+ -8 -56 24 194.15 95.64 102.00 33.65 820.1 1020.7 q2a10
+ -8 -40 18 109.15 79.96 101.00 52.41 1081.3 821.4 q2a9
+ -8 -36 15 210.37 174.55 165.00 66.38 1152.8 779.4 q2a9
+ -8 -28 7 -304.60 215.00 208.00 119.93 1060.7 7.6 q2a1
+ -8 -22 -2 853.59 326.30 517.00 157.29 927.8 44.7 q2a0
+ -8 -18 -76 50.79 60.52 52.00 32.41 455.7 1020.5 q1a10
+ -8 -18 -10 296.51 231.19 264.00 131.81 820.4 60.3 q2a0
+ -8 -16 -16 268.24 607.92 463.00 168.48 766.9 1468.1 q1a15
+ -8 -14 -63 -36.15 95.36 89.00 47.62 594.3 877.9 q1a9
+ -8 -14 -23 19.31 474.99 463.00 143.85 683.1 1463.0 q1a15
+ -8 -12 -48 -153.16 145.08 167.00 79.84 400.1 1376.4 q1a14
+ -8 -12 -38 -129.66 356.74 338.00 116.20 514.5 1422.6 q1a14
+ -8 -12 -37 -46.96 243.26 226.00 103.77 525.5 1427.1 q1a14
+ -8 -12 -36 -859.90 279.08 269.00 118.39 536.6 1431.5 q1a14
+ -7 -47 26 242.66 106.14 85.00 46.54 913.6 869.0 q2a8
+ -7 -39 22 67.96 106.27 101.00 57.78 1046.4 771.0 q2a9
+ -7 -25 9 226.74 206.64 326.00 141.78 1058.1 70.9 q2a1
+ -7 -17 -4 -49.22 131.67 164.00 108.13 873.7 113.9 q2a0
+ -7 -15 -9 25.20 173.57 206.00 99.55 811.0 117.4 q2a0
+ -7 -11 -64 -16.94 63.34 84.00 48.94 650.1 908.5 q1a9
+ -7 -11 -22 -64.56 331.32 434.00 123.97 747.7 267.4 q1a3
+ -7 -9 -51 -266.60 208.88 267.00 61.40 742.6 752.8 q1a9
+ -6 -50 31 -13.12 101.07 95.00 47.12 812.7 873.0 q2a8
+ -6 -44 29 30.64 197.14 274.00 49.76 913.3 791.3 q2a8
+ -6 -42 28 -242.07 139.36 118.00 52.67 948.0 767.2 q2a8
+ -6 -34 23 238.51 142.73 158.00 87.68 806.1 1372.9 q2a14
+ -6 -24 13 -676.48 460.18 396.00 177.44 1091.7 117.0 q2a1
+ -6 -10 -72 149.53 87.00 77.00 40.27 639.5 1001.6 q1a11
+ -6 -10 -14 1150.00 159.98 817.00 66.00 686.7 341.5 q1a3
+ -6 -8 -22 212.11 154.09 203.00 80.57 695.4 248.9 q1a3
+ -6 -6 -39 501.10 219.57 238.00 130.14 739.7 84.5 q1a1
+ -6 -6 -38 542.38 275.77 309.00 133.97 735.6 95.6 q1a1
+ -6 -6 -37 1234.12 168.17 387.00 127.41 731.5 106.7 q1a1
+ -5 -45 33 -30.21 87.26 78.00 46.82 850.9 768.4 q2a8
+ -5 -29 23 207.29 209.24 218.00 107.32 887.2 1417.7 q2a14
+ -5 -27 21 -15.13 244.75 392.00 121.33 903.1 1456.0 q2a14
+ -5 -9 -78 71.53 74.30 72.00 40.27 639.0 1101.3 q1a11
+ -5 -7 -15 -92.47 111.56 119.00 62.24 639.1 312.9 q1a3
+ -5 -5 -24 340.87 156.72 144.00 66.31 651.2 210.1 q1a3
+ -4 -30 28 -272.82 247.55 261.00 110.42 914.4 1353.8 q2a14
+ -4 -18 15 635.64 164.10 149.00 76.27 1068.0 202.6 q2a3
+ -4 -16 12 1367.26 153.68 650.00 65.40 1023.5 213.0 q2a3
+ -4 -12 5 1952.51 211.80 772.00 51.97 929.9 230.0 q2a2
+ -4 -10 1 1932.27 174.58 1127.00 53.55 877.6 236.5 q2a2
+ -4 -8 -4 119.69 103.18 113.00 49.72 816.0 239.4 q2a2
+ -4 -2 -60 -89.37 83.41 97.00 59.29 614.8 409.9 q1a5
+ -3 -35 35 352.90 121.96 264.00 60.90 900.8 1251.4 q2a12
+ -3 -17 18 586.30 347.30 502.00 96.10 1091.4 243.8 q2a3
+ -3 -15 15 78.18 105.72 118.00 68.69 1046.9 254.0 q2a3
+ -3 -13 12 365.27 124.62 125.00 65.24 1002.8 264.0 q2a3
+ -3 -5 -5 1891.73 184.07 919.00 49.99 787.3 286.1 q2a2
+ -3 -3 -11 1738.12 249.50 662.00 50.51 547.5 327.5 q1a2
+ -3 -1 -19 523.08 173.46 279.00 45.59 555.1 236.0 q1a2
+ -3 1 -55 -122.48 116.45 119.00 68.52 659.7 488.1 q1a5
+ -3 1 -54 -413.25 178.81 192.00 75.74 671.9 492.3 q1a5
+ -2 -40 41 59.36 96.37 96.00 56.24 881.8 1120.9 q2a12
+ -2 -38 40 -70.57 107.13 103.00 58.17 903.7 1156.7 q2a12
+ -2 -14 18 158.88 146.87 139.00 78.64 1070.2 294.8 q2a3
+ -2 -12 15 230.95 126.73 164.00 65.16 1026.0 304.7 q2a3
+ -2 -8 8 365.93 150.03 136.00 52.25 933.1 320.6 q2a2
+ -2 -4 -1 2119.11 220.86 1078.00 62.94 819.9 329.6 q2a2
+ -2 2 -63 -149.13 160.75 163.00 61.51 550.3 486.1 q1a4
+ -1 -33 40 129.29 157.34 155.00 63.91 983.3 1209.0 q2a13
+ -1 -25 34 370.23 176.84 193.00 105.97 1052.2 1328.5 q2a15
+ -1 -19 28 -317.63 504.78 521.00 195.65 1094.5 1444.0 q2a15
+ -1 3 -69 48.09 76.91 77.00 51.32 457.8 492.9 q1a4
+ -1 3 -17 219.66 106.62 77.00 41.35 468.0 231.1 q1a2
+ -1 5 -30 1021.13 180.32 549.00 112.69 490.8 114.5 q1a0
+ 0 -30 41 235.99 123.91 124.00 63.61 1043.5 1225.9 q2a13
+ 0 -16 28 -292.24 611.37 546.00 207.47 1146.1 1466.4 q2a15
+ 0 -2 5 8242.71 1054.79 5023.00 288.99 1191.0 354.8 q3a2
+ 0 2 -6 776.25 489.61 842.00 115.04 421.1 345.2 q1a2
+ 0 4 -13 2982.53 203.45 2228.00 42.56 424.6 264.3 q1a2
+ 1 -29 43 228.93 106.49 148.00 64.67 1084.2 1209.2 q2a13
+ 1 -25 40 -178.32 282.82 235.00 83.92 1116.8 1283.7 q2a13
+ 1 -11 25 2018.23 290.74 891.00 113.08 1191.4 124.5 q3a0
+ 1 -9 22 -40.46 117.88 155.00 99.72 1200.8 169.1 q3a0
+ 1 9 -54 309.56 111.29 146.00 77.56 616.4 638.9 q1a7
+ 1 9 -53 -94.25 120.41 154.00 86.74 628.7 642.5 q1a7
+ 1 9 -33 2673.40 326.74 795.00 146.40 418.2 56.4 q1a0
+ 2 -28 45 444.82 147.06 142.00 58.58 1125.0 1192.4 q2a13
+ 2 -24 42 -560.09 480.28 387.00 100.43 1156.9 1267.5 q2a13
+ 2 -14 32 7720.91 388.69 1672.00 157.29 1207.3 27.3 q3a0
+ 2 -10 27 407.74 176.09 233.00 114.03 1229.2 109.8 q3a0
+ 2 -8 24 -81.73 115.41 151.00 106.12 1238.4 154.6 q3a0
+ 2 10 -61 75.71 115.02 130.00 66.37 518.7 647.0 q1a6
+ 3 -29 48 -94.15 135.66 136.00 61.35 1148.2 1140.9 q2a13
+ 3 -21 42 -358.46 198.42 245.00 93.66 1436.4 709.1 q3a7
+ 3 -19 40 1.69 306.86 353.00 111.31 1476.6 696.1 q3a7
+ 3 5 2 127.01 125.51 180.00 57.63 41.4 303.3 q0a2
+ 3 7 -4 19.78 108.46 169.00 59.51 112.3 303.5 q0a2
+ 3 11 -65 -218.27 99.03 104.00 62.60 452.8 666.7 q1a6
+ 3 11 -22 -88.37 265.63 277.00 88.70 314.3 321.1 q0a3
+ 4 -2 21 546.67 174.14 204.00 66.80 1328.9 194.9 q3a2
+ 4 4 9 181.90 238.07 231.00 47.86 1345.2 352.5 q3a2
+ 4 8 -2 1739.25 163.36 1116.00 54.75 99.1 266.1 q0a2
+ 4 10 -9 2273.66 227.03 1175.00 56.35 180.4 269.0 q0a2
+ 4 12 -18 -0.40 96.56 111.00 72.48 280.2 277.4 q0a3
+ 4 14 -52 -345.49 214.71 161.00 75.17 380.9 1232.2 q0a13
+ 4 14 -51 -195.22 209.07 207.00 76.07 377.6 1244.6 q0a13
+ 4 14 -50 -427.49 253.18 277.00 81.48 374.4 1257.0 q0a13
+ 4 14 -36 1072.90 321.71 622.00 147.19 331.5 1395.2 q0a15
+ 4 14 -35 -1171.00 595.29 428.00 188.29 328.5 1406.5 q0a15
+ 5 -19 45 -175.34 132.93 145.00 89.54 1413.1 631.8 q3a7
+ 5 -17 43 -193.88 159.70 191.00 91.88 1453.8 619.5 q3a7
+ 5 -15 41 -46.94 288.90 304.00 109.24 1493.8 607.3 q3a7
+ 5 -13 39 -409.61 402.41 348.00 128.01 1533.1 595.4 q3a7
+ 5 11 -7 623.61 158.58 212.00 58.09 167.2 231.3 q0a2
+ 5 13 -16 548.88 154.55 465.00 74.10 267.2 239.4 q0a3
+ 5 15 -57 -122.97 156.51 173.00 65.82 362.2 1156.8 q0a13
+ 5 15 -30 1658.29 378.34 700.00 152.01 280.9 1453.2 q0a15
+ 5 15 -29 50.20 439.27 477.00 169.71 278.1 1464.3 q0a15
+ 6 -28 54 80.30 116.97 116.00 62.30 1208.4 665.1 q3a6
+ 6 -4 30 7942.09 390.68 2003.00 151.61 1382.3 113.9 q3a1
+ 6 -2 27 1313.78 212.19 733.00 129.37 1390.6 159.1 q3a1
+ 6 2 20 -108.51 120.76 128.00 71.83 1404.4 229.1 q3a3
+ 6 4 16 -6.84 112.65 123.00 70.16 1409.6 282.1 q3a3
+ 6 10 1 1279.16 156.95 843.00 54.73 82.2 193.4 q0a2
+ 6 14 -14 335.76 139.99 190.00 70.21 254.0 201.2 q0a3
+ 7 -25 54 131.64 101.80 103.00 57.76 1236.2 609.0 q3a6
+ 7 -21 51 243.11 130.58 150.00 64.49 1316.0 580.5 q3a6
+ 7 -5 34 -8.88 225.61 268.00 144.88 1410.2 62.1 q3a1
+ 7 -3 31 -103.42 340.18 353.00 157.89 1418.4 108.1 q3a1
+ 7 -1 28 468.91 223.47 266.00 137.25 1426.5 153.5 q3a1
+ 7 3 21 -62.15 142.14 136.00 76.55 1440.1 224.4 q3a3
+ 8 -24 55 -61.74 121.65 113.00 62.14 1227.4 569.2 q3a6
+ 8 -4 35 107.27 202.09 292.00 136.53 1446.9 56.0 q3a1
+ 8 -2 32 -220.09 380.95 392.00 163.43 1454.9 102.3 q3a1
+ 8 0 29 649.45 380.48 466.00 171.34 1462.8 147.9 q3a1
+ 8 4 22 463.95 265.77 489.00 97.37 1476.1 219.5 q3a3
+ 8 6 18 356.75 197.52 224.00 89.41 1481.1 273.0 q3a3
+ 8 14 -3 -256.30 222.45 226.00 113.76 146.7 150.3 q0a0
+ 8 16 -11 171.83 187.15 323.00 138.39 237.3 154.5 q0a1
+ 8 18 -22 410.85 367.72 493.00 156.62 364.8 165.9 q0a1
+ 9 -19 53 -424.48 189.26 221.00 72.28 1299.2 529.2 q3a4
+ 9 -1 33 -515.77 290.29 465.00 150.97 1491.7 96.3 q3a1
+ 9 7 19 1339.80 404.32 397.00 134.88 1517.4 268.4 q3a3
+ 9 13 4 250.06 145.11 244.00 111.53 70.4 114.7 q0a0
+ 9 17 -10 551.46 283.24 285.00 158.62 234.2 118.0 q0a1
+ 9 19 -21 -688.25 471.38 428.00 159.25 362.4 128.9 q0a1
+ 10 -22 57 -177.80 117.11 121.00 61.20 1209.1 515.0 q3a4
+ 10 -18 54 -148.31 162.70 218.00 65.31 1291.0 489.3 q3a4
+ 10 -8 44 -190.15 202.75 233.00 87.35 1499.5 436.4 q3a5
+ 10 20 -20 -206.24 307.13 343.00 138.52 359.9 91.6 q0a1
+ 11 -21 58 15.34 104.47 101.00 59.46 1200.2 473.8 q3a4
+ 11 -15 53 -82.48 172.37 159.00 64.28 1327.1 438.3 q3a4
+ 11 -9 47 -99.20 119.31 143.00 71.80 1451.8 407.5 q3a5
+ 11 3 31 416.05 241.04 460.00 122.47 1299.6 1471.9 q3a14
+ 11 7 24 -280.87 386.94 442.00 146.49 1397.5 1460.0 q3a15
+ 11 9 20 -134.93 624.36 537.00 164.73 1452.0 1455.2 q3a15
+ 11 15 5 -415.94 272.23 306.00 150.20 72.6 43.3 q0a0
+ 11 21 -20 -370.36 172.37 257.00 122.23 368.5 56.0 q0a1
+ 12 -18 57 -177.32 107.16 95.00 56.92 1237.7 421.4 q3a4
+ 12 6 28 -171.28 379.64 359.00 128.92 1349.7 1429.2 q3a14
+ 12 20 -9 -370.13 172.58 170.00 124.68 246.2 10.3 q0a1
+ 12 22 -20 -74.30 183.48 217.00 118.41 377.3 19.8 q0a1
+ 13 -7 48 -562.14 170.98 150.00 61.74 1543.0 853.1 q3a9
+ 13 1 38 -61.31 127.28 198.00 91.31 1202.6 1411.4 q3a14
+ 13 3 35 507.59 146.01 195.00 87.21 1250.4 1404.5 q3a14
+ 13 13 16 489.07 254.68 338.00 117.73 1516.8 1379.3 q3a15
+ 14 4 35 -98.24 129.09 152.00 87.47 1253.8 1367.5 q3a14
+ 14 18 5 -252.03 357.04 389.00 99.08 352.3 648.5 q0a7
+ 14 20 -2 -220.23 176.65 199.00 89.70 353.7 562.3 q0a7
+ 14 22 -10 436.60 188.03 286.00 77.31 356.8 492.7 q0a5
+ 15 -11 55 114.20 75.56 92.00 51.20 1491.6 962.9 q3a11
+ 15 -7 51 -154.47 99.18 133.00 60.27 1472.8 901.7 q3a9
+ 15 23 -11 -221.55 155.65 175.00 72.64 321.3 473.0 q0a5
+ 15 25 -23 161.76 169.01 188.00 63.21 373.9 802.9 q0a9
+ 16 -14 59 4.21 89.87 126.00 50.59 1469.8 1055.4 q3a11
+ 16 0 44 -36.75 89.48 94.00 54.75 1409.8 763.4 q3a9
+ 16 18 10 13.34 153.81 209.00 83.61 280.1 701.0 q0a7
+ 16 20 4 -202.66 151.71 172.00 78.01 279.4 624.3 q0a7
+ 16 24 -12 -225.45 104.87 126.00 65.93 285.0 452.9 q0a5
+ 16 26 -25 19.50 141.25 152.00 57.79 339.8 837.9 q0a9
+ 17 -3 49 -120.49 119.40 110.00 54.89 1384.5 855.1 q3a9
+ 17 7 35 29.49 89.23 131.00 54.11 1264.2 1280.5 q3a12
+ 17 13 24 76.70 115.66 125.00 59.19 1425.3 1265.8 q3a13
+ 17 21 3 -26.58 103.07 125.00 70.05 242.6 606.4 q0a7
+ 17 27 -28 -41.26 92.06 99.00 54.84 292.2 872.2 q0a9
+ 18 -2 49 2.40 125.98 98.00 45.40 1346.7 853.3 q3a8
+ 18 6 38 -107.41 93.90 90.00 53.21 1218.0 1246.9 q3a12
+ 18 16 19 133.33 125.28 188.00 60.54 1497.9 1224.1 q3a13
+ 18 22 2 -37.27 90.19 119.00 65.17 205.1 588.2 q0a7
+ 18 28 -33 -94.45 131.50 125.00 55.23 217.2 904.1 q0a9
+ 18 28 -32 24.00 91.58 112.00 53.71 230.2 905.9 q0a9
+ 19 13 27 215.93 115.67 168.00 55.67 1386.8 1192.5 q3a13
+ 19 17 18 -131.08 117.88 100.00 55.08 1513.9 1185.8 q3a13
+ 19 19 13 -104.99 192.77 190.00 60.45 171.6 728.1 q0a6
+ 19 25 -7 -328.39 179.95 160.00 56.95 171.6 494.1 q0a4
+ 20 -2 51 226.76 84.58 90.00 47.64 1270.2 894.3 q3a8
+ 20 2 46 58.21 83.27 79.00 48.59 1257.6 795.9 q3a8
+ 20 8 37 48.41 93.25 109.00 45.79 1234.5 1166.8 q3a12
+ 20 12 30 197.38 113.57 143.00 49.01 1345.2 1157.2 q3a12
+ 20 16 22 81.76 72.09 83.00 49.03 1460.9 1149.3 q3a13
+ 20 20 12 50.57 112.46 172.00 54.70 132.5 710.9 q0a6
+ 20 22 6 -162.78 119.53 141.00 54.93 131.5 630.8 q0a6
+ 20 26 -9 156.01 92.44 88.00 47.96 133.6 461.7 q0a4
+ 20 28 -21 -200.46 103.67 91.00 42.72 355.4 969.3 q0a11
+ 21 11 33 -175.69 90.28 88.00 50.69 1299.1 1120.9 q3a12
+ 21 29 -25 -40.45 73.00 74.00 39.23 293.4 1006.5 q0a11
+ 22 -8 59 119.80 88.24 80.00 40.80 1210.3 1056.6 q3a10
+ 22 -6 57 -101.20 74.55 79.00 39.80 1203.3 1006.9 q3a10
+ 22 -4 55 -185.96 91.69 73.00 42.16 1196.4 958.2 q3a10
+ 22 4 45 315.54 98.83 89.00 43.66 1172.8 781.1 q3a8
+ 22 24 3 -113.18 102.33 81.00 49.53 51.6 581.8 q0a6
+ 22 26 -5 19.83 88.81 93.00 48.17 52.5 502.0 q0a4
+ 22 30 -31 -46.82 106.21 100.00 36.79 201.5 1042.7 q0a11
+ 23 29 -18 -28.82 113.93 108.00 38.28 370.0 1094.9 q0a11
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035217_1eb28.h5
+Image serial number: 3
+hit = 1
+indexed_by = none
+photon_energy_eV = 9510.493771
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9510.493771
+average_camera_length = 0.152001 m
+num_peaks = 16
+peak_resolution = 4.471160 nm^-1 or 2.236556 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 182.50 23.90 2.41 287.81 q0a0
+ 43.50 77.91 2.01 1846.91 q0a0
+ 13.88 112.78 1.83 3693.14 q0a0
+ 253.50 35.16 2.51 383.39 q0a1
+ 932.50 12.91 2.39 1758.50 q2a0
+1183.33 65.20 2.05 7249.26 q3a0
+ 100.70 273.05 0.90 15609.16 q0a2
+ 274.26 273.50 1.57 1300.06 q0a3
+ 203.30 339.50 1.07 1080.39 q0a3
+ 491.19 329.89 0.62 3174.74 q1a2
+ 571.18 330.50 0.95 3997.45 q1a2
+ 751.96 271.83 1.97 1606.36 q1a3
+1093.12 270.50 1.76 1736.10 q2a3
+1540.42 248.61 2.09 1591.91 q3a3
+1482.50 1047.08 4.47 174.03 q3a11
+1411.50 1442.46 2.41 2238.30 q3a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035224_1f48e.h5
+Image serial number: 5
+hit = 1
+indexed_by = none
+photon_energy_eV = 9501.940564
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9501.940564
+average_camera_length = 0.152001 m
+num_peaks = 16
+peak_resolution = 3.173814 nm^-1 or 3.150783 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 296.96 86.24 2.41 1253.02 q0a1
+ 767.22 74.02 2.69 1491.15 q1a1
+1063.14 80.86 2.38 1550.51 q2a1
+1194.27 13.93 2.31 1634.60 q3a0
+ 56.50 347.10 0.43 1052.46 q0a2
+ 279.14 195.73 1.83 5666.83 q0a3
+ 206.86 290.50 1.22 696.21 q0a3
+ 488.50 251.73 0.98 1940.94 q1a2
+ 521.50 312.82 0.80 1260.25 q1a2
+ 807.04 234.50 0.98 835.21 q2a2
+ 827.85 275.50 0.77 1024.61 q2a2
+1198.25 281.02 0.74 23033.25 q3a2
+1209.00 293.50 0.68 927.30 q3a2
+1236.50 334.11 0.51 818.43 q3a2
+ 638.34 665.23 3.17 457.93 q1a7
+ 256.05 1449.43 2.37 1393.75 q0a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035133_1ac22.h5
+Image serial number: 6
+hit = 1
+indexed_by = none
+photon_energy_eV = 9497.857114
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9497.857114
+average_camera_length = 0.152001 m
+num_peaks = 12
+peak_resolution = 4.102175 nm^-1 or 2.437731 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 157.04 62.96 2.18 284.90 q0a0
+ 77.68 79.75 2.01 1960.65 q0a0
+ 556.50 149.86 1.76 955.07 q1a0
+ 670.01 155.99 2.06 837.06 q1a1
+ 436.50 250.56 0.92 4284.92 q1a2
+1252.50 349.84 0.49 1055.98 q3a2
+1387.50 313.96 1.22 1797.20 q3a3
+1310.05 798.95 4.10 -317.24 q3a8
+ 344.86 1442.52 2.26 1954.58 q0a15
+ 355.71 1445.85 2.23 2294.20 q0a15
+ 365.90 1450.50 2.20 5426.83 q0a15
+1520.50 1403.21 2.43 1804.32 q3a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035129_1a6a3.h5
+Image serial number: 7
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9507.846671
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9507.846671
+average_camera_length = 0.152001 m
+num_peaks = 19
+peak_resolution = 2.508610 nm^-1 or 3.986271 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 147.93 10.07 2.43 467.28 q0a0
+ 203.12 34.97 2.40 5077.60 q0a1
+ 291.50 130.04 2.22 1116.10 q0a1
+1376.93 11.28 2.51 1673.15 q3a1
+1412.13 146.55 2.00 2870.31 q3a1
+ 206.86 320.50 1.13 935.44 q0a3
+ 302.23 357.50 1.54 1221.09 q0a3
+ 451.54 204.27 1.18 11844.61 q1a2
+ 564.01 236.78 1.26 2518.23 q1a2
+ 563.23 352.60 0.86 1909.43 q1a2
+ 816.17 331.45 0.45 4752.46 q2a2
+ 945.68 357.90 0.83 905.74 q2a2
+1067.66 326.50 1.52 1783.45 q2a3
+1232.37 198.07 1.21 1584.50 q3a2
+1224.55 252.08 0.92 8327.43 q3a2
+1254.12 306.50 0.69 1013.68 q3a2
+1372.13 203.32 1.52 4779.59 q3a3
+1495.09 319.39 1.74 1562.18 q3a3
+1386.28 357.17 1.12 13495.85 q3a3
+End of peak list
+--- Begin crystal
+Cell parameters 6.17927 12.20990 16.83813 nm, 90.43911 90.84531 90.74889 deg
+astar = -0.0812404 +0.1289888 +0.0544203 nm^-1
+bstar = +0.0403058 +0.0487117 -0.0520760 nm^-1
+cstar = -0.0421830 -0.0081572 -0.0410133 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00203 nm^-1
+predict_refine/final_residual = 4.336953e-07
+predict_refine/det_shift x = -0.002 y = 0.056 mm
+diffraction_resolution_limit = 2.23 nm^-1 or 4.49 A
+num_reflections = 232
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -31 7 -9 -99.45 79.41 87.00 47.05 1221.2 1074.3 q3a10
+ -31 9 -11 8.20 107.15 112.00 47.20 1180.2 1050.9 q3a10
+ -30 4 -7 -73.86 94.56 103.00 51.26 1301.4 1064.5 q3a10
+ -30 10 -13 87.25 92.60 99.00 46.75 1181.2 995.3 q3a10
+ -29 5 -9 165.69 97.23 100.00 51.31 1300.7 1010.1 q3a10
+ -29 9 -13 95.32 98.15 86.00 47.08 1221.9 964.4 q3a10
+ -28 6 -11 11.05 96.65 109.00 52.55 1300.0 957.2 q3a10
+ -28 8 -13 -93.45 89.89 78.00 49.05 1261.3 934.5 q3a10
+ -27 -1 -4 -157.39 85.19 104.00 59.99 1452.4 1000.8 q3a11
+ -26 -4 -1 -398.36 198.70 232.00 64.76 1529.1 999.6 q3a11
+ -26 0 -6 14.25 99.47 95.00 56.75 1449.7 949.7 q3a11
+ -25 -13 12 -44.79 132.03 142.00 70.59 1184.9 525.8 q3a4
+ -25 11 -18 36.03 94.72 101.00 59.77 1265.2 816.6 q3a8
+ -24 6 -14 129.69 109.91 115.00 64.31 1372.1 835.3 q3a9
+ -24 14 -21 75.57 142.41 112.00 54.83 1232.2 751.0 q3a8
+ -23 -17 18 116.40 147.17 186.00 80.40 1197.4 623.2 q3a6
+ -23 -15 14 -78.62 140.79 137.00 76.62 1232.1 571.9 q3a6
+ -23 -9 4 -275.09 185.27 163.00 80.29 1320.5 464.6 q3a4
+ -23 -7 1 43.50 143.56 136.00 75.50 1347.7 423.0 q3a4
+ -22 -10 5 -123.32 256.18 241.00 81.92 1341.8 500.7 q3a4
+ -22 -6 -1 127.48 108.74 138.00 83.72 1392.4 418.4 q3a5
+ -22 4 -13 47.94 102.61 110.00 68.06 1445.0 790.2 q3a9
+ -22 6 -15 -118.86 112.42 97.00 65.26 1409.7 768.6 q3a9
+ -22 14 -22 85.09 109.97 102.00 63.71 1189.4 1199.2 q3a12
+ -22 18 -25 170.11 119.44 127.00 59.49 1230.0 1129.5 q3a12
+ -21 -19 21 -191.36 132.21 148.00 83.76 1237.0 701.2 q3a6
+ -21 -15 13 -23.86 149.68 142.00 86.26 1304.0 599.5 q3a6
+ -21 -9 3 -305.23 195.66 238.00 91.03 1386.3 495.2 q3a5
+ -21 -7 0 -111.40 135.94 154.00 87.60 1412.7 454.4 q3a5
+ -21 19 -26 246.04 108.45 126.00 62.16 1271.4 1134.0 q3a12
+ -20 -10 4 -73.19 146.15 222.00 96.19 1406.5 530.2 q3a5
+ -20 -8 1 220.18 133.31 191.00 90.42 1432.6 489.8 q3a5
+ -20 12 -21 86.31 99.20 146.00 67.69 1230.9 1274.1 q3a12
+ -20 20 -27 -76.40 170.16 235.00 66.60 1312.2 1138.5 q3a12
+ -19 -19 20 -145.71 203.41 203.00 88.91 1308.5 725.8 q3a6
+ -19 -17 16 -199.69 219.37 272.00 95.69 1341.0 675.5 q3a6
+ -19 -3 -6 761.00 287.96 355.00 112.00 1524.3 411.5 q3a5
+ -19 5 -15 109.43 150.44 214.00 106.17 1189.0 1383.4 q3a14
+ -18 -20 22 171.22 189.42 228.00 84.24 1151.7 1177.0 q2a13
+ -18 -14 10 -99.57 147.30 170.00 109.17 1416.0 618.4 q3a7
+ -18 -4 -5 -278.60 404.56 361.00 136.40 1542.8 446.5 q3a5
+ -18 2 -12 174.11 223.01 283.00 123.49 1186.1 1453.4 q3a14
+ -18 8 -18 3.38 142.56 155.00 104.62 1249.2 1351.9 q3a14
+ -18 18 -26 14.99 158.63 141.00 69.63 1350.7 1214.9 q3a12
+ -17 -23 29 -109.77 121.35 123.00 77.97 1049.1 1154.2 q2a13
+ -17 -21 24 -149.85 215.36 198.00 87.41 1110.4 1192.6 q2a13
+ -17 -11 5 290.75 159.59 199.00 120.25 1486.3 571.0 q3a7
+ -17 -7 -1 -390.95 535.06 430.00 143.55 1535.9 520.1 q3a5
+ -17 9 -19 37.41 197.40 226.00 116.79 1287.9 1354.7 q3a14
+ -17 15 -24 -167.43 287.15 260.00 83.83 1348.9 1284.3 q3a12
+ -16 0 -10 -825.92 283.91 294.00 170.32 1519.8 62.1 q3a1
+ -16 10 -20 -132.73 210.62 229.00 128.53 1326.0 1357.4 q3a14
+ -16 24 -30 -148.41 106.73 147.00 69.21 1464.9 1160.0 q3a13
+ -15 -23 29 -135.16 127.62 174.00 81.96 1019.1 1217.8 q2a13
+ -15 -21 24 193.87 181.46 228.00 92.92 1079.9 1254.7 q2a13
+ -15 -11 5 -1280.85 567.50 451.00 183.65 1543.8 604.2 q3a7
+ -15 -7 -1 1880.16 285.58 919.00 168.04 1375.6 11.2 q3a1
+ -15 1 -11 -242.84 407.15 408.00 179.04 1518.3 99.9 q3a1
+ -15 9 -19 435.36 372.61 335.00 140.24 1342.5 1393.5 q3a14
+ -14 -14 10 392.31 438.49 396.00 170.69 1533.2 683.4 q3a7
+ -14 -4 -5 578.01 392.28 477.00 196.39 1413.8 72.8 q3a1
+ -14 2 -12 -424.98 516.75 472.00 211.78 1516.8 137.2 q3a1
+ -14 26 -31 314.79 159.08 138.00 64.41 1539.5 1172.6 q3a13
+ -14 30 -33 -36.14 89.67 134.00 65.74 96.8 728.4 q0a6
+ -13 -25 35 98.90 160.54 177.00 79.41 920.8 1237.6 q2a12
+ -13 -19 20 -491.21 232.01 344.00 160.41 1100.2 1317.4 q2a15
+ -13 -3 -6 510.34 388.71 454.00 198.46 1412.9 109.9 q3a1
+ -13 3 -13 974.77 568.87 491.00 216.03 1515.3 174.0 q3a1
+ -13 7 -17 522.49 350.57 415.00 176.11 1371.6 1463.8 q3a15
+ -12 -10 4 656.61 409.78 450.00 198.99 1268.1 56.1 q3a0
+ -12 -8 1 399.70 592.42 482.00 212.70 1306.8 79.7 q3a0
+ -12 -2 -7 2870.31 351.28 1416.00 169.69 1412.1 146.6 q3a1
+ -11 -29 50 56.50 91.31 113.00 64.50 882.5 781.4 q2a8
+ -11 -11 6 -299.09 363.35 519.00 183.29 1229.4 69.6 q3a0
+ -11 11 -20 1730.33 583.56 588.00 201.07 1462.5 1441.2 q3a15
+ -10 -32 68 149.80 84.61 88.00 40.80 784.2 1019.9 q2a10
+ -10 -28 47 114.89 130.02 115.00 67.51 937.5 754.3 q2a8
+ -10 -12 8 491.25 273.14 448.00 164.26 1191.0 83.0 q3a0
+ -10 -6 -1 -282.21 220.12 208.00 134.41 1306.3 152.6 q3a0
+ -10 4 -13 634.11 357.32 405.00 118.49 1473.3 231.7 q3a3
+ -10 6 -15 -383.52 536.92 427.00 160.72 1504.8 252.3 q3a3
+ -10 8 -17 1293.69 661.87 467.00 221.31 1536.6 273.1 q3a3
+ -10 26 -30 -98.12 124.71 164.00 94.12 248.2 669.0 q0a7
+ -10 28 -31 26.32 118.05 145.00 88.08 218.1 647.6 q0a7
+ -9 -31 63 129.26 92.34 79.00 45.14 859.1 956.4 q2a10
+ -9 -23 32 -492.00 256.18 325.00 133.57 908.0 1356.4 q2a14
+ -9 -19 22 -791.05 398.61 375.00 184.61 1024.5 1422.6 q2a15
+ -9 -11 7 -76.42 188.75 216.00 131.89 1191.4 119.5 q3a0
+ -9 -1 -7 4779.59 240.02 2129.00 86.21 1372.1 203.3 q3a3
+ -9 25 -29 -142.54 141.14 176.00 99.34 285.9 655.3 q0a7
+ -8 -10 6 -29.81 132.26 188.00 119.85 1191.9 155.6 q3a0
+ -8 4 -12 250.79 129.16 206.00 86.41 1433.1 279.3 q3a3
+ -8 6 -14 285.95 199.49 268.00 96.45 1464.2 299.9 q3a3
+ -8 8 -16 1490.08 345.50 983.00 128.32 1495.6 320.6 q3a3
+ -8 24 -28 -150.39 241.85 300.00 106.99 323.0 641.8 q0a7
+ -8 40 -35 -110.16 83.72 99.00 60.96 83.4 487.2 q0a4
+ -7 -31 68 3.29 82.87 79.00 44.91 897.0 1052.1 q2a10
+ -7 -27 47 -106.62 107.29 124.00 68.62 1033.8 788.2 q2a9
+ -7 -25 40 -106.91 145.96 175.00 107.14 787.4 1367.4 q2a14
+ -7 -23 34 58.48 175.71 294.00 124.72 861.1 1405.5 q2a14
+ -7 25 -28 -217.82 170.41 241.00 108.42 331.1 607.4 q0a7
+ -7 33 -32 -373.57 161.27 194.00 84.17 212.2 546.3 q0a5
+ -6 -28 53 -90.19 89.22 92.00 65.19 1028.9 877.2 q2a9
+ -6 -26 45 45.35 88.60 133.00 68.85 1079.5 773.3 q2a9
+ -6 -12 11 1725.26 189.62 1283.00 90.97 1068.8 327.7 q2a3
+ -6 14 -20 -6.69 193.19 356.00 152.69 41.6 96.5 q0a0
+ -6 18 -23 363.00 349.65 513.00 179.00 82.7 38.0 q0a0
+ -6 26 -28 -208.31 197.66 248.00 108.31 339.2 573.0 q0a7
+ -6 32 -31 -18.10 122.57 141.00 81.90 251.0 534.0 q0a5
+ -6 44 -35 16.22 115.55 98.00 57.98 72.1 386.7 q0a4
+ -5 -25 43 -11.18 161.05 173.00 78.72 1124.2 758.7 q2a9
+ -5 -5 1 8227.96 307.07 4127.00 63.84 1223.3 252.5 q3a2
+ -5 5 -11 13505.76 393.12 6597.00 82.64 1386.1 358.5 q3a3
+ -5 15 -20 780.85 210.48 334.00 140.35 74.7 104.0 q0a0
+ -5 19 -23 901.01 368.18 532.00 188.39 116.1 45.6 q0a0
+ -5 39 -33 -299.38 161.63 280.00 71.38 175.1 426.5 q0a4
+ -4 -20 30 -166.88 334.96 362.00 179.67 1131.7 107.0 q2a1
+ -4 -12 13 -137.67 146.29 153.00 87.67 1023.5 282.8 q2a3
+ -4 -2 -2 1051.32 142.93 724.00 67.08 1253.3 307.2 q3a2
+ -4 16 -20 -101.25 195.72 439.00 154.25 107.7 111.5 q0a0
+ -4 38 -32 129.18 103.10 114.00 72.42 212.2 415.0 q0a5
+ -3 -19 29 366.91 460.87 511.00 200.39 1094.5 109.4 q2a1
+ -3 -7 6 310.40 191.65 493.00 65.91 946.2 359.5 q2a2
+ -3 -5 3 186.64 118.99 162.00 62.56 1178.5 296.7 q3a2
+ -3 23 -24 5103.14 356.40 1757.00 181.04 201.2 34.1 q0a1
+ -3 35 -30 42.85 104.98 114.00 78.35 281.6 428.1 q0a5
+ -3 49 -34 -4.49 71.52 92.00 54.89 293.1 1037.6 q0a11
+ -2 -10 12 68.53 195.78 138.00 59.40 958.9 276.3 q2a2
+ -2 30 -27 658.20 267.07 374.00 105.20 376.8 464.2 q0a5
+ -2 32 -28 -492.94 246.82 203.00 101.94 348.5 440.8 q0a5
+ -2 48 -33 -30.99 92.93 133.00 52.39 282.7 994.2 q0a11
+ -1 -15 23 -115.55 181.60 226.00 151.77 996.0 163.2 q2a1
+ -1 11 -13 -233.74 101.49 104.00 68.14 123.0 224.1 q0a2
+ -1 17 -18 484.88 216.35 517.00 124.12 185.4 165.7 q0a0
+ -1 55 -33 -150.26 143.98 129.00 52.86 153.4 1077.7 q0a10
+ 0 -24 51 -134.28 114.00 116.00 76.13 1002.4 419.4 q2a5
+ 0 -18 32 90.09 361.67 421.00 178.47 1016.7 46.8 q2a1
+ 0 -16 27 -200.32 456.24 450.00 203.99 988.2 106.8 q2a1
+ 0 -10 15 -27.09 141.77 131.00 70.86 916.6 223.3 q2a2
+ 0 6 -7 -33.00 86.82 187.00 69.00 92.6 322.8 q0a2
+ 0 8 -9 549.25 130.90 478.00 68.75 113.4 292.6 q0a2
+ 0 10 -11 -211.64 182.91 220.00 74.24 134.4 262.2 q0a2
+ 0 28 -24 7.58 247.65 430.00 162.82 324.8 35.9 q0a1
+ 0 30 -25 81.30 180.95 380.00 156.30 347.7 8.3 q0a1
+ 0 54 -32 137.66 114.66 121.00 49.54 144.1 1032.1 q0a10
+ 1 -21 43 455.36 217.38 274.00 99.56 1096.2 497.0 q2a5
+ 1 23 -20 1484.31 519.23 744.00 207.69 291.4 129.5 q0a1
+ 1 37 -27 214.01 151.74 191.00 78.39 358.4 780.1 q0a9
+ 1 43 -29 -101.36 107.27 129.00 69.76 279.4 865.1 q0a9
+ 1 55 -31 95.03 63.56 71.00 46.77 101.7 1018.3 q0a10
+ 2 4 -2 -89.73 225.93 345.00 67.71 405.6 331.7 q1a2
+ 2 14 -12 254.93 126.52 144.00 84.67 216.7 253.5 q0a3
+ 2 40 -27 -130.88 124.47 163.00 73.88 296.0 795.6 q0a9
+ 2 48 -29 384.90 172.14 177.00 63.06 186.4 909.6 q0a8
+ 2 56 -30 -55.76 93.07 96.00 49.36 58.9 1004.3 q0a10
+ 2 58 -30 83.81 84.63 131.00 44.19 23.6 1036.2 q0a10
+ 3 -23 58 19.09 123.08 138.00 62.57 884.6 489.0 q2a4
+ 3 -7 15 159.45 127.04 133.00 65.71 819.2 201.1 q2a2
+ 3 11 -8 1112.30 153.94 678.00 81.30 206.5 322.1 q0a3
+ 3 33 -23 187.64 175.43 236.00 127.76 39.3 1426.5 q0a14
+ 3 41 -26 118.01 113.25 116.00 68.39 258.5 781.6 q0a9
+ 3 49 -28 -327.43 174.87 141.00 71.83 146.3 895.4 q0a8
+ 4 -2 9 2085.70 232.25 1263.00 53.19 563.1 353.8 q1a2
+ 4 4 1 -85.71 162.36 213.00 54.91 457.9 289.2 q1a2
+ 4 16 -11 78.68 120.54 172.00 91.92 281.6 275.6 q0a3
+ 4 20 -14 631.12 321.32 419.00 129.88 325.4 220.3 q0a3
+ 4 36 -23 17.09 152.66 191.00 117.71 25.4 1365.6 q0a14
+ 5 -19 49 133.61 108.00 152.00 85.95 986.8 576.9 q2a7
+ 5 -11 27 522.74 242.74 323.00 159.03 824.8 70.1 q2a0
+ 5 -9 23 -307.17 176.46 199.00 126.17 800.9 119.4 q2a0
+ 5 3 4 62.47 117.60 143.00 57.58 503.0 278.8 q1a2
+ 5 37 -22 49.68 131.80 153.00 103.92 39.6 1329.0 q0a14
+ 5 43 -24 242.79 123.13 179.00 65.41 185.3 752.9 q0a8
+ 5 47 -25 97.86 113.54 128.00 67.74 126.6 808.3 q0a8
+ 5 53 -26 15.29 108.54 129.00 62.91 30.9 894.4 q0a8
+ 6 -20 58 20.31 108.18 85.00 56.69 860.1 573.1 q2a6
+ 6 -14 37 -439.20 550.12 392.00 155.80 1132.7 672.5 q2a7
+ 6 8 0 11651.10 358.84 7791.00 52.94 450.8 204.1 q1a2
+ 6 14 -6 1012.09 169.21 742.00 95.71 303.4 359.3 q0a3
+ 6 20 -11 1846.74 672.60 627.00 208.86 369.6 273.8 q0a3
+ 6 26 -15 -958.60 498.58 443.00 201.40 211.9 1441.7 q0a15
+ 7 -17 50 363.27 193.77 214.00 69.42 961.5 646.0 q2a6
+ 7 -7 24 -634.82 476.03 387.00 147.94 764.4 348.3 q1a3
+ 7 3 8 2530.65 236.58 1171.00 58.72 564.2 236.6 q1a2
+ 7 7 3 -259.41 134.42 116.00 61.21 496.2 193.5 q1a2
+ 7 27 -14 827.20 218.03 496.00 165.20 226.5 1407.0 q0a15
+ 7 43 -21 -125.09 125.41 134.00 76.29 16.5 1225.3 q0a12
+ 8 -16 51 -151.91 159.83 147.00 72.32 940.9 679.9 q2a6
+ 8 -14 44 -84.53 116.93 156.00 94.13 1030.0 711.1 q2a7
+ 8 -4 21 -677.73 375.80 373.00 127.97 732.6 292.9 q1a3
+ 8 22 -9 -603.86 679.43 550.00 248.26 323.0 1442.8 q0a15
+ 8 28 -13 31.84 258.87 375.00 157.96 241.3 1371.9 q0a15
+ 8 30 -14 -320.09 216.62 288.00 149.29 215.7 1347.1 q0a15
+ 9 -15 52 147.52 136.57 124.00 65.28 920.1 714.1 q2a6
+ 9 -3 22 269.21 517.60 414.00 160.55 749.7 260.6 q1a3
+ 9 9 5 -89.36 175.59 228.00 124.13 527.0 157.0 q1a0
+ 9 17 -3 504.50 346.90 454.00 166.50 404.4 69.2 q1a0
+ 10 -2 23 107.10 588.28 426.00 201.59 767.1 228.0 q1a3
+ 10 6 11 712.58 211.52 484.00 141.89 609.1 167.4 q1a1
+ 10 16 0 504.48 253.86 388.00 168.95 450.7 57.6 q1a0
+ 10 26 -8 253.06 217.73 361.00 162.94 328.9 1349.2 q0a15
+ 10 40 -15 1.98 122.38 140.00 78.22 147.7 1192.6 q0a12
+ 11 -11 48 101.46 141.66 148.00 66.22 724.0 1201.1 q1a13
+ 11 -9 42 298.62 196.69 311.00 74.99 697.4 1280.7 q1a13
+ 11 -3 28 -228.56 305.56 321.00 157.85 625.2 1433.2 q1a15
+ 11 5 15 272.38 235.96 331.00 168.62 664.8 156.0 q1a1
+ 11 35 -11 370.45 142.92 281.00 83.95 241.8 1236.8 q0a13
+ 11 43 -14 -126.43 134.95 174.00 76.83 141.6 1121.8 q0a12
+ 12 40 -11 143.16 111.86 140.00 77.04 210.5 1140.1 q0a13
+ 13 -9 52 -376.82 132.07 109.00 58.14 654.9 1133.7 q1a13
+ 13 27 -2 482.32 174.20 288.00 107.18 660.2 732.3 q1a7
+ 14 0 33 -23.45 214.57 214.00 117.95 526.3 1356.5 q1a14
+ 14 10 17 -470.46 225.66 276.00 157.78 694.5 30.9 q1a1
+ 14 20 6 351.95 262.60 314.00 127.45 721.3 596.3 q1a7
+ 15 15 14 -31.85 446.54 376.00 129.65 754.9 504.3 q1a5
+ 15 21 8 -151.29 206.20 211.00 108.09 683.7 570.5 q1a7
+ 15 27 3 206.99 125.17 220.00 99.63 608.8 658.4 q1a7
+ 16 6 30 109.35 175.29 175.00 105.28 409.3 1391.7 q1a14
+ 16 12 21 90.43 241.88 309.00 106.48 764.6 404.3 q1a5
+ 16 16 16 115.51 179.35 211.00 103.95 717.8 476.9 q1a5
+ 17 1 45 -189.49 115.43 102.00 56.68 438.8 1209.8 q1a12
+ 17 21 14 127.77 135.41 143.00 86.39 630.4 512.6 q1a5
+ 17 31 6 -130.55 118.76 185.00 76.95 502.6 630.6 q1a6
+ 18 26 13 -7.44 190.09 217.00 75.44 540.3 539.8 q1a4
+ 19 5 47 -4.72 105.65 89.00 46.08 471.5 762.9 q1a8
+ 19 29 14 -27.86 93.34 126.00 67.26 469.2 534.7 q1a4
+ 20 10 42 -80.53 125.57 112.00 54.58 541.5 850.9 q1a8
+ 20 14 35 -212.43 116.21 112.00 59.83 641.7 897.1 q1a9
+ 21 11 46 -74.81 91.52 83.00 52.51 479.5 897.0 q1a8
+ 21 21 30 -43.43 126.04 129.00 55.83 721.0 988.7 q1a11
+ 22 26 29 -139.84 189.23 162.00 55.04 744.6 1091.4 q1a11
+ 23 19 44 -56.56 155.68 202.00 46.56 509.1 1042.7 q1a10
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035214_1e5eb.h5
+Image serial number: 8
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 2
+photon_energy_eV = 9508.058973
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9508.058973
+average_camera_length = 0.152001 m
+num_peaks = 14
+peak_resolution = 4.489771 nm^-1 or 2.227285 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 15.50 98.29 1.90 1426.56 q0a0
+ 849.50 149.98 1.61 1404.66 q2a0
+ 144.21 276.50 1.01 1357.88 q0a2
+ 185.59 296.09 1.09 4502.33 q0a2
+ 227.74 326.00 1.22 1860.00 q0a3
+ 562.85 261.92 1.15 806.60 q1a2
+ 481.50 290.16 0.77 678.28 q1a2
+ 663.70 295.95 1.50 1210.61 q1a3
+ 941.06 297.79 0.98 4350.59 q2a2
+ 922.85 348.77 0.74 1161.16 q2a2
+1309.94 799.06 4.11 -258.53 q3a8
+1536.50 1020.13 4.29 371.84 q3a11
+1510.12 1068.88 4.49 896.11 q3a11
+ 597.70 1471.89 2.36 822.71 q1a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.08811 12.46284 16.85876 nm, 89.04950 89.82735 90.46422 deg
+astar = -0.0541754 -0.1394940 +0.0677352 nm^-1
+bstar = +0.0047091 +0.0328758 +0.0730577 nm^-1
+cstar = -0.0558777 +0.0189941 -0.0060282 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00145 nm^-1
+predict_refine/final_residual = 2.560572e-07
+predict_refine/det_shift x = 0.005 y = -0.039 mm
+diffraction_resolution_limit = 1.90 nm^-1 or 5.26 A
+num_reflections = 139
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -26 2 -32 117.44 95.72 115.00 53.85 108.6 951.3 q0a10
+ -26 4 -24 121.13 100.00 239.00 71.67 71.5 872.1 q0a8
+ -25 7 -8 116.59 139.29 121.00 79.36 53.0 1126.6 q0a12
+ -23 3 -31 8.89 112.83 157.00 73.70 211.4 904.0 q0a9
+ -22 8 -4 1.14 232.19 270.00 94.53 145.5 1217.4 q0a12
+ -21 3 -32 -23.00 199.61 236.00 79.00 285.6 879.8 q0a9
+ -21 7 39 -48.91 127.04 129.00 78.90 424.9 522.2 q1a4
+ -20 8 32 23.10 111.14 145.00 87.57 497.2 572.0 q1a6
+ -19 5 -24 33.71 139.57 170.00 87.86 315.3 749.7 q0a9
+ -19 9 12 17.22 312.49 347.00 121.53 359.0 1249.9 q0a13
+ -18 6 -19 128.49 206.91 229.00 139.85 34.5 1389.8 q0a14
+ -17 7 39 -315.49 354.27 345.00 92.91 571.6 487.4 q1a4
+ -16 6 -18 261.40 221.69 282.00 153.54 73.8 1448.5 q0a14
+ -15 7 37 282.35 146.54 148.00 95.32 646.2 493.8 q1a5
+ -14 0 66 -33.75 122.42 109.00 56.75 536.3 947.4 q1a10
+ -14 4 52 -159.96 204.76 236.00 74.10 734.4 908.0 q1a9
+ -14 6 42 105.40 121.66 137.00 90.83 659.0 424.9 q1a5
+ -14 8 1 288.36 489.87 528.00 247.69 299.1 1429.4 q0a15
+ -14 8 25 -721.90 436.47 506.00 161.10 729.1 593.2 q1a7
+ -13 -1 -42 -97.77 123.02 144.00 93.61 260.6 544.7 q0a5
+ -13 7 33 100.94 419.76 368.00 150.63 728.7 522.2 q1a5
+ -12 -8 -58 201.15 120.86 117.00 69.65 63.9 647.4 q0a6
+ -12 0 64 158.26 158.23 286.00 68.14 551.4 891.0 q1a8
+ -12 4 -23 -379.45 215.59 422.00 205.09 285.8 76.8 q0a1
+ -11 -1 -40 101.01 171.07 235.00 115.45 314.5 567.2 q0a7
+ -11 -1 66 97.29 137.32 149.00 66.91 513.2 863.8 q1a8
+ -11 3 -26 -494.04 473.89 525.00 220.23 241.8 57.1 q0a1
+ -11 3 52 -177.58 208.92 293.00 77.11 709.2 804.5 q1a9
+ -11 5 -16 -62.72 458.35 478.00 227.63 287.8 164.3 q0a1
+ -11 7 0 -1310.89 602.41 450.00 186.57 355.5 303.1 q0a3
+ -10 -4 -47 1.52 140.80 165.00 108.05 242.0 638.5 q0a7
+ -10 6 33 -487.74 262.59 263.00 178.91 659.8 18.9 q1a1
+ -9 -7 -53 -44.04 312.79 298.00 89.84 180.8 708.2 q0a6
+ -9 -3 -43 -307.48 226.35 259.00 125.05 305.4 645.6 q0a7
+ -9 -3 69 124.31 108.72 107.00 58.69 449.0 804.3 q1a8
+ -9 3 -22 -56.69 317.70 425.00 199.28 201.1 125.2 q0a1
+ -9 5 -11 387.09 161.94 166.00 98.63 250.8 212.3 q0a3
+ -9 5 37 102.32 184.80 293.00 181.97 715.1 35.3 q1a1
+ -8 0 -32 -826.79 556.77 530.00 230.42 124.8 28.9 q0a0
+ -8 4 -14 -423.94 192.30 183.00 104.75 208.2 192.6 q0a3
+ -8 6 22 770.05 338.47 602.00 173.82 562.6 121.8 q1a0
+ -7 3 43 294.47 204.80 231.00 136.13 460.3 1462.4 q1a14
+ -7 5 -2 2020.42 191.23 1022.00 90.83 228.7 326.1 q0a3
+ -7 5 28 -296.60 334.36 379.00 203.40 634.2 130.5 q1a1
+ -6 -8 -51 561.62 292.66 337.00 94.99 1520.6 1259.5 q3a13
+ -6 -4 -41 278.09 575.77 474.00 177.18 368.1 725.8 q0a7
+ -6 -4 67 104.39 105.05 116.00 68.01 408.3 1154.8 q1a12
+ -6 -2 61 14.79 128.71 130.00 69.82 429.7 1244.9 q1a12
+ -6 0 54 269.05 159.51 174.00 98.55 454.3 1314.1 q1a14
+ -6 2 45 101.53 290.43 342.00 137.87 485.4 1428.4 q1a14
+ -6 4 -6 4562.78 277.36 2639.00 70.84 185.9 296.4 q0a2
+ -5 -3 62 243.65 102.81 140.00 64.15 460.5 1220.2 q1a12
+ -5 -1 -29 384.32 187.04 278.00 173.01 50.4 98.0 q0a0
+ -5 3 -9 1380.25 203.02 1043.00 80.75 144.0 276.8 q0a2
+ -5 3 35 604.71 554.63 532.00 238.35 731.9 167.5 q1a1
+ -4 -2 -30 974.18 311.13 1107.00 179.36 14.8 98.8 q0a0
+ -4 2 -11 1388.30 183.63 1142.00 77.95 105.6 267.3 q0a2
+ -3 -7 -43 -67.34 300.25 394.00 174.99 1478.8 1367.9 q3a15
+ -3 -3 57 -450.70 198.02 154.00 76.04 544.3 1269.9 q1a12
+ -3 1 39 995.06 567.74 1102.00 223.37 597.2 1469.6 q1a15
+ -3 3 8 -321.95 131.44 117.00 61.08 469.7 294.4 q1a2
+ -3 3 9 960.55 136.62 710.00 55.58 479.8 290.9 q1a2
+ -3 3 10 -187.11 113.30 105.00 58.49 490.0 287.4 q1a2
+ -3 3 17 937.16 250.13 436.00 62.34 561.7 262.4 q1a2
+ -3 3 18 218.78 220.38 175.00 62.56 572.1 258.8 q1a2
+ -2 -2 50 60.44 208.25 242.00 140.44 595.7 1324.6 q1a15
+ -2 0 -14 122.98 117.40 130.00 74.27 32.6 258.4 q0a2
+ -2 0 40 -469.00 414.78 464.00 197.00 625.9 1447.2 q1a15
+ -2 2 4 805.25 454.82 1036.00 107.77 439.8 339.6 q1a2
+ -1 -7 -38 -1067.36 573.31 499.00 231.64 1445.9 1448.2 q3a15
+ -1 -7 64 52.29 111.07 126.00 69.44 589.7 1144.8 q1a13
+ -1 -1 41 397.40 295.22 472.00 176.69 654.7 1424.7 q1a15
+ -1 1 25 1138.50 202.24 552.00 94.50 663.7 296.6 q1a3
+ 0 -18 -60 171.21 115.82 140.00 70.59 1245.0 1208.6 q3a12
+ 0 -8 -38 633.80 436.82 465.00 209.80 1413.2 1459.1 q3a15
+ 0 -8 64 -139.61 119.80 122.00 69.01 625.1 1131.9 q1a13
+ 0 0 26 120.68 172.54 208.00 97.09 685.2 324.7 q1a3
+ 1 -13 -48 -247.55 233.10 250.00 146.95 1313.3 1352.1 q3a14
+ 1 -1 27 473.84 194.26 401.00 102.27 706.7 352.8 q1a3
+ 2 -4 -15 800.63 176.16 202.00 71.48 1323.0 289.6 q3a2
+ 2 -2 0 64.00 1132.54 702.00 297.43 1172.4 353.9 q3a2
+ 3 -25 -65 190.71 120.01 111.00 64.09 1236.0 804.3 q3a8
+ 3 -23 -62 192.66 101.27 106.00 66.54 1283.5 768.2 q3a8
+ 3 -15 -47 -238.24 176.24 214.00 132.64 1248.9 1385.0 q3a14
+ 3 -11 -37 537.63 470.76 494.00 227.29 1541.5 161.9 q3a1
+ 3 -9 57 -319.77 191.58 188.00 83.97 747.9 1195.2 q1a13
+ 3 -3 26 72.00 164.73 231.00 137.43 807.9 140.9 q2a0
+ 4 -4 2 1357.95 181.63 492.00 71.92 922.4 349.4 q2a2
+ 4 -4 24 1611.78 203.56 793.00 133.70 846.7 150.6 q2a0
+ 5 -23 -57 17.35 114.71 141.00 73.85 1371.4 798.8 q3a9
+ 5 -9 48 -249.27 183.91 215.00 121.03 1047.3 697.7 q2a7
+ 5 -5 6 4164.87 280.91 1760.00 72.66 940.4 297.9 q2a2
+ 6 -24 -56 63.36 110.08 137.00 74.24 1394.2 831.6 q3a9
+ 6 -14 60 47.10 109.25 135.00 72.10 863.2 681.2 q2a6
+ 6 -12 -28 691.65 480.36 537.00 239.21 1411.8 113.0 q3a1
+ 6 -12 54 -122.21 223.25 229.00 89.41 953.1 672.3 q2a6
+ 7 -35 -69 -35.22 89.23 95.00 54.02 1192.9 1037.4 q3a10
+ 7 -27 -58 -372.99 157.38 130.00 77.39 1372.8 902.0 q3a9
+ 7 -15 -33 23.47 326.05 463.00 194.42 1455.4 43.6 q3a1
+ 7 -11 -19 -402.69 346.82 423.00 174.77 1309.8 129.4 q3a0
+ 8 -22 -46 122.38 243.83 279.00 91.01 1544.4 818.7 q3a9
+ 8 -16 57 161.98 108.23 135.00 71.22 874.3 598.3 q2a6
+ 9 -21 -40 328.04 229.62 287.00 116.10 1490.3 414.3 q3a5
+ 9 -19 -35 -113.78 407.29 377.00 153.65 1530.0 472.4 q3a5
+ 9 -13 -14 -16.72 333.45 451.00 187.63 1236.1 81.5 q3a0
+ 9 -11 0 332.94 338.45 313.00 140.06 1100.6 312.6 q2a3
+ 9 -11 26 61.03 353.10 529.00 227.88 1012.4 63.8 q2a1
+ 10 -36 -62 153.72 135.91 214.00 57.48 1330.7 1098.5 q3a10
+ 10 -22 -38 -32.96 210.61 269.00 113.35 1462.1 447.2 q3a5
+ 10 -20 -33 -146.28 502.58 416.00 160.94 1502.4 504.9 q3a5
+ 10 -16 -20 -829.24 518.10 595.00 231.21 1286.9 8.7 q3a0
+ 10 -12 9 1212.51 334.87 387.00 167.46 1103.3 207.0 q2a3
+ 10 -12 10 -23.61 459.44 422.00 180.36 1100.0 196.4 q2a3
+ 10 -12 15 -122.44 635.09 552.00 263.97 1082.8 170.6 q2a1
+ 10 -12 16 1170.05 543.55 507.00 262.08 1079.4 159.9 q2a1
+ 10 -12 17 1479.92 464.00 537.00 252.35 1076.0 149.2 q2a1
+ 11 -19 50 -82.29 191.02 222.00 73.09 921.2 492.2 q2a4
+ 11 -15 -6 2823.13 756.07 611.00 303.51 1145.4 1451.8 q2a15
+ 12 -26 -38 138.74 184.87 233.00 100.23 1365.7 465.7 q3a5
+ 12 -20 47 -13.22 231.87 306.00 72.76 945.1 445.7 q2a4
+ 12 -16 0 -853.05 720.01 610.00 270.41 1070.4 1438.6 q2a15
+ 12 -16 25 -53.75 213.62 271.00 181.75 1133.1 29.7 q2a1
+ 13 -19 -8 568.42 461.80 424.00 201.85 1141.0 1357.7 q2a15
+ 14 -32 -41 -75.44 120.82 134.00 81.15 1227.0 446.4 q3a4
+ 14 -30 -37 -178.44 114.83 133.00 84.74 1270.9 496.6 q3a4
+ 14 -24 -21 161.15 229.13 315.00 131.51 1404.4 652.7 q3a7
+ 14 -20 -1 251.70 201.44 269.00 170.43 1053.6 1347.0 q2a15
+ 15 -33 -38 127.43 153.59 170.00 86.48 1199.3 493.4 q3a4
+ 15 -29 -29 109.73 139.74 148.00 91.82 1290.9 574.8 q3a6
+ 16 -32 -30 173.92 114.13 133.00 84.55 1220.7 574.4 q3a6
+ 16 -30 -25 189.05 112.30 141.00 88.63 1267.8 632.4 q3a6
+ 16 -30 50 -47.71 68.32 85.00 58.44 1064.9 1089.5 q2a11
+ 16 -28 44 210.28 104.05 127.00 60.57 1068.9 991.7 q2a11
+ 16 -26 36 -160.46 109.88 125.00 80.72 1065.3 902.3 q2a9
+ 17 -31 -20 -36.75 116.40 141.00 87.75 1247.8 702.1 q3a6
+ 17 -29 -13 -338.82 143.73 139.00 94.53 1139.0 1153.3 q2a13
+ 17 -27 -2 114.26 129.75 162.00 94.40 1018.1 1217.6 q2a13
+ 18 -30 30 176.81 170.44 153.00 71.15 947.8 869.4 q2a8
+ 19 -33 31 -53.26 96.70 137.00 73.60 884.7 910.9 q2a8
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035136_1b0d2.h5
+Image serial number: 9
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9515.867410
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9515.867410
+average_camera_length = 0.152001 m
+num_peaks = 16
+peak_resolution = 3.951940 nm^-1 or 2.530402 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 136.50 12.01 2.41 288.55 q0a0
+ 422.50 101.84 1.86 1106.00 q1a0
+ 647.78 33.22 2.51 1311.43 q1a1
+ 900.18 28.40 2.27 2878.76 q2a0
+1240.40 39.88 2.19 3120.67 q3a0
+ 41.50 215.89 1.13 929.43 q0a2
+ 421.50 232.81 1.01 1145.35 q1a2
+ 413.60 289.95 0.70 4229.97 q1a2
+ 655.75 269.04 1.53 1102.70 q1a3
+ 787.50 268.84 0.80 934.45 q2a2
+ 930.54 301.50 0.92 2090.94 q2a2
+1048.96 315.50 1.45 1000.70 q2a3
+1070.12 349.11 1.51 1716.93 q2a3
+1277.22 284.45 0.86 10072.25 q3a2
+1285.50 317.90 0.74 3161.79 q3a2
+1091.03 912.50 3.95 395.84 q2a9
+End of peak list
+--- Begin crystal
+Cell parameters 6.15440 12.32532 16.77194 nm, 89.84931 89.25412 90.33793 deg
+astar = -0.0463150 +0.1554948 -0.0091201 nm^-1
+bstar = +0.0493927 +0.0188252 +0.0615544 nm^-1
+cstar = +0.0441864 +0.0100762 -0.0387506 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00192 nm^-1
+predict_refine/final_residual = 3.084987e-07
+predict_refine/det_shift x = 0.057 y = 0.041 mm
+diffraction_resolution_limit = 2.27 nm^-1 or 4.41 A
+num_reflections = 166
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -26 -4 40 -184.85 124.31 115.00 62.65 1329.1 1086.3 q3a10
+ -23 -3 30 -60.44 83.82 104.00 68.44 1479.1 951.0 q3a11
+ -23 -1 35 -81.59 98.34 107.00 70.75 1405.6 939.8 q3a11
+ -22 -14 7 112.60 130.77 151.00 87.60 1286.8 582.4 q3a6
+ -22 -10 13 268.70 189.93 249.00 90.19 1315.7 515.1 q3a4
+ -21 1 33 -8.49 101.22 120.00 75.68 1437.5 879.9 q3a9
+ -20 -16 0 360.56 192.68 194.00 98.44 1341.7 685.6 q3a6
+ -20 0 27 415.61 155.32 142.00 76.62 1523.1 850.3 q3a9
+ -20 2 32 339.78 208.07 296.00 80.76 1453.1 838.1 q3a9
+ -20 4 38 -299.92 177.93 170.00 79.20 1368.9 826.7 q3a9
+ -19 -3 18 127.25 153.67 186.00 108.34 1463.3 437.8 q3a5
+ -19 -1 22 70.33 160.71 181.00 105.54 1476.6 381.6 q3a5
+ -19 7 44 -62.97 107.66 123.00 70.90 1289.8 774.0 q3a8
+ -18 -26 -14 -116.73 160.97 187.00 88.53 988.2 1182.3 q2a13
+ -18 -10 4 -270.38 239.67 338.00 127.99 1448.5 611.9 q3a7
+ -18 -8 7 -323.52 188.49 337.00 136.95 1462.3 566.7 q3a7
+ -18 2 26 -177.69 230.64 243.00 97.36 1539.8 771.1 q3a9
+ -17 -33 -21 -50.20 107.40 118.00 80.80 838.9 1155.2 q2a12
+ -17 -29 -18 -82.70 151.56 164.00 88.30 913.8 1190.6 q2a12
+ -17 -21 -11 -160.76 189.18 228.00 105.36 1060.4 1255.9 q2a13
+ -16 -34 -23 80.48 143.13 148.00 82.72 800.9 1180.4 q2a12
+ -16 -26 -17 198.04 205.32 270.00 90.16 949.3 1248.8 q2a12
+ -16 6 31 -39.04 206.07 240.00 130.65 1193.5 1378.1 q3a14
+ -16 10 44 224.53 118.94 185.00 74.42 1219.6 1229.0 q3a12
+ -15 -1 13 24.41 242.24 290.00 180.75 1421.5 19.5 q3a1
+ -15 1 17 -499.78 257.41 378.00 188.24 1475.4 32.2 q3a1
+ -15 5 26 -206.23 309.66 400.00 147.39 1217.4 1447.8 q3a14
+ -14 -16 -10 -101.24 317.59 526.00 196.64 1095.0 1358.9 q2a15
+ -14 -6 3 720.62 502.95 557.00 236.99 1283.3 16.9 q3a0
+ -14 0 13 281.95 316.24 578.00 208.53 1420.6 55.5 q3a1
+ -14 2 17 804.99 346.35 627.00 201.55 1474.1 68.4 q3a1
+ -14 12 45 -166.10 166.12 188.00 77.41 1296.2 1224.9 q3a12
+ -13 -7 0 2936.96 521.14 1187.00 234.90 1240.0 39.8 q3a0
+ -13 -5 3 1197.77 532.43 514.00 249.39 1283.4 52.7 q3a0
+ -13 9 32 -180.68 284.77 393.00 149.22 1304.0 1375.4 q3a14
+ -12 -42 -32 213.45 164.70 270.00 68.95 928.6 906.9 q2a8
+ -12 -40 -31 62.18 164.97 158.00 66.42 947.0 868.5 q2a8
+ -12 14 47 642.51 177.29 258.00 76.68 1369.1 1208.1 q3a13
+ -11 -47 -35 -8.29 94.56 85.00 53.09 915.1 994.2 q2a10
+ -11 -25 -22 10.73 248.15 300.00 156.47 879.0 1385.6 q2a14
+ -11 3 14 -162.31 305.21 403.00 208.23 1427.5 161.1 q3a1
+ -9 -39 -33 -71.26 96.63 108.00 72.86 1051.4 895.9 q2a9
+ -9 -5 -2 -409.27 191.58 230.00 143.47 1207.5 166.3 q3a0
+ -9 11 30 -221.64 376.33 474.00 181.73 1429.4 1419.2 q3a15
+ -9 13 36 -225.09 253.57 324.00 147.25 1445.6 1342.3 q3a15
+ -8 -36 -32 -218.59 138.04 192.00 77.79 1107.2 853.7 q2a9
+ -8 -8 -7 1874.07 182.99 673.00 101.33 1071.3 350.5 q2a3
+ -7 -19 -20 118.83 714.88 626.00 280.57 1111.7 157.1 q2a1
+ -7 -15 -16 -195.60 297.31 297.00 145.40 1087.1 202.9 q2a3
+ -7 5 13 4.42 152.10 179.00 101.81 1400.2 257.1 q3a3
+ -7 9 22 275.20 539.18 454.00 183.63 1513.8 285.8 q3a3
+ -7 11 27 2790.91 622.12 1232.00 253.57 1484.4 1467.2 q3a15
+ -6 -24 -25 493.04 341.97 430.00 191.16 1114.3 53.8 q2a1
+ -6 -10 -11 360.62 155.72 160.00 92.38 1028.1 283.1 q2a3
+ -6 0 3 301.03 120.10 203.00 76.73 1267.8 251.4 q3a2
+ -6 20 63 -103.45 150.74 155.00 67.05 10.2 696.1 q0a6
+ -5 -47 -39 27.16 120.87 109.00 53.04 1117.0 1081.9 q2a11
+ -5 -33 -32 -28.96 121.78 138.00 88.16 1072.5 397.6 q2a5
+ -5 -21 -23 -429.56 565.16 534.00 243.56 1066.5 95.2 q2a1
+ -5 -7 -8 301.50 137.80 226.00 91.50 982.3 326.8 q2a3
+ -5 1 4 10128.16 338.54 6013.00 72.77 1276.2 285.2 q3a2
+ -5 19 54 92.83 149.62 160.00 73.17 145.7 687.4 q0a6
+ -4 2 5 3205.64 233.53 1760.00 77.70 1284.6 318.8 q3a2
+ -4 16 39 -855.08 528.75 408.00 154.25 346.8 698.6 q0a7
+ -4 18 47 -379.96 209.50 243.00 106.22 243.5 675.0 q0a7
+ -4 20 58 17.72 123.86 175.00 66.92 97.5 642.7 q0a6
+ -3 -21 -24 1380.04 548.97 774.00 242.16 1008.9 70.7 q2a1
+ -3 -7 -9 1965.50 219.70 1174.00 74.50 930.2 302.2 q2a2
+ -3 21 63 -235.97 114.54 119.00 65.73 33.6 593.8 q0a6
+ -2 -42 -38 -44.10 103.93 107.00 68.90 867.2 427.9 q2a4
+ -2 -40 -37 -29.64 112.28 121.00 72.24 906.6 442.0 q2a4
+ -2 -38 -36 -24.82 209.40 171.00 72.42 944.9 455.7 q2a4
+ -2 -36 -35 850.75 158.41 311.00 83.25 979.3 469.1 q2a5
+ -2 12 25 -355.71 220.73 253.00 154.14 59.5 117.8 q0a0
+ -2 18 45 -90.56 134.94 172.00 106.26 284.2 618.3 q0a7
+ -1 -15 -19 364.52 191.29 278.00 139.28 920.5 157.4 q2a0
+ -1 5 9 426.76 148.67 192.00 72.47 34.8 295.5 q0a2
+ -1 7 13 480.04 113.34 409.00 71.04 49.0 244.9 q0a2
+ -1 11 22 434.34 154.56 546.00 132.01 79.2 161.8 q0a0
+ -1 17 40 -263.83 344.65 310.00 138.30 355.1 603.2 q0a7
+ 0 -20 -24 -53.51 785.82 649.00 279.11 919.8 56.2 q2a0
+ 0 -4 -6 -123.64 190.84 188.00 83.24 829.7 328.4 q2a2
+ 1 -43 -39 -104.60 173.22 240.00 68.40 811.6 517.9 q2a4
+ 1 -21 -25 1367.45 557.99 1297.00 231.95 896.3 28.3 q2a0
+ 1 21 58 -263.91 222.73 216.00 80.90 136.5 505.8 q0a4
+ 2 -6 -9 1042.10 170.69 482.00 71.10 785.7 269.4 q2a2
+ 2 2 3 4532.55 549.22 2943.00 135.59 396.1 348.0 q1a2
+ 2 20 52 153.88 143.28 171.00 86.96 223.4 496.5 q0a5
+ 2 22 66 -192.79 128.05 131.00 69.59 31.3 441.3 q0a4
+ 3 -35 -35 -252.89 171.27 158.00 78.49 947.2 603.0 q2a6
+ 3 -21 -25 91.30 307.51 544.00 204.30 837.7 10.2 q2a0
+ 3 15 32 -227.50 535.70 594.00 233.50 227.4 68.2 q0a1
+ 3 19 47 561.33 168.25 323.00 93.67 297.4 484.2 q0a5
+ 3 21 58 -159.54 201.13 229.00 76.34 154.0 441.0 q0a4
+ 4 -26 -29 201.81 333.91 305.00 136.19 1102.4 682.1 q2a7
+ 4 2 3 3923.43 274.36 1768.00 60.30 412.8 291.5 q1a2
+ 4 20 52 -187.55 136.02 157.00 85.91 240.7 433.2 q0a5
+ 5 -41 -38 -100.82 131.02 142.00 70.42 809.1 633.8 q2a6
+ 5 -39 -37 -72.94 90.29 109.00 67.94 849.3 644.7 q2a6
+ 5 -37 -36 139.68 97.53 120.00 70.92 888.4 655.3 q2a6
+ 5 3 5 393.25 171.15 171.00 60.75 396.2 255.8 q1a2
+ 6 -18 -22 -500.80 693.41 518.00 288.29 753.7 1448.1 q1a15
+ 6 -14 -18 1194.35 352.46 409.00 132.85 745.5 325.8 q1a3
+ 6 8 15 130.49 122.30 152.00 93.05 253.2 277.3 q0a3
+ 6 22 68 120.48 166.86 190.00 64.72 345.7 1073.2 q0a11
+ 7 -9 -12 1014.20 210.63 819.00 93.20 657.0 269.6 q1a3
+ 7 -3 -4 446.46 147.00 136.00 58.34 539.6 235.4 q1a2
+ 7 -1 -1 278.00 135.82 188.00 59.00 497.3 223.2 q1a2
+ 8 -30 -31 -515.84 416.06 395.00 94.04 750.0 1236.5 q1a13
+ 8 -4 -5 111.66 193.56 154.00 69.09 565.7 211.5 q1a2
+ 8 14 31 -207.48 440.11 437.00 203.52 372.2 125.7 q0a1
+ 8 20 55 -196.96 145.76 143.00 77.35 340.3 897.8 q0a9
+ 9 15 35 -44.14 270.53 371.00 158.51 81.6 1461.0 q0a14
+ 9 19 51 -230.93 176.78 179.00 82.33 326.4 834.4 q0a9
+ 9 21 64 -66.31 82.70 101.00 61.31 262.5 985.7 q0a11
+ 10 -22 -24 -63.48 190.55 229.00 140.28 649.8 1345.8 q1a15
+ 10 -2 -1 181.83 194.82 257.00 136.57 532.3 166.8 q1a0
+ 10 4 9 737.92 189.09 436.00 142.08 395.9 127.5 q1a0
+ 10 6 13 1305.12 469.77 732.00 165.67 360.5 344.9 q0a3
+ 11 -29 -29 -180.07 140.07 139.00 77.67 648.4 1232.7 q1a13
+ 11 -9 -10 232.04 302.96 447.00 203.16 678.1 175.0 q1a1
+ 11 3 8 1215.47 299.72 598.00 157.68 421.6 102.5 q1a0
+ 11 13 31 -15.03 354.61 445.00 182.10 153.2 1416.7 q0a14
+ 11 21 70 332.49 132.69 234.00 56.11 160.5 1054.7 q0a10
+ 12 -30 -29 42.02 118.85 146.00 72.78 618.9 1206.8 q1a13
+ 12 -8 -8 282.35 541.11 484.00 230.85 661.7 137.8 q1a1
+ 12 2 7 643.39 273.78 436.00 183.24 447.5 77.2 q1a0
+ 12 8 19 1377.03 652.73 591.00 253.08 311.6 1436.5 q0a15
+ 12 18 51 120.07 110.67 149.00 75.33 227.9 802.8 q0a9
+ 12 20 64 -125.29 124.16 115.00 61.09 160.1 954.8 q0a10
+ 13 -23 -23 -165.99 159.69 208.00 123.39 559.6 1308.5 q1a14
+ 13 -11 -11 636.66 584.65 612.00 228.54 726.1 121.2 q1a1
+ 13 7 18 231.99 565.34 521.00 240.59 337.5 1410.6 q0a15
+ 14 -32 -29 -70.75 134.62 123.00 64.75 561.0 1153.4 q1a12
+ 14 2 9 -104.80 334.77 467.00 198.12 448.3 9.9 q1a0
+ 14 6 17 106.08 626.33 554.00 228.45 363.7 1384.5 q0a15
+ 14 12 32 -466.91 388.31 381.00 154.90 176.0 1318.9 q0a14
+ 14 18 56 -155.76 199.86 259.00 77.36 135.3 847.3 q0a8
+ 14 20 73 -65.62 110.08 122.00 51.62 27.6 1069.6 q0a10
+ 15 -7 -4 1293.27 291.89 677.00 176.53 648.5 32.7 q1a1
+ 15 19 67 -97.19 87.65 90.00 55.19 30.7 966.0 q0a10
+ 16 -30 -26 -44.21 94.78 109.00 63.41 482.3 1181.1 q1a12
+ 16 -26 -23 119.38 103.69 138.00 67.62 467.8 1261.4 q1a12
+ 16 0 8 -15.34 646.64 460.00 210.09 757.9 634.6 q1a7
+ 16 16 51 125.30 114.47 105.00 70.30 93.7 755.4 q0a8
+ 17 1 11 0.27 375.48 380.00 167.53 714.0 660.2 q1a7
+ 17 3 15 157.77 349.39 388.00 155.39 696.5 713.5 q1a7
+ 18 -12 -7 -439.66 413.10 402.00 122.46 758.9 396.7 q1a5
+ 18 -6 1 -362.71 435.38 396.00 142.91 724.6 525.8 q1a5
+ 18 8 28 61.81 127.20 146.00 96.84 279.4 1235.0 q0a13
+ 18 14 48 -141.55 130.16 135.00 80.71 21.5 1129.0 q0a12
+ 19 -7 1 -157.06 300.33 325.00 117.06 692.5 504.7 q1a5
+ 19 9 33 194.53 146.80 167.00 89.42 230.2 1175.9 q0a13
+ 20 -16 -9 -214.35 163.79 164.00 77.15 747.1 821.4 q1a9
+ 20 -8 1 -332.74 174.47 225.00 100.14 659.9 483.2 q1a5
+ 20 -6 4 165.95 168.10 180.00 99.45 646.7 529.3 q1a5
+ 21 -7 4 -147.89 211.40 193.00 101.49 613.3 507.8 q1a5
+ 21 1 18 363.73 254.40 261.00 99.47 553.1 683.2 q1a6
+ 21 5 27 -345.41 163.32 202.00 96.25 342.9 1136.2 q0a13
+ 22 -26 -16 215.66 140.91 206.00 63.54 535.4 862.5 q1a8
+ 22 0 18 -221.84 167.28 163.00 92.04 517.9 663.4 q1a6
+ 23 -29 -17 35.00 94.46 94.00 58.00 467.6 896.2 q1a8
+ 24 -18 -5 -10.56 101.81 153.00 63.56 703.9 952.1 q1a11
+ 25 -17 -2 111.40 127.02 212.00 65.40 728.2 1002.8 q1a11
+ 25 -13 3 -253.14 148.93 127.00 70.74 475.5 382.8 q1a4
+ 25 -7 12 50.89 121.43 162.00 75.51 434.2 530.2 q1a4
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035157_1ce27.h5
+Image serial number: 10
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9506.871687
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9506.871687
+average_camera_length = 0.152001 m
+num_peaks = 42
+peak_resolution = 4.683999 nm^-1 or 2.134928 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 124.88 23.88 2.33 479.56 q0a0
+ 129.70 41.48 2.25 923.04 q0a0
+ 85.76 55.13 2.14 1387.24 q0a0
+ 66.50 57.09 2.12 2928.15 q0a0
+ 104.43 122.47 1.82 4764.71 q0a0
+ 301.22 165.06 2.12 4510.97 q0a1
+ 422.68 33.85 2.20 242.43 q1a0
+ 468.50 138.99 1.68 4592.53 q1a0
+ 789.95 95.12 1.88 6908.65 q2a0
+ 875.50 96.79 1.91 1569.62 q2a0
+1051.27 153.34 2.06 4518.55 q2a1
+1434.44 146.39 2.08 6417.83 q3a1
+ 146.17 200.88 1.36 2328.88 q0a2
+ 138.12 280.50 0.97 3109.29 q0a2
+ 88.95 348.13 0.51 2322.79 q0a2
+ 220.02 256.98 1.38 920.22 q0a3
+ 467.45 220.23 1.10 11959.41 q1a2
+ 537.50 259.07 1.07 344.95 q1a2
+ 436.50 269.88 0.81 1190.77 q1a2
+ 462.50 277.70 0.79 1127.44 q1a2
+ 711.05 232.03 1.88 4240.26 q1a3
+ 705.78 301.96 1.69 955.97 q1a3
+ 910.93 323.50 0.77 2195.51 q2a2
+1082.50 215.89 1.86 455.61 q2a3
+1053.29 284.19 1.55 4955.39 q2a3
+1025.29 331.50 1.31 2763.00 q2a3
+1312.50 201.07 1.35 2158.83 q3a2
+1205.50 213.62 1.12 2131.67 q3a2
+1268.50 231.34 1.10 9063.86 q3a2
+1263.80 262.61 0.93 6035.86 q3a2
+1324.96 276.15 1.06 2559.38 q3a2
+1259.19 293.50 0.77 2776.30 q3a2
+1324.50 316.02 0.91 3002.25 q3a2
+1218.50 327.91 0.51 3252.52 q3a2
+1207.50 329.04 0.49 439.15 q3a2
+1521.82 194.99 2.14 3365.46 q3a3
+1392.50 295.02 1.29 928.97 q3a3
+ 731.01 406.50 3.19 672.50 q1a5
+ 314.13 657.50 2.90 877.32 q0a7
+1310.06 799.50 4.11 285.60 q3a8
+ 638.04 1076.96 4.68 295.12 q1a11
+ 232.51 1459.47 2.37 2353.50 q0a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.11913 12.25531 16.84812 nm, 90.80982 90.67353 89.80557 deg
+astar = +0.0211854 +0.1128626 +0.1162922 nm^-1
+bstar = -0.0015605 -0.0585933 +0.0567794 nm^-1
+cstar = +0.0589170 -0.0062814 -0.0036602 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00210 nm^-1
+predict_refine/final_residual = 1.294359e-06
+predict_refine/det_shift x = -0.026 y = -0.088 mm
+diffraction_resolution_limit = 2.39 nm^-1 or 4.18 A
+num_reflections = 187
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -24 16 -50 -54.29 104.03 133.00 42.09 797.5 1055.0 q2a10
+ -23 17 -46 49.61 73.07 73.00 42.99 824.2 976.6 q2a10
+ -21 19 -36 139.82 93.02 95.00 58.49 869.8 833.9 q2a8
+ -21 23 34 77.74 110.54 130.00 69.03 1180.9 410.1 q3a4
+ -20 18 54 135.15 126.05 236.00 44.65 1343.4 1063.9 q3a10
+ -20 22 -20 122.91 98.02 109.00 69.14 870.4 1173.4 q2a12
+ -20 24 -3 301.45 109.23 123.00 74.34 1075.4 1131.9 q2a13
+ -20 24 19 -195.07 191.24 220.00 66.96 1240.7 575.1 q3a6
+ -20 24 20 -16.54 154.72 158.00 70.54 1239.0 562.7 q3a6
+ -19 13 -50 -112.40 94.49 95.00 50.60 1004.8 979.4 q2a11
+ -19 17 55 132.20 140.03 114.00 50.87 1330.8 1019.9 q3a10
+ -19 21 -22 -105.35 106.57 128.00 74.99 854.4 1218.3 q2a12
+ -19 23 -8 -96.40 125.01 138.00 80.46 1021.8 1182.0 q2a13
+ -19 23 24 461.36 128.22 209.00 70.56 1274.1 537.1 q3a4
+ -18 14 62 222.61 91.91 94.00 44.99 1224.1 974.7 q3a10
+ -18 16 56 121.30 145.51 181.00 53.30 1318.5 976.6 q3a10
+ -18 18 49 -30.29 105.69 110.00 57.56 1418.8 976.6 q3a11
+ -18 20 40 63.58 151.21 152.00 62.19 1543.1 973.2 q3a11
+ -18 22 -11 306.80 151.00 158.00 78.09 992.8 1227.7 q2a13
+ -18 22 27 59.28 242.17 287.00 77.06 1311.2 497.8 q3a4
+ -17 11 -51 30.93 80.14 98.00 51.67 1089.7 968.6 q2a11
+ -17 19 41 64.68 127.93 123.00 60.39 1529.6 932.6 q3a11
+ -17 21 29 -66.63 192.56 184.00 80.42 1349.3 471.1 q3a4
+ -16 8 -56 54.19 141.23 114.00 47.81 1155.4 1030.1 q2a11
+ -16 12 63 -66.14 113.66 111.00 56.74 1214.3 914.0 q3a8
+ -16 14 57 170.37 147.20 125.00 57.65 1307.1 917.8 q3a8
+ -16 16 -34 14.18 119.42 117.00 70.65 1055.4 755.2 q2a9
+ -16 18 -26 -80.07 184.56 182.00 99.27 831.5 1316.9 q2a14
+ -16 20 31 -181.47 197.72 196.00 88.81 1383.8 444.9 q3a5
+ -15 5 -60 76.49 89.44 103.00 56.11 806.8 394.5 q2a4
+ -15 11 63 -39.86 83.74 89.00 54.26 1216.4 870.4 q3a8
+ -15 13 -41 -240.30 243.69 298.00 74.11 1120.6 835.9 q2a9
+ -15 19 -16 -244.67 280.87 299.00 135.67 958.0 1325.4 q2a14
+ -15 19 32 340.08 121.82 131.00 80.69 1422.3 431.1 q3a5
+ -14 10 63 113.65 100.14 98.00 57.15 1218.5 827.7 q3a8
+ -14 14 51 231.62 112.95 118.00 58.99 1393.9 838.6 q3a9
+ -14 16 -27 -61.46 188.88 222.00 121.62 835.6 1394.8 q2a14
+ -14 16 43 109.77 147.00 143.00 67.92 1502.3 840.6 q3a9
+ -13 13 51 -6.13 86.29 110.00 65.33 1394.3 798.2 q3a9
+ -13 15 -27 486.66 183.85 216.00 120.99 843.2 1432.0 q2a14
+ -13 15 43 446.40 155.96 313.00 69.93 1501.7 801.0 q3a9
+ -13 17 33 -396.36 196.89 189.00 104.99 1498.8 416.0 q3a5
+ -12 8 -46 -38.29 126.12 132.00 78.56 1037.2 434.3 q2a5
+ -12 10 57 53.97 101.13 115.00 58.27 1311.9 751.7 q3a8
+ -12 14 43 -234.18 160.65 143.00 76.72 1501.1 762.1 q3a9
+ -11 7 62 73.46 104.70 105.00 56.15 1171.5 1162.9 q3a12
+ -11 15 -16 1798.77 558.65 586.00 202.05 980.8 1472.6 q2a15
+ -10 6 -45 481.49 130.40 286.00 87.32 1067.3 506.0 q2a5
+ -10 14 -15 2830.25 726.86 580.00 253.40 1149.7 202.5 q2a3
+ -10 14 31 452.30 164.40 353.00 155.30 1496.0 31.4 q3a1
+ -9 -1 -57 -124.59 148.22 174.00 70.79 912.9 591.9 q2a6
+ -9 5 -44 210.81 400.60 407.00 108.27 1087.5 540.3 q2a5
+ -9 7 55 -0.84 91.20 95.00 59.77 1242.9 1264.9 q3a12
+ -9 13 -14 424.90 456.44 436.00 154.72 1116.3 219.4 q2a3
+ -9 13 30 642.19 344.77 566.00 167.16 1486.7 68.9 q3a1
+ -8 -2 -56 427.79 146.09 182.00 67.41 935.4 626.3 q2a6
+ -8 0 -52 -218.27 219.35 302.00 90.29 988.8 599.1 q2a7
+ -8 2 64 170.49 88.00 107.00 56.11 1304.5 1129.1 q3a12
+ -8 8 -31 438.63 247.81 523.00 181.11 1022.5 60.3 q2a1
+ -8 8 47 -227.15 149.02 155.00 106.82 1274.3 1343.8 q3a14
+ -8 10 -23 5036.10 317.76 2753.00 178.39 1051.8 152.1 q2a1
+ -8 10 39 80.77 259.02 331.00 129.54 1268.1 1445.6 q3a14
+ -8 12 -12 401.63 161.00 201.00 103.48 1084.6 246.8 q2a3
+ -8 12 28 1175.99 337.49 480.00 184.37 1466.2 107.3 q3a1
+ -7 3 58 30.94 171.88 195.00 62.06 1332.0 1218.3 q3a12
+ -7 11 -9 5053.66 255.26 2333.00 85.84 1054.7 284.6 q2a3
+ -7 11 25 6492.70 417.86 3399.00 180.05 1435.0 146.3 q3a1
+ -6 -6 -57 -339.19 199.60 196.00 74.19 934.3 720.8 q2a6
+ -6 0 -45 -338.18 370.36 425.00 116.92 1095.7 637.6 q2a7
+ -6 10 -5 2721.69 205.27 2257.00 81.31 1026.4 332.6 q2a3
+ -5 7 32 4198.36 698.70 1315.00 205.69 1522.9 195.9 q3a3
+ -5 9 2 1248.13 154.84 720.00 63.55 1193.6 215.4 q3a2
+ -5 9 3 1946.05 170.03 1657.00 62.08 1204.3 214.2 q3a2
+ -5 9 4 366.78 116.76 139.00 60.72 1215.1 212.9 q3a2
+ -5 9 12 32.44 152.53 168.00 66.46 1301.4 202.9 q3a2
+ -5 9 13 2182.33 197.41 1222.00 67.10 1312.3 201.7 q3a2
+ -5 9 14 515.78 151.86 146.00 67.13 1323.1 200.4 q3a2
+ -4 -12 -60 111.43 93.07 166.00 61.17 692.4 1139.2 q1a13
+ -4 -10 -57 -65.98 131.45 135.00 66.78 722.0 1185.3 q1a13
+ -4 -4 -46 212.75 242.10 321.00 113.66 1094.5 728.0 q2a7
+ -4 4 -23 -369.00 172.27 203.00 122.00 903.0 175.0 q2a0
+ -4 4 39 -339.74 410.30 415.00 162.40 1423.2 1434.4 q3a15
+ -4 6 28 194.31 320.74 299.00 118.77 1480.1 234.7 q3a3
+ -3 -15 -61 -66.85 101.09 107.00 57.65 630.4 1127.1 q1a13
+ -3 -13 -58 209.05 99.75 92.00 56.47 661.2 1173.7 q1a13
+ -3 -11 -55 21.91 120.38 159.00 66.43 691.0 1218.8 q1a13
+ -3 -1 -34 150.96 336.76 446.00 173.88 815.1 55.1 q2a0
+ -3 5 -7 2026.37 241.77 1390.00 73.03 910.5 324.9 q2a2
+ -3 5 23 186.17 126.82 153.00 78.08 1427.1 273.8 q3a3
+ -2 -16 -59 -80.71 90.85 108.00 60.91 599.4 1161.9 q1a13
+ -2 -14 -56 175.36 128.38 118.00 66.24 630.4 1207.5 q1a13
+ -2 -12 -53 14.29 114.45 166.00 69.44 660.5 1251.9 q1a13
+ -2 -10 66 176.04 113.30 140.00 62.16 62.5 722.9 q0a6
+ -2 -4 53 220.01 287.32 350.00 84.45 1535.3 1271.7 q3a13
+ -2 -2 -31 5156.58 301.31 2238.00 135.87 786.9 94.9 q2a0
+ -2 2 -15 47.14 116.60 209.00 65.45 849.2 243.6 q2a2
+ -2 2 31 26.84 587.84 397.00 159.27 1522.2 316.6 q3a3
+ -2 4 2 548.44 201.48 465.00 73.79 1206.5 331.2 q3a2
+ -2 4 3 3246.05 214.45 1924.00 66.08 1217.1 330.0 q3a2
+ -2 4 4 -31.26 144.76 142.00 64.90 1227.8 328.8 q3a2
+ -2 4 12 899.26 196.27 290.00 58.10 1313.5 319.4 q3a2
+ -2 4 13 2632.56 263.00 1383.00 64.27 1324.2 318.2 q3a2
+ -2 4 14 39.41 164.91 153.00 51.09 1335.0 317.0 q3a2
+ -1 -13 67 78.70 98.75 97.00 61.70 37.5 663.6 q0a6
+ -1 -11 -47 174.80 193.90 182.00 100.13 661.1 1310.5 q1a15
+ -1 -7 55 -57.12 140.16 166.00 87.88 223.0 721.0 q0a7
+ -1 1 -10 815.24 145.92 524.00 64.40 823.6 301.9 q2a2
+ -1 1 26 254.50 184.59 216.00 92.50 1468.7 355.0 q3a3
+ 0 -20 -57 89.76 91.17 155.00 61.64 510.7 1196.1 q1a12
+ 0 -8 52 89.55 144.50 189.00 94.66 259.7 683.4 q0a7
+ 0 -4 -24 28.86 133.78 148.00 77.23 676.0 344.4 q1a3
+ 0 0 15 152.56 120.36 126.00 62.68 13.6 259.3 q0a2
+ 0 0 16 2573.84 209.73 2780.00 69.06 12.4 248.5 q0a2
+ 1 -25 -59 -159.15 109.44 120.00 58.35 415.0 1161.2 q1a12
+ 1 -17 65 62.41 109.80 100.00 58.79 53.6 564.3 q0a6
+ 1 -11 -37 -288.28 419.59 455.00 168.94 634.8 1444.8 q1a15
+ 1 -9 -32 1210.03 540.60 711.00 174.18 763.6 257.7 q1a3
+ 1 -5 35 2981.06 315.91 1501.00 173.20 64.3 56.5 q0a0
+ 1 -3 -9 -94.56 100.41 98.00 51.60 511.6 352.7 q1a2
+ 1 -3 25 -61.20 124.36 183.00 118.80 54.3 173.2 q0a0
+ 2 -20 65 86.35 108.16 122.00 59.85 41.0 528.5 q0a4
+ 2 -14 54 120.38 112.51 137.00 84.46 215.6 569.9 q0a7
+ 2 -10 -28 4621.75 382.61 1631.00 120.35 713.5 231.5 q1a3
+ 2 -10 44 878.89 269.58 393.00 118.68 354.3 608.1 q0a7
+ 2 -6 -13 499.00 205.62 191.00 57.29 550.2 295.4 q1a2
+ 2 -6 29 4942.38 339.56 3682.00 147.26 103.1 121.9 q0a0
+ 3 -23 -48 -50.45 108.73 150.00 87.05 426.0 1303.2 q1a14
+ 3 -21 -45 84.37 136.10 157.00 93.65 458.9 1345.6 q1a14
+ 3 -17 -38 -995.53 560.21 540.00 147.19 522.9 1437.7 q1a14
+ 3 -11 -23 370.89 176.10 386.00 84.29 653.1 206.6 q1a3
+ 3 -7 -3 -386.08 419.72 496.00 62.41 439.0 276.0 q1a2
+ 3 -7 -2 134.10 145.08 120.00 50.16 428.3 277.1 q1a2
+ 3 -7 18 -256.38 130.33 128.00 70.89 147.1 212.0 q0a2
+ 3 -7 19 2372.94 188.03 1187.00 71.06 146.0 201.1 q0a2
+ 4 -32 -54 110.18 127.17 141.00 58.42 530.4 839.7 q1a8
+ 4 -24 61 112.36 94.06 86.00 56.24 83.6 426.9 q0a4
+ 4 -22 -41 395.50 195.06 231.00 103.50 432.6 1399.6 q1a14
+ 4 -18 50 -251.64 151.48 188.00 82.58 254.5 501.3 q0a5
+ 4 -16 -29 2438.26 688.50 887.00 214.40 718.3 146.1 q1a1
+ 4 -12 33 1103.20 253.50 544.00 189.34 205.1 61.6 q0a1
+ 4 -10 -6 12081.22 369.71 8113.00 48.16 466.6 219.2 q1a2
+ 5 -41 -57 -19.10 74.12 75.00 44.90 458.0 996.4 q1a10
+ 5 -31 -48 -66.73 90.80 94.00 61.71 619.5 830.6 q1a9
+ 5 -27 -43 110.39 109.47 113.00 64.38 694.5 760.4 q1a9
+ 5 -21 -33 552.88 162.24 334.00 140.12 764.0 56.5 q1a1
+ 5 -19 45 447.00 131.96 184.00 84.86 315.2 464.2 q0a5
+ 5 -15 33 88.70 258.37 516.00 169.27 261.3 53.5 q0a1
+ 5 -13 23 269.32 212.32 306.00 156.71 247.1 171.8 q0a1
+ 6 -42 -53 -34.06 87.61 87.00 48.06 521.0 1023.8 q1a10
+ 6 -34 -46 44.27 86.98 93.00 62.71 644.3 893.6 q1a9
+ 6 -30 58 55.54 136.09 149.00 50.66 344.0 1012.1 q0a11
+ 6 -28 55 147.37 157.09 158.00 52.65 373.2 959.7 q0a11
+ 6 -24 48 -1.49 156.31 142.00 69.91 259.6 378.4 q0a5
+ 6 -22 44 299.45 128.68 172.00 78.62 318.1 403.6 q0a5
+ 6 -18 -16 1516.50 385.01 388.00 163.93 566.5 101.1 q1a0
+ 6 -16 -7 3786.94 546.57 2400.00 133.25 467.7 137.4 q1a0
+ 6 -16 23 4775.55 585.37 1976.00 205.64 302.8 164.6 q0a1
+ 7 -45 -50 26.84 141.53 140.00 48.96 559.8 1093.2 q1a10
+ 7 -33 -39 -170.94 218.08 232.00 70.84 744.4 882.4 q1a9
+ 7 -31 53 -111.79 90.96 102.00 51.59 306.4 945.3 q0a11
+ 7 -21 -14 -27.42 458.20 589.00 204.15 540.3 46.4 q1a0
+ 7 -19 -5 483.95 343.64 415.00 151.80 441.0 83.6 q1a0
+ 7 -19 -4 206.55 235.18 391.00 145.70 430.1 84.7 q1a0
+ 8 -36 53 -24.82 90.58 92.00 49.65 205.4 970.0 q0a11
+ 8 -32 47 9.18 88.07 132.00 68.08 268.3 894.8 q0a9
+ 8 -30 -27 54.67 363.83 506.00 99.33 689.0 466.0 q1a5
+ 8 -28 -23 -9.89 452.67 414.00 116.73 724.3 515.3 q1a5
+ 8 -24 27 763.37 234.37 548.00 141.81 93.7 1438.2 q0a14
+ 8 -22 2 -755.17 792.47 532.00 282.17 378.5 1441.7 q0a15
+ 8 -22 14 -242.50 472.38 415.00 209.50 244.2 1453.8 q0a15
+ 8 -22 15 -1253.33 1453.57 1772.00 231.33 232.9 1454.8 q0a15
+ 8 -22 16 -775.79 599.50 517.00 204.42 221.6 1455.8 q0a15
+ 9 -33 -23 269.80 159.08 216.00 85.72 630.5 515.2 q1a5
+ 9 -33 40 -90.96 132.76 155.00 69.22 230.7 806.2 q0a9
+ 9 -29 30 112.52 161.20 173.00 112.89 43.8 1350.7 q0a14
+ 9 -27 -6 110.03 447.56 409.00 148.18 742.8 686.5 q1a7
+ 9 -27 -5 -808.41 548.56 411.00 153.91 743.8 697.8 q1a7
+ 9 -27 22 63.20 237.76 292.00 142.77 144.2 1373.7 q0a14
+ 10 -40 -25 -212.62 162.76 176.00 73.46 496.9 487.5 q1a4
+ 10 -34 -13 323.77 129.00 219.00 98.70 611.3 610.0 q1a7
+ 10 -34 30 68.84 161.43 176.00 75.51 27.6 1283.6 q0a12
+ 10 -32 -6 208.07 160.60 173.00 106.75 651.0 691.7 q1a7
+ 11 -43 35 -246.01 123.41 103.00 65.63 23.2 781.1 q0a8
+ 11 -39 -10 -90.94 247.94 307.00 83.37 518.5 649.5 q1a6
+ 11 -39 27 -115.34 106.89 140.00 71.39 48.3 1180.9 q0a12
+ 11 -37 -3 -450.79 221.23 192.00 91.87 560.4 732.8 q1a6
+ 11 -37 20 -176.78 182.98 171.00 79.65 141.3 1209.9 q0a12
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035219_1ee2b.h5
+Image serial number: 4
+hit = 1
+indexed_by = none
+photon_energy_eV = 9503.785752
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9503.785752
+average_camera_length = 0.152001 m
+num_peaks = 59
+peak_resolution = 3.150323 nm^-1 or 3.174278 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 102.32 71.39 2.07 701.40 q0a0
+ 143.21 127.67 1.85 2956.69 q0a0
+ 532.13 48.13 2.21 2661.42 q1a0
+ 906.50 61.96 2.11 495.54 q2a0
+ 844.50 104.95 1.84 1855.18 q2a0
+1074.74 170.81 2.07 1949.06 q2a1
+1471.11 128.39 2.26 3396.42 q3a1
+1528.36 130.49 2.45 2095.34 q3a1
+ 161.50 230.19 1.27 3368.23 q0a2
+ 57.65 233.39 1.04 1373.61 q0a2
+ 52.56 238.34 1.01 6285.34 q0a2
+ 57.38 245.42 0.97 2905.90 q0a2
+ 21.50 251.94 0.93 956.43 q0a2
+ 162.71 263.50 1.13 1065.09 q0a2
+ 178.22 303.50 1.04 1101.80 q0a2
+ 100.83 316.50 0.69 1087.20 q0a2
+ 12.50 319.05 0.57 857.44 q0a2
+ 29.30 318.86 0.56 831.75 q0a2
+ 23.82 338.50 0.45 -123.85 q0a2
+ 39.85 345.50 0.42 3090.33 q0a2
+ 174.50 348.96 0.89 748.10 q0a2
+ 122.50 360.82 0.61 727.43 q0a2
+ 301.95 214.50 1.86 1428.65 q0a3
+ 458.07 262.31 0.87 2259.31 q1a2
+ 512.50 275.16 0.93 983.98 q1a2
+ 564.76 286.50 1.07 1083.82 q1a2
+ 422.50 287.65 0.71 1203.30 q1a2
+ 457.15 297.97 0.68 4331.16 q1a2
+ 489.50 308.83 0.70 1279.41 q1a2
+ 538.66 314.72 0.86 1760.65 q1a2
+ 438.66 324.18 0.52 4589.71 q1a2
+ 754.17 295.50 1.93 2124.41 q1a3
+ 873.50 200.12 1.22 2407.35 q2a2
+ 956.74 202.94 1.42 1649.36 q2a2
+ 907.75 302.50 0.83 1308.25 q2a2
+ 957.12 303.11 1.03 4387.96 q2a2
+ 952.90 350.50 0.89 657.34 q2a2
+1072.97 228.50 1.78 1114.95 q2a3
+1004.19 325.27 1.21 1720.01 q2a3
+1062.50 324.94 1.50 649.11 q2a3
+1277.50 224.51 1.15 3438.50 q3a2
+1322.50 244.96 1.18 666.22 q3a2
+1300.05 246.50 1.10 1360.81 q3a2
+1183.99 249.50 0.92 2005.43 q3a2
+1320.50 273.21 1.05 401.99 q3a2
+1305.50 275.74 0.99 776.04 q3a2
+1264.50 282.81 0.83 625.60 q3a2
+1204.50 286.02 0.72 1169.75 q3a2
+1273.79 287.50 0.83 1368.51 q3a2
+1296.47 289.42 0.90 6999.85 q3a2
+1228.50 291.96 0.71 2585.65 q3a2
+1335.09 305.50 0.99 916.11 q3a2
+1286.69 317.57 0.75 2800.94 q3a2
+1324.50 351.98 0.80 791.28 q3a2
+1279.17 361.50 0.56 611.44 q3a2
+1367.50 311.35 1.13 1909.64 q3a3
+1398.89 342.50 1.21 2102.83 q3a3
+1026.92 691.08 3.15 758.15 q2a7
+ 284.50 1453.84 2.29 1202.57 q0a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035119_198cc.h5
+Image serial number: 12
+hit = 1
+indexed_by = none
+photon_energy_eV = 9507.347050
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9507.347050
+average_camera_length = 0.152001 m
+num_peaks = 16
+peak_resolution = 2.565385 nm^-1 or 3.898051 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 156.50 95.79 2.02 1217.66 q0a0
+ 202.76 160.50 1.83 908.90 q0a1
+ 35.29 231.13 1.04 1268.85 q0a2
+ 11.50 237.75 1.01 1854.12 q0a2
+ 185.50 300.93 1.08 2539.16 q0a2
+ 128.98 324.34 0.76 3904.99 q0a2
+ 171.43 330.67 0.92 4173.56 q0a2
+ 34.50 332.06 0.49 1920.11 q0a2
+ 239.50 356.79 1.22 1227.54 q0a3
+ 722.32 229.71 1.93 1426.39 q1a3
+ 668.95 297.50 1.52 455.88 q1a3
+ 923.80 295.61 0.92 6295.74 q2a2
+ 928.50 305.17 0.90 1076.73 q2a2
+1237.75 262.98 0.88 2934.38 q3a2
+1371.40 318.50 1.13 2020.95 q3a3
+ 215.50 1425.12 2.57 520.82 q0a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035137_1b2a6.h5
+Image serial number: 13
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9515.964196
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9515.964196
+average_camera_length = 0.152001 m
+num_peaks = 47
+peak_resolution = 2.714785 nm^-1 or 3.683533 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 151.36 52.88 2.23 1279.66 q0a0
+ 73.50 86.85 1.97 1524.35 q0a0
+ 107.32 97.40 1.95 5345.50 q0a0
+ 15.50 133.89 1.72 1504.55 q0a0
+ 207.50 159.74 1.85 1377.31 q0a1
+ 712.84 103.02 2.41 1569.41 q1a1
+ 862.50 34.55 2.21 1727.39 q2a0
+ 798.01 36.49 2.18 7941.38 q2a0
+ 866.40 68.23 2.04 3125.20 q2a0
+ 847.84 90.61 1.92 1934.15 q2a0
+ 942.50 129.14 1.85 1231.65 q2a0
+ 910.50 150.98 1.68 967.09 q2a0
+1030.50 52.93 2.41 1626.88 q2a1
+1149.56 143.53 2.44 1445.51 q2a1
+1252.17 19.81 2.30 3101.45 q3a0
+1185.31 39.52 2.18 2381.41 q3a0
+1290.11 85.48 2.01 2998.19 q3a0
+1345.42 104.75 2.01 3224.80 q3a0
+1341.50 160.88 1.74 1908.94 q3a0
+1385.78 90.76 2.17 2751.34 q3a1
+1464.90 114.00 2.30 2032.62 q3a1
+1416.66 153.17 1.99 1523.31 q3a1
+1372.98 166.73 1.80 2114.84 q3a1
+1479.06 166.92 2.15 2076.31 q3a1
+ 145.06 243.64 1.16 4749.09 q0a2
+ 58.69 268.80 0.85 1746.30 q0a2
+ 550.61 264.04 1.10 2627.77 q1a2
+ 449.64 285.22 0.74 16163.30 q1a2
+ 476.50 293.32 0.74 1768.81 q1a2
+ 503.09 304.34 0.77 1089.86 q1a2
+ 494.50 358.63 0.52 1765.34 q1a2
+ 842.70 206.50 1.15 2069.51 q2a2
+ 920.95 265.50 1.03 1029.62 q2a2
+ 945.21 324.44 0.92 29150.36 q2a2
+1026.22 243.18 1.54 1562.23 q2a3
+1136.90 268.66 1.97 3884.69 q2a3
+1243.50 212.21 1.15 614.43 q3a2
+1284.50 248.10 1.05 2058.92 q3a2
+1215.31 249.80 0.92 3505.86 q3a2
+1320.50 285.89 1.00 1016.96 q3a2
+1225.53 315.28 0.58 8305.64 q3a2
+1223.50 343.03 0.44 345.90 q3a2
+1260.97 352.50 0.51 1178.52 q3a2
+ 110.49 1461.61 2.71 3153.66 q0a14
+ 714.40 1436.55 2.29 6115.60 q1a15
+1041.50 1380.88 2.66 959.27 q2a15
+1071.00 1442.91 2.32 1990.93 q2a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.15326 12.23272 16.88779 nm, 90.02603 90.23742 90.06821 deg
+astar = -0.0336553 -0.1528320 +0.0438345 nm^-1
+bstar = -0.0678258 +0.0017537 -0.0455995 nm^-1
+cstar = +0.0306460 -0.0203217 -0.0464139 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00531 nm^-1
+predict_refine/final_residual = 1.844770e-06
+predict_refine/det_shift x = -0.004 y = -0.017 mm
+diffraction_resolution_limit = 2.41 nm^-1 or 4.15 A
+num_reflections = 491
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -26 -18 24 -133.39 143.20 132.00 61.99 26.2 895.9 q0a8
+ -25 -23 32 16.81 67.00 84.00 46.19 86.9 1002.9 q0a10
+ -25 -21 28 36.25 114.45 107.00 47.75 78.9 934.2 q0a10
+ -25 -17 21 -129.85 107.52 111.00 63.65 62.4 840.5 q0a8
+ -25 -15 18 291.34 112.13 136.00 61.46 54.1 787.3 q0a8
+ -25 -11 12 296.51 136.59 164.00 76.68 26.7 1127.3 q0a12
+ -24 -24 33 79.20 107.79 94.00 47.20 130.9 1012.2 q0a10
+ -24 -22 29 -111.01 84.66 85.00 50.61 122.3 943.7 q0a10
+ -24 -20 25 215.24 115.27 205.00 64.36 113.6 904.6 q0a8
+ -24 -10 10 -202.80 138.15 142.00 71.20 66.5 1160.6 q0a12
+ -24 -6 5 36.21 174.06 199.00 81.59 157.4 1143.1 q0a12
+ -24 12 -11 -52.95 125.65 145.00 78.55 430.9 637.6 q1a6
+ -23 -25 34 -98.79 133.89 142.00 51.59 174.3 1021.3 q0a10
+ -23 -23 30 68.65 131.11 134.00 52.15 165.1 953.2 q0a10
+ -23 -21 26 8.25 148.66 182.00 62.75 155.8 914.4 q0a8
+ -23 -17 19 -269.12 170.84 187.00 71.12 138.4 797.9 q0a8
+ -23 -13 13 -13.93 143.53 132.00 79.33 14.7 1210.8 q0a12
+ -23 -3 1 73.46 120.16 169.00 81.34 232.0 1166.5 q0a13
+ -23 -1 -1 -26.65 121.26 127.00 79.85 272.3 1157.5 q0a13
+ -23 1 -3 -248.49 135.62 143.00 88.89 312.6 1148.5 q0a13
+ -23 3 -5 367.24 165.65 233.00 86.36 352.8 1139.5 q0a13
+ -23 11 -11 299.64 94.82 124.00 74.76 474.0 645.6 q1a6
+ -23 19 -16 183.04 173.33 207.00 74.16 433.3 523.8 q1a4
+ -23 21 -17 -67.62 190.55 248.00 77.01 422.8 486.9 q1a4
+ -22 -26 35 11.86 112.65 181.00 51.74 214.1 1030.3 q0a11
+ -22 -24 31 262.28 106.92 120.00 50.08 204.3 962.5 q0a11
+ -22 -18 20 -21.70 200.73 191.00 67.81 179.3 808.1 q0a8
+ -22 -12 11 18.45 126.86 129.00 76.95 53.9 1242.3 q0a12
+ -22 -2 -1 29.23 134.72 136.00 84.97 267.7 1198.2 q0a13
+ -22 6 -8 -176.30 186.61 197.00 89.70 534.4 727.5 q1a6
+ -22 10 -11 394.01 185.43 190.00 85.39 515.9 653.4 q1a6
+ -21 -27 36 -135.40 92.77 101.00 51.60 256.3 1039.2 q0a11
+ -21 -25 32 42.49 97.26 105.00 51.32 245.9 971.7 q0a11
+ -21 -21 24 -267.32 176.57 187.00 71.92 225.8 870.0 q0a9
+ -21 -11 9 76.18 110.55 136.00 79.42 92.1 1273.0 q0a12
+ -21 -7 4 437.23 326.07 338.00 88.97 179.8 1255.3 q0a12
+ -21 3 -6 553.62 184.91 296.00 88.38 374.4 1211.0 q0a13
+ -21 9 -11 15.41 180.24 197.00 86.79 556.7 661.0 q1a6
+ -21 25 -20 -165.96 129.40 114.00 70.16 479.2 397.9 q1a4
+ -21 33 -23 -14.43 102.33 160.00 58.83 684.4 1063.6 q1a11
+ -21 37 -24 -37.25 133.32 180.00 58.25 606.1 1087.6 q1a11
+ -20 -28 38 -206.32 111.18 117.00 53.78 298.8 1060.6 q0a11
+ -20 -26 33 -70.32 89.05 91.00 52.92 287.0 980.8 q0a11
+ -20 -22 25 -115.62 99.23 118.00 70.62 265.8 879.7 q0a9
+ -20 -6 2 29.67 193.44 204.00 101.46 212.6 1285.2 q0a13
+ -20 -4 0 62.16 152.94 181.00 94.04 251.6 1276.4 q0a13
+ -19 -15 13 518.61 134.42 199.00 106.99 31.6 1331.5 q0a14
+ -19 -9 5 -18.77 200.14 234.00 130.61 165.7 1304.4 q0a14
+ -19 5 -9 42.60 199.87 276.00 119.60 640.7 714.3 q1a7
+ -19 9 -12 -73.71 146.93 222.00 110.91 623.5 642.5 q1a7
+ -19 25 -21 -37.31 170.56 171.00 81.31 553.9 384.8 q1a4
+ -19 33 -24 201.75 113.33 144.00 58.25 673.7 985.4 q1a11
+ -19 37 -25 -184.54 132.63 112.00 61.34 596.8 1007.2 q1a11
+ -19 43 -26 15.19 70.01 82.00 49.81 478.8 1042.5 q1a10
+ -18 -26 32 54.86 116.75 121.00 56.74 357.2 945.3 q0a11
+ -18 -24 28 554.09 178.55 346.00 70.32 345.5 909.4 q0a9
+ -18 -22 24 84.05 165.80 172.00 73.55 334.5 847.8 q0a9
+ -18 -16 14 127.50 224.56 246.00 126.50 21.3 1369.5 q0a14
+ -18 -14 11 -39.38 147.57 193.00 120.99 69.0 1360.0 q0a14
+ -18 -10 6 625.60 246.58 319.00 142.60 154.7 1342.0 q0a14
+ -18 -4 -1 33.61 233.95 248.00 148.99 274.5 1315.8 q0a15
+ -18 -2 -3 -236.08 236.24 258.00 155.68 312.8 1307.3 q0a15
+ -18 6 -10 -49.16 327.58 359.00 129.96 670.1 688.5 q1a7
+ -18 10 -13 12.25 153.86 160.00 110.75 653.1 616.9 q1a7
+ -18 16 -17 134.75 235.96 288.00 98.25 626.8 538.1 q1a5
+ -18 18 -18 -44.91 153.46 195.00 91.71 618.2 503.4 q1a5
+ -18 20 -19 275.01 125.81 216.00 86.39 609.4 468.3 q1a5
+ -18 22 -20 -298.52 157.33 182.00 90.72 600.6 432.7 q1a5
+ -18 24 -21 6.44 124.72 138.00 83.56 591.6 396.7 q1a5
+ -18 32 -24 31.39 87.54 88.00 61.01 687.8 942.7 q1a11
+ -18 36 -25 55.21 100.58 123.00 59.59 612.3 963.3 q1a11
+ -18 40 -26 165.34 103.43 144.00 52.46 536.5 984.7 q1a10
+ -17 -17 15 282.65 178.17 225.00 121.72 11.2 1407.0 q0a14
+ -17 -11 7 581.17 320.29 347.00 153.43 143.9 1379.2 q0a14
+ -17 -7 2 -317.75 367.93 524.00 165.75 225.0 1361.3 q0a15
+ -17 -5 0 -401.01 235.61 244.00 163.61 263.1 1352.8 q0a15
+ -17 1 -6 -69.10 282.21 332.00 171.90 377.2 1327.4 q0a15
+ -17 7 -11 -262.42 284.57 346.00 144.82 699.1 662.9 q1a7
+ -17 11 -14 130.95 200.82 298.00 120.45 682.4 591.7 q1a7
+ -17 19 -19 -449.59 152.12 180.00 93.79 648.4 478.8 q1a5
+ -17 21 -20 -73.23 122.28 126.00 86.03 639.9 443.7 q1a5
+ -17 39 -26 148.81 123.54 211.00 57.19 553.0 940.7 q1a10
+ -17 45 -27 181.69 92.62 90.00 45.31 431.1 973.3 q1a10
+ -16 -30 40 -124.66 108.44 95.00 58.46 58.7 401.9 q0a4
+ -16 -12 8 4.00 397.63 455.00 165.00 133.2 1415.9 q0a14
+ -16 -8 3 379.30 329.81 447.00 177.30 213.9 1397.9 q0a15
+ -16 4 -9 823.69 533.85 459.00 175.31 743.9 707.8 q1a7
+ -16 8 -12 -635.58 428.00 397.00 160.18 727.7 637.7 q1a7
+ -16 12 -15 814.88 172.08 352.00 121.12 711.3 566.7 q1a7
+ -16 28 -23 -96.99 138.29 178.00 67.39 751.7 879.2 q1a9
+ -16 34 -25 83.84 91.97 106.00 62.96 641.7 906.3 q1a9
+ -15 -27 33 116.65 149.42 133.00 67.15 179.6 415.3 q0a4
+ -15 -21 21 -43.12 180.70 172.00 94.96 357.7 379.2 q0a5
+ -15 -13 9 -29.35 473.71 428.00 170.15 122.7 1452.1 q0a14
+ -15 -9 4 -972.69 434.04 495.00 198.69 202.9 1434.0 q0a15
+ -15 9 -13 69.62 456.29 526.00 175.38 756.0 612.8 q1a7
+ -15 15 -17 793.86 437.79 430.00 139.74 731.6 537.2 q1a5
+ -15 27 -23 639.81 208.74 305.00 67.49 764.2 840.1 q1a9
+ -15 33 -25 -117.31 101.02 109.00 66.31 656.0 865.8 q1a9
+ -15 43 -27 -101.43 98.57 90.00 58.83 467.0 912.2 q1a8
+ -14 -28 35 49.10 133.45 147.00 65.10 159.4 455.3 q0a4
+ -14 -18 16 318.41 207.12 284.00 158.79 370.9 24.4 q0a1
+ -14 -4 -2 -142.68 751.45 657.00 262.18 310.9 1443.4 q0a15
+ -14 -2 -4 -414.15 715.68 580.00 300.35 348.0 1435.1 q0a15
+ -14 18 -19 268.89 412.80 408.00 144.51 752.7 479.3 q1a5
+ -14 20 -20 -276.95 317.78 319.00 121.55 745.1 445.2 q1a5
+ -14 22 -21 -301.06 238.91 251.00 111.06 737.4 410.6 q1a5
+ -14 30 -24 125.93 129.67 167.00 70.67 707.0 818.0 q1a9
+ -14 36 -26 -26.25 110.30 109.00 64.25 596.5 843.3 q1a9
+ -14 42 -27 -12.15 95.04 128.00 58.35 484.4 869.9 q1a8
+ -13 -31 42 -25.45 102.46 114.00 63.05 62.6 511.7 q0a4
+ -13 -29 37 -159.25 168.19 162.00 69.25 139.1 495.2 q0a4
+ -13 -21 21 220.65 324.10 381.00 118.15 376.8 443.4 q0a5
+ -13 -3 -3 -384.09 702.90 540.00 287.29 336.5 1470.3 q0a15
+ -13 -1 -5 -135.35 680.79 708.00 283.15 373.4 1462.0 q0a15
+ -13 5 -10 56.26 316.14 505.00 197.14 458.4 30.5 q1a0
+ -13 27 -23 44.89 158.34 149.00 77.51 756.1 772.1 q1a9
+ -13 33 -25 -113.82 106.07 102.00 65.42 649.1 795.6 q1a9
+ -13 41 -27 86.99 163.34 209.00 58.61 501.3 828.7 q1a8
+ -12 -28 35 613.77 242.62 258.00 71.03 181.8 521.2 q0a4
+ -12 -18 16 898.92 209.39 547.00 171.68 308.3 42.8 q0a1
+ -12 -16 13 32.01 332.44 424.00 191.39 319.0 88.6 q0a1
+ -12 -14 10 -158.36 600.16 495.00 225.70 329.5 133.9 q0a1
+ -12 -4 -2 211.10 711.35 493.00 217.10 374.9 305.7 q0a3
+ -12 6 -11 127.04 428.11 549.00 192.16 483.0 57.3 q1a0
+ -12 10 -14 -908.56 634.36 588.00 248.56 551.7 41.9 q1a0
+ -12 18 -19 -1.04 175.68 267.00 158.84 684.4 11.5 q1a1
+ -12 30 -24 77.27 108.36 128.00 68.53 699.6 749.8 q1a9
+ -12 36 -26 34.54 98.53 101.00 63.66 590.4 772.9 q1a9
+ -12 42 -27 219.39 106.60 109.00 55.01 479.6 796.6 q1a8
+ -11 -13 9 -633.81 618.81 482.00 238.81 303.3 160.7 q0a1
+ -11 -3 -3 86.82 355.63 330.00 143.21 348.6 330.8 q0a3
+ -11 5 -10 -388.05 277.71 389.00 162.45 470.8 92.2 q1a0
+ -11 9 -13 17.20 572.20 474.00 217.20 539.0 77.0 q1a0
+ -11 13 -16 504.30 516.51 523.00 223.30 605.0 61.7 q1a1
+ -11 15 -17 942.80 360.17 520.00 188.80 637.7 54.6 q1a1
+ -11 41 -27 -86.53 104.86 114.00 59.73 496.4 757.1 q1a8
+ -10 -30 40 -165.52 128.70 129.00 71.72 131.4 576.3 q0a6
+ -10 -22 23 -1317.35 589.80 396.00 158.15 376.6 543.5 q0a5
+ -10 -10 5 -59.18 205.07 251.00 116.21 288.3 203.5 q0a3
+ -10 4 -9 56.21 180.36 239.00 131.59 458.7 126.7 q1a0
+ -10 12 -15 448.41 477.09 514.00 211.79 592.0 96.7 q1a1
+ -10 30 -24 -307.70 175.77 201.00 114.30 416.3 1369.0 q1a14
+ -9 -33 49 -185.49 131.85 141.00 63.89 10.0 643.9 q0a6
+ -9 -31 43 88.75 112.81 148.00 66.25 99.9 619.8 q0a6
+ -9 -29 38 200.06 144.41 169.00 69.94 174.2 600.4 q0a6
+ -9 -25 29 -176.82 198.05 247.00 105.42 301.2 566.9 q0a7
+ -9 -19 18 -263.78 430.99 440.00 207.65 210.3 42.7 q0a1
+ -9 -17 15 515.23 465.59 484.00 220.97 221.5 88.0 q0a1
+ -9 -15 12 -614.63 360.32 368.00 198.01 232.6 132.8 q0a1
+ -9 -9 4 -43.00 184.88 175.00 93.57 262.6 229.1 q0a3
+ -9 -7 2 733.95 154.78 236.00 90.45 270.7 265.4 q0a3
+ -9 3 -8 539.38 177.23 447.00 123.62 446.8 160.8 q1a0
+ -9 17 -18 160.69 399.77 431.00 209.31 680.7 109.7 q1a1
+ -9 19 -19 1185.17 525.60 746.00 216.43 713.8 103.0 q1a1
+ -9 21 -20 -112.01 519.63 595.00 187.61 747.3 96.1 q1a1
+ -9 25 -22 -64.74 214.54 339.00 130.14 465.7 1451.8 q1a14
+ -9 31 -24 -15.64 144.46 156.00 102.24 446.1 1348.7 q1a14
+ -9 43 -27 -125.28 110.51 103.00 63.48 404.4 1154.9 q1a12
+ -8 -30 41 -178.80 139.39 138.00 72.20 143.4 643.5 q0a6
+ -8 -28 36 -163.91 161.13 179.00 93.71 212.8 623.9 q0a7
+ -8 -20 20 -600.62 405.16 482.00 203.62 176.4 24.6 q0a0
+ -8 -14 11 1377.31 226.17 846.00 156.69 207.2 159.3 q0a1
+ -8 -6 1 -21.77 133.91 184.00 90.97 245.3 290.6 q0a3
+ -8 -4 -1 -302.32 144.85 150.00 89.92 253.3 326.6 q0a3
+ -8 -2 -3 -292.85 152.18 154.00 90.41 261.4 362.7 q0a3
+ -8 14 -16 258.40 236.28 339.00 174.40 634.8 150.9 q1a1
+ -8 16 -17 302.26 273.03 425.00 190.14 667.2 144.5 q1a1
+ -8 24 -21 -8.29 371.53 388.00 153.09 501.5 1466.5 q1a14
+ -8 26 -22 730.35 319.60 472.00 139.85 494.8 1432.0 q1a14
+ -8 32 -24 245.09 162.91 167.00 98.71 475.9 1328.4 q1a14
+ -8 40 -26 -102.14 103.23 108.00 61.74 449.8 1210.6 q1a12
+ -7 -33 50 -72.35 133.13 124.00 67.15 23.2 713.1 q0a6
+ -7 -31 44 -386.48 126.55 142.00 76.05 112.2 687.3 q0a6
+ -7 -29 39 422.44 212.58 235.00 77.56 185.7 666.6 q0a6
+ -7 -25 30 -303.66 210.49 236.00 115.91 311.6 631.1 q0a7
+ -7 -23 26 -172.10 437.25 379.00 140.90 368.4 615.9 q0a7
+ -7 -19 19 1279.66 608.00 1078.00 239.54 151.1 52.2 q0a0
+ -7 -17 16 -481.46 571.06 585.00 208.66 162.6 97.2 q0a0
+ -7 -15 13 456.55 272.34 368.00 148.05 173.9 141.7 q0a0
+ -7 -9 5 2152.27 195.28 979.00 88.71 201.6 236.9 q0a3
+ -7 27 -22 808.91 253.36 376.00 138.29 523.8 1412.2 q1a14
+ -7 33 -24 95.36 143.68 147.00 105.24 505.7 1308.1 q1a14
+ -7 41 -26 57.39 88.07 100.00 63.01 480.8 1189.4 q1a12
+ -6 -26 33 155.72 180.06 227.00 105.13 283.1 672.8 q0a7
+ -6 -18 18 154.61 458.20 499.00 204.99 126.0 79.5 q0a0
+ -6 -16 15 525.95 236.49 570.00 154.45 137.6 124.0 q0a0
+ -6 -14 12 685.14 147.91 297.00 129.26 149.1 168.0 q0a0
+ -6 2 -6 231.30 142.11 122.00 53.30 442.0 226.1 q1a2
+ -6 8 -11 384.96 175.80 533.00 64.84 544.6 204.5 q1a2
+ -6 28 -22 105.92 371.98 376.00 145.68 552.9 1392.5 q1a14
+ -6 38 -25 -372.93 262.46 276.00 81.33 523.8 1243.3 q1a12
+ -6 44 -26 -175.91 96.36 103.00 61.71 506.5 1130.0 q1a12
+ -5 -27 36 -421.96 145.77 168.00 103.10 254.1 715.0 q0a7
+ -5 -17 17 726.94 216.38 300.00 160.16 101.3 106.4 q0a0
+ -5 -15 14 327.88 164.22 262.00 142.12 113.0 150.5 q0a0
+ -5 -9 6 4685.84 286.21 2497.00 78.96 144.2 244.6 q0a2
+ -5 5 -8 236.29 139.11 124.00 55.91 496.3 245.6 q1a2
+ -4 -20 23 171.34 353.47 407.00 202.91 49.1 35.5 q0a0
+ -4 -16 16 30.14 153.11 197.00 137.45 76.9 133.0 q0a0
+ -4 -10 8 60.52 120.74 125.00 71.28 108.7 227.1 q0a2
+ -4 -6 3 34.77 200.11 256.00 73.03 127.9 305.2 q0a2
+ -4 -4 1 10.98 137.76 198.00 75.22 135.8 340.9 q0a2
+ -4 0 -3 8.71 135.94 113.00 53.09 412.9 294.1 q1a2
+ -4 2 -5 16227.95 421.44 8218.00 49.45 448.5 286.1 q1a2
+ -4 8 -10 2647.74 236.04 1210.00 58.86 550.6 265.0 q1a2
+ -4 14 -14 53.38 170.79 160.00 84.62 646.7 246.3 q1a3
+ -4 28 -21 289.71 202.80 309.00 143.09 614.1 1387.9 q1a15
+ -4 30 -22 389.81 213.90 260.00 136.19 608.1 1352.9 q1a15
+ -3 -29 43 -65.65 161.78 204.00 76.85 1504.5 1199.0 q3a13
+ -3 -27 38 -229.09 298.10 282.00 93.29 1527.4 1269.6 q3a13
+ -3 -19 22 559.44 305.77 353.00 189.85 24.7 62.9 q0a0
+ -3 -11 10 53.32 207.45 324.00 70.08 73.1 209.6 q0a2
+ -3 -7 5 454.52 114.89 315.00 67.28 92.5 287.9 q0a2
+ -3 5 -7 1255.14 156.73 568.00 57.26 502.6 305.5 q1a2
+ -3 9 -10 -77.66 215.63 184.00 55.46 569.1 292.5 q1a2
+ -3 15 -14 -147.71 152.73 160.00 85.91 665.4 274.1 q1a3
+ -3 29 -21 -69.48 228.60 246.00 142.28 643.1 1368.3 q1a15
+ -3 41 -24 -158.12 97.27 105.00 68.12 614.7 1182.3 q1a13
+ -2 -30 47 -18.06 79.68 104.00 68.16 1454.9 1157.5 q3a13
+ -2 -16 18 1143.92 197.78 703.00 135.68 12.9 134.2 q0a0
+ -2 -14 15 2057.76 207.76 1767.00 126.03 25.1 178.0 q0a0
+ -2 -12 12 270.63 123.03 137.00 64.99 37.5 192.1 q0a2
+ -2 -8 7 1664.74 168.54 973.00 69.86 57.1 270.5 q0a2
+ -2 6 -7 -68.45 192.67 166.00 60.05 520.9 332.8 q1a2
+ -2 14 -13 -69.38 149.30 183.00 82.38 652.1 307.0 q1a3
+ -2 16 -14 -720.85 266.78 284.00 99.65 684.1 301.9 q1a3
+ -2 26 -19 -622.42 420.99 413.00 177.82 683.0 1417.9 q1a15
+ -2 28 -20 508.81 206.91 417.00 149.19 677.6 1383.5 q1a15
+ -2 38 -23 80.30 107.08 124.00 69.30 654.6 1235.7 q1a13
+ -2 44 -24 -361.50 139.06 119.00 64.50 642.1 1123.5 q1a13
+ -1 -29 46 81.56 102.36 157.00 71.44 1429.4 1189.2 q3a13
+ -1 -19 24 -139.87 642.93 544.00 227.67 1530.3 1467.8 q3a15
+ -1 -9 9 34.60 115.39 142.00 67.09 21.8 253.1 q0a2
+ -1 7 -7 35.80 232.88 201.00 56.80 539.3 360.1 q1a2
+ -1 17 -14 63.89 147.57 154.00 95.51 702.9 329.7 q1a3
+ -1 19 -15 -837.24 348.37 358.00 120.64 735.4 324.8 q1a3
+ -1 21 -16 -675.66 591.84 453.00 191.91 768.4 319.8 q1a3
+ -1 23 -17 -632.35 678.68 491.00 234.15 722.1 1466.3 q1a15
+ -1 25 -18 -581.05 1045.28 1066.00 238.45 716.9 1432.6 q1a15
+ -1 27 -19 256.02 298.29 482.00 173.78 711.7 1398.5 q1a15
+ -1 37 -22 -149.54 151.98 167.00 79.34 690.4 1252.4 q1a13
+ -1 41 -23 125.22 97.52 100.00 64.24 682.0 1178.8 q1a13
+ 0 -28 45 130.60 109.66 116.00 73.60 1404.3 1220.4 q3a13
+ 0 -24 35 -57.82 177.00 197.00 128.14 1453.2 1330.7 q3a15
+ 0 -22 31 912.17 223.44 415.00 154.43 1471.4 1386.8 q3a15
+ 0 -20 27 -84.20 681.16 487.00 238.80 1489.1 1441.5 q3a15
+ 0 -16 20 236.27 356.90 318.00 127.53 1504.9 335.6 q3a3
+ 0 -14 17 -235.16 220.19 253.00 100.96 1461.0 347.9 q3a3
+ 0 -12 14 117.31 135.87 159.00 83.69 1417.7 360.1 q3a3
+ 0 -4 4 -1153.95 829.23 474.00 202.84 14.1 349.0 q0a2
+ 0 32 -20 -114.27 183.13 321.00 137.47 733.3 1311.6 q1a15
+ 0 36 -21 38.80 191.19 194.00 88.80 725.8 1268.9 q1a13
+ 0 40 -22 2.11 102.47 127.00 73.49 718.1 1196.1 q1a13
+ 1 -27 44 78.50 172.58 184.00 82.50 1379.5 1251.2 q3a13
+ 1 -21 30 485.41 293.78 351.00 162.42 1447.4 1414.8 q3a15
+ 1 -17 23 1728.65 686.43 774.00 195.15 1530.4 294.9 q3a3
+ 1 -11 14 -45.90 141.52 148.00 83.94 1399.3 332.5 q3a3
+ 1 3 -2 2369.75 1327.32 964.00 570.25 823.9 358.7 q2a2
+ 1 9 -7 52.96 138.99 156.00 73.79 803.7 256.9 q2a2
+ 1 35 -20 201.80 273.49 309.00 88.80 760.8 1285.2 q1a13
+ 1 39 -21 -945.77 301.86 274.00 87.97 753.8 1213.2 q1a13
+ 2 -24 38 301.84 168.09 189.00 119.84 1380.7 1322.2 q3a15
+ 2 -22 34 901.71 206.79 565.00 139.56 1400.0 1378.8 q3a15
+ 2 -20 30 710.25 311.89 588.00 172.34 1418.7 1434.0 q3a15
+ 2 -8 11 42.55 195.75 148.00 58.05 1341.3 317.3 q3a2
+ 2 -2 4 -389.29 462.80 461.00 112.09 1228.2 345.5 q3a2
+ 2 0 2 -310.55 1219.31 858.00 432.95 1192.7 353.5 q3a2
+ 2 8 -5 156.96 120.01 123.00 69.84 839.1 274.1 q2a2
+ 2 12 -8 282.59 130.10 126.00 70.21 826.9 207.1 q2a2
+ 2 18 -12 -185.34 254.98 356.00 133.54 809.4 136.2 q2a0
+ 2 20 -13 371.46 214.43 256.00 144.34 804.8 103.5 q2a0
+ 2 22 -14 -649.50 402.26 407.00 184.50 800.2 70.5 q2a0
+ 2 24 -15 8079.70 674.81 2959.00 219.70 795.5 37.0 q2a0
+ 3 -29 54 69.23 82.10 104.00 65.97 1265.6 1146.2 q3a12
+ 3 -27 48 259.20 135.07 199.00 74.20 1300.7 1231.2 q3a12
+ 3 -17 26 2240.62 727.39 1049.00 276.54 1537.4 225.3 q3a3
+ 3 -7 11 1217.32 208.60 355.00 71.08 1322.9 289.8 q3a2
+ 3 29 -16 -760.20 585.39 453.00 166.80 1144.5 697.6 q2a7
+ 3 31 -17 -7.69 297.80 371.00 127.69 1109.5 702.2 q2a7
+ 3 35 -18 331.05 132.26 162.00 101.55 1040.1 707.3 q2a7
+ 3 45 -20 81.84 85.83 116.00 65.96 857.8 719.2 q2a6
+ 4 -28 53 -2.65 78.82 96.00 63.12 1240.9 1178.7 q3a12
+ 4 -26 47 89.01 122.36 144.00 75.37 1276.4 1262.2 q3a12
+ 4 -24 42 173.36 157.69 189.00 111.01 1304.1 1304.0 q3a14
+ 4 -20 33 313.19 453.17 442.00 164.14 1350.3 1426.4 q3a14
+ 4 -16 26 -395.76 723.78 617.00 244.34 1518.5 196.9 q3a3
+ 4 -4 9 85.64 105.24 112.00 68.42 1268.7 270.4 q3a2
+ 4 6 -1 -505.73 201.14 183.00 76.93 909.9 308.6 q2a2
+ 4 8 -3 -299.81 145.52 145.00 75.51 901.9 272.9 q2a2
+ 4 12 -6 79.57 132.72 131.00 75.83 890.1 205.9 q2a2
+ 4 20 -11 425.02 200.12 379.00 151.78 869.1 101.8 q2a0
+ 4 22 -12 2797.25 406.47 1770.00 183.75 864.8 68.7 q2a0
+ 4 24 -13 1543.33 283.74 886.00 194.07 860.5 35.2 q2a0
+ 4 38 -18 -263.35 230.52 237.00 97.15 985.0 677.9 q2a7
+ 4 44 -19 -143.52 98.65 176.00 71.72 876.1 683.2 q2a6
+ 5 -27 53 -47.27 107.25 114.00 66.47 1209.5 1199.6 q3a12
+ 5 -25 47 -83.09 118.06 159.00 72.43 1245.9 1282.6 q3a12
+ 5 -23 42 -105.15 148.40 182.00 111.35 1274.2 1324.0 q3a14
+ 5 -21 37 -0.46 311.85 371.00 140.62 1301.1 1390.4 q3a14
+ 5 -19 33 -393.41 370.65 396.00 169.23 1321.4 1445.8 q3a14
+ 5 -7 14 544.11 193.17 372.00 74.49 1328.2 222.0 q3a2
+ 5 -3 9 221.46 114.61 152.00 67.34 1250.3 243.0 q3a2
+ 5 -1 7 3242.75 229.21 1461.00 68.66 1214.5 251.0 q3a2
+ 5 3 3 -103.71 195.53 190.00 65.97 953.4 361.6 q2a2
+ 5 5 1 28910.30 586.72 7965.00 72.30 945.4 325.9 q2a2
+ 5 11 -4 387.18 175.46 233.00 75.42 925.7 223.2 q2a2
+ 5 17 -8 956.90 202.14 649.00 140.90 909.5 151.7 q2a0
+ 5 29 -14 451.24 352.56 369.00 141.36 1143.0 631.3 q2a7
+ 5 35 -16 -119.02 133.22 181.00 101.22 1038.4 639.3 q2a7
+ 5 45 -18 244.10 84.80 99.00 65.10 855.9 647.5 q2a6
+ 6 -22 42 -193.55 172.28 177.00 104.95 1244.2 1344.0 q3a14
+ 6 -20 37 141.84 321.63 380.00 140.04 1271.8 1410.0 q3a14
+ 6 -18 33 49.71 403.12 416.00 167.68 1292.5 1465.2 q3a14
+ 6 -14 26 2328.13 581.36 933.00 234.49 1479.9 167.5 q3a1
+ 6 10 -2 -203.79 236.85 232.00 75.59 961.4 240.6 q2a2
+ 6 16 -6 377.29 196.63 244.00 121.91 945.7 169.0 q2a0
+ 6 32 -14 -393.62 286.71 377.00 126.62 1090.6 601.7 q2a7
+ 6 36 -15 -203.59 136.25 146.00 97.79 1020.3 604.9 q2a7
+ 6 40 -16 65.09 177.78 151.00 79.71 950.2 608.3 q2a6
+ 6 46 -17 135.06 97.56 129.00 62.94 835.4 611.2 q2a6
+ 6 48 -17 39.60 116.37 121.00 66.60 795.6 610.6 q2a6
+ 7 -27 59 -71.06 105.99 96.00 54.06 1229.1 767.5 q3a8
+ 7 -21 42 404.79 161.83 182.00 101.41 1214.3 1364.0 q3a14
+ 7 -13 26 -757.35 587.83 529.00 233.15 1460.8 139.2 q3a1
+ 7 -11 23 1523.31 372.31 780.00 176.69 1416.7 153.5 q3a1
+ 7 -9 20 2032.40 245.44 960.00 141.40 1373.1 167.5 q3a1
+ 7 5 4 96.80 125.65 150.00 88.88 1010.4 329.8 q2a3
+ 7 7 2 575.49 146.29 490.00 86.11 1002.2 293.9 q2a3
+ 7 23 -9 -53.59 771.73 575.00 254.36 962.6 51.0 q2a0
+ 7 33 -13 -147.07 151.28 185.00 106.67 1073.0 567.4 q2a7
+ 7 37 -14 4.69 149.00 192.00 97.31 1001.9 570.1 q2a7
+ 7 41 -15 126.18 123.40 128.00 72.42 931.0 572.8 q2a6
+ 8 -26 59 192.14 115.88 110.00 53.26 1250.5 800.0 q3a8
+ 8 -20 42 -325.09 181.12 186.00 117.25 1184.3 1384.0 q3a14
+ 8 -14 30 685.17 459.33 594.00 203.83 1493.9 90.1 q3a1
+ 8 -4 15 -94.43 151.74 191.00 134.52 1278.1 162.1 q3a0
+ 8 10 1 1562.23 194.18 788.00 98.97 1026.9 243.9 q2a3
+ 8 22 -7 272.17 515.52 583.00 227.43 996.5 68.5 q2a1
+ 8 24 -8 -586.50 504.18 530.00 217.50 993.0 34.8 q2a1
+ 9 -25 59 -66.09 127.44 174.00 61.29 1271.9 832.4 q3a8
+ 9 -21 47 55.91 133.48 130.00 69.86 1435.6 751.6 q3a9
+ 9 -17 38 86.80 213.58 220.00 124.13 1177.0 1460.4 q3a14
+ 9 -15 34 -94.86 211.80 351.00 166.26 1527.9 39.8 q3a1
+ 9 -11 27 479.62 280.95 472.00 194.38 1429.7 76.4 q3a1
+ 9 -9 24 2448.81 613.78 1111.00 229.19 1385.5 91.2 q3a1
+ 9 -7 21 3478.10 507.82 1664.00 187.10 1344.9 105.7 q3a0
+ 9 -3 16 857.17 179.13 302.00 143.30 1265.3 128.6 q3a0
+ 9 1 11 249.79 142.48 292.00 127.41 1186.8 151.1 q3a0
+ 9 5 7 379.64 201.79 204.00 105.76 1079.2 333.8 q2a3
+ 9 11 2 1169.30 211.90 938.00 102.30 1060.0 229.7 q2a3
+ 9 21 -5 629.31 379.32 495.00 209.69 1033.4 86.1 q2a1
+ 9 23 -6 1626.88 297.41 779.00 190.12 1030.2 52.4 q2a1
+ 9 25 -7 986.73 262.76 468.00 167.47 1026.8 18.4 q2a1
+ 9 45 -13 -229.74 101.38 96.00 65.14 852.6 524.7 q2a4
+ 9 47 -13 -116.36 166.31 229.00 64.76 813.0 522.2 q2a4
+ 10 -24 60 107.53 124.15 129.00 59.27 1281.9 873.6 q3a8
+ 10 -22 53 -179.36 158.72 157.00 66.76 1375.4 822.5 q3a9
+ 10 -20 48 81.71 115.22 112.00 66.09 1446.3 789.9 q3a9
+ 10 -18 43 -203.77 176.35 176.00 76.97 1514.2 758.6 q3a9
+ 10 -12 31 5.88 270.70 359.00 171.12 1462.6 26.1 q3a1
+ 10 -4 19 3007.91 478.51 1517.00 196.29 1289.1 86.1 q3a0
+ 10 0 14 41.35 213.06 342.00 147.85 1209.9 109.1 q3a0
+ 10 2 12 591.41 270.17 471.00 146.79 1173.5 117.5 q3a0
+ 10 4 10 839.79 402.48 516.00 139.47 1121.0 356.6 q2a3
+ 10 6 8 1370.39 390.21 406.00 132.01 1112.8 320.2 q2a3
+ 10 8 6 1423.95 372.45 417.00 139.45 1104.5 283.7 q2a3
+ 10 16 0 -746.55 604.84 538.00 234.34 1082.0 173.6 q2a1
+ 10 22 -4 86.52 374.76 419.00 197.28 1067.4 70.1 q2a1
+ 10 24 -5 -220.95 232.19 280.00 173.55 1064.3 36.2 q2a1
+ 10 34 -9 319.84 136.12 282.00 88.96 1055.7 486.8 q2a5
+ 10 38 -10 283.01 148.25 158.00 82.39 983.2 486.8 q2a5
+ 10 42 -11 43.88 129.15 169.00 69.12 910.8 486.9 q2a4
+ 11 -25 68 -23.46 78.47 76.00 45.66 1188.3 945.2 q3a10
+ 11 -21 54 299.04 120.93 142.00 63.16 1386.0 862.3 q3a9
+ 11 -17 44 404.71 201.76 238.00 73.56 1525.3 796.4 q3a9
+ 11 -3 20 687.00 655.15 609.00 228.12 1276.2 51.7 q3a0
+ 11 1 15 1068.30 358.12 594.00 178.30 1196.6 75.0 q3a0
+ 11 5 11 1298.34 580.34 491.00 214.61 1155.0 343.1 q2a3
+ 11 7 9 1241.20 560.73 459.00 183.12 1146.7 306.4 q2a3
+ 11 9 7 4639.75 758.79 1452.00 215.25 1138.4 269.7 q2a3
+ 11 17 1 228.08 679.67 517.00 255.32 1116.1 158.3 q2a1
+ 11 33 -7 240.66 129.46 283.00 94.54 1074.5 448.1 q2a5
+ 11 45 -10 -180.86 103.00 93.00 63.26 852.1 445.8 q2a4
+ 11 47 -10 -100.76 129.41 120.00 67.36 812.1 442.2 q2a4
+ 12 -24 69 -62.66 87.71 89.00 46.46 1198.2 989.6 q3a10
+ 12 -24 70 -37.69 86.55 95.00 45.69 1185.4 1000.0 q3a10
+ 12 -20 55 36.12 108.87 111.00 65.88 1396.6 902.8 q3a9
+ 12 -14 40 26.42 145.41 146.00 94.97 1496.8 389.8 q3a5
+ 12 -10 33 433.89 514.90 424.00 145.51 1535.8 491.3 q3a5
+ 12 -2 21 -412.89 370.49 486.00 201.49 1263.2 16.8 q3a0
+ 12 2 16 3477.23 433.96 1643.00 211.97 1183.1 40.5 q3a0
+ 12 6 12 521.70 797.62 567.00 284.19 1124.6 1466.5 q2a15
+ 12 18 2 2133.02 479.93 921.00 204.78 1150.6 142.8 q2a1
+ 12 32 -5 6.01 151.10 199.00 95.39 1093.4 409.3 q2a5
+ 12 38 -7 -195.60 142.61 178.00 81.40 983.7 410.3 q2a5
+ 12 44 -8 96.59 97.89 104.00 60.21 872.0 404.7 q2a4
+ 13 -23 71 53.31 100.83 82.00 45.69 1195.4 1045.5 q3a10
+ 13 -21 63 -88.97 136.79 132.00 54.77 1313.3 973.4 q3a10
+ 13 -17 51 -38.56 105.50 114.00 64.56 1479.1 908.1 q3a9
+ 13 -9 34 -304.23 387.65 467.00 131.03 1498.9 503.3 q3a5
+ 13 5 15 1546.25 657.82 890.00 261.75 1147.8 1423.1 q2a15
+ 13 7 13 512.49 565.68 529.00 252.11 1110.7 1431.6 q2a15
+ 13 9 11 885.29 664.51 949.00 254.91 1073.5 1440.1 q2a15
+ 13 21 2 -406.87 312.14 340.00 155.67 864.7 1472.2 q2a14
+ 14 -20 64 109.65 139.08 136.00 53.15 1324.0 1017.1 q3a10
+ 14 -18 58 43.57 96.60 94.00 59.83 1408.4 967.7 q3a11
+ 14 -8 35 -55.81 219.57 300.00 109.81 1461.5 515.4 q3a5
+ 14 -2 26 -339.29 422.96 384.00 164.09 1510.5 623.4 q3a7
+ 14 0 23 647.92 433.05 396.00 167.55 1526.3 667.5 q3a7
+ 14 14 9 156.27 393.80 427.00 190.53 988.8 1415.2 q2a15
+ 14 18 6 -333.16 409.27 387.00 165.96 920.6 1425.8 q2a14
+ 14 34 -2 -293.61 207.29 177.00 73.01 1153.2 851.7 q2a9
+ 14 42 -4 -234.65 159.15 123.00 57.85 1147.6 975.3 q2a11
+ 14 48 -5 -118.71 170.97 216.00 50.91 1139.2 1096.9 q2a11
+ 15 -19 66 -69.76 113.20 95.00 49.36 1323.3 1072.2 q3a10
+ 15 -17 59 80.49 95.84 115.00 58.11 1419.6 1010.4 q3a11
+ 15 -11 44 59.70 119.83 242.00 85.19 1373.0 416.3 q3a5
+ 15 -9 40 -56.64 279.55 388.00 98.44 1398.6 472.7 q3a5
+ 15 -3 30 118.55 179.00 214.00 124.05 1457.4 591.6 q3a7
+ 15 -1 27 -569.14 380.26 383.00 151.08 1473.8 636.6 q3a7
+ 15 3 22 -1072.55 520.87 440.00 183.87 1498.6 718.9 q3a7
+ 15 11 14 184.81 205.53 377.00 165.19 1049.3 1362.0 q2a15
+ 15 13 12 365.09 257.81 627.00 173.71 1011.5 1370.7 q2a15
+ 15 17 9 310.56 297.28 327.00 152.44 942.9 1381.0 q2a14
+ 15 23 5 809.04 203.37 489.00 124.16 835.8 1393.3 q2a14
+ 15 25 4 -379.21 192.86 197.00 126.41 800.6 1395.1 q2a14
+ 15 29 2 -28.66 132.56 160.00 80.46 1110.0 758.9 q2a9
+ 15 31 1 -61.40 214.96 245.00 82.60 1111.7 795.5 q2a9
+ 15 37 -1 94.32 123.50 172.00 67.08 1109.7 906.3 q2a9
+ 15 41 -2 155.12 88.96 106.00 54.88 1106.3 955.5 q2a11
+ 15 47 -3 -182.61 102.84 98.00 56.01 1096.3 1076.4 q2a11
+ 16 -16 61 -2.64 81.32 88.00 56.24 1420.3 1064.2 q3a11
+ 16 -14 55 -167.36 156.74 167.00 64.76 1504.2 1013.7 q3a11
+ 16 -10 46 507.40 145.68 172.00 69.40 1327.1 419.7 q3a4
+ 16 -6 38 155.46 209.00 235.00 97.22 1376.8 532.5 q3a5
+ 16 2 26 47.06 246.68 344.00 129.94 1445.3 688.4 q3a7
+ 16 8 19 13.09 210.34 254.00 163.47 1110.7 1307.9 q2a15
+ 16 10 17 75.45 188.75 242.00 155.48 1072.6 1316.7 q2a15
+ 16 20 9 266.19 203.60 263.00 128.81 892.8 1345.9 q2a14
+ 16 22 8 110.41 156.43 167.00 117.79 857.9 1347.4 q2a14
+ 16 32 3 -262.89 132.78 192.00 76.49 1066.2 810.8 q2a9
+ 16 34 2 160.59 94.65 108.00 70.21 1067.7 848.5 q2a9
+ 16 42 0 76.79 85.51 87.00 55.41 1058.5 974.3 q2a11
+ 16 48 -1 59.43 73.45 84.00 53.17 1046.7 1097.8 q2a11
+ 17 -5 40 21.36 315.73 370.00 83.24 1331.7 537.6 q3a4
+ 17 -1 33 -29.45 189.77 244.00 115.13 1373.3 611.3 q3a7
+ 17 3 28 -260.00 222.98 275.00 123.00 1399.5 696.0 q3a7
+ 17 7 23 -521.69 526.41 423.00 131.69 1139.9 1281.3 q2a13
+ 17 35 4 109.09 102.96 155.00 71.71 1020.6 864.9 q2a9
+ 17 43 2 127.12 87.34 111.00 54.88 1009.3 993.8 q2a11
+ 18 -8 50 98.93 115.71 116.00 66.67 1225.2 427.0 q3a4
+ 18 -4 42 47.55 155.73 236.00 81.05 1282.3 542.7 q3a4
+ 18 -2 38 -115.51 163.70 191.00 87.09 1310.4 571.0 q3a6
+ 18 0 35 923.85 176.69 243.00 86.35 1328.5 618.0 q3a6
+ 18 2 32 -147.71 339.27 398.00 102.97 1346.4 664.4 q3a6
+ 18 8 25 206.60 457.59 460.00 110.60 1130.8 1234.9 q2a13
+ 18 14 19 2.02 124.67 149.00 92.78 1013.3 1262.2 q2a13
+ 18 20 14 -523.45 231.57 238.00 99.05 903.0 1281.3 q2a12
+ 18 22 13 200.57 116.24 157.00 83.83 867.4 1282.4 q2a12
+ 18 44 4 -120.24 162.91 145.00 51.64 961.6 1013.8 q2a10
+ 19 -7 52 -71.73 113.15 120.00 70.53 1172.0 430.7 q3a4
+ 19 -5 48 -152.90 141.43 139.00 74.10 1202.1 490.2 q3a4
+ 19 1 37 -23.09 127.91 178.00 86.72 1279.4 625.0 q3a6
+ 19 9 27 -530.45 314.36 378.00 99.05 1121.4 1187.3 q2a13
+ 19 15 21 -224.69 183.10 187.00 90.69 1002.3 1214.9 q2a13
+ 19 21 16 -156.52 135.70 198.00 84.72 890.4 1234.1 q2a12
+ 19 23 15 -229.24 136.90 160.00 82.64 854.2 1234.8 q2a12
+ 19 35 9 49.50 168.35 162.00 68.50 924.8 859.4 q2a8
+ 19 37 8 -149.40 130.10 114.00 64.60 925.3 899.2 q2a8
+ 19 41 7 -18.56 101.00 98.00 54.56 917.7 951.4 q2a10
+ 19 47 6 200.53 92.71 102.00 46.27 900.2 1077.0 q2a10
+ 20 0 43 -86.05 133.80 169.00 80.45 1199.4 576.5 q3a6
+ 20 6 34 -293.82 160.45 219.00 84.42 1257.3 720.3 q3a6
+ 20 10 29 -310.86 163.53 165.00 89.26 1111.8 1138.3 q2a13
+ 20 12 27 -73.06 120.04 124.00 82.06 1071.5 1147.7 q2a13
+ 20 14 25 88.49 141.29 134.00 82.11 1031.3 1157.0 q2a13
+ 20 16 23 42.82 156.47 198.00 88.58 991.0 1166.4 q2a13
+ 20 20 20 -283.81 151.68 158.00 82.51 917.9 1176.1 q2a12
+ 20 24 17 -32.06 118.03 135.00 79.06 840.7 1185.9 q2a12
+ 20 26 16 114.85 183.74 275.00 79.35 803.5 1186.3 q2a12
+ 20 34 12 -82.32 91.34 98.00 66.92 873.6 836.8 q2a8
+ 20 36 11 210.90 73.83 138.00 64.90 873.8 876.6 q2a8
+ 20 44 9 26.01 90.51 110.00 49.39 855.4 1012.3 q2a10
+ 20 46 9 -128.78 84.02 83.00 46.98 845.3 1054.9 q2a10
+ 21 5 39 189.84 157.95 240.00 86.96 1186.5 681.0 q3a6
+ 21 21 22 394.38 125.28 149.00 77.01 905.1 1126.0 q2a12
+ 21 27 18 178.20 109.70 125.00 73.20 788.9 1135.7 q2a12
+ 21 31 16 -151.14 108.66 103.00 64.74 821.8 774.3 q2a8
+ 21 33 15 49.54 118.69 120.00 67.66 821.6 813.7 q2a8
+ 21 43 12 -164.99 87.19 80.00 48.39 800.5 989.8 q2a10
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035109_18bac.h5
+Image serial number: 14
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9513.372348
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9513.372348
+average_camera_length = 0.152001 m
+num_peaks = 30
+peak_resolution = 4.108967 nm^-1 or 2.433702 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 169.50 45.99 2.29 470.64 q0a0
+ 497.60 124.20 1.79 3156.80 q1a0
+ 852.50 78.21 1.98 908.75 q2a0
+ 863.50 78.12 1.99 1477.54 q2a0
+1322.42 60.43 2.18 3097.10 q3a0
+1208.50 81.85 1.96 1417.44 q3a0
+1446.41 111.61 2.25 2065.31 q3a1
+1378.85 139.32 1.94 5418.46 q3a1
+ 134.94 262.50 1.04 619.32 q0a2
+ 145.50 262.82 1.07 635.61 q0a2
+ 17.63 318.25 0.57 2948.31 q0a2
+ 341.55 248.19 1.94 7295.25 q0a3
+ 564.18 227.50 1.30 1430.56 q1a2
+ 713.01 286.68 1.75 1248.51 q1a3
+ 807.50 269.27 0.79 3242.75 q2a2
+ 942.50 313.89 0.93 724.59 q2a2
+ 856.94 320.50 0.59 5205.74 q2a2
+1273.11 216.50 1.18 718.85 q3a2
+1254.18 229.50 1.08 1626.90 q3a2
+1223.55 284.61 0.74 3860.95 q3a2
+1194.50 302.90 0.62 782.74 q3a2
+1345.59 334.31 0.95 12884.18 q3a2
+1346.26 344.81 0.93 638.05 q3a2
+1406.36 255.78 1.47 1735.35 q3a3
+1381.07 314.50 1.18 1335.35 q3a3
+ 354.50 519.16 2.92 488.22 q0a5
+ 359.50 720.98 2.68 748.51 q0a7
+1310.18 799.15 4.11 284.40 q3a8
+1151.03 1330.23 2.78 2044.98 q2a15
+1404.50 1431.99 2.47 620.15 q3a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.15143 12.29565 16.85745 nm, 90.19056 90.08579 90.20985 deg
+astar = -0.1587129 +0.0033653 -0.0350181 nm^-1
+bstar = +0.0171901 -0.0018342 -0.0794720 nm^-1
+cstar = -0.0015332 -0.0592956 +0.0008347 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00187 nm^-1
+predict_refine/final_residual = 6.429598e-07
+predict_refine/det_shift x = -0.018 y = 0.025 mm
+diffraction_resolution_limit = 2.17 nm^-1 or 4.60 A
+num_reflections = 179
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -22 24 -18 -39.88 70.64 63.00 32.88 34.2 537.8 q0a4
+ -20 20 -14 17.08 78.42 71.00 37.55 145.7 564.2 q0a6
+ -20 20 -13 41.03 68.97 60.00 34.18 146.1 576.4 q0a6
+ -20 20 10 -78.41 69.91 60.00 34.58 1455.9 1167.4 q3a13
+ -20 22 -28 -100.06 69.12 57.00 32.76 115.5 414.3 q0a4
+ -20 22 24 -172.36 79.50 81.00 34.84 1282.2 1149.6 q3a12
+ -20 26 -43 -123.56 68.07 51.00 26.85 252.0 1055.0 q0a11
+ -19 19 -19 -147.62 135.68 116.00 37.97 183.7 531.2 q0a4
+ -19 19 16 -181.15 96.09 82.00 37.55 1386.3 1210.3 q3a13
+ -19 21 -31 114.71 76.21 74.00 33.37 156.1 378.4 q0a4
+ -19 23 -39 -78.85 70.43 63.00 28.45 318.0 982.9 q0a11
+ -19 27 47 -77.89 119.73 152.00 31.30 1199.4 916.7 q3a8
+ -18 18 -23 196.57 84.15 85.00 39.76 219.3 483.8 q0a5
+ -18 20 30 71.35 78.24 72.00 33.12 1216.1 1234.1 q3a12
+ -17 15 -7 49.78 80.69 99.00 51.82 285.2 647.8 q0a7
+ -17 15 -6 30.49 89.60 97.00 53.70 285.6 659.4 q0a7
+ -17 15 -5 136.59 80.33 136.00 51.91 286.0 671.0 q0a7
+ -17 17 -26 -14.36 78.20 77.00 42.03 257.8 448.9 q0a5
+ -17 19 32 262.92 93.13 77.00 34.25 1195.8 1275.1 q3a12
+ -17 27 55 -31.00 53.99 54.00 28.00 1265.8 1001.1 q3a10
+ -17 29 59 -26.26 46.31 48.00 26.86 1241.3 1076.0 q3a10
+ -16 14 -13 -90.60 106.48 104.00 56.34 320.8 577.9 q0a7
+ -16 14 9 -29.16 99.42 102.00 71.94 1479.7 1316.5 q3a15
+ -16 14 10 38.80 103.89 114.00 66.80 1468.2 1316.9 q3a15
+ -16 16 25 12.64 93.29 98.00 54.07 1291.5 1303.7 q3a14
+ -16 20 41 -143.28 95.53 106.00 36.72 1368.8 795.7 q3a9
+ -16 26 -60 54.54 76.98 73.00 25.66 10.7 937.5 q0a10
+ -15 13 13 67.03 104.67 100.00 65.22 1435.8 1355.2 q3a15
+ -15 15 -30 92.25 84.40 147.00 46.75 333.9 403.8 q0a5
+ -15 17 -39 -130.83 100.67 86.00 41.83 336.3 824.1 q0a9
+ -15 19 -46 -31.81 72.98 77.00 37.51 239.5 847.0 q0a9
+ -15 21 48 142.42 85.62 100.00 34.11 1391.0 891.5 q3a9
+ -15 23 53 -3.77 72.84 79.00 32.61 1371.9 943.7 q3a11
+ -14 12 15 408.67 131.30 225.00 72.54 1415.2 1392.7 q3a15
+ -14 14 28 12.10 147.74 153.00 60.81 1262.9 1380.5 q3a14
+ -14 16 -40 50.45 68.88 81.00 40.87 326.3 785.4 q0a9
+ -14 18 -47 -106.74 92.80 85.00 40.97 229.8 807.2 q0a9
+ -14 20 49 37.00 67.79 60.00 35.00 1431.9 898.7 q3a9
+ -14 22 54 -146.46 76.34 68.00 32.66 1413.9 950.4 q3a11
+ -13 11 -20 -18.11 123.36 152.00 87.27 239.5 11.5 q0a1
+ -13 13 29 -153.04 104.53 92.00 64.23 1254.7 1418.0 q3a14
+ -13 15 -41 -115.46 103.97 102.00 43.72 316.4 747.2 q0a9
+ -13 17 44 42.91 74.01 79.00 36.10 1488.5 818.6 q3a9
+ -12 10 -21 955.96 169.90 597.00 92.23 250.7 47.2 q0a1
+ -12 18 -54 -93.49 103.39 90.00 40.68 138.4 749.0 q0a8
+ -12 20 -59 -70.90 80.85 68.00 36.10 59.1 770.0 q0a8
+ -11 9 18 419.02 367.35 421.00 107.73 1542.9 204.9 q3a3
+ -11 13 -42 134.13 111.36 121.00 63.49 39.7 1373.2 q0a14
+ -10 8 -21 -177.42 323.96 324.00 114.17 250.3 118.0 q0a1
+ -10 8 18 -664.02 361.78 284.00 94.27 1507.9 207.1 q3a3
+ -10 10 30 392.68 169.32 324.00 92.39 1516.4 93.7 q3a1
+ -10 12 -42 61.88 110.35 114.00 62.96 76.8 1375.2 q0a14
+ -9 7 -21 -116.17 148.07 167.00 96.92 250.2 152.8 q0a1
+ -9 7 17 -99.94 126.89 125.00 58.53 1473.7 220.3 q3a3
+ -9 11 -42 -135.74 183.44 244.00 72.97 113.5 1377.1 q0a14
+ -9 15 51 -181.80 92.70 84.00 47.20 1402.1 414.8 q3a5
+ -9 17 -60 17.65 91.15 74.00 40.15 60.5 1147.7 q0a12
+ -8 6 16 240.64 106.95 117.00 47.27 1439.8 233.4 q3a3
+ -8 8 29 1992.03 407.80 1375.00 111.18 1446.6 111.4 q3a1
+ -8 12 45 -350.59 230.43 265.00 60.36 1491.1 464.0 q3a5
+ -8 14 51 -47.74 80.58 93.00 46.97 1407.0 452.3 q3a5
+ -8 16 -60 -46.80 78.35 74.00 42.20 99.8 1151.4 q0a12
+ -8 20 65 16.40 75.26 76.00 38.40 1184.2 412.6 q3a4
+ -7 5 -18 0.50 90.16 114.00 49.50 217.3 194.3 q0a3
+ -7 5 14 1512.72 152.09 913.00 46.78 1406.7 257.1 q3a3
+ -7 7 28 1095.57 171.12 647.00 97.25 1412.5 125.7 q3a1
+ -7 9 -41 26.66 270.82 290.00 85.03 185.8 1392.4 q0a14
+ -7 15 56 -411.53 181.44 143.00 44.73 1339.6 477.7 q3a4
+ -7 19 65 -81.53 87.84 94.00 39.73 1190.9 452.5 q3a4
+ -6 4 11 55.56 86.20 86.00 45.21 1374.2 291.4 q3a3
+ -6 6 27 5457.67 295.51 2672.00 87.54 1378.8 139.7 q3a1
+ -6 8 -40 914.62 197.53 568.00 88.03 218.4 1405.6 q0a15
+ -6 10 44 436.88 217.18 217.00 63.64 1510.8 535.5 q3a5
+ -5 3 -11 697.11 123.62 481.00 41.14 144.3 263.0 q0a2
+ -5 3 -10 632.81 127.30 339.00 40.35 133.5 263.3 q0a2
+ -5 3 7 13252.44 392.68 8160.00 29.56 1345.4 336.1 q3a2
+ -5 5 -29 7551.55 356.72 3659.00 77.70 342.0 247.8 q0a3
+ -5 7 -39 625.44 186.71 581.00 91.34 253.6 1418.6 q0a15
+ -5 15 60 -305.81 137.96 119.00 44.81 1284.8 541.5 q3a4
+ -4 4 -27 -111.86 192.14 206.00 62.61 319.1 282.0 q0a3
+ -4 6 34 2882.80 490.15 1882.00 136.37 1321.4 60.8 q3a0
+ -4 8 42 98.82 236.03 207.00 82.06 1542.2 576.4 q3a7
+ -4 12 -58 -19.14 77.43 85.00 44.96 249.4 1189.9 q0a13
+ -3 3 -24 350.00 83.94 204.00 48.00 285.5 316.0 q0a3
+ -3 5 -36 -17.37 321.04 383.00 121.62 323.0 1455.4 q0a15
+ -2 2 17 1594.73 144.53 1135.00 33.52 1253.2 230.2 q3a2
+ -2 4 30 508.18 138.22 271.00 77.69 1256.1 111.5 q3a0
+ -2 16 67 126.84 80.38 75.00 39.96 1178.8 608.6 q3a6
+ -1 1 12 3892.61 207.86 3200.00 33.35 1222.4 285.8 q3a2
+ -1 5 -41 -200.30 289.69 318.00 104.56 380.6 1393.6 q0a15
+ -1 9 -55 577.09 136.42 266.00 48.61 359.2 1235.3 q0a13
+ -1 15 66 -64.11 84.22 84.00 43.51 1198.1 646.0 q3a6
+ 0 2 -28 7.10 119.45 177.00 70.14 405.4 139.5 q1a0
+ 0 4 35 -278.92 387.47 443.00 112.55 1195.4 54.6 q3a0
+ 0 6 43 -478.04 337.91 296.00 90.04 1535.5 705.0 q3a7
+ 0 14 65 -24.88 93.14 111.00 40.88 1217.0 682.9 q3a6
+ 1 3 -36 -94.90 183.21 203.00 98.14 428.9 45.1 q1a0
+ 1 9 54 -182.59 130.36 157.00 61.79 1387.1 729.5 q3a7
+ 1 13 64 -59.93 86.58 75.00 42.33 1235.8 719.3 q3a6
+ 2 2 -33 107.58 205.34 279.00 87.25 462.7 79.6 q1a0
+ 2 2 29 285.31 264.29 288.00 68.01 1119.8 351.9 q2a3
+ 2 6 46 783.56 340.90 558.00 87.32 1152.7 1326.6 q2a15
+ 3 -1 -9 79.14 77.11 82.00 28.81 507.3 317.4 q1a2
+ 3 -1 -8 243.00 87.67 93.00 31.00 507.6 328.2 q1a2
+ 3 -1 4 34.50 80.29 65.00 37.50 845.7 322.3 q2a2
+ 3 -1 5 5207.88 242.47 2796.00 34.98 856.4 322.0 q2a2
+ 3 1 -29 3043.09 194.56 1753.00 76.67 496.4 124.7 q1a0
+ 3 7 -54 168.87 121.52 142.00 57.33 614.7 655.5 q1a7
+ 3 9 56 160.85 135.36 180.00 48.59 1125.4 1214.4 q2a13
+ 3 11 -65 -56.46 80.50 79.00 43.66 452.2 670.7 q1a6
+ 4 2 -36 1287.19 301.75 456.00 107.96 521.8 40.9 q1a0
+ 4 4 -45 -33.47 128.61 122.00 72.40 734.5 613.8 q1a7
+ 4 4 41 73.94 209.50 292.00 96.63 1087.8 1391.5 q2a15
+ 4 6 -52 18.49 76.95 98.00 58.05 641.3 620.5 q1a7
+ 4 8 -58 -60.38 119.67 116.00 49.99 558.6 627.2 q1a6
+ 4 12 -68 83.70 82.45 116.00 43.70 399.7 641.0 q1a6
+ 5 -1 -17 1543.25 174.19 1030.00 34.75 564.0 228.5 q1a2
+ 5 -1 13 1122.11 178.11 445.00 41.14 942.1 261.2 q2a2
+ 5 3 38 -670.35 225.10 207.00 102.68 1056.1 1428.9 q2a15
+ 5 7 52 -173.64 190.29 248.00 52.30 1058.2 1271.8 q2a13
+ 6 4 43 45.01 139.84 159.00 80.35 1024.9 1365.6 q2a15
+ 7 -1 17 877.21 126.45 829.00 46.02 982.7 200.4 q2a3
+ 7 5 47 449.65 133.58 456.00 76.68 993.0 1311.9 q2a15
+ 8 -2 -9 135.50 92.60 75.00 42.50 654.0 312.8 q1a3
+ 8 -2 -8 336.81 93.00 280.00 43.68 654.3 323.6 q1a3
+ 8 0 -29 -140.42 170.41 209.00 101.03 646.5 116.2 q1a1
+ 9 -1 19 -171.97 156.31 202.00 84.18 1004.4 166.9 q2a1
+ 9 9 -63 -8.31 62.70 70.00 39.31 465.8 489.5 q1a4
+ 10 -2 -11 1476.05 183.18 706.00 55.20 714.4 288.6 q1a3
+ 10 -2 -10 164.69 147.17 147.00 53.31 714.7 299.6 q1a3
+ 10 -2 7 1011.94 126.04 859.00 70.23 874.0 139.8 q2a0
+ 10 0 -30 809.36 190.63 316.00 97.77 708.5 100.1 q1a1
+ 10 0 26 281.81 283.05 347.00 114.19 1085.1 133.7 q2a1
+ 10 4 -48 -75.29 141.45 199.00 52.56 679.4 450.8 q1a5
+ 10 6 51 240.81 115.09 116.00 45.49 896.7 1279.6 q2a12
+ 11 -1 19 -393.92 346.74 427.00 112.47 1004.7 104.8 q2a1
+ 12 -2 5 1023.58 147.23 735.00 83.97 850.9 78.4 q2a0
+ 12 -2 6 1780.69 196.38 1016.00 82.82 862.0 78.1 q2a0
+ 12 2 36 -79.04 159.24 194.00 72.12 837.1 1447.3 q2a14
+ 12 4 44 88.55 110.42 107.00 59.52 833.2 1343.6 q2a14
+ 13 3 40 90.14 113.12 118.00 63.94 802.0 1394.4 q2a14
+ 14 0 -28 283.62 117.99 218.00 65.03 496.7 1430.0 q1a14
+ 14 4 -47 -159.82 170.17 133.00 39.14 752.5 846.0 q1a9
+ 15 -1 -18 -87.07 138.66 171.00 78.84 608.7 1396.3 q1a15
+ 15 5 46 118.58 78.36 72.00 35.89 1018.7 758.4 q2a9
+ 15 7 -56 81.76 62.88 58.00 32.64 714.8 955.3 q1a11
+ 16 0 -25 -149.10 121.88 148.00 67.61 526.8 1363.2 q1a14
+ 16 0 21 73.44 204.72 173.00 59.34 1135.1 510.5 q2a5
+ 17 -1 -11 32.50 239.60 324.00 72.93 685.7 1328.5 q1a15
+ 17 -1 7 88.99 145.03 146.00 62.41 1107.9 644.3 q2a7
+ 17 1 26 -172.87 110.98 111.00 49.32 1098.2 448.5 q2a5
+ 17 3 -40 34.53 81.35 77.00 36.32 649.1 765.5 q1a9
+ 17 5 -48 -61.76 70.59 76.00 37.34 645.4 875.8 q1a9
+ 17 5 44 122.00 69.51 68.00 35.00 1038.4 828.4 q2a9
+ 18 4 39 -13.15 96.95 84.00 36.62 1103.2 859.7 q2a9
+ 18 10 58 -139.21 80.13 66.00 35.41 822.5 885.3 q2a8
+ 19 1 -25 40.76 80.63 94.00 38.94 516.7 1286.0 q1a12
+ 19 1 21 45.39 80.53 83.00 44.56 1030.5 505.4 q2a5
+ 19 9 -58 77.99 123.87 104.00 28.61 563.3 1017.7 q1a10
+ 20 0 -10 -49.54 76.81 78.00 40.52 691.7 1250.7 q1a13
+ 20 0 -9 134.28 89.19 95.00 39.83 703.5 1250.4 q1a13
+ 20 0 5 -170.42 120.30 123.00 51.25 1003.5 667.7 q2a7
+ 20 0 6 75.34 86.45 101.00 49.56 1003.3 656.0 q2a7
+ 20 2 -29 -23.86 68.77 78.00 36.59 462.6 1248.3 q1a12
+ 20 8 -54 42.09 69.68 75.00 30.14 528.0 960.8 q1a10
+ 21 5 38 30.66 60.47 58.00 30.09 1104.5 944.8 q2a11
+ 21 11 -61 88.35 58.18 65.00 25.85 475.5 1088.9 q1a10
+ 21 11 57 -99.55 76.69 64.00 26.95 815.3 980.1 q2a10
+ 22 2 -22 77.54 75.10 69.00 32.46 542.8 1174.5 q1a12
+ 22 12 58 195.16 70.30 67.00 23.04 787.6 1026.9 q2a10
+ 23 3 22 64.99 65.70 66.00 32.41 881.3 483.7 q2a4
+ 23 5 -37 -118.53 82.09 63.00 32.58 424.1 758.3 q1a8
+ 23 9 -52 -65.97 65.00 68.00 27.77 404.0 957.1 q1a10
+ 23 9 48 13.63 86.16 63.00 22.35 946.6 1046.2 q2a10
+ 23 11 54 -81.56 53.32 52.00 24.56 848.4 1060.6 q2a10
+ 24 2 2 46.01 61.29 62.00 32.59 854.6 704.6 q2a6
+ 24 2 3 -25.46 67.11 62.00 35.48 854.4 692.4 q2a6
+ 24 2 4 104.12 71.91 66.00 34.04 854.1 680.1 q2a6
+ 25 3 10 191.92 67.09 57.00 31.08 809.3 605.0 q2a6
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035157_1ceb7.h5
+Image serial number: 11
+hit = 1
+indexed_by = none
+photon_energy_eV = 9511.555092
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9511.555092
+average_camera_length = 0.152001 m
+num_peaks = 41
+peak_resolution = 3.509832 nm^-1 or 2.849139 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 185.98 41.98 2.33 732.29 q0a0
+ 68.50 92.90 1.94 1069.54 q0a0
+ 290.86 42.14 2.57 708.21 q0a1
+ 325.23 107.50 2.42 86.51 q0a1
+ 321.80 162.78 2.21 1777.40 q0a1
+ 420.73 33.09 2.21 950.81 q1a0
+ 601.50 129.90 1.97 664.62 q1a1
+ 882.83 103.75 1.88 987.99 q2a0
+1205.36 70.00 2.03 1460.38 q3a0
+ 84.17 208.50 1.20 1728.71 q0a2
+ 15.50 241.96 0.98 2193.71 q0a2
+ 73.50 253.88 0.95 2269.64 q0a2
+ 99.50 256.32 0.98 2165.84 q0a2
+ 130.50 271.17 0.99 1576.85 q0a2
+ 179.90 271.50 1.16 590.97 q0a2
+ 121.31 285.19 0.90 2084.73 q0a2
+ 161.68 287.03 1.03 1426.36 q0a2
+ 139.62 309.60 0.86 2947.45 q0a2
+ 76.50 338.31 0.52 5148.46 q0a2
+ 65.91 345.50 0.46 993.21 q0a2
+ 212.93 361.50 1.07 944.86 q0a3
+ 517.41 237.09 1.12 7567.15 q1a2
+ 498.96 241.50 1.05 1463.80 q1a2
+ 444.71 299.93 0.66 674.00 q1a2
+ 457.50 320.29 0.57 5562.88 q1a2
+ 850.17 278.50 0.78 1445.02 q2a2
+ 947.87 327.09 0.92 3923.35 q2a2
+1333.50 196.18 1.43 2205.21 q3a2
+1310.85 215.67 1.27 2534.70 q3a2
+1273.03 217.22 1.18 2304.73 q3a2
+1234.89 227.23 1.06 2066.98 q3a2
+1257.86 233.68 1.06 1154.75 q3a2
+1204.77 244.55 0.95 7324.09 q3a2
+1259.90 265.78 0.90 2792.38 q3a2
+1182.50 269.07 0.81 -4706.91 q3a2
+1179.41 275.49 0.78 11313.81 q3a2
+1298.64 277.89 0.96 2943.84 q3a2
+1182.23 296.83 0.66 1426.09 q3a2
+1394.01 305.50 1.27 730.53 q3a3
+1380.99 318.74 1.17 1363.34 q3a3
+ 597.05 518.05 3.51 462.55 q1a5
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035204_1d7fc.h5
+Image serial number: 15
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9505.897388
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9505.897388
+average_camera_length = 0.152001 m
+num_peaks = 44
+peak_resolution = 4.105748 nm^-1 or 2.435610 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 137.00 14.50 2.39 1360.34 q0a0
+ 30.03 18.18 2.31 2112.39 q0a0
+ 54.66 40.83 2.20 1656.12 q0a0
+ 102.19 86.22 2.00 1016.91 q0a0
+ 253.71 158.67 1.99 3623.96 q0a1
+ 460.37 43.34 2.17 2076.59 q1a0
+ 619.69 98.23 2.16 2163.34 q1a1
+ 799.86 28.50 2.22 1373.23 q2a0
+ 802.50 123.99 1.73 1364.88 q2a0
+1022.31 61.88 2.34 2219.29 q2a1
+1077.28 64.88 2.48 1500.46 q2a1
+1064.50 166.86 2.04 1272.38 q2a1
+1001.19 168.74 1.83 2855.11 q2a1
+ 991.85 174.50 1.77 734.79 q2a1
+1449.91 18.79 2.64 2897.27 q3a1
+1475.53 70.19 2.50 1544.10 q3a1
+ 42.05 210.68 1.15 4501.01 q0a2
+ 37.50 216.09 1.12 646.32 q0a2
+ 184.88 219.63 1.39 2096.95 q0a2
+ 56.50 236.98 1.02 841.76 q0a2
+ 46.64 242.11 0.99 16023.86 q0a2
+ 60.50 268.26 0.86 931.31 q0a2
+ 372.29 224.84 2.14 -559.69 q0a3
+ 324.50 252.17 1.85 893.94 q0a3
+ 370.25 293.99 1.98 4076.83 q0a3
+ 565.94 306.53 1.00 10163.96 q1a2
+ 524.05 319.06 0.78 29167.48 q1a2
+ 823.50 220.13 1.06 1320.64 q2a2
+ 846.50 242.35 0.96 2041.98 q2a2
+ 903.85 322.68 0.74 1779.44 q2a2
+ 885.50 332.95 0.62 544.65 q2a2
+ 866.45 343.42 0.51 9131.36 q2a2
+ 857.03 348.50 0.45 1028.81 q2a2
+1028.96 284.50 1.42 995.66 q2a3
+1009.87 295.25 1.31 902.62 q2a3
+1117.03 303.52 1.81 1984.89 q2a3
+1345.76 283.77 1.11 6728.08 q3a2
+ 514.93 520.07 3.85 193.55 q1a4
+1310.03 798.97 4.11 -368.61 q3a8
+ 314.04 1363.50 2.67 671.96 q0a15
+ 295.07 1436.23 2.36 1997.02 q0a15
+ 755.95 1307.44 2.87 1366.59 q1a15
+1153.97 1453.86 2.17 7801.85 q2a15
+1296.90 1359.50 3.03 680.85 q3a14
+End of peak list
+--- Begin crystal
+Cell parameters 6.20814 12.29674 16.80834 nm, 89.64434 90.05004 90.37597 deg
+astar = -0.0134391 +0.0252260 -0.1585262 nm^-1
+bstar = -0.0710340 +0.0378889 +0.0115093 nm^-1
+cstar = +0.0289154 +0.0516804 +0.0057222 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.01165 nm^-1
+predict_refine/final_residual = 2.959117e-06
+predict_refine/det_shift x = 0.038 y = 0.036 mm
+diffraction_resolution_limit = 2.49 nm^-1 or 4.02 A
+num_reflections = 1072
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ 0 -30 -20 -47.33 176.80 270.00 160.33 1486.8 26.4 q3a1
+ 0 -30 -19 -184.38 191.53 247.00 165.56 1492.2 36.6 q3a1
+ 0 -30 -18 -107.76 437.51 496.00 179.48 1497.6 46.8 q3a1
+ 0 -30 -17 504.33 188.09 366.00 164.24 1502.9 57.0 q3a1
+ 0 -30 -16 551.51 215.86 461.00 162.81 1508.2 67.1 q3a1
+ 0 -30 -15 350.46 243.00 352.00 164.60 1513.6 77.3 q3a1
+ 0 -30 -14 749.08 257.86 356.00 166.65 1518.9 87.4 q3a1
+ 0 -30 -13 -328.60 323.33 404.00 174.52 1524.2 97.5 q3a1
+ 0 -30 -12 -238.24 350.50 342.00 177.52 1529.5 107.6 q3a1
+ 0 -30 -11 -382.15 471.99 424.00 181.62 1534.8 117.7 q3a1
+ 0 -30 -10 174.11 362.39 394.00 171.71 1540.1 127.8 q3a1
+ 0 -28 -23 590.48 214.70 223.00 149.58 1442.6 11.8 q3a1
+ 0 -28 -22 1054.43 352.16 1004.00 155.52 1448.0 22.0 q3a1
+ 0 -28 -21 -488.65 329.95 461.00 161.18 1453.4 32.2 q3a1
+ 0 -28 -20 220.20 184.74 239.00 164.89 1458.8 42.4 q3a1
+ 0 -28 -19 799.88 200.36 362.00 162.10 1464.2 52.6 q3a1
+ 0 -28 -18 525.30 212.73 362.00 169.61 1469.5 62.7 q3a1
+ 0 -28 -17 1380.22 332.94 621.00 186.59 1474.9 72.8 q3a1
+ 0 -28 -16 16.83 340.50 417.00 180.92 1480.2 82.9 q3a1
+ 0 -28 -15 346.80 324.42 402.00 188.11 1485.6 93.0 q3a1
+ 0 -28 -10 1233.00 443.12 474.00 205.00 1512.1 143.3 q3a1
+ 0 -28 -9 525.45 615.11 532.00 221.91 1517.4 153.3 q3a1
+ 0 -28 -8 -827.77 615.73 496.00 237.08 1522.7 163.3 q3a1
+ 0 -28 -7 -1049.05 724.75 556.00 239.41 1528.0 173.3 q3a1
+ 0 -26 -25 345.97 195.52 251.00 153.12 1403.9 7.5 q3a1
+ 0 -26 -24 -103.44 243.99 243.00 159.62 1409.4 17.7 q3a1
+ 0 -26 -23 100.78 195.59 343.00 163.98 1414.8 27.8 q3a1
+ 0 -26 -2 -67.28 816.66 516.00 254.78 1526.7 210.8 q3a3
+ 0 -26 -1 -992.39 887.20 575.00 259.64 1531.9 220.7 q3a3
+ 0 -26 0 1031.46 774.31 640.00 241.15 1537.0 230.6 q3a3
+ 0 -26 1 -2122.40 1088.49 1076.00 280.60 1542.2 240.4 q3a3
+ 0 -24 2 1186.88 433.51 422.00 166.12 1519.7 264.9 q3a3
+ 0 -24 3 1384.91 525.13 485.00 183.59 1524.8 274.6 q3a3
+ 0 -24 4 -400.56 707.25 470.00 209.56 1530.0 284.4 q3a3
+ 0 -24 5 -1310.77 622.33 439.00 205.08 1535.1 294.1 q3a3
+ 0 -24 6 451.90 635.15 421.00 184.49 1540.2 303.8 q3a3
+ 0 -22 -33 185.10 434.63 411.00 155.53 1539.0 596.2 q3a7
+ 0 -22 4 -191.58 339.57 283.00 133.34 1502.5 298.9 q3a3
+ 0 -22 5 116.77 282.77 301.00 129.92 1507.6 308.6 q3a3
+ 0 -22 6 1413.28 460.58 434.00 132.89 1512.7 318.3 q3a3
+ 0 -22 7 614.56 315.13 378.00 130.21 1517.9 327.9 q3a3
+ 0 -22 8 -281.70 566.86 429.00 157.52 1523.0 337.6 q3a3
+ 0 -20 -34 -378.03 585.14 435.00 182.82 1544.8 629.1 q3a7
+ 0 -20 6 -282.74 304.79 319.00 108.95 1485.5 332.6 q3a3
+ 0 -20 7 386.68 247.07 414.00 108.29 1490.6 342.2 q3a3
+ 0 -20 8 500.87 259.86 349.00 108.66 1495.7 351.8 q3a3
+ 0 -20 9 -676.97 380.93 294.00 126.39 1500.8 361.4 q3a3
+ 0 -18 7 111.18 137.47 222.00 94.36 1463.5 356.4 q3a3
+ 0 -14 -34 391.89 314.83 398.00 194.78 1194.0 11.9 q3a0
+ 0 -14 -33 -211.60 552.52 554.00 211.34 1199.5 22.0 q3a0
+ 0 -14 8 96.06 108.09 118.00 63.77 8.2 195.9 q0a2
+ 0 -12 -33 924.11 458.28 480.00 217.37 1172.8 37.7 q3a0
+ 0 -12 8 108.92 125.25 130.00 62.53 22.1 222.5 q0a2
+ 0 -12 9 597.03 134.58 419.00 64.88 31.5 217.4 q0a2
+ 0 -12 10 4211.98 516.03 1679.00 70.27 40.9 212.3 q0a2
+ 0 -12 11 -164.22 269.24 339.00 66.13 50.3 207.2 q0a2
+ 0 -10 -36 -473.82 752.64 599.00 256.69 1145.1 1432.3 q2a15
+ 0 -10 -35 -466.10 666.81 544.00 268.19 1150.6 1442.3 q2a15
+ 0 -10 -34 6595.97 834.44 2473.00 291.90 1156.1 1452.3 q2a15
+ 0 -10 8 264.61 104.49 126.00 61.64 35.9 249.0 q0a2
+ 0 -10 9 15939.62 416.72 8204.00 65.89 45.3 243.8 q0a2
+ 0 -10 10 893.75 140.41 488.00 62.25 54.6 238.7 q0a2
+ 0 -10 11 -54.08 124.33 130.00 57.31 64.0 233.6 q0a2
+ 0 -8 -35 -90.40 710.67 566.00 257.60 1124.2 1457.9 q2a15
+ 0 -8 -34 -1147.34 639.49 495.00 235.93 1129.7 1467.8 q2a15
+ 0 -8 7 53.22 101.68 177.00 64.16 40.2 280.4 q0a2
+ 0 -8 8 378.11 114.78 183.00 61.79 49.6 275.3 q0a2
+ 0 -8 9 942.40 129.84 715.00 60.34 59.0 270.1 q0a2
+ 0 -8 10 -34.56 100.22 112.00 62.89 68.3 265.0 q0a2
+ 0 -6 -32 -57.79 606.17 469.00 198.57 1152.9 319.0 q2a3
+ 0 -6 -31 432.35 541.78 477.00 169.18 1143.0 324.4 q2a3
+ 0 -6 -30 -85.77 486.71 419.00 148.08 1133.1 329.9 q2a3
+ 0 -6 5 181.82 136.15 122.00 62.90 35.2 316.9 q0a2
+ 0 -6 6 42.85 103.61 121.00 62.76 44.6 311.7 q0a2
+ 0 -6 7 309.89 122.57 177.00 62.92 53.9 306.6 q0a2
+ 0 -6 8 740.87 137.19 310.00 64.45 63.3 301.4 q0a2
+ 0 -6 9 -135.58 114.28 114.00 65.03 72.6 296.3 q0a2
+ 0 -4 -32 755.75 617.19 431.00 179.25 1137.8 292.9 q2a3
+ 0 -4 -31 367.69 455.31 378.00 145.15 1127.9 298.3 q2a3
+ 0 -4 -30 1269.37 356.11 755.00 137.30 1118.1 303.8 q2a3
+ 0 -4 -29 668.09 299.14 340.00 111.67 1108.2 309.2 q2a3
+ 0 -4 -28 -38.22 263.63 329.00 111.86 1098.4 314.7 q2a3
+ 0 -4 4 -1506.79 770.93 472.00 182.02 39.6 348.0 q0a2
+ 0 -4 5 143.10 316.09 312.00 99.10 48.9 342.9 q0a2
+ 0 -4 6 -90.47 135.70 133.00 75.89 58.2 337.7 q0a2
+ 0 -4 7 -240.03 125.87 109.00 70.61 67.5 332.5 q0a2
+ 0 -2 -30 -128.31 459.17 463.00 131.15 1103.1 277.8 q2a3
+ 0 -2 -29 -173.12 295.92 296.00 113.10 1093.3 283.3 q2a3
+ 0 -2 -28 554.63 203.96 349.00 103.70 1083.5 288.7 q2a3
+ 0 -2 -27 104.31 133.25 199.00 91.77 1073.7 294.1 q2a3
+ 0 -2 -26 -199.22 172.41 212.00 87.72 1064.0 299.6 q2a3
+ 0 0 -27 -114.72 175.13 221.00 89.22 1059.0 268.3 q2a3
+ 0 0 -26 298.89 121.93 132.00 83.29 1049.3 273.8 q2a3
+ 0 0 -25 -103.17 131.46 129.00 82.68 1039.6 279.2 q2a3
+ 0 0 -24 860.94 185.63 551.00 82.06 1029.9 284.6 q2a3
+ 0 0 -23 -33.23 133.93 136.00 77.92 1020.2 290.0 q2a3
+ 0 0 -22 1038.89 141.49 376.00 77.63 1010.6 295.4 q2a3
+ 0 0 -21 383.97 123.05 150.00 73.80 1001.0 300.8 q2a3
+ 0 2 -23 -257.48 138.30 130.00 82.91 1005.7 264.4 q2a3
+ 0 2 -22 367.88 124.53 136.00 79.12 996.1 269.8 q2a3
+ 0 2 -21 66.35 147.45 156.00 78.58 986.5 275.2 q2a3
+ 0 2 -18 310.89 239.23 266.00 60.92 960.9 291.3 q2a2
+ 0 2 -17 -69.67 236.63 173.00 63.10 951.3 296.7 q2a2
+ 0 2 -16 409.71 170.39 371.00 66.27 941.8 302.0 q2a2
+ 0 2 -15 -104.89 225.14 221.00 65.22 932.3 307.3 q2a2
+ 0 2 -14 -186.93 195.77 171.00 67.73 922.8 312.7 q2a2
+ 0 2 -13 545.24 149.52 437.00 61.42 913.3 318.0 q2a2
+ 0 2 -12 1879.95 177.85 818.00 61.25 903.9 323.3 q2a2
+ 0 2 -11 174.80 128.06 122.00 64.98 894.4 328.6 q2a2
+ 0 2 -10 702.08 125.70 295.00 62.59 885.0 333.9 q2a2
+ 0 2 -9 271.84 118.86 131.00 60.06 875.6 339.2 q2a2
+ 0 2 -8 9019.35 331.31 8049.00 70.26 866.2 344.5 q2a2
+ 0 2 -7 1177.30 177.08 736.00 79.30 856.8 349.8 q2a2
+ 0 2 -6 11761.55 606.44 8502.00 135.58 847.4 355.0 q2a2
+ 0 2 -5 2723.52 1480.33 2177.00 395.19 838.1 360.3 q2a2
+ 0 4 -15 -208.55 151.06 146.00 64.42 918.2 281.9 q2a2
+ 0 4 -14 -160.67 143.90 140.00 63.52 908.7 287.2 q2a2
+ 0 4 -13 -44.40 169.12 191.00 66.66 899.3 292.6 q2a2
+ 0 4 -12 -99.33 141.70 119.00 66.19 889.9 297.9 q2a2
+ 0 4 -11 268.61 116.46 108.00 60.35 880.5 303.2 q2a2
+ 0 4 -10 -2.89 131.87 134.00 64.85 871.1 308.5 q2a2
+ 1 -39 -18 -351.14 242.68 301.00 83.23 1508.9 747.7 q3a9
+ 1 -39 -13 11.38 196.22 248.00 107.97 1181.1 1382.9 q3a14
+ 1 -39 -12 302.59 181.80 266.00 106.85 1191.7 1377.5 q3a14
+ 1 -39 -11 -120.20 155.56 177.00 108.66 1202.2 1372.2 q3a14
+ 1 -39 -10 -80.60 170.64 188.00 106.54 1212.7 1366.8 q3a14
+ 1 -39 -9 245.80 129.45 167.00 99.72 1223.2 1361.5 q3a14
+ 1 -39 -8 70.50 147.73 148.00 99.50 1233.7 1356.2 q3a14
+ 1 -37 -6 -128.00 188.74 209.00 121.29 1270.7 1375.1 q3a14
+ 1 -37 -5 -211.49 196.54 228.00 123.28 1281.1 1369.8 q3a14
+ 1 -37 -4 -199.60 288.10 442.00 130.11 1291.4 1364.5 q3a14
+ 1 -37 -3 -23.61 373.70 493.00 130.87 1301.8 1359.2 q3a14
+ 1 -37 -2 -161.97 270.27 237.00 123.10 1312.1 1353.9 q3a14
+ 1 -37 -1 -15.74 211.03 230.00 118.91 1322.5 1348.7 q3a14
+ 1 -37 0 -181.66 239.97 271.00 125.54 1332.8 1343.4 q3a14
+ 1 -37 1 -257.33 254.76 276.00 124.33 1343.1 1338.2 q3a14
+ 1 -35 -32 105.83 134.24 140.00 85.49 1434.9 431.5 q3a5
+ 1 -35 -31 -33.42 126.30 144.00 90.74 1445.7 426.1 q3a5
+ 1 -35 -30 -20.09 135.81 175.00 90.57 1456.5 420.6 q3a5
+ 1 -35 -29 154.01 125.11 141.00 90.96 1467.3 415.2 q3a5
+ 1 -35 -28 45.30 145.99 240.00 98.89 1478.1 409.8 q3a5
+ 1 -35 2 -221.01 279.03 334.00 138.45 1365.9 1362.2 q3a15
+ 1 -35 3 -55.40 158.85 236.00 131.93 1376.1 1356.9 q3a15
+ 1 -35 4 -186.72 201.83 257.00 134.46 1386.3 1351.7 q3a15
+ 1 -35 5 17.99 182.84 205.00 131.45 1396.5 1346.5 q3a15
+ 1 -35 6 536.26 201.18 267.00 126.38 1406.7 1341.3 q3a15
+ 1 -33 -35 -40.00 141.43 167.00 88.00 1419.3 477.4 q3a5
+ 1 -33 -34 445.64 135.03 174.00 86.91 1430.2 471.9 q3a5
+ 1 -33 -33 -31.80 117.74 155.00 94.34 1441.0 466.4 q3a5
+ 1 -33 -32 -14.31 137.88 217.00 93.99 1451.8 460.9 q3a5
+ 1 -33 7 502.22 186.57 260.00 125.18 1432.1 1365.1 q3a15
+ 1 -33 8 -180.41 189.26 219.00 129.29 1442.1 1359.9 q3a15
+ 1 -33 9 -125.10 197.97 224.00 133.19 1452.2 1354.7 q3a15
+ 1 -33 10 360.40 192.65 258.00 133.54 1462.3 1349.5 q3a15
+ 1 -31 -38 297.73 134.73 196.00 92.03 1403.8 523.2 q3a5
+ 1 -31 -37 632.86 159.88 326.00 93.51 1414.6 517.6 q3a5
+ 1 -31 -36 324.17 204.33 268.00 96.83 1425.4 512.1 q3a5
+ 1 -31 10 243.34 250.75 381.00 151.54 1477.3 1378.4 q3a15
+ 1 -31 11 -72.36 216.00 286.00 144.23 1487.3 1373.2 q3a15
+ 1 -31 12 209.07 220.34 359.00 150.75 1497.3 1368.0 q3a15
+ 1 -31 13 -259.00 298.42 316.00 152.71 1507.2 1362.8 q3a15
+ 1 -29 13 -361.59 470.79 414.00 177.71 1522.0 1391.5 q3a15
+ 1 -29 14 -262.71 477.37 415.00 167.65 1531.9 1386.3 q3a15
+ 1 -29 15 -447.20 452.45 408.00 162.80 1541.8 1381.2 q3a15
+ 1 -27 -42 63.43 152.31 159.00 99.09 1395.3 575.6 q3a7
+ 1 -27 -41 291.60 149.93 178.00 99.60 1406.0 570.0 q3a7
+ 1 -27 -40 265.39 165.62 163.00 96.87 1416.8 564.3 q3a7
+ 1 -25 -44 158.00 144.18 165.00 103.29 1390.9 615.5 q3a7
+ 1 -25 -43 -175.74 144.76 168.00 103.97 1401.6 609.8 q3a7
+ 1 -25 -42 56.81 141.42 217.00 104.86 1412.4 604.2 q3a7
+ 1 -25 17 125.17 375.17 411.00 186.61 19.9 23.6 q0a0
+ 1 -25 18 2578.71 265.72 819.00 167.35 29.6 18.4 q0a0
+ 1 -25 19 -26.05 284.48 308.00 173.18 39.3 13.3 q0a0
+ 1 -23 -45 76.29 158.85 195.00 104.14 1397.2 649.6 q3a7
+ 1 -23 -44 387.42 156.73 255.00 103.05 1407.9 643.9 q3a7
+ 1 -23 -43 -58.99 168.62 175.00 109.55 1418.7 638.2 q3a7
+ 1 -23 18 186.68 299.34 389.00 186.09 44.0 46.4 q0a0
+ 1 -23 19 1607.13 364.17 843.00 174.69 53.7 41.3 q0a0
+ 1 -23 20 513.88 249.27 501.00 174.49 63.4 36.1 q0a0
+ 1 -21 -46 -214.26 213.69 256.00 116.84 1403.5 683.5 q3a7
+ 1 -21 -45 -507.55 216.46 279.00 112.34 1414.2 677.8 q3a7
+ 1 -21 -44 334.65 157.39 217.00 109.80 1424.9 672.1 q3a7
+ 1 -21 19 10.88 237.34 336.00 166.94 68.0 69.1 q0a0
+ 1 -21 20 316.03 378.64 491.00 181.10 77.6 63.9 q0a0
+ 1 -21 21 1057.32 332.64 457.00 167.91 87.2 58.7 q0a0
+ 1 -19 -47 68.64 186.99 216.00 106.84 1409.8 717.2 q3a7
+ 1 -19 -46 251.92 157.62 216.00 111.31 1420.5 711.5 q3a7
+ 1 -19 -45 -12.80 160.56 311.00 115.12 1431.2 705.8 q3a7
+ 1 -19 20 973.61 255.52 482.00 150.13 91.8 91.6 q0a0
+ 1 -19 21 965.51 224.18 555.00 163.28 101.4 86.4 q0a0
+ 1 -19 22 -175.46 338.65 382.00 171.30 110.9 81.2 q0a0
+ 1 -17 21 688.78 336.18 469.00 145.74 115.4 113.9 q0a0
+ 1 -17 22 65.37 165.98 213.00 146.52 124.9 108.7 q0a0
+ 1 -15 21 -156.84 184.51 258.00 131.06 129.3 141.2 q0a0
+ 1 -15 22 -194.99 268.11 365.00 137.61 138.8 136.0 q0a0
+ 1 -13 21 119.34 205.39 245.00 122.07 143.2 168.3 q0a0
+ 1 -13 22 969.66 191.86 544.00 116.46 152.6 163.1 q0a0
+ 1 -11 -47 16.36 169.33 289.00 145.87 1092.2 1305.6 q2a15
+ 1 -11 -46 126.87 232.81 307.00 149.68 1097.9 1316.1 q2a15
+ 1 -9 -47 654.84 177.15 228.00 135.51 1065.0 1322.1 q2a15
+ 1 -9 -46 273.17 309.37 438.00 147.10 1070.8 1332.5 q2a15
+ 1 -9 -45 -191.89 259.45 351.00 156.22 1076.5 1342.9 q2a15
+ 1 -9 20 -63.62 193.54 241.00 78.26 161.6 198.9 q0a2
+ 1 -9 21 -481.12 200.59 176.00 77.49 171.0 193.8 q0a2
+ 1 -7 -46 -470.21 199.46 225.00 147.62 1043.8 1348.9 q2a15
+ 1 -7 -45 -83.49 189.55 218.00 148.30 1049.6 1359.2 q2a15
+ 1 -7 20 56.21 138.01 154.00 69.85 175.1 225.6 q0a2
+ 1 -7 21 2214.00 225.54 913.00 71.00 184.4 220.5 q0a2
+ 1 -5 -45 102.97 179.65 225.00 148.31 1022.8 1375.4 q2a15
+ 1 -5 -44 232.24 196.46 220.00 152.79 1028.5 1385.7 q2a15
+ 1 -5 19 107.62 164.43 164.00 67.74 179.2 257.4 q0a2
+ 1 -3 -44 -355.39 314.53 318.00 170.72 1001.9 1401.8 q2a15
+ 1 -3 -43 -33.68 321.01 364.00 172.01 1007.6 1412.0 q2a15
+ 1 -3 18 -297.43 241.61 203.00 74.25 183.2 288.9 q0a2
+ 1 -1 -43 -311.33 408.12 446.00 187.33 981.2 1427.9 q2a15
+ 1 -1 -42 1443.21 338.49 523.00 173.79 986.9 1438.1 q2a15
+ 1 -1 -41 248.72 340.99 403.00 185.99 992.6 1448.2 q2a15
+ 1 -1 16 7.80 204.25 183.00 61.80 178.0 325.6 q0a2
+ 1 1 14 -259.00 210.71 164.00 68.14 172.7 362.1 q0a2
+ 1 1 15 122.69 176.58 144.00 64.31 182.0 356.9 q0a2
+ 1 3 12 270.11 128.11 118.00 47.85 399.1 278.4 q1a2
+ 1 5 -37 -1040.88 681.16 517.00 238.41 1120.7 168.8 q2a1
+ 1 5 -36 1625.22 654.34 743.00 240.26 1110.7 174.5 q2a1
+ 1 5 9 406.14 124.89 178.00 48.81 440.7 292.9 q1a2
+ 1 5 10 80.55 139.38 148.00 51.58 435.4 283.6 q1a2
+ 1 5 11 214.75 124.87 144.00 48.25 430.2 274.3 q1a2
+ 1 5 12 -76.92 132.81 118.00 52.59 424.9 265.1 q1a2
+ 1 7 -34 365.71 548.21 508.00 212.17 1075.7 160.2 q2a1
+ 1 7 -33 895.16 484.73 735.00 198.96 1065.9 165.9 q2a1
+ 1 7 -32 54.96 248.41 359.00 173.35 1056.1 171.5 q2a1
+ 1 7 -31 -152.06 207.82 249.00 160.47 1046.2 177.2 q2a1
+ 1 7 6 63.78 94.05 78.00 48.27 482.2 307.3 q1a2
+ 1 7 7 324.33 117.93 247.00 50.10 476.9 298.1 q1a2
+ 1 7 8 1524.92 157.86 1216.00 45.53 471.6 288.8 q1a2
+ 1 7 9 -160.00 121.33 104.00 51.29 466.3 279.5 q1a2
+ 1 9 -30 326.25 184.88 226.00 155.40 1021.5 157.3 q2a1
+ 1 9 -29 91.39 202.22 225.00 148.79 1011.8 163.0 q2a1
+ 1 9 -28 2995.34 262.84 1606.00 151.54 1002.0 168.6 q2a1
+ 1 9 -27 467.51 188.95 570.00 143.81 992.3 174.2 q2a1
+ 1 9 0 -164.61 138.69 143.00 52.34 539.6 349.7 q1a2
+ 1 9 1 -57.19 185.72 153.00 62.68 534.2 340.4 q1a2
+ 1 9 2 133.63 150.28 140.00 54.05 528.9 331.1 q1a2
+ 1 9 3 28828.60 561.26 7545.00 62.66 523.6 321.8 q1a2
+ 1 9 4 190.10 146.27 141.00 55.16 518.3 312.5 q1a2
+ 1 9 5 -279.83 132.98 110.00 57.02 513.0 303.2 q1a2
+ 1 11 -24 252.67 177.02 195.00 112.33 951.7 165.7 q2a0
+ 1 11 -23 -79.12 186.91 293.00 115.49 942.1 171.3 q2a0
+ 1 11 -22 -224.54 171.00 244.00 114.15 932.5 176.9 q2a0
+ 1 11 -14 -97.00 127.00 116.00 62.00 856.6 192.5 q2a2
+ 1 11 -13 -173.51 149.32 118.00 63.54 847.2 197.9 q2a2
+ 1 11 -12 497.77 150.43 120.00 58.29 837.7 203.4 q2a2
+ 1 11 -11 180.18 112.19 108.00 62.10 828.2 208.8 q2a2
+ 1 11 -10 -1.74 117.03 129.00 61.69 818.8 214.2 q2a2
+ 1 11 -9 378.60 142.10 148.00 62.66 809.3 219.7 q2a2
+ 1 11 -8 88.69 124.95 113.00 62.82 799.9 225.1 q2a2
+ 1 11 -7 442.94 121.42 189.00 59.23 790.5 230.5 q2a2
+ 1 11 -1 -30.56 181.01 122.00 52.46 570.3 345.5 q1a2
+ 2 -44 -25 -116.24 98.19 106.00 69.94 1462.9 874.2 q3a9
+ 2 -44 -24 -185.41 134.06 158.00 70.78 1457.3 863.0 q3a9
+ 2 -44 -23 60.85 94.68 106.00 66.68 1451.8 851.9 q3a9
+ 2 -44 -22 80.66 91.72 108.00 65.80 1446.3 840.7 q3a9
+ 2 -44 -21 -101.00 110.33 117.00 67.57 1440.9 829.6 q3a9
+ 2 -44 -20 -95.81 112.31 113.00 69.42 1435.4 818.5 q3a9
+ 2 -44 -19 -24.78 115.23 125.00 66.44 1429.9 807.4 q3a9
+ 2 -44 -18 -163.74 116.23 122.00 69.22 1424.5 796.3 q3a9
+ 2 -44 -17 -116.46 125.75 111.00 66.62 1419.0 785.3 q3a9
+ 2 -44 -16 -178.95 107.20 102.00 65.84 1413.6 774.2 q3a9
+ 2 -44 -15 174.90 109.93 109.00 62.29 1408.1 763.2 q3a9
+ 2 -44 -6 140.67 117.21 123.00 67.33 1209.9 1288.0 q3a12
+ 2 -44 -5 -10.06 125.87 138.00 66.39 1220.7 1282.5 q3a12
+ 2 -44 -4 -141.32 129.31 160.00 68.99 1231.5 1277.1 q3a12
+ 2 -44 -3 -58.11 80.41 122.00 64.78 1242.2 1271.8 q3a12
+ 2 -44 -2 -215.29 111.07 97.00 66.99 1253.0 1266.4 q3a12
+ 2 -44 -1 136.86 104.58 132.00 65.47 1263.7 1261.0 q3a12
+ 2 -44 0 -352.00 123.84 123.00 71.00 1274.4 1255.6 q3a12
+ 2 -42 -30 -127.96 204.81 242.00 68.88 1521.6 912.6 q3a9
+ 2 -42 -29 -438.26 312.77 280.00 76.23 1516.0 901.4 q3a9
+ 2 -42 -28 491.82 163.04 155.00 70.06 1510.4 890.1 q3a9
+ 2 -42 3 146.57 200.28 210.00 75.48 1322.7 1270.2 q3a12
+ 2 -42 4 389.48 245.70 276.00 74.11 1333.3 1264.9 q3a12
+ 2 -42 5 141.71 228.87 204.00 72.29 1343.9 1259.6 q3a12
+ 2 -40 -37 -24.15 173.14 218.00 75.49 1329.0 378.8 q3a4
+ 2 -40 8 -259.30 197.99 233.00 83.99 1388.4 1274.0 q3a13
+ 2 -40 9 268.24 144.85 180.00 76.06 1398.9 1268.7 q3a13
+ 2 -40 10 -10.42 125.44 191.00 75.42 1409.3 1263.4 q3a13
+ 2 -40 11 101.28 110.89 152.00 74.01 1419.7 1258.1 q3a13
+ 2 -38 -40 -568.68 162.04 149.00 82.18 1313.0 426.4 q3a4
+ 2 -38 -39 434.23 155.14 178.00 77.08 1324.3 420.7 q3a4
+ 2 -38 -38 96.34 207.95 211.00 77.20 1335.6 415.1 q3a4
+ 2 -38 13 -132.42 135.93 163.00 81.25 1456.2 1277.7 q3a13
+ 2 -38 14 -68.15 136.46 191.00 78.82 1466.5 1272.5 q3a13
+ 2 -38 15 -299.61 331.00 340.00 89.79 1476.8 1267.2 q3a13
+ 2 -36 -43 -102.42 137.41 135.00 78.89 1297.0 473.9 q3a4
+ 2 -36 -42 -116.49 133.27 148.00 74.95 1308.3 468.2 q3a4
+ 2 -36 -41 77.03 181.91 190.00 76.18 1319.6 462.5 q3a4
+ 2 -36 17 -784.94 340.46 305.00 100.61 1512.7 1286.7 q3a13
+ 2 -36 18 245.27 240.62 228.00 88.52 1522.9 1281.4 q3a13
+ 2 -34 -46 302.08 118.82 192.00 73.20 1281.0 521.3 q3a4
+ 2 -34 -45 -66.57 159.81 167.00 77.48 1292.3 515.5 q3a4
+ 2 -34 -44 -136.48 149.71 181.00 79.52 1303.6 509.8 q3a4
+ 2 -32 21 -266.73 271.62 282.00 116.55 310.4 727.4 q0a7
+ 2 -32 22 -38.21 264.81 418.00 117.62 305.2 717.4 q0a7
+ 2 -32 23 78.73 178.40 248.00 102.76 300.0 707.3 q0a7
+ 2 -30 -50 -165.12 126.71 158.00 75.33 1272.6 577.3 q3a6
+ 2 -30 -49 35.56 105.32 136.00 74.15 1283.8 571.5 q3a6
+ 2 -30 -48 -202.55 209.25 275.00 83.87 1295.1 565.7 q3a6
+ 2 -30 23 236.75 370.39 358.00 117.25 329.4 692.7 q0a7
+ 2 -30 24 325.36 275.28 319.00 114.93 324.2 682.7 q0a7
+ 2 -28 -51 -217.50 160.43 209.00 84.50 1279.5 612.8 q3a6
+ 2 -28 -50 -94.94 118.59 126.00 79.24 1290.7 606.9 q3a6
+ 2 -28 25 -110.96 482.77 370.00 133.96 348.2 658.2 q0a7
+ 2 -28 26 198.67 261.27 313.00 112.33 343.0 648.3 q0a7
+ 2 -26 -52 103.07 143.05 156.00 80.33 1286.4 648.0 q3a6
+ 2 -26 -51 -130.27 195.50 197.00 84.76 1297.6 642.2 q3a6
+ 2 -26 26 302.10 462.42 348.00 134.10 372.0 633.9 q0a7
+ 2 -26 27 830.33 383.04 342.00 125.01 366.8 624.1 q0a7
+ 2 -24 -53 -132.45 174.79 173.00 85.05 1293.2 683.1 q3a6
+ 2 -24 -52 21.65 189.98 249.00 87.68 1304.4 677.2 q3a6
+ 2 -22 -54 233.53 166.13 281.00 83.42 1300.0 718.0 q3a6
+ 2 -22 -53 358.67 171.88 183.00 85.33 1311.1 712.1 q3a6
+ 2 -20 29 769.43 329.47 406.00 176.24 178.3 24.9 q0a0
+ 2 -18 -55 -158.00 152.27 168.00 80.00 1137.8 1177.5 q2a13
+ 2 -18 -54 590.11 196.28 248.00 80.71 1143.8 1188.5 q2a13
+ 2 -16 -56 -375.79 259.53 323.00 86.18 1103.5 1184.3 q2a13
+ 2 -16 -55 -364.36 196.41 200.00 85.44 1109.4 1195.3 q2a13
+ 2 -16 30 -342.76 485.46 430.00 205.73 212.9 75.8 q0a1
+ 2 -16 31 1524.95 320.29 517.00 185.18 222.4 70.6 q0a1
+ 2 -14 -56 -75.26 113.31 137.00 81.86 1075.3 1202.0 q2a13
+ 2 -14 -55 -40.10 150.15 265.00 84.43 1081.2 1212.9 q2a13
+ 2 -14 30 -608.62 371.10 476.00 203.62 226.7 103.5 q0a1
+ 2 -14 31 52.70 400.11 451.00 199.43 236.2 98.3 q0a1
+ 2 -12 -56 121.94 133.96 169.00 82.16 1047.3 1219.6 q2a13
+ 2 -12 -55 80.80 137.70 158.00 82.88 1053.2 1230.5 q2a13
+ 2 -12 30 862.25 429.11 499.00 189.75 240.4 131.2 q0a1
+ 2 -12 31 -951.30 487.01 516.00 205.05 249.9 125.9 q0a1
+ 2 -10 -56 15.68 130.73 154.00 80.03 1019.5 1237.0 q2a13
+ 2 -10 -55 285.09 134.54 147.00 82.43 1025.4 1247.9 q2a13
+ 2 -10 30 3418.62 340.46 1638.00 176.38 254.0 158.6 q0a1
+ 2 -10 31 218.75 329.95 393.00 180.98 263.5 153.4 q0a1
+ 2 -8 -55 -241.02 190.94 182.00 90.22 997.8 1265.2 q2a13
+ 2 -8 -54 180.66 225.27 315.00 87.35 1003.8 1275.9 q2a13
+ 2 -4 28 209.03 167.20 167.00 90.18 275.9 222.7 q0a3
+ 2 -4 29 35.48 185.91 194.00 99.17 285.3 217.5 q0a3
+ 2 -2 -53 -217.28 202.11 213.00 120.92 931.1 1310.0 q2a14
+ 2 -2 -52 -40.07 213.11 236.00 124.04 937.0 1320.6 q2a14
+ 2 -2 27 286.29 130.35 224.00 88.01 279.8 254.8 q0a3
+ 2 -2 28 -242.45 161.76 189.00 96.07 289.2 249.6 q0a3
+ 2 0 -52 -392.96 220.87 214.00 128.12 910.1 1337.2 q2a14
+ 2 0 -51 158.18 296.23 337.00 129.69 916.0 1347.8 q2a14
+ 2 0 -50 1322.86 226.61 321.00 122.55 921.9 1358.3 q2a14
+ 2 0 26 -110.20 235.13 321.00 92.09 283.7 286.7 q0a3
+ 2 0 27 7.60 189.57 234.00 95.60 293.0 281.5 q0a3
+ 2 2 -50 -31.12 257.40 286.00 131.96 895.1 1374.7 q2a14
+ 2 2 -49 47.67 240.08 274.00 135.99 901.1 1385.2 q2a14
+ 2 2 24 197.08 106.41 136.00 80.65 278.2 323.7 q0a3
+ 2 2 25 164.64 140.88 166.00 89.23 287.5 318.5 q0a3
+ 2 2 26 -56.69 172.37 231.00 96.83 296.8 313.2 q0a3
+ 2 4 -49 21.14 227.91 308.00 126.49 874.5 1401.5 q2a14
+ 2 4 -48 646.12 288.93 356.00 133.63 880.4 1411.8 q2a14
+ 2 4 -47 -500.93 300.89 301.00 145.75 886.3 1422.2 q2a14
+ 2 4 23 140.93 119.60 150.00 87.25 282.0 355.3 q0a3
+ 2 4 24 101.68 134.69 192.00 87.86 291.3 350.1 q0a3
+ 2 6 -47 -430.83 242.29 278.00 133.51 859.9 1438.3 q2a14
+ 2 6 -46 771.18 366.91 528.00 138.47 865.8 1448.6 q2a14
+ 2 6 -45 71.44 230.87 338.00 141.32 871.6 1458.9 q2a14
+ 2 10 -42 -221.44 339.66 442.00 159.32 1134.1 65.7 q2a1
+ 2 10 -41 490.40 274.18 361.00 166.81 1124.0 71.5 q2a1
+ 2 10 -40 -149.64 222.85 301.00 167.36 1113.9 77.4 q2a1
+ 2 10 15 41.18 132.34 110.00 49.02 476.6 195.7 q1a2
+ 2 12 -38 1280.89 319.89 920.00 172.78 1078.3 63.3 q2a1
+ 2 12 -37 1113.18 248.87 556.00 175.49 1068.3 69.2 q2a1
+ 2 12 -36 636.50 215.45 425.00 173.93 1058.3 75.0 q2a1
+ 2 12 11 107.90 146.87 149.00 54.90 523.8 219.7 q1a2
+ 2 12 12 -98.41 131.80 183.00 60.91 518.4 210.4 q1a2
+ 2 12 13 133.52 128.09 312.00 56.23 513.1 201.1 q1a2
+ 2 14 -34 1919.36 399.55 785.00 182.97 1023.2 61.0 q2a1
+ 2 14 -33 816.67 489.01 507.00 183.33 1013.3 66.8 q2a1
+ 2 14 -32 641.51 564.47 662.00 216.28 1003.4 72.6 q2a1
+ 2 14 -31 716.96 434.14 439.00 202.10 993.5 78.4 q2a1
+ 2 14 7 344.68 193.29 141.00 55.52 571.0 243.6 q1a2
+ 2 14 8 153.05 157.65 189.00 55.82 565.6 234.3 q1a2
+ 2 14 9 442.33 161.43 123.00 52.95 560.2 225.0 q1a2
+ 2 14 10 431.44 159.77 142.00 59.56 554.8 215.7 q1a2
+ 2 16 -29 -14.15 604.12 523.00 215.62 961.9 64.5 q2a0
+ 2 16 -28 1748.10 593.42 572.00 200.86 952.1 70.3 q2a0
+ 2 16 -27 776.06 617.82 638.00 205.53 942.4 76.1 q2a0
+ 2 16 -26 1120.67 265.81 457.00 183.33 932.6 81.8 q2a0
+ 2 16 -25 -43.48 298.66 412.00 174.03 922.9 87.6 q2a0
+ 2 16 -24 419.17 314.68 389.00 163.83 913.1 93.3 q2a0
+ 2 18 -20 102.61 173.55 217.00 142.21 860.0 90.8 q2a0
+ 2 18 -19 1.25 197.06 362.00 144.02 850.4 96.5 q2a0
+ 2 18 -18 533.75 203.30 237.00 129.98 840.8 102.2 q2a0
+ 2 18 -17 -110.88 137.74 188.00 131.51 831.2 107.9 q2a0
+ 2 18 -16 487.91 188.66 337.00 130.59 821.6 113.6 q2a0
+ 2 18 -15 90.36 140.61 189.00 123.73 812.1 119.2 q2a0
+ 2 18 -14 1409.52 235.63 743.00 121.91 802.6 124.9 q2a0
+ 2 18 -13 301.70 183.14 208.00 119.05 793.0 130.5 q2a0
+ 2 18 -12 1359.27 191.06 764.00 120.48 783.5 136.1 q2a0
+ 2 18 -8 -84.33 190.84 212.00 89.05 700.9 357.5 q1a3
+ 2 18 -7 -122.78 166.29 188.00 88.44 695.4 348.1 q1a3
+ 2 18 -6 168.44 152.10 160.00 84.17 689.9 338.6 q1a3
+ 2 18 -5 94.11 115.32 145.00 82.37 684.4 329.2 q1a3
+ 2 18 -4 29.74 116.80 202.00 86.90 678.8 319.8 q1a3
+ 3 -49 -24 -31.61 120.95 153.00 63.56 1367.9 917.4 q3a9
+ 3 -49 -20 42.79 213.83 184.00 61.47 1348.5 871.2 q3a8
+ 3 -49 -19 -47.19 214.57 259.00 59.86 1342.9 859.7 q3a8
+ 3 -49 -5 122.57 129.41 129.00 64.91 1173.5 1191.5 q3a12
+ 3 -49 -4 -243.81 117.06 106.00 66.57 1184.7 1186.0 q3a12
+ 3 -49 -3 3.75 101.70 120.00 63.41 1195.8 1180.5 q3a12
+ 3 -49 -2 183.96 101.70 118.00 63.12 1206.9 1175.0 q3a12
+ 3 -49 -1 -34.80 100.75 97.00 60.20 1218.0 1169.6 q3a12
+ 3 -49 0 -86.92 103.54 103.00 62.08 1229.1 1164.1 q3a12
+ 3 -49 1 -17.13 105.77 103.00 61.53 1240.2 1158.6 q3a12
+ 3 -47 -34 -42.16 92.29 104.00 60.11 1457.4 988.0 q3a11
+ 3 -47 -33 -104.62 91.27 90.00 59.85 1451.7 976.3 q3a11
+ 3 -47 -32 -83.19 92.59 90.00 59.58 1445.9 964.6 q3a11
+ 3 -47 -31 134.47 124.21 112.00 55.68 1440.2 952.9 q3a11
+ 3 -47 -30 39.24 111.94 110.00 58.53 1434.5 941.3 q3a11
+ 3 -47 5 158.68 113.56 233.00 64.95 1301.2 1168.8 q3a12
+ 3 -47 6 -17.31 109.16 134.00 66.03 1312.1 1163.4 q3a12
+ 3 -47 7 115.22 118.94 132.00 64.65 1323.1 1158.0 q3a12
+ 3 -47 8 251.90 117.49 138.00 59.47 1333.9 1152.6 q3a12
+ 3 -45 -39 -298.32 184.52 240.00 65.88 1518.4 1027.9 q3a11
+ 3 -45 -38 177.90 118.43 111.00 57.41 1512.6 1016.1 q3a11
+ 3 -45 -37 -119.76 129.16 170.00 63.53 1506.8 1004.4 q3a11
+ 3 -45 -36 -25.00 112.58 123.00 62.00 1501.0 992.7 q3a11
+ 3 -45 11 -297.91 122.07 131.00 68.43 1380.0 1168.2 q3a13
+ 3 -45 12 74.88 106.77 132.00 63.88 1390.7 1162.8 q3a13
+ 3 -45 13 50.70 94.14 111.00 62.90 1401.5 1157.4 q3a13
+ 3 -43 15 193.56 112.55 93.00 63.11 1439.1 1178.1 q3a13
+ 3 -43 16 60.68 96.80 99.00 65.03 1449.7 1172.8 q3a13
+ 3 -43 17 -299.19 134.15 145.00 70.43 1460.3 1167.5 q3a13
+ 3 -41 -46 -258.48 115.64 126.00 72.28 1202.5 409.1 q3a4
+ 3 -41 -45 -25.24 101.42 111.00 69.03 1214.4 403.3 q3a4
+ 3 -41 19 117.79 111.11 120.00 69.62 1497.4 1188.0 q3a13
+ 3 -41 20 18.18 125.49 169.00 72.47 1507.9 1182.7 q3a13
+ 3 -41 21 167.33 142.75 218.00 67.67 1518.4 1177.4 q3a13
+ 3 -39 -49 171.05 132.08 142.00 71.79 1186.1 458.3 q3a4
+ 3 -39 -48 -37.64 114.54 142.00 72.56 1197.9 452.4 q3a4
+ 3 -39 22 16.15 211.27 235.00 76.81 1544.5 1203.0 q3a13
+ 3 -37 -51 -290.04 166.81 197.00 77.84 1181.4 501.5 q3a4
+ 3 -37 -50 -15.32 126.17 145.00 72.78 1193.2 495.6 q3a4
+ 3 -37 25 171.32 132.18 150.00 81.01 203.3 719.4 q0a7
+ 3 -35 -53 -238.12 133.98 126.00 77.12 1176.8 544.5 q3a4
+ 3 -35 -52 -44.86 145.90 168.00 75.41 1188.6 538.6 q3a4
+ 3 -35 27 69.81 134.07 211.00 88.04 223.4 683.7 q0a7
+ 3 -35 28 330.87 194.14 219.00 88.92 218.1 673.4 q0a7
+ 3 -33 29 -93.65 136.23 170.00 91.32 243.2 648.3 q0a7
+ 3 -33 30 128.51 162.04 213.00 88.91 238.0 638.2 q0a7
+ 3 -31 -56 -98.18 129.95 134.00 77.58 1180.4 597.7 q3a6
+ 3 -31 31 118.73 144.02 151.00 88.19 262.9 613.3 q0a7
+ 3 -31 32 225.31 119.21 142.00 85.36 257.6 603.2 q0a7
+ 3 -29 -58 185.79 147.58 143.00 76.41 1176.1 640.3 q3a6
+ 3 -29 -57 40.38 163.61 186.00 77.85 1187.7 634.2 q3a6
+ 3 -29 32 41.10 143.73 149.00 92.28 287.5 588.7 q0a7
+ 3 -29 33 4.55 156.31 147.00 92.13 282.3 578.6 q0a7
+ 3 -27 -59 58.44 177.30 208.00 78.56 1183.4 676.6 q3a6
+ 3 -27 -58 -210.58 152.73 158.00 78.05 1195.1 670.5 q3a6
+ 3 -27 33 -145.85 134.54 173.00 99.30 312.0 564.2 q0a7
+ 3 -25 -60 -52.74 137.20 133.00 80.14 1190.8 712.8 q3a6
+ 3 -25 -59 124.12 137.80 146.00 77.36 1202.4 706.7 q3a6
+ 3 -23 35 313.24 454.31 333.00 120.48 359.9 544.4 q0a5
+ 3 -23 36 1013.82 340.78 422.00 114.35 354.7 534.5 q0a5
+ 3 -21 37 1224.68 366.44 394.00 114.21 378.8 510.9 q0a5
+ 3 -17 37 181.39 202.06 219.00 147.24 282.9 18.8 q0a1
+ 3 -15 37 237.26 180.68 416.00 157.97 296.7 47.2 q0a1
+ 3 -15 38 353.32 171.01 385.00 156.12 306.3 41.9 q0a1
+ 3 -13 -63 115.27 129.62 135.00 69.53 1011.9 1121.4 q2a13
+ 3 -13 -62 -329.27 141.10 117.00 72.74 1018.1 1132.7 q2a13
+ 3 -13 37 -0.72 197.83 260.00 168.57 310.5 75.5 q0a1
+ 3 -13 38 240.57 191.44 265.00 165.48 320.1 70.2 q0a1
+ 3 -11 -63 -269.61 142.54 130.00 75.38 983.3 1139.7 q2a13
+ 3 -11 -62 91.65 123.51 172.00 73.99 989.5 1151.0 q2a13
+ 3 -11 37 294.11 456.66 496.00 184.67 324.1 103.6 q0a1
+ 3 -11 38 -161.09 338.62 430.00 180.37 333.7 98.3 q0a1
+ 3 -9 37 991.91 528.10 591.00 199.14 337.7 131.5 q0a1
+ 3 -7 -62 -57.24 216.76 239.00 74.64 936.0 1187.2 q2a12
+ 3 -7 -61 455.73 165.22 198.00 73.07 942.2 1198.3 q2a12
+ 3 -7 36 -858.32 529.53 525.00 234.95 341.7 164.5 q0a1
+ 3 -7 37 1675.37 479.27 539.00 208.89 351.2 159.2 q0a1
+ 3 -5 -61 123.90 185.57 186.00 76.90 914.2 1216.2 q2a12
+ 3 -3 -61 133.60 104.13 129.00 74.60 886.4 1234.0 q2a12
+ 3 -3 -60 250.82 124.97 155.00 74.47 892.6 1245.0 q2a12
+ 3 -3 35 610.41 617.24 554.00 203.77 359.4 197.7 q0a3
+ 3 -3 36 -325.68 761.66 551.00 245.87 368.9 192.4 q0a3
+ 3 -1 -60 -108.96 104.48 123.00 73.16 865.0 1262.6 q2a12
+ 3 -1 -59 202.00 139.08 160.00 75.86 871.2 1273.5 q2a12
+ 3 -1 34 316.31 541.65 458.00 190.36 363.2 230.3 q0a3
+ 3 -1 35 -796.24 809.16 1110.00 259.52 372.6 225.0 q0a3
+ 3 1 33 3177.04 699.93 747.00 194.12 366.9 262.7 q0a3
+ 3 1 34 959.96 637.36 518.00 217.35 376.3 257.4 q0a3
+ 3 3 -56 92.53 158.00 143.00 97.56 835.1 1312.8 q2a14
+ 3 3 32 3572.58 628.30 1147.00 191.27 370.6 295.0 q0a3
+ 3 3 33 2934.45 809.58 1041.00 225.83 380.0 289.7 q0a3
+ 3 5 -56 9.08 134.82 177.00 101.20 808.0 1329.7 q2a14
+ 3 5 -55 27.36 127.03 206.00 102.01 814.1 1340.5 q2a14
+ 3 5 30 361.08 458.96 358.00 158.92 364.9 332.4 q0a3
+ 3 5 31 -388.23 629.58 482.00 194.54 374.3 327.1 q0a3
+ 3 7 -54 177.54 179.40 197.00 104.78 793.4 1367.9 q2a14
+ 3 7 -53 31.75 177.66 209.00 111.64 799.5 1378.6 q2a14
+ 3 9 -51 -169.62 204.99 231.00 115.32 784.9 1416.3 q2a14
+ 3 9 26 -280.28 215.58 244.00 132.39 406.7 118.4 q1a0
+ 3 9 27 40.24 149.50 196.00 132.06 401.3 109.1 q1a0
+ 3 9 28 115.30 214.23 294.00 139.87 395.8 99.8 q1a0
+ 3 11 24 358.55 149.39 196.00 120.05 443.8 123.8 q1a0
+ 3 11 25 -277.90 129.57 178.00 127.10 438.4 114.5 q1a0
+ 3 13 21 -155.22 150.15 197.00 128.70 486.3 138.5 q1a0
+ 3 13 22 664.54 166.14 260.00 126.40 480.8 129.2 q1a0
+ 3 13 23 -268.46 159.73 200.00 127.38 475.4 119.9 q1a0
+ 3 15 18 -522.56 310.60 425.00 135.75 528.7 153.2 q1a0
+ 3 15 19 -254.59 171.07 229.00 127.32 523.2 143.9 q1a0
+ 3 15 20 109.09 163.10 220.00 132.67 517.7 134.6 q1a0
+ 3 17 15 662.88 212.03 557.00 116.49 571.0 167.8 q1a0
+ 3 17 16 489.54 241.31 247.00 116.03 565.5 158.5 q1a0
+ 3 21 -26 165.03 292.17 402.00 171.26 893.2 7.1 q2a0
+ 3 21 2 -189.11 252.08 255.00 102.15 691.8 235.2 q1a3
+ 3 21 3 214.87 151.98 165.00 95.45 686.3 225.8 q1a3
+ 3 21 4 188.40 175.77 197.00 97.40 680.7 216.3 q1a3
+ 3 21 5 409.40 163.27 148.00 94.40 675.1 206.9 q1a3
+ 3 21 6 502.25 174.65 144.00 91.02 669.6 197.5 q1a3
+ 3 23 -21 10.32 228.26 269.00 172.91 829.6 11.0 q2a0
+ 3 23 -20 1124.21 251.47 362.00 164.42 819.9 16.8 q2a0
+ 3 23 -19 196.30 432.18 518.00 192.24 810.2 22.7 q2a0
+ 3 23 -18 937.20 345.92 726.00 184.89 800.5 28.5 q2a0
+ 3 23 -17 1013.33 378.25 643.00 180.46 790.8 34.3 q2a0
+ 3 23 -12 -786.22 666.39 479.00 210.86 762.4 1471.6 q1a15
+ 3 23 -7 -607.98 450.62 367.00 153.73 767.9 307.1 q1a3
+ 3 23 -6 143.91 473.68 394.00 162.37 762.3 297.6 q1a3
+ 3 23 -5 250.91 348.81 353.00 141.59 756.6 288.1 q1a3
+ 3 23 -4 70.58 477.51 422.00 145.66 751.0 278.5 q1a3
+ 3 23 -3 -52.48 425.03 376.00 150.91 745.3 269.0 q1a3
+ 4 -54 -24 185.58 86.67 95.00 48.74 1275.7 948.3 q3a10
+ 4 -54 -23 19.57 64.83 84.00 49.70 1270.0 936.2 q3a10
+ 4 -54 -19 -284.38 125.31 153.00 60.86 1246.8 915.6 q3a8
+ 4 -54 -18 -11.89 97.96 105.00 57.26 1241.1 903.6 q3a8
+ 4 -54 -17 -70.65 98.41 99.00 59.05 1235.5 891.7 q3a8
+ 4 -54 -16 296.58 93.51 143.00 56.42 1229.8 879.8 q3a8
+ 4 -54 -15 -121.04 87.20 106.00 57.12 1224.2 868.0 q3a8
+ 4 -54 -14 180.82 95.50 99.00 54.21 1218.6 856.1 q3a8
+ 4 -54 -13 13.04 75.40 87.00 56.12 1213.0 844.3 q3a8
+ 4 -54 -12 -180.64 84.87 94.00 60.36 1207.4 832.5 q3a8
+ 4 -54 -11 -211.31 89.73 114.00 60.64 1201.8 820.8 q3a8
+ 4 -54 -10 4.29 86.42 99.00 55.14 1196.2 809.0 q3a8
+ 4 -54 -9 2.62 92.06 98.00 56.17 1190.6 797.3 q3a8
+ 4 -54 -8 -126.54 99.94 89.00 56.28 1185.0 785.6 q3a8
+ 4 -54 -7 98.49 105.39 119.00 56.52 1179.5 773.9 q3a8
+ 4 -54 -6 -19.47 97.73 95.00 56.32 1173.9 762.2 q3a8
+ 4 -52 -31 -50.62 147.60 119.00 56.83 1349.9 1013.5 q3a10
+ 4 -52 -30 -21.28 139.63 119.00 55.48 1344.1 1001.4 q3a10
+ 4 -52 -29 201.92 164.03 168.00 53.80 1338.3 989.3 q3a10
+ 4 -50 -39 0.03 71.94 86.00 56.69 1427.4 1091.3 q3a11
+ 4 -50 -38 -67.28 92.42 100.00 57.92 1421.5 1079.1 q3a11
+ 4 -50 -37 97.87 94.99 104.00 59.51 1415.6 1066.8 q3a11
+ 4 -42 27 -80.73 101.24 124.00 61.81 103.7 732.2 q0a6
+ 4 -42 28 109.36 113.60 113.00 62.16 98.4 721.6 q0a6
+ 4 -40 29 -50.53 122.73 125.00 64.44 124.9 695.4 q0a6
+ 4 -40 30 108.79 110.63 114.00 64.47 119.5 684.8 q0a6
+ 4 -38 31 -77.72 164.99 246.00 67.12 145.8 658.9 q0a6
+ 4 -38 32 12.09 164.35 143.00 65.90 140.5 648.4 q0a6
+ 4 -36 33 -252.31 189.57 155.00 68.56 166.6 622.7 q0a6
+ 4 -36 34 136.86 200.65 271.00 70.06 161.3 612.3 q0a6
+ 4 -34 36 -174.96 153.82 141.00 68.10 181.8 576.7 q0a6
+ 4 -30 39 178.35 119.01 132.00 72.05 224.1 544.2 q0a5
+ 4 -28 39 -105.98 108.92 134.00 79.69 254.6 529.9 q0a5
+ 4 -28 40 169.08 150.45 184.00 79.20 249.4 519.7 q0a5
+ 4 -26 40 -140.97 207.94 272.00 84.88 279.8 505.6 q0a5
+ 4 -26 41 452.01 123.05 228.00 78.45 274.6 495.5 q0a5
+ 4 -24 41 11.76 110.43 232.00 86.94 304.7 481.5 q0a5
+ 4 -24 42 242.76 218.45 295.00 83.76 299.5 471.4 q0a5
+ 4 -22 42 -77.20 198.42 265.00 96.88 329.4 457.5 q0a5
+ 4 -20 42 -159.06 308.99 303.00 100.06 359.1 443.8 q0a5
+ 4 -20 43 394.19 269.10 271.00 97.81 353.9 433.8 q0a5
+ 4 -14 43 -168.75 192.76 236.00 143.75 373.4 23.1 q0a1
+ 4 -8 43 -295.25 284.72 284.00 150.66 104.5 1465.2 q0a14
+ 4 -6 -67 -38.29 90.63 95.00 67.03 880.3 1127.8 q2a12
+ 4 -6 42 -111.88 466.18 446.00 168.41 138.1 1461.4 q0a14
+ 4 -6 43 839.34 297.33 371.00 147.91 132.8 1451.8 q0a14
+ 4 -4 -67 11.26 115.59 107.00 64.14 851.8 1146.5 q2a12
+ 4 -4 42 1338.10 456.30 475.00 172.59 166.2 1448.1 q0a14
+ 4 -2 -66 -143.16 104.82 124.00 70.96 829.9 1176.3 q2a12
+ 4 0 -65 198.71 151.48 174.00 67.56 808.1 1205.9 q2a12
+ 4 0 40 1300.35 348.98 510.00 171.20 229.6 1440.8 q0a15
+ 4 0 41 543.83 505.13 499.00 181.17 224.3 1431.3 q0a15
+ 4 2 -64 -0.46 133.32 136.00 71.66 786.6 1235.2 q2a12
+ 4 2 39 1219.75 395.25 457.00 183.35 262.6 1437.1 q0a15
+ 4 2 40 -694.30 424.00 406.00 192.11 257.3 1427.6 q0a15
+ 4 4 38 680.94 576.03 871.00 223.39 295.4 1433.5 q0a15
+ 4 6 36 752.89 747.92 595.00 238.78 333.5 1439.3 q0a15
+ 4 6 37 1276.36 443.78 483.00 209.44 328.1 1429.8 q0a15
+ 4 8 -60 -203.07 118.24 107.00 63.67 1015.8 757.8 q2a9
+ 4 8 -59 56.33 117.76 107.00 62.67 1026.8 751.5 q2a9
+ 4 8 35 1167.86 615.05 619.00 233.08 366.0 1435.6 q0a15
+ 4 8 36 -624.30 720.87 511.00 247.56 360.6 1426.2 q0a15
+ 4 10 -59 -294.68 117.19 102.00 66.97 1044.0 778.8 q2a9
+ 4 10 -58 37.20 110.39 110.00 66.87 1054.9 772.5 q2a9
+ 4 12 -56 -4.66 105.70 129.00 68.91 1093.6 787.1 q2a9
+ 4 12 31 -1012.50 374.22 346.00 193.50 421.4 39.3 q1a0
+ 4 12 32 448.60 320.29 371.00 183.07 416.0 30.0 q1a0
+ 4 14 -54 -69.56 196.00 211.00 73.56 1131.9 801.6 q2a9
+ 4 14 -53 -81.55 252.77 236.00 76.64 1142.7 795.4 q2a9
+ 4 14 29 1971.33 318.21 853.00 170.67 459.0 44.9 q1a0
+ 4 14 30 358.21 383.93 455.00 182.79 453.5 35.6 q1a0
+ 4 16 26 1002.38 605.97 529.00 195.46 502.1 59.9 q1a0
+ 4 16 27 286.96 441.53 588.00 191.04 496.5 50.5 q1a0
+ 4 18 -49 246.78 132.32 150.00 79.37 1087.7 393.6 q2a5
+ 4 18 -48 358.37 152.96 260.00 81.42 1093.8 404.1 q2a5
+ 4 18 -47 212.17 126.45 137.00 84.32 1099.9 414.7 q2a5
+ 4 18 23 712.05 510.83 488.00 198.08 545.0 74.8 q1a0
+ 4 18 24 -1086.97 624.89 518.00 220.18 539.4 65.4 q1a0
+ 4 20 -45 -172.75 185.45 195.00 92.75 1085.7 451.6 q2a5
+ 4 20 -44 449.59 143.93 204.00 89.78 1091.8 462.1 q2a5
+ 4 20 -43 -314.41 277.37 278.00 97.91 1097.9 472.5 q2a5
+ 4 20 19 734.14 423.39 423.00 187.77 590.5 99.1 q1a1
+ 4 22 -41 16.27 253.90 309.00 92.81 1083.8 508.9 q2a5
+ 4 22 -40 -476.58 447.19 481.00 109.73 1089.8 519.2 q2a5
+ 4 22 -39 -191.42 348.58 353.00 107.66 1095.9 529.5 q2a5
+ 4 22 15 -24.47 406.81 503.00 194.97 639.0 123.4 q1a1
+ 4 22 16 508.81 363.87 610.00 195.04 633.3 114.0 q1a1
+ 4 22 17 -103.88 487.98 453.00 199.90 627.7 104.6 q1a1
+ 4 24 -34 -244.35 222.95 260.00 109.42 1100.7 567.8 q2a7
+ 4 24 -33 -249.82 202.69 209.00 115.10 1106.8 578.0 q2a7
+ 4 24 9 -139.33 537.20 444.00 221.76 698.9 166.5 q1a1
+ 4 24 10 -893.09 506.82 466.00 206.82 693.1 157.1 q1a1
+ 4 24 11 947.26 514.11 501.00 198.38 687.5 147.7 q1a1
+ 4 24 12 931.39 441.75 461.00 201.79 681.8 138.2 q1a1
+ 4 26 -29 467.47 367.65 383.00 120.19 1105.1 633.3 q2a7
+ 4 26 -28 35.70 293.17 277.00 118.43 1111.1 643.4 q2a7
+ 4 26 -27 -7.25 307.61 306.00 129.64 1117.1 653.4 q2a7
+ 4 26 -26 242.32 460.03 459.00 131.01 1123.0 663.4 q2a7
+ 4 26 -25 -187.68 531.35 448.00 143.91 1129.0 673.3 q2a7
+ 4 26 -24 -297.83 392.57 354.00 133.32 1135.0 683.3 q2a7
+ 4 26 2 180.75 570.62 466.00 182.98 765.0 192.3 q1a3
+ 5 -57 -29 125.62 70.67 73.00 44.99 1238.0 1053.2 q3a10
+ 5 -57 -28 -75.12 64.66 66.00 47.96 1232.1 1040.6 q3a10
+ 5 -57 -27 -90.28 88.19 81.00 47.48 1226.2 1028.1 q3a10
+ 5 -57 -26 48.84 81.27 89.00 47.23 1220.4 1015.5 q3a10
+ 5 -57 -25 -34.76 90.27 91.00 49.36 1214.5 1003.0 q3a10
+ 5 -57 -24 77.37 84.97 92.00 48.65 1208.6 990.6 q3a10
+ 5 -55 -34 334.08 98.77 129.00 47.20 1302.9 1095.8 q3a10
+ 5 -45 30 -118.29 142.37 132.00 62.99 22.4 718.7 q0a6
+ 5 -45 31 -181.26 128.54 111.00 60.03 17.0 707.8 q0a6
+ 5 -43 33 -34.96 105.63 130.00 63.35 39.2 670.1 q0a6
+ 5 -43 34 -0.09 112.88 128.00 60.57 33.8 659.2 q0a6
+ 5 -41 35 -14.10 80.21 90.00 58.76 61.1 632.8 q0a6
+ 5 -41 36 -83.00 101.59 105.00 60.29 55.8 622.0 q0a6
+ 5 -39 37 76.66 121.52 112.00 57.93 82.8 595.8 q0a6
+ 5 -39 38 137.73 103.54 98.00 55.60 77.5 585.2 q0a6
+ 5 -33 42 249.72 169.34 181.00 63.99 151.7 525.0 q0a4
+ 5 -33 43 137.09 126.09 128.00 59.47 146.4 514.5 q0a4
+ 5 -31 43 138.98 249.48 267.00 67.08 178.0 500.0 q0a4
+ 5 -31 44 31.71 199.20 220.00 64.09 172.7 489.6 q0a4
+ 5 -29 44 188.05 158.76 186.00 69.59 201.1 475.2 q0a5
+ 5 -27 45 120.62 127.73 133.00 72.89 226.9 450.6 q0a5
+ 5 -27 46 67.80 152.31 199.00 72.80 221.7 440.3 q0a5
+ 5 -25 46 -67.80 121.55 125.00 74.28 252.6 426.2 q0a5
+ 5 -25 47 264.44 120.32 124.00 65.44 247.3 416.0 q0a5
+ 5 -23 47 -104.42 136.27 130.00 74.89 278.0 402.0 q0a5
+ 5 -21 48 131.80 110.67 126.00 74.13 303.3 378.1 q0a5
+ 5 -15 49 -297.00 266.78 265.00 86.00 375.3 747.5 q0a9
+ 5 -11 48 -260.59 243.91 426.00 130.95 28.7 1422.7 q0a14
+ 5 -11 49 265.94 218.75 249.00 120.06 23.3 1412.9 q0a14
+ 5 -9 48 54.51 191.34 204.00 121.28 57.9 1409.2 q0a14
+ 5 -9 49 -287.28 185.78 188.00 122.43 52.5 1399.5 q0a14
+ 5 -7 48 -41.05 193.30 246.00 125.16 86.9 1395.8 q0a14
+ 5 -5 47 148.43 242.05 285.00 140.34 121.1 1392.1 q0a14
+ 5 -5 48 -232.10 222.10 236.00 137.06 115.8 1382.5 q0a14
+ 5 -3 47 -559.62 309.52 293.00 149.14 149.8 1378.8 q0a14
+ 5 -1 46 -319.48 400.44 430.00 148.89 183.7 1375.3 q0a14
+ 5 -1 47 131.43 270.99 258.00 143.30 178.3 1365.6 q0a14
+ 5 1 45 -194.06 296.23 392.00 156.25 214.4 1371.7 q0a15
+ 5 1 46 332.68 205.61 391.00 153.21 209.0 1362.1 q0a15
+ 5 3 -70 194.16 115.87 110.00 55.51 851.0 766.3 q2a8
+ 5 3 -69 94.03 113.06 97.00 57.77 862.6 759.8 q2a8
+ 5 3 44 -336.51 249.24 314.00 160.19 248.0 1368.1 q0a15
+ 5 3 45 215.64 260.56 270.00 155.44 242.5 1358.6 q0a15
+ 5 5 -68 76.54 97.62 100.00 58.66 892.6 781.7 q2a8
+ 5 5 43 -98.07 218.72 228.00 156.84 281.4 1364.6 q0a15
+ 5 5 44 123.45 264.20 333.00 142.64 275.9 1355.1 q0a15
+ 5 7 -67 -233.34 169.09 162.00 62.54 922.3 803.4 q2a8
+ 5 7 -66 -23.18 114.22 117.00 56.53 933.8 796.8 q2a8
+ 5 7 42 1012.55 347.31 638.00 168.95 314.6 1361.1 q0a15
+ 5 9 -66 -6.12 149.75 122.00 55.33 951.8 824.8 q2a8
+ 5 9 40 547.97 357.35 436.00 173.90 353.2 1367.1 q0a15
+ 5 9 41 579.67 364.35 432.00 169.46 347.7 1357.6 q0a15
+ 5 11 -64 113.44 98.34 118.00 59.85 989.3 839.7 q2a9
+ 5 11 -63 -274.20 122.32 159.00 63.88 1000.6 833.2 q2a9
+ 5 13 -62 5.16 94.03 110.00 64.04 1029.4 854.3 q2a9
+ 5 13 -61 144.30 97.27 106.00 62.38 1040.6 847.9 q2a9
+ 5 13 37 841.18 680.20 425.00 180.51 766.2 724.2 q1a7
+ 5 15 -60 21.78 79.75 113.00 63.07 1069.1 868.8 q2a9
+ 5 15 -59 6.57 89.80 121.00 63.52 1080.2 862.4 q2a9
+ 5 17 -58 -364.91 297.92 370.00 69.43 1108.3 883.2 q2a9
+ 5 17 -57 -156.40 198.54 206.00 65.60 1119.3 876.8 q2a9
+ 5 21 -52 233.24 112.86 123.00 68.36 1012.9 382.7 q2a5
+ 5 21 -51 -108.37 119.88 147.00 72.58 1019.2 393.5 q2a5
+ 5 21 26 430.14 328.02 427.00 173.77 573.1 13.2 q1a0
+ 5 23 -48 99.30 108.76 115.00 72.38 1011.4 442.0 q2a5
+ 5 23 -47 18.35 120.38 146.00 76.22 1017.7 452.7 q2a5
+ 5 23 23 648.51 219.04 369.00 159.28 613.6 28.4 q1a1
+ 5 23 24 207.30 217.64 260.00 167.73 607.9 19.0 q1a1
+ 5 25 -44 -149.66 179.01 212.00 81.61 1009.9 500.5 q2a5
+ 5 25 -43 -95.68 160.71 188.00 81.79 1016.2 511.1 q2a5
+ 5 25 18 110.22 237.71 352.00 158.59 668.5 62.5 q1a1
+ 5 25 19 -340.10 236.72 314.00 166.61 662.7 53.0 q1a1
+ 5 25 20 109.01 201.66 219.00 157.59 657.0 43.6 q1a1
+ 5 27 13 -329.45 369.06 348.00 180.70 723.5 96.7 q1a1
+ 5 27 14 458.90 370.28 459.00 181.14 717.7 87.2 q1a1
+ 5 27 15 -169.93 436.94 445.00 180.75 711.9 77.7 q1a1
+ 5 29 -33 33.33 133.19 144.00 91.67 1026.6 618.4 q2a7
+ 5 29 -32 146.46 149.59 161.00 92.54 1032.8 628.6 q2a7
+ 5 29 -31 213.02 122.89 170.00 91.94 1039.0 638.8 q2a7
+ 5 29 -30 252.28 132.67 159.00 94.06 1045.1 649.0 q2a7
+ 5 29 5 -503.66 531.43 479.00 171.54 543.2 1471.5 q1a14
+ 5 31 -19 -145.88 188.78 218.00 130.41 761.4 1302.7 q1a15
+ 5 31 -18 116.83 313.78 371.00 133.39 751.5 1308.8 q1a15
+ 5 31 -17 -364.19 217.82 255.00 133.84 741.5 1314.8 q1a15
+ 5 31 -16 -583.28 294.89 357.00 141.99 731.6 1320.9 q1a15
+ 5 31 -15 -28.19 198.91 261.00 138.84 721.7 1326.9 q1a15
+ 5 31 -14 296.75 193.82 285.00 129.64 711.8 1332.9 q1a15
+ 5 31 -13 -56.07 282.12 389.00 136.84 701.9 1338.9 q1a15
+ 5 31 -12 214.12 182.69 234.00 132.90 692.0 1345.0 q1a15
+ 5 31 -11 -523.07 203.75 217.00 139.84 682.1 1351.0 q1a15
+ 5 31 -10 393.31 182.88 304.00 129.28 672.3 1356.9 q1a15
+ 5 31 -9 293.57 226.15 269.00 125.66 662.5 1362.9 q1a15
+ 5 31 -8 148.90 216.34 270.00 127.72 652.7 1368.9 q1a15
+ 5 31 -7 -38.59 196.57 255.00 131.71 642.9 1374.9 q1a15
+ 5 31 -6 -360.84 242.03 270.00 139.73 633.1 1380.8 q1a15
+ 5 31 -5 167.73 204.98 329.00 137.99 623.4 1386.7 q1a15
+ 5 31 -4 421.57 245.19 313.00 131.25 613.6 1392.7 q1a15
+ 5 31 -3 -122.96 309.12 390.00 141.90 603.9 1398.6 q1a15
+ 5 31 -2 11.59 209.30 283.00 139.78 594.2 1404.5 q1a15
+ 6 -38 44 -170.41 143.55 173.00 58.64 44.5 530.5 q0a4
+ 6 -36 45 130.25 98.25 134.00 56.40 72.2 504.7 q0a4
+ 6 -36 46 25.49 88.50 93.00 57.05 66.8 494.0 q0a4
+ 6 -34 47 -11.03 90.76 100.00 57.23 94.2 468.5 q0a4
+ 6 -32 48 66.50 96.04 110.00 58.50 121.3 443.2 q0a4
+ 6 -30 49 -156.73 120.32 128.00 61.40 148.2 418.1 q0a4
+ 6 -28 50 -51.91 140.64 125.00 62.61 174.9 393.3 q0a4
+ 6 -22 52 311.26 216.13 233.00 69.16 378.8 879.9 q0a9
+ 6 -20 53 -217.12 195.66 170.00 69.12 354.6 854.2 q0a9
+ 6 -18 53 -265.05 199.96 172.00 73.45 340.8 823.4 q0a9
+ 6 -16 53 -9.33 137.27 164.00 71.46 327.0 792.7 q0a9
+ 6 -14 53 -32.23 100.56 145.00 68.31 313.4 762.3 q0a9
+ 6 -14 54 63.10 85.21 118.00 66.57 303.4 767.7 q0a9
+ 6 -10 53 33.05 168.62 231.00 108.84 9.4 1351.0 q0a14
+ 6 -8 53 -251.94 181.26 182.00 108.94 39.2 1337.5 q0a14
+ 6 -6 53 173.88 170.22 167.00 99.12 68.8 1324.1 q0a14
+ 6 -4 52 -26.80 159.12 184.00 110.12 103.6 1320.5 q0a14
+ 6 -2 51 -193.01 196.17 188.00 122.37 138.3 1317.0 q0a14
+ 6 -2 52 128.59 167.55 195.00 116.25 132.8 1307.2 q0a14
+ 6 0 51 225.31 197.40 217.00 119.69 167.3 1303.8 q0a14
+ 6 4 -74 -146.39 113.28 115.00 57.99 800.3 823.0 q2a8
+ 6 6 -73 -87.10 93.14 96.00 56.90 831.4 845.2 q2a8
+ 6 6 -72 -70.50 96.49 124.00 58.50 843.3 838.4 q2a8
+ 6 8 -72 131.14 95.76 101.00 55.04 862.2 867.2 q2a8
+ 6 8 -71 69.56 90.10 98.00 58.44 874.0 860.4 q2a8
+ 6 10 -70 226.10 125.16 123.00 55.10 904.5 882.2 q2a8
+ 6 12 -69 59.96 138.09 129.00 56.65 934.7 903.8 q2a8
+ 6 12 -68 353.14 162.02 178.00 53.26 946.3 897.1 q2a8
+ 6 12 43 182.73 336.87 461.00 156.07 379.0 1302.5 q0a15
+ 6 14 -66 63.37 150.13 143.00 58.01 984.7 911.9 q2a9
+ 6 16 40 -1103.53 493.34 436.00 146.60 702.0 697.3 q1a7
+ 6 18 37 34.85 365.77 296.00 137.62 717.7 653.0 q1a7
+ 6 18 38 -282.63 274.04 302.00 123.89 708.2 658.6 q1a7
+ 6 20 35 930.44 329.28 465.00 142.34 723.9 614.4 q1a7
+ 6 20 36 509.51 343.26 453.00 129.30 714.3 620.1 q1a7
+ 6 22 32 -158.45 316.07 346.00 136.93 739.6 570.2 q1a7
+ 6 22 33 -473.74 304.56 334.00 132.91 730.1 575.9 q1a7
+ 6 24 -54 132.39 128.70 117.00 59.01 944.5 382.4 q2a4
+ 6 24 -53 1.40 124.25 110.00 59.40 951.0 393.4 q2a4
+ 6 26 -51 -99.05 129.78 117.00 60.45 936.9 432.0 q2a4
+ 6 26 -50 277.24 142.82 137.00 61.24 943.4 442.9 q2a4
+ 6 26 -49 112.11 145.15 132.00 61.22 949.9 453.8 q2a4
+ 6 28 -47 163.41 215.10 199.00 66.79 936.0 491.8 q2a4
+ 6 28 -46 -158.70 171.66 156.00 64.38 942.4 502.5 q2a4
+ 6 28 -45 257.00 197.46 246.00 63.00 948.8 513.3 q2a4
+ 6 30 15 -14.09 212.29 249.00 147.59 760.6 44.1 q1a1
+ 6 30 16 -42.30 195.33 249.00 147.39 754.7 34.5 q1a1
+ 6 30 17 386.14 181.06 243.00 141.51 748.8 24.9 q1a1
+ 6 32 -36 -447.92 175.71 158.00 74.08 954.1 613.2 q2a6
+ 6 32 -35 183.19 163.91 143.00 72.57 960.5 623.7 q2a6
+ 6 32 8 -110.82 235.41 275.00 122.36 481.9 1438.8 q1a14
+ 6 32 9 381.10 190.53 237.00 115.96 472.1 1444.8 q1a14
+ 6 32 10 -336.30 263.00 283.00 124.27 462.4 1450.7 q1a14
+ 6 32 11 -223.99 190.20 227.00 119.55 452.7 1456.6 q1a14
+ 6 34 -27 -132.31 141.47 136.00 88.64 982.0 721.8 q2a7
+ 6 34 -26 -102.44 130.97 142.00 87.11 988.3 732.1 q2a7
+ 6 34 -22 -241.85 385.40 336.00 80.18 763.0 1256.8 q1a13
+ 6 34 -21 -282.54 285.43 259.00 89.52 752.8 1263.0 q1a13
+ 6 34 -20 -67.30 296.40 265.00 88.99 742.7 1269.3 q1a13
+ 6 34 -2 0.32 247.52 222.00 118.91 566.0 1352.6 q1a14
+ 6 34 -1 84.43 283.19 278.00 122.34 556.2 1358.7 q1a14
+ 6 34 0 -279.38 241.50 229.00 123.68 546.3 1364.7 q1a14
+ 6 34 1 59.65 247.16 283.00 122.78 536.5 1370.8 q1a14
+ 6 34 2 450.00 255.66 335.00 123.00 526.7 1376.8 q1a14
+ 7 -37 50 27.74 102.45 106.00 57.86 11.4 446.3 q0a4
+ 7 -35 51 7.19 83.33 104.00 54.81 39.6 420.4 q0a4
+ 7 -33 52 23.23 108.06 100.00 51.69 67.6 394.7 q0a4
+ 7 -33 53 -108.64 133.95 103.00 54.58 62.2 384.0 q0a4
+ 7 -27 55 -96.85 114.61 120.00 48.65 368.5 961.2 q0a11
+ 7 -25 56 47.07 132.99 163.00 52.33 343.6 934.3 q0a11
+ 7 -21 57 69.39 86.09 122.00 62.01 304.5 903.2 q0a9
+ 7 -19 57 139.41 101.60 110.00 64.36 290.5 871.5 q0a9
+ 7 -17 57 -61.17 92.18 223.00 67.39 276.6 840.0 q0a9
+ 7 -17 58 17.49 92.01 126.00 63.05 266.4 845.4 q0a9
+ 7 -15 58 -287.46 146.70 148.00 65.66 252.6 814.2 q0a9
+ 7 -13 58 45.12 107.64 139.00 66.88 239.0 783.1 q0a9
+ 7 -11 58 86.55 109.44 109.00 65.05 225.5 752.3 q0a9
+ 7 -5 57 24.71 118.58 125.00 71.56 55.3 1287.6 q0a12
+ 7 -3 56 141.93 120.15 159.00 72.21 90.8 1284.1 q0a12
+ 7 -3 57 72.89 112.13 122.00 72.78 85.3 1274.2 q0a12
+ 7 -1 56 -269.30 211.28 255.00 85.70 120.6 1270.7 q0a12
+ 7 1 55 160.20 184.40 221.00 82.20 155.7 1267.3 q0a12
+ 7 5 53 -596.00 290.08 314.00 91.14 222.5 1260.5 q0a13
+ 7 7 52 -95.09 109.52 139.00 85.45 257.1 1257.1 q0a13
+ 7 13 -73 -81.51 88.28 88.00 45.11 886.2 937.4 q2a10
+ 7 13 48 194.56 196.90 223.00 92.74 365.6 1256.7 q0a13
+ 7 15 -71 66.65 122.89 106.00 47.15 929.1 952.1 q2a10
+ 7 17 44 389.55 163.68 212.00 106.07 639.0 703.3 q1a7
+ 7 17 45 68.92 148.66 207.00 105.45 629.3 709.0 q1a7
+ 7 19 -67 51.84 80.74 88.00 48.96 1010.5 981.1 q2a11
+ 7 19 -66 -235.51 100.58 98.00 51.09 1022.1 974.2 q2a11
+ 7 19 42 -9.73 135.04 190.00 104.71 645.4 663.9 q1a7
+ 7 19 43 262.30 137.30 261.00 102.57 635.7 669.7 q1a7
+ 7 21 -65 136.06 82.49 75.00 45.94 1052.0 995.4 q2a11
+ 7 21 -64 -121.38 76.36 79.00 48.99 1063.5 988.5 q2a11
+ 7 21 40 125.54 151.39 197.00 104.66 651.8 624.7 q1a7
+ 7 23 -62 -98.89 115.00 111.00 47.49 1104.5 1002.7 q2a11
+ 7 23 -61 -115.51 112.08 95.00 49.85 1116.0 995.8 q2a11
+ 7 23 37 281.53 145.25 155.00 99.58 667.9 579.7 q1a7
+ 7 23 38 -147.87 134.85 162.00 102.69 658.2 585.5 q1a7
+ 7 25 -59 -44.94 120.96 121.00 45.84 1156.4 1009.8 q2a11
+ 7 27 -56 -57.25 101.45 101.00 54.66 870.1 382.1 q2a4
+ 7 27 -55 -103.31 93.07 93.00 54.03 876.8 393.3 q2a4
+ 7 27 31 149.39 263.34 315.00 113.05 699.6 518.3 q1a5
+ 7 27 32 -202.95 312.87 316.00 109.16 689.8 524.1 q1a5
+ 7 29 -52 -5.01 78.60 110.00 55.55 869.5 443.8 q2a4
+ 7 29 -51 -20.12 85.64 86.00 59.59 876.2 454.9 q2a4
+ 7 29 27 717.78 296.50 371.00 107.35 725.6 467.9 q1a5
+ 7 29 28 374.11 245.99 250.00 102.77 715.8 473.7 q1a5
+ 7 31 -48 322.54 97.76 134.00 55.66 869.0 504.7 q2a4
+ 7 31 -47 94.01 103.39 101.00 57.96 875.6 515.7 q2a4
+ 7 31 22 10.39 284.17 263.00 113.87 761.3 411.5 q1a5
+ 7 31 23 -187.84 308.25 330.00 108.49 751.5 417.4 q1a5
+ 7 31 24 293.93 263.43 344.00 113.21 741.8 423.3 q1a5
+ 7 33 -41 12.06 79.10 92.00 60.20 889.0 570.3 q2a6
+ 7 35 -37 249.68 114.53 204.00 62.21 888.7 629.2 q2a6
+ 7 35 -36 -86.20 124.58 128.00 63.39 895.2 639.8 q2a6
+ 7 35 -35 205.90 99.38 134.00 64.43 901.8 650.5 q2a6
+ 7 35 -34 -256.11 227.97 259.00 72.33 908.3 661.1 q2a6
+ 7 35 10 -14.81 172.14 201.00 107.16 428.5 1399.1 q1a14
+ 7 35 11 -168.80 163.30 195.00 105.63 418.7 1405.1 q1a14
+ 7 35 12 108.89 200.29 218.00 106.27 408.9 1411.2 q1a14
+ 7 35 13 613.90 202.90 312.00 109.14 399.1 1417.3 q1a14
+ 7 37 -25 -112.01 204.35 176.00 70.65 764.7 1180.6 q1a13
+ 7 37 -24 209.08 117.98 240.00 60.92 754.3 1187.1 q1a13
+ 7 37 -23 -412.54 233.94 274.00 71.54 744.0 1193.5 q1a13
+ 7 37 -22 -414.41 214.66 266.00 75.23 733.7 1200.0 q1a13
+ 7 37 -1 458.96 155.72 182.00 102.10 523.7 1305.1 q1a14
+ 7 37 0 257.49 128.93 251.00 100.72 513.8 1311.3 q1a14
+ 7 37 1 -208.60 158.84 179.00 101.97 503.8 1317.5 q1a14
+ 7 37 2 -467.10 151.97 179.00 104.86 493.9 1323.7 q1a14
+ 7 37 3 466.00 171.31 161.00 94.00 483.9 1329.8 q1a14
+ 7 37 4 -67.49 151.53 144.00 92.81 474.0 1336.0 q1a14
+ 8 -32 57 -79.68 193.37 195.00 47.18 368.0 1071.3 q0a11
+ 8 -30 58 184.19 118.56 132.00 48.81 342.3 1043.0 q0a11
+ 8 -28 59 -33.12 91.78 127.00 47.12 316.9 1015.0 q0a11
+ 8 -26 60 36.34 63.92 76.00 47.46 291.7 987.2 q0a11
+ 8 -24 60 -107.54 93.41 99.00 47.34 277.3 954.1 q0a11
+ 8 -18 61 166.14 130.52 141.00 59.92 223.9 889.3 q0a9
+ 8 -18 62 29.25 223.41 256.00 66.59 213.5 894.8 q0a9
+ 8 -12 62 -118.81 180.04 164.00 63.81 175.2 799.1 q0a8
+ 8 -10 62 197.60 127.34 113.00 57.60 161.7 767.6 q0a8
+ 8 -6 61 25.36 152.54 164.00 70.24 10.7 1234.5 q0a12
+ 8 -4 61 -222.12 128.70 153.00 70.12 41.5 1221.0 q0a12
+ 8 -2 60 67.23 101.26 109.00 70.61 77.7 1217.6 q0a12
+ 8 0 59 9.44 133.82 255.00 78.97 113.7 1214.2 q0a12
+ 8 0 60 -157.09 110.32 120.00 72.53 108.0 1204.2 q0a12
+ 8 2 59 16.66 140.69 139.00 72.54 143.8 1200.9 q0a12
+ 8 4 58 -24.16 153.78 178.00 75.96 179.5 1197.5 q0a12
+ 8 6 57 104.01 125.75 133.00 77.39 211.9 1194.2 q0a13
+ 8 8 56 -146.12 123.62 124.00 78.12 247.2 1191.0 q0a13
+ 8 10 55 -154.19 107.42 115.00 79.19 282.3 1187.7 q0a13
+ 8 12 -78 -125.46 92.46 83.00 42.66 802.4 979.5 q2a10
+ 8 12 53 -298.40 173.08 193.00 86.09 323.0 1194.3 q0a13
+ 8 14 -77 93.25 72.60 70.00 39.75 834.8 1001.7 q2a10
+ 8 14 -76 -62.65 77.47 73.00 40.85 847.1 994.4 q2a10
+ 8 14 52 733.51 205.76 259.00 76.89 357.8 1191.0 q0a13
+ 8 16 -75 114.44 64.03 75.00 39.56 879.1 1016.4 q2a10
+ 8 16 -74 168.38 80.14 82.00 41.83 891.4 1009.3 q2a10
+ 8 18 -73 -3.47 92.20 94.00 44.27 923.0 1031.1 q2a10
+ 8 22 -69 61.53 91.69 89.00 46.27 1006.2 1059.8 q2a11
+ 8 22 -68 113.49 70.36 76.00 45.11 1018.1 1052.7 q2a11
+ 8 24 -66 -153.36 78.77 76.00 45.76 1060.4 1066.9 q2a11
+ 8 24 41 309.22 123.75 159.00 89.65 603.4 583.7 q1a7
+ 8 24 42 155.04 121.53 158.00 94.04 593.6 589.6 q1a7
+ 8 26 -64 -166.46 105.06 95.00 47.72 1102.3 1080.9 q2a11
+ 8 26 -63 14.07 94.24 93.00 44.33 1114.0 1073.8 q2a11
+ 8 28 -61 -165.67 140.62 136.00 43.67 1155.3 1087.7 q2a11
+ 8 28 35 -380.23 223.84 233.00 92.92 635.8 520.3 q1a5
+ 8 28 36 -237.28 205.96 260.00 94.13 625.9 526.2 q1a5
+ 8 30 -57 -68.51 115.41 107.00 56.11 799.5 393.2 q2a4
+ 8 30 -56 86.11 97.58 98.00 55.22 806.4 404.7 q2a4
+ 8 30 32 188.09 150.96 189.00 85.90 652.4 474.9 q1a5
+ 8 30 33 171.86 107.32 165.00 85.47 642.5 480.8 q1a5
+ 8 32 -53 328.59 108.56 138.00 53.21 799.4 456.1 q2a4
+ 8 32 -52 -167.10 134.76 134.00 59.29 806.3 467.5 q2a4
+ 8 32 28 65.79 123.69 143.00 84.13 678.8 423.6 q1a5
+ 8 32 29 137.65 133.08 134.00 82.88 668.9 429.5 q1a5
+ 8 34 -49 281.91 117.78 114.00 53.86 799.4 518.2 q2a4
+ 8 34 -48 -169.21 113.83 117.00 56.82 806.2 529.4 q2a4
+ 8 34 25 226.04 117.23 161.00 82.77 695.3 378.3 q1a5
+ 8 36 -44 227.25 104.23 124.00 54.34 806.9 563.9 q2a6
+ 8 36 -43 -66.01 116.54 118.00 56.65 813.7 574.9 q2a6
+ 8 36 -42 59.70 93.99 94.00 58.13 820.5 585.9 q2a6
+ 8 36 18 251.70 129.51 161.00 68.11 745.1 772.3 q1a9
+ 8 36 19 -7.96 136.44 127.00 68.88 751.2 782.2 q1a9
+ 8 38 -37 11.58 94.69 101.00 61.19 827.4 656.7 q2a6
+ 8 38 -36 -86.91 105.95 100.00 61.86 834.1 667.5 q2a6
+ 8 38 -35 -130.12 142.44 203.00 61.37 840.9 678.3 q2a6
+ 8 38 -34 -80.66 96.15 114.00 59.97 847.6 689.1 q2a6
+ 8 40 -25 -28.52 90.76 100.00 61.56 734.8 1121.2 q1a13
+ 8 40 -24 -11.41 94.28 104.00 60.25 724.3 1127.8 q1a13
+ 8 40 -23 -147.31 91.82 93.00 64.03 713.8 1134.5 q1a13
+ 8 40 -22 -392.55 102.54 89.00 64.64 703.3 1141.1 q1a13
+ 8 40 -2 113.62 110.25 178.00 65.38 500.0 1271.0 q1a12
+ 8 40 -1 -205.30 276.23 376.00 70.41 489.9 1277.3 q1a12
+ 8 40 0 9.42 99.19 131.00 63.75 479.8 1283.7 q1a12
+ 9 -31 61 -37.48 73.03 83.00 46.83 299.7 1094.6 q0a11
+ 9 -31 62 139.64 69.04 76.00 44.76 288.7 1100.2 q0a11
+ 9 -29 62 36.84 70.35 71.00 44.11 273.8 1065.7 q0a11
+ 9 -27 63 63.41 80.44 155.00 46.79 248.2 1037.0 q0a11
+ 9 -25 64 56.46 96.76 96.00 47.34 222.8 1008.6 q0a11
+ 9 -23 64 98.85 92.62 82.00 46.35 208.4 974.8 q0a11
+ 9 -21 65 20.20 123.59 105.00 48.87 186.4 946.9 q0a10
+ 9 -17 65 -49.06 130.49 125.00 58.06 157.8 907.9 q0a8
+ 9 -15 65 -226.03 139.13 161.00 63.92 143.9 875.0 q0a8
+ 9 -13 65 124.91 122.01 118.00 58.53 130.1 842.4 q0a8
+ 9 -13 66 -116.00 135.23 153.00 61.71 119.6 848.1 q0a8
+ 9 -11 65 -68.91 133.28 156.00 63.04 116.4 810.1 q0a8
+ 9 -9 65 62.31 93.16 111.00 58.69 102.7 777.9 q0a8
+ 9 -3 64 -59.93 108.88 125.00 68.33 32.9 1162.0 q0a12
+ 9 -1 64 145.88 118.33 99.00 65.12 64.0 1148.6 q0a12
+ 9 1 63 177.61 102.64 122.00 66.99 100.8 1145.3 q0a12
+ 9 3 62 -16.45 122.28 129.00 74.05 137.3 1142.0 q0a12
+ 9 5 61 498.94 167.51 145.00 67.63 173.6 1138.8 q0a12
+ 9 7 60 146.34 124.16 135.00 73.20 206.8 1135.6 q0a13
+ 9 9 59 -42.96 125.80 114.00 70.22 242.8 1132.4 q0a13
+ 9 11 58 53.31 140.35 145.00 71.69 278.6 1129.2 q0a13
+ 9 13 57 -94.38 103.99 119.00 75.38 314.2 1126.1 q0a13
+ 9 15 -80 -141.40 97.32 95.00 37.60 793.1 1062.1 q2a10
+ 9 15 55 336.86 144.97 145.00 74.59 355.5 1132.9 q0a13
+ 9 17 -78 4.20 59.80 62.00 38.60 838.9 1076.9 q2a10
+ 9 19 -77 -127.69 76.96 69.00 41.69 871.6 1099.0 q2a10
+ 9 19 -76 -28.91 67.90 71.00 40.71 884.2 1091.6 q2a10
+ 9 19 52 -146.11 199.16 232.00 82.70 509.1 716.0 q1a6
+ 9 21 50 -139.95 126.72 147.00 76.55 516.0 675.1 q1a6
+ 9 23 47 -117.95 183.65 169.00 81.59 532.8 628.4 q1a6
+ 9 23 48 206.90 128.60 161.00 77.90 522.8 634.4 q1a6
+ 9 25 45 -56.23 146.70 163.00 78.92 539.6 587.8 q1a6
+ 9 25 46 0.80 131.66 156.00 77.09 529.7 593.8 q1a6
+ 9 29 40 309.22 261.45 244.00 79.24 562.7 528.3 q1a4
+ 9 33 33 -513.42 224.89 274.00 85.89 603.5 429.9 q1a5
+ 9 35 29 179.64 126.19 126.00 74.42 630.4 377.7 q1a5
+ 9 37 23 -214.74 218.31 273.00 67.16 749.6 846.4 q1a9
+ 9 37 24 -156.16 245.39 220.00 68.49 755.9 856.5 q1a9
+ 9 37 25 31.91 146.62 124.00 63.21 762.1 866.5 q1a9
+ 9 39 17 -20.93 81.15 104.00 62.73 684.8 799.5 q1a9
+ 9 39 18 211.24 93.74 157.00 61.34 691.0 809.6 q1a9
+ 9 39 19 226.58 104.78 335.00 64.03 697.3 819.6 q1a9
+ 9 41 -34 -50.72 135.61 135.00 62.28 784.5 718.1 q2a6
+ 9 41 11 -188.08 120.97 108.00 64.45 619.7 752.4 q1a9
+ 9 41 12 -7.30 83.64 101.00 61.39 626.0 762.5 q1a9
+ 9 43 -6 -62.36 98.41 116.00 61.07 506.6 1187.0 q1a12
+ 9 43 -5 105.71 78.88 91.00 59.37 496.2 1193.6 q1a12
+ 9 43 -4 148.72 76.07 148.00 59.17 485.9 1200.2 q1a12
+ 9 43 -3 -18.93 97.92 92.00 58.79 475.5 1206.7 q1a12
+ 9 43 -2 -223.11 102.64 92.00 60.23 465.2 1213.3 q1a12
+ 9 43 -1 157.70 114.59 117.00 60.90 454.9 1219.8 q1a12
+ 9 43 0 61.03 80.91 95.00 58.08 444.7 1226.4 q1a12
+ 9 43 1 77.78 119.95 142.00 59.66 434.4 1232.9 q1a12
+ 9 43 2 -174.67 115.14 112.00 61.67 424.2 1239.4 q1a12
+ 10 -28 66 29.07 100.63 107.00 41.33 202.6 1089.3 q0a11
+ 10 -26 67 126.64 100.25 138.00 39.76 179.8 1059.9 q0a10
+ 10 -24 68 61.97 112.45 113.00 44.10 154.2 1030.8 q0a10
+ 10 -22 68 241.68 133.13 118.00 45.92 139.8 996.3 q0a10
+ 10 -20 68 -65.76 76.43 79.00 44.36 125.4 962.0 q0a10
+ 10 -18 69 -16.71 82.28 89.00 43.91 100.4 933.7 q0a10
+ 10 -14 69 180.69 94.71 92.00 56.31 72.0 893.6 q0a8
+ 10 -12 69 -89.79 111.98 120.00 58.59 58.2 860.3 q0a8
+ 10 -10 69 5.10 100.46 126.00 59.10 44.5 827.2 q0a8
+ 10 -8 69 -87.16 126.08 125.00 57.96 30.8 794.4 q0a8
+ 10 -6 68 -128.07 113.70 112.00 57.67 27.8 756.0 q0a8
+ 10 20 55 0.46 112.89 123.00 71.34 449.0 716.6 q1a6
+ 10 22 53 -104.99 94.56 125.00 70.39 456.1 674.9 q1a6
+ 10 24 51 90.52 108.86 115.00 70.28 463.2 633.4 q1a6
+ 10 26 49 -55.64 117.89 110.00 68.24 470.3 592.1 q1a6
+ 10 30 43 98.73 150.66 163.00 72.03 504.1 524.4 q1a4
+ 10 30 44 107.21 101.28 127.00 69.87 494.0 530.5 q1a4
+ 10 32 40 114.78 167.36 243.00 77.07 521.4 477.3 q1a4
+ 10 32 41 -180.68 155.97 208.00 71.05 511.3 483.4 q1a4
+ 10 34 37 116.23 148.74 155.00 72.97 538.7 430.3 q1a4
+ 10 36 33 -255.35 209.24 216.00 73.88 566.1 377.1 q1a4
+ 10 36 34 17.96 131.12 123.00 68.96 556.0 383.3 q1a4
+ 10 40 23 -67.00 152.43 222.00 64.71 694.7 885.7 q1a9
+ 10 40 24 24.20 128.52 202.00 65.49 701.1 895.9 q1a9
+ 10 42 16 130.09 89.63 108.00 59.32 622.1 827.7 q1a9
+ 10 42 17 -45.53 76.67 96.00 60.19 628.5 837.9 q1a9
+ 10 42 18 106.90 87.76 97.00 61.33 635.0 848.2 q1a9
+ 10 44 7 30.51 102.75 99.00 57.17 539.0 748.6 q1a8
+ 10 44 8 -339.28 143.34 119.00 60.17 545.5 759.0 q1a8
+ 10 44 9 -232.37 155.59 140.00 60.29 552.1 769.3 q1a8
+ 10 44 10 -266.14 149.86 124.00 60.49 558.6 779.7 q1a8
+ 10 44 11 114.79 133.28 113.00 57.13 565.1 790.0 q1a8
+ 10 46 -7 175.63 98.23 96.00 52.58 481.7 1119.7 q1a12
+ 10 46 -6 -263.20 125.84 103.00 56.88 471.1 1126.5 q1a12
+ 10 46 -5 -196.28 113.46 109.00 55.43 460.6 1133.2 q1a12
+ 10 46 -4 -173.71 103.82 89.00 54.71 450.1 1140.0 q1a12
+ 10 46 -3 207.21 119.61 99.00 54.53 439.6 1146.7 q1a12
+ 11 -25 71 156.54 67.55 86.00 39.66 105.4 1083.8 q0a10
+ 11 -23 71 -2.55 53.37 74.00 39.95 90.8 1048.1 q0a10
+ 11 -21 71 -14.62 65.61 83.00 40.62 76.3 1012.8 q0a10
+ 11 -19 72 -63.50 85.15 85.00 41.50 50.9 983.6 q0a10
+ 11 -17 72 75.35 76.66 80.00 41.85 36.6 948.8 q0a10
+ 11 -13 72 -286.31 168.82 151.00 60.31 8.1 907.1 q0a8
+ 11 25 54 413.91 128.94 148.00 70.29 401.2 632.4 q1a6
+ 11 27 52 265.73 116.84 154.00 67.47 408.5 590.3 q1a6
+ 11 31 46 -45.38 101.74 110.00 68.15 443.2 520.3 q1a4
+ 11 31 47 100.48 124.42 125.00 69.72 432.9 526.6 q1a4
+ 11 33 43 44.93 86.97 112.00 63.21 460.9 472.3 q1a4
+ 11 33 44 -13.82 46.19 99.00 62.91 450.6 478.6 q1a4
+ 11 35 40 78.82 106.15 103.00 64.29 478.6 424.4 q1a4
+ 11 35 41 91.18 130.33 125.00 63.47 468.3 430.7 q1a4
+ 11 39 32 -4.42 118.64 115.00 56.89 753.3 964.8 q1a11
+ 11 39 33 353.87 150.93 173.00 56.53 759.7 975.1 q1a11
+ 11 41 28 54.37 86.89 88.00 56.42 699.0 937.1 q1a11
+ 11 41 29 -94.76 95.68 111.00 57.48 705.5 947.4 q1a11
+ 11 43 22 69.92 95.07 116.00 60.31 631.2 916.1 q1a9
+ 11 45 14 -170.58 190.10 190.00 57.81 553.3 846.5 q1a8
+ 11 45 15 13.56 133.56 130.00 57.74 559.9 857.0 q1a8
+ 11 45 16 332.69 168.99 184.00 53.64 566.6 867.5 q1a8
+ 11 45 17 -193.83 164.74 130.00 56.32 573.2 877.9 q1a8
+ 11 47 4 45.00 109.75 83.00 48.71 458.3 755.3 q1a8
+ 11 47 5 -25.84 112.50 95.00 52.51 465.1 765.9 q1a8
+ 11 47 6 -86.59 115.83 103.00 56.15 471.8 776.5 q1a8
+ 11 47 7 26.36 93.35 97.00 52.93 478.6 787.1 q1a8
+ 11 47 8 -81.57 95.79 104.00 55.52 485.3 797.6 q1a8
+ 12 -24 74 -195.01 94.75 79.00 38.63 39.3 1102.7 q0a10
+ 12 -22 74 -49.46 73.87 62.00 35.66 24.6 1066.2 q0a10
+ 12 40 36 250.56 185.16 201.00 57.74 751.8 1036.7 q1a11
+ 12 40 37 -125.50 217.76 243.00 60.50 758.4 1047.1 q1a11
+ 12 42 31 -84.45 90.45 88.00 57.95 689.8 998.0 q1a11
+ 12 42 32 -97.80 126.42 141.00 57.61 696.4 1008.5 q1a11
+ 12 44 26 -116.41 125.99 169.00 55.21 627.7 959.3 q1a11
+ 12 44 27 84.62 84.29 89.00 52.38 634.4 969.8 q1a11
+ 12 48 11 -76.23 96.43 99.00 53.92 471.6 855.5 q1a8
+ 12 48 12 88.06 100.01 121.00 53.84 478.4 866.2 q1a8
+ 12 48 13 -101.25 95.77 104.00 57.35 485.3 876.9 q1a8
+ 12 48 14 11.00 73.56 91.00 53.29 492.1 887.5 q1a8
+ 13 41 39 -74.10 170.11 173.00 58.90 743.5 1100.9 q1a11
+ 13 43 35 163.00 81.08 135.00 57.00 687.0 1072.1 q1a11
+ 13 45 30 -46.24 101.74 96.00 54.47 623.7 1032.6 q1a11
+ 13 45 31 -90.07 86.67 88.00 56.25 630.5 1043.2 q1a11
+ 13 47 24 153.03 123.00 120.00 50.77 556.3 982.4 q1a10
+ 13 47 25 207.82 117.56 130.00 46.06 563.2 993.1 q1a10
+ 14 46 33 -44.89 122.21 137.00 53.49 612.5 1098.1 q1a11
+ 14 48 27 352.31 125.29 195.00 46.69 543.6 1046.9 q1a10
+ 14 48 28 453.42 107.56 109.00 42.05 550.7 1057.8 q1a10
+ 14 50 21 62.45 95.91 90.00 43.95 471.5 995.5 q1a10
+ 14 50 22 -139.88 81.23 75.00 46.36 478.7 1006.5 q1a10
+ 15 51 24 115.79 70.04 83.00 42.41 456.7 1061.9 q1a10
+ 15 51 25 -14.64 56.35 63.00 41.01 464.0 1073.0 q1a10
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035106_186c3.h5
+Image serial number: 16
+hit = 1
+indexed_by = none
+photon_energy_eV = 9499.865457
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9499.865457
+average_camera_length = 0.152001 m
+num_peaks = 19
+peak_resolution = 3.489221 nm^-1 or 2.865969 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 877.50 12.84 2.32 2035.42 q2a0
+1232.79 106.50 1.85 891.78 q3a0
+1511.75 97.50 2.51 3683.71 q3a1
+1414.68 102.40 2.19 247.64 q3a1
+1400.50 156.76 1.92 1554.81 q3a1
+ 274.69 338.50 1.43 1970.75 q0a3
+ 488.55 251.18 0.98 12152.14 q1a2
+ 557.50 267.07 1.11 1541.55 q1a2
+ 430.74 314.21 0.57 917.36 q1a2
+ 936.71 287.71 1.00 1113.55 q2a2
+ 828.74 323.50 0.51 1216.39 q2a2
+ 948.50 350.85 0.86 883.31 q2a2
+ 854.51 353.50 0.43 8312.05 q2a2
+1185.50 285.18 0.72 1103.79 q3a2
+1327.43 358.85 0.80 6524.56 q3a2
+1370.50 298.08 1.18 514.59 q3a3
+1061.88 665.12 3.00 638.11 q2a7
+1046.51 679.50 3.06 1770.26 q2a7
+1128.50 803.09 3.49 330.85 q2a9
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035050_16fec.h5
+Image serial number: 18
+hit = 1
+indexed_by = none
+photon_energy_eV = 9495.658621
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998596
+hdf5/LCLS/photon_energy_eV = 9495.658621
+average_camera_length = 0.152001 m
+num_peaks = 23
+peak_resolution = 2.667844 nm^-1 or 3.748346 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 96.02 55.98 2.14 254.49 q0a0
+ 272.29 114.23 2.22 1388.32 q0a1
+1005.76 107.96 2.10 1224.43 q2a1
+1004.74 128.74 2.01 2838.29 q2a1
+1222.38 78.07 1.99 1748.59 q3a0
+1396.93 64.42 2.31 2556.84 q3a1
+ 127.71 218.83 1.23 2996.74 q0a2
+ 46.19 279.19 0.78 1471.50 q0a2
+ 157.78 297.50 0.97 2597.19 q0a2
+ 445.17 285.50 0.73 1618.70 q1a2
+ 549.99 316.99 0.90 361.64 q1a2
+ 471.09 350.78 0.46 7873.30 q1a2
+ 732.50 274.21 1.87 1306.04 q1a3
+ 867.68 253.10 0.94 2118.75 q2a2
+ 901.50 293.09 0.85 1139.86 q2a2
+ 951.50 344.09 0.89 2184.04 q2a2
+ 986.12 332.25 1.10 1769.90 q2a3
+1336.06 293.50 1.03 635.01 q3a2
+1282.50 314.57 0.74 4981.25 q3a2
+1292.08 344.50 0.67 1083.61 q3a2
+ 716.50 1367.07 2.62 602.81 q1a15
+1094.50 1362.10 2.67 612.43 q2a15
+1128.39 1421.66 2.35 2150.76 q2a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035146_1beee.h5
+Image serial number: 17
+hit = 1
+indexed_by = none
+photon_energy_eV = 9516.915412
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9516.915412
+average_camera_length = 0.152001 m
+num_peaks = 33
+peak_resolution = 3.481099 nm^-1 or 2.872656 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 253.79 72.99 2.35 2001.77 q0a1
+ 400.50 18.51 2.29 918.04 q1a0
+ 542.50 136.79 1.80 1345.54 q1a0
+ 668.50 79.80 2.37 1176.77 q1a1
+ 929.50 18.97 2.36 1172.15 q2a0
+1014.13 160.14 1.91 2435.10 q2a1
+1049.50 170.12 1.99 2974.00 q2a1
+1172.62 48.42 2.14 2861.96 q3a0
+1346.06 54.47 2.25 2946.88 q3a0
+1301.50 103.73 1.94 467.01 q3a0
+ 14.50 238.12 1.00 1076.11 q0a2
+ 163.95 280.30 1.07 642.93 q0a2
+ 34.85 307.50 0.62 1068.16 q0a2
+ 220.50 263.78 1.36 1529.43 q0a3
+ 284.80 273.41 1.62 2728.45 q0a3
+ 409.74 240.50 0.97 1210.52 q1a2
+ 570.39 354.81 0.90 2263.12 q1a2
+ 756.30 195.45 2.18 2031.54 q1a3
+ 961.50 286.65 1.11 2390.74 q2a2
+ 785.50 331.33 0.46 2288.66 q2a2
+1092.81 298.70 1.70 1126.71 q2a3
+1138.47 341.94 1.87 2483.26 q2a3
+1053.82 359.10 1.41 2167.10 q2a3
+1287.50 194.34 1.32 3017.71 q3a2
+1258.38 259.87 0.93 6143.35 q3a2
+1192.50 273.15 0.79 898.04 q3a2
+1253.68 309.60 0.67 4430.35 q3a2
+1341.08 323.50 0.96 1098.02 q3a2
+1179.50 333.93 0.46 972.05 q3a2
+1272.41 344.21 0.59 4118.33 q3a2
+1398.44 338.96 1.21 5517.94 q3a3
+ 989.09 521.50 3.48 700.62 q2a5
+ 615.11 703.50 3.28 644.15 q1a7
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035028_151aa.h5
+Image serial number: 21
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9511.311227
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9511.311227
+average_camera_length = 0.152001 m
+num_peaks = 35
+peak_resolution = 3.706096 nm^-1 or 2.698257 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 141.50 104.23 1.96 300.81 q0a0
+ 326.28 118.39 2.38 2383.17 q0a1
+ 491.66 10.73 2.35 3880.65 q1a0
+ 403.72 85.36 1.95 1176.90 q1a0
+ 460.35 131.01 1.72 1606.16 q1a0
+ 628.76 92.08 2.21 3793.34 q1a1
+ 933.38 78.48 2.08 5516.39 q2a0
+1033.03 176.91 1.90 3993.05 q2a1
+1197.19 73.38 2.01 2144.06 q3a0
+ 25.90 207.68 1.17 2022.73 q0a2
+ 62.50 247.96 0.97 1610.30 q0a2
+ 162.77 311.72 0.94 1567.55 q0a2
+ 127.79 361.75 0.63 3250.38 q0a2
+ 222.50 213.00 1.55 654.11 q0a3
+ 244.96 239.50 1.55 1023.18 q0a3
+ 222.84 304.15 1.25 4926.83 q0a3
+ 455.24 206.50 1.17 1358.19 q1a2
+ 430.75 261.68 0.85 1968.54 q1a2
+ 435.63 279.78 0.76 15118.38 q1a2
+ 512.98 287.02 0.87 738.55 q1a2
+ 519.50 292.33 0.87 1254.16 q1a2
+ 556.12 329.50 0.89 800.78 q1a2
+ 714.68 276.80 1.78 2357.15 q1a3
+ 863.50 223.69 1.09 5582.28 q2a2
+ 847.23 295.04 0.69 10126.46 q2a2
+ 919.08 307.50 0.86 751.75 q2a2
+1009.24 282.50 1.34 3449.34 q2a3
+1347.50 255.87 1.22 1328.00 q3a2
+1262.83 268.50 0.90 1054.90 q3a2
+1330.50 301.18 0.98 1870.41 q3a2
+1308.58 347.33 0.74 4476.91 q3a2
+1441.98 315.50 1.48 1256.62 q3a3
+ 328.99 841.50 3.71 673.54 q0a9
+1102.91 835.91 3.67 360.60 q2a9
+ 270.04 1447.43 2.35 5548.55 q0a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.09500 12.28673 16.91872 nm, 90.53338 89.23643 90.40983 deg
+astar = -0.0338196 +0.0776410 +0.1405448 nm^-1
+bstar = -0.0705310 +0.0263924 -0.0308840 nm^-1
+cstar = -0.0273425 -0.0486870 +0.0194014 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00337 nm^-1
+predict_refine/final_residual = 1.159727e-06
+predict_refine/det_shift x = 0.006 y = -0.027 mm
+diffraction_resolution_limit = 2.21 nm^-1 or 4.53 A
+num_reflections = 293
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -21 -41 8 -96.68 97.44 109.00 64.08 1194.3 944.0 q3a10
+ -20 -30 30 454.20 193.76 222.00 76.20 1524.7 1072.1 q3a11
+ -19 -41 2 195.79 165.54 204.00 78.13 1192.9 854.8 q3a8
+ -19 -39 8 -8.94 119.90 139.00 80.37 1265.6 902.0 q3a8
+ -19 -33 22 -51.71 121.31 126.00 78.97 1445.0 978.8 q3a11
+ -19 -31 26 87.20 124.16 157.00 78.12 1499.8 1007.5 q3a11
+ -18 -26 32 -296.68 132.04 130.00 91.08 1261.8 409.2 q3a4
+ -18 -24 35 -90.49 125.84 141.00 91.89 1241.4 456.0 q3a4
+ -18 -22 38 252.80 131.68 167.00 91.80 1221.1 502.7 q3a4
+ -18 -18 43 290.76 160.42 213.00 99.64 1188.9 563.9 q3a6
+ -17 -35 12 -534.36 209.84 237.00 93.56 1383.6 866.0 q3a9
+ -17 -27 28 -93.44 134.07 153.00 93.44 1323.8 383.9 q3a4
+ -17 -21 37 201.84 151.96 205.00 95.96 1263.7 522.2 q3a4
+ -17 -17 42 55.05 162.46 158.00 95.55 1232.2 581.9 q3a6
+ -16 -36 6 51.35 175.19 179.00 85.79 1349.8 789.6 q3a8
+ -16 -34 11 -21.15 115.18 139.00 88.62 1407.3 826.5 q3a9
+ -16 -30 20 -103.68 198.54 413.00 100.05 1519.7 890.8 q3a9
+ -15 -39 -9 -28.00 137.19 129.00 79.00 1233.0 1146.7 q3a12
+ -15 -33 10 141.89 141.63 156.00 91.70 1430.4 788.0 q3a9
+ -15 -29 19 -25.67 290.79 331.00 103.20 1541.1 851.8 q3a9
+ -15 -25 26 39.63 132.60 168.00 105.35 1400.9 424.9 q3a5
+ -15 -15 40 -196.75 202.01 253.00 115.75 1315.5 616.7 q3a6
+ -14 -36 -3 249.75 168.95 291.00 92.25 1214.6 1248.4 q3a12
+ -14 -24 25 181.60 167.85 259.00 117.60 1439.4 444.5 q3a5
+ -14 -12 41 -184.51 267.09 300.00 123.11 1344.3 672.5 q3a6
+ -14 -6 47 27.60 166.10 316.00 109.60 1127.6 1163.2 q2a13
+ -14 22 62 -265.89 148.85 193.00 79.49 786.2 892.2 q2a8
+ -14 28 63 -198.47 106.18 97.00 59.27 790.0 984.7 q2a10
+ -13 -37 -13 -202.69 162.18 176.00 85.93 1323.6 1182.2 q3a12
+ -13 -33 2 -234.27 169.44 182.00 126.31 1205.9 1310.4 q3a14
+ -13 -25 20 431.54 282.21 299.00 142.66 1504.0 413.8 q3a5
+ -13 -21 27 -314.18 316.29 365.00 147.35 1458.0 507.4 q3a5
+ -13 -15 35 -287.89 262.98 361.00 142.49 1410.2 605.5 q3a7
+ -13 7 54 -94.95 201.81 300.00 101.55 892.6 1167.2 q2a12
+ -13 9 55 56.46 164.17 188.00 96.34 855.4 1163.6 q2a12
+ -13 11 56 -327.65 160.54 210.00 102.85 817.8 1160.0 q2a12
+ -13 27 61 -61.31 108.28 90.00 57.31 839.9 948.6 q2a10
+ -12 -34 -7 280.75 142.24 186.00 92.41 1303.4 1281.0 q3a12
+ -12 -32 0 114.89 184.13 205.00 125.23 1249.9 1325.7 q3a14
+ -12 -22 22 -648.55 607.66 452.00 194.34 1521.6 476.4 q3a5
+ -12 -16 31 -171.59 294.52 350.00 164.79 1466.4 578.3 q3a7
+ -12 -12 36 -191.66 234.75 292.00 152.46 1437.3 659.9 q3a7
+ -12 -4 44 977.76 221.32 309.00 121.64 1104.6 1250.2 q2a13
+ -12 4 50 103.01 374.27 317.00 118.39 958.1 1222.3 q2a12
+ -12 16 56 -270.76 133.11 136.00 85.36 889.0 750.4 q2a8
+ -12 22 58 -189.94 148.79 167.00 86.94 886.3 864.0 q2a8
+ -12 28 59 -309.86 140.37 169.00 65.26 892.6 951.7 q2a10
+ -11 -37 -39 -38.27 135.25 134.00 75.88 9.0 697.6 q0a6
+ -11 -37 -38 -163.92 138.31 160.00 79.92 17.4 708.0 q0a6
+ -11 -37 -37 108.73 170.85 187.00 81.07 25.7 718.3 q0a6
+ -11 -37 -36 226.92 113.18 128.00 76.08 33.9 728.5 q0a6
+ -11 -35 -19 -233.85 141.39 162.00 89.51 1426.0 1201.3 q3a13
+ -11 -31 -2 -448.18 237.97 326.00 158.47 1293.0 1340.7 q3a14
+ -11 -25 13 -512.26 303.17 385.00 204.23 1533.5 27.9 q3a1
+ -11 -13 32 537.83 560.23 556.00 205.57 1492.6 632.3 q3a7
+ -11 -1 44 -273.99 232.87 312.00 130.39 1057.1 1285.7 q2a13
+ -11 3 47 -36.05 268.77 315.00 120.45 983.1 1272.3 q2a13
+ -11 19 55 573.75 156.19 177.00 79.25 934.8 794.1 q2a8
+ -11 23 56 -31.82 169.62 173.00 84.42 936.6 868.2 q2a8
+ -11 29 57 -102.64 142.47 129.00 67.24 944.1 954.8 q2a10
+ -10 -34 -23 -300.48 137.14 171.00 95.89 1486.9 1203.3 q3a13
+ -10 -30 -5 -368.45 399.09 350.00 181.07 1344.0 1348.7 q3a14
+ -10 -28 1 480.97 390.38 428.00 189.08 1299.8 1411.6 q3a14
+ -10 -24 11 222.50 239.80 333.00 212.50 1520.8 70.6 q3a1
+ -10 -22 15 -299.45 314.78 457.00 224.52 1472.1 44.6 q3a1
+ -10 20 53 115.49 136.13 159.00 87.11 980.3 799.0 q2a9
+ -10 24 54 -94.65 135.09 129.00 85.85 982.8 872.4 q2a9
+ -10 30 55 -57.65 96.06 107.00 68.85 991.5 957.8 q2a11
+ -10 32 55 -260.15 266.77 375.00 69.35 997.3 995.4 q2a11
+ -9 -29 -8 -387.56 256.16 270.00 188.34 1391.2 1356.6 q3a15
+ -9 -5 35 -426.20 663.75 567.00 250.80 1150.2 1370.3 q2a15
+ -9 19 50 57.23 140.51 146.00 87.97 1030.3 766.3 q2a9
+ -9 27 52 -44.95 106.90 131.00 86.55 1036.9 911.8 q2a9
+ -8 -28 -12 -232.80 257.99 285.00 181.91 1449.7 1357.7 q3a15
+ -8 -22 6 341.00 671.78 542.00 313.14 1502.3 162.0 q3a1
+ -8 -20 10 2290.97 596.54 730.00 292.69 1454.4 136.2 q3a1
+ -8 -18 14 -245.34 554.41 563.00 280.99 1406.7 110.5 q3a1
+ -8 -10 26 1505.17 479.38 510.00 256.83 1242.1 40.7 q3a0
+ -8 2 38 -798.10 350.45 388.00 223.90 1033.4 1391.6 q2a15
+ -8 24 49 123.84 126.36 173.00 88.96 1080.3 842.3 q2a9
+ -7 -29 -57 53.62 129.52 162.00 75.17 48.8 425.6 q0a4
+ -7 -29 -28 -128.26 234.20 288.00 130.60 267.1 701.3 q0a7
+ -7 -27 -16 286.10 285.50 350.00 200.57 1507.7 1358.8 q3a15
+ -7 -17 11 -123.29 302.38 343.00 217.35 1401.3 159.4 q3a1
+ -7 -13 18 412.43 411.09 510.00 207.24 1315.7 116.7 q3a0
+ -7 -11 21 -590.13 514.30 521.00 233.51 1274.2 99.4 q3a0
+ -7 -7 26 1053.39 600.08 1127.00 255.24 1196.1 72.9 q3a0
+ -7 1 34 -1738.99 932.67 971.00 328.45 1063.3 1443.9 q2a15
+ -7 9 40 163.85 458.43 453.00 215.35 923.5 1421.2 q2a14
+ -7 11 41 14.06 493.59 613.00 195.94 889.2 1419.4 q2a14
+ -7 13 42 478.42 246.34 294.00 166.18 854.5 1417.7 q2a14
+ -7 15 43 -173.90 336.53 347.00 168.10 819.4 1415.9 q2a14
+ -7 17 44 -144.81 230.25 252.00 162.51 783.8 1414.2 q2a14
+ -7 23 46 -206.00 384.96 419.00 103.00 1128.1 809.2 q2a9
+ -7 29 47 -172.09 236.94 252.00 81.29 1139.7 915.4 q2a9
+ -6 -26 -63 24.07 212.14 208.00 63.33 375.2 1053.1 q0a11
+ -6 -26 -22 485.28 645.25 509.00 192.46 359.3 727.4 q0a7
+ -6 -24 -13 -841.63 685.23 565.00 303.30 1511.2 1427.9 q3a15
+ -6 -18 4 59.77 231.85 364.00 149.19 1443.3 205.6 q3a3
+ -6 -12 15 890.19 224.48 511.00 162.14 1311.0 165.1 q3a0
+ -6 -10 18 55.06 177.62 277.00 177.37 1269.8 148.0 q3a0
+ -6 -8 21 381.88 202.65 268.00 170.33 1228.5 130.9 q3a0
+ -5 -25 -54 180.24 145.65 137.00 79.34 164.5 412.6 q0a4
+ -5 -25 -53 -229.87 180.14 168.00 86.08 172.2 423.6 q0a4
+ -5 -25 -52 -265.38 251.17 282.00 87.15 179.7 434.6 q0a4
+ -5 -25 -33 -195.56 309.19 390.00 141.34 313.6 603.1 q0a7
+ -5 -25 -32 624.10 329.44 581.00 143.43 320.4 612.9 q0a7
+ -5 -25 -31 718.36 274.76 425.00 148.77 327.2 622.6 q0a7
+ -5 -23 -66 -24.34 74.76 98.00 63.54 309.1 1019.0 q0a11
+ -5 -23 -19 657.74 396.45 420.00 226.62 15.3 12.2 q0a0
+ -5 -15 5 249.42 191.84 229.00 116.97 1390.9 227.3 q3a3
+ -5 -1 25 -107.92 286.47 339.00 155.20 1103.0 330.3 q2a3
+ -5 1 27 466.24 523.97 528.00 188.97 1112.2 293.8 q2a3
+ -5 29 41 72.07 130.16 167.00 97.33 1030.6 415.5 q2a5
+ -4 -20 -68 106.92 107.03 111.00 65.80 255.0 976.6 q0a11
+ -4 -16 -81 99.61 89.81 92.00 52.99 55.3 1038.9 q0a10
+ -4 -16 -4 1262.57 278.77 733.00 121.72 1443.0 317.1 q3a3
+ -4 -14 1 151.74 166.60 232.00 114.09 1391.0 282.7 q3a3
+ -4 -12 5 1341.90 251.30 877.00 93.14 1347.9 257.1 q3a2
+ -4 0 22 -52.55 198.09 223.00 118.34 1055.1 326.8 q2a3
+ -4 2 24 -47.79 202.66 253.00 129.18 1064.1 290.5 q2a3
+ -4 30 38 -292.43 281.47 407.00 111.83 1030.4 467.9 q2a5
+ -4 40 38 -81.91 101.52 144.00 75.71 857.4 509.3 q2a4
+ -3 -19 -61 154.48 215.05 302.00 87.72 323.6 915.6 q0a9
+ -3 -19 -60 -116.35 183.40 239.00 88.15 335.1 908.1 q0a9
+ -3 -19 -25 1155.84 535.45 598.00 264.27 119.6 48.9 q0a0
+ -3 -19 -24 1346.47 505.54 559.00 266.24 110.3 55.2 q0a0
+ -3 -17 -15 127.55 184.89 239.00 168.09 38.3 133.1 q0a0
+ -3 -15 -76 -117.85 83.73 87.00 61.65 110.7 959.2 q0a10
+ -3 -13 -4 35.09 166.17 223.00 110.41 1396.6 346.4 q3a3
+ -3 -7 8 1049.97 154.58 827.00 89.74 1262.0 269.6 q3a2
+ -3 -5 11 943.77 179.92 746.00 85.19 1221.5 252.6 q3a2
+ -3 7 24 366.46 173.13 216.00 114.28 1025.9 219.0 q2a3
+ -3 11 27 4151.47 344.83 1985.00 213.68 1034.8 177.3 q2a1
+ -3 21 32 -105.23 283.56 322.00 210.03 1036.7 8.4 q2a1
+ -3 27 34 577.96 369.40 395.00 142.84 1099.5 512.0 q2a5
+ -2 -16 -61 2.82 115.93 301.00 85.86 294.7 860.3 q0a9
+ -2 -16 -24 901.96 466.64 1048.00 228.16 139.3 103.3 q0a0
+ -2 -14 -70 -338.38 221.37 229.00 78.38 174.5 904.1 q0a8
+ -2 -12 -9 1636.70 193.64 628.00 83.39 24.0 208.6 q0a2
+ -2 -8 0 4141.34 260.95 3356.00 91.07 1308.1 349.7 q3a2
+ -2 -4 7 13.94 155.89 181.00 91.80 1222.3 307.3 q3a2
+ -2 16 26 366.00 437.16 536.00 255.29 987.2 109.3 q2a1
+ -2 18 27 2066.76 568.84 656.00 288.03 987.3 75.7 q2a1
+ -2 38 31 -19.45 149.55 184.00 92.05 935.1 579.5 q2a6
+ -2 44 30 292.62 114.67 136.00 77.99 830.6 618.7 q2a6
+ -1 -13 -61 -102.68 148.27 164.00 89.18 266.2 805.8 q0a9
+ -1 -13 -60 76.95 112.89 129.00 83.53 277.7 798.7 q0a9
+ -1 -13 -25 -75.73 327.56 359.00 186.55 177.3 144.9 q0a0
+ -1 -13 -24 -318.24 257.84 331.00 181.52 167.9 150.8 q0a0
+ -1 -11 -69 -187.12 226.06 211.00 89.12 158.2 839.7 q0a8
+ -1 -9 -75 -98.91 118.50 133.00 78.71 65.3 860.5 q0a8
+ -1 -9 -10 1606.55 174.25 815.00 82.78 61.3 249.0 q0a2
+ -1 -1 5 -2254.39 1125.63 812.00 521.21 1187.8 353.3 q3a2
+ -1 15 21 -228.48 337.01 432.00 177.52 934.0 145.0 q2a0
+ -1 17 22 241.14 431.92 563.00 215.49 933.8 112.0 q2a0
+ -1 19 23 5397.36 583.28 3135.00 264.44 933.6 78.6 q2a0
+ -1 21 24 2473.36 729.46 638.00 300.87 933.4 44.8 q2a0
+ -1 27 26 1223.11 493.73 468.00 180.49 1138.2 592.4 q2a7
+ -1 35 27 397.24 183.37 220.00 121.36 1004.7 620.7 q2a7
+ -1 43 26 54.91 98.32 118.00 85.53 872.1 670.7 q2a6
+ -1 47 25 -212.27 157.22 144.00 83.29 801.8 702.3 q2a6
+ 0 -8 -67 262.98 162.89 247.00 82.22 154.2 769.5 q0a8
+ 0 -8 -18 -43.28 154.79 157.00 93.11 151.7 227.1 q0a2
+ 0 -6 -73 27.20 118.89 144.00 80.20 62.5 788.1 q0a8
+ 0 -6 -12 1514.56 169.28 1450.00 85.44 107.4 283.8 q0a2
+ 0 6 8 10029.77 341.99 3884.00 86.19 846.4 296.2 q2a2
+ 0 8 10 366.52 146.37 140.00 83.83 854.6 260.3 q2a2
+ 0 10 12 5715.06 273.84 4337.00 82.20 862.9 224.2 q2a2
+ 0 30 22 -1209.00 598.63 489.00 192.71 1110.0 659.7 q2a7
+ 0 32 22 -212.58 351.08 439.00 148.73 1078.0 669.5 q2a7
+ 0 40 22 -12.27 242.57 244.00 96.45 947.3 710.5 q2a6
+ 1 -7 -55 329.59 215.01 228.00 139.36 52.1 1342.7 q0a14
+ 1 -7 -54 -148.29 194.94 253.00 150.29 58.6 1353.8 q0a14
+ 1 -5 -64 113.35 175.09 240.00 99.12 16.3 1251.8 q0a12
+ 1 -5 -21 -401.05 193.94 188.00 110.18 204.3 256.7 q0a3
+ 1 -3 -15 1475.34 194.63 780.00 83.16 162.5 313.3 q0a2
+ 1 1 -6 -1744.86 737.58 533.00 238.02 409.9 344.2 q1a2
+ 1 9 5 635.99 255.62 495.00 90.37 791.5 266.4 q2a2
+ 1 11 7 322.06 171.07 188.00 86.53 799.6 230.4 q2a2
+ 1 19 13 32.66 191.42 269.00 167.03 813.6 121.6 q2a0
+ 1 21 14 -424.36 389.63 450.00 205.07 812.7 88.4 q2a0
+ 1 23 15 36.76 482.87 583.00 258.90 811.8 54.9 q2a0
+ 1 31 17 409.20 542.90 501.00 196.61 1117.2 726.7 q2a7
+ 1 41 17 438.56 171.23 262.00 84.74 755.3 1195.5 q1a13
+ 1 45 16 -6.27 147.19 237.00 79.88 722.0 1128.9 q1a13
+ 2 -2 -59 -285.44 210.64 274.00 105.15 102.3 1282.1 q0a12
+ 2 -2 -27 -249.41 242.13 248.00 127.68 288.8 270.2 q0a3
+ 2 -2 -26 626.56 213.14 251.00 113.62 279.1 275.7 q0a3
+ 2 0 -66 -115.46 144.43 153.00 94.85 81.4 1182.9 q0a12
+ 2 0 -19 95.45 165.84 190.00 103.22 224.1 337.7 q0a3
+ 2 4 -10 15132.89 414.66 8192.00 68.43 434.5 280.3 q1a2
+ 2 8 -4 172.55 178.91 197.00 67.78 515.4 314.0 q1a2
+ 2 10 -1 944.16 205.08 499.00 70.18 556.0 330.8 q1a2
+ 2 18 6 86.74 187.40 246.00 114.09 694.0 353.5 q1a3
+ 2 26 10 473.51 740.11 545.00 297.30 756.2 1440.7 q1a15
+ 2 28 11 -1004.16 644.92 534.00 266.90 755.0 1406.4 q1a15
+ 2 34 12 -454.60 256.52 290.00 177.69 732.0 1308.8 q1a15
+ 2 42 11 -197.33 105.00 128.00 86.33 675.5 1207.2 q1a13
+ 2 46 10 195.72 119.52 111.00 74.13 640.5 1140.7 q1a13
+ 3 1 -49 617.60 327.75 397.00 196.07 212.1 1338.8 q0a15
+ 3 1 -48 624.75 290.20 368.00 196.25 218.0 1349.6 q0a15
+ 3 1 -47 -16.96 286.99 372.00 202.77 224.0 1360.4 q0a15
+ 3 1 -46 206.72 275.53 377.00 210.94 229.8 1371.1 q0a15
+ 3 1 -45 355.39 389.54 442.00 209.87 235.7 1381.7 q0a15
+ 3 1 -44 407.58 389.95 404.00 223.25 241.5 1392.3 q0a15
+ 3 1 -43 1241.64 396.45 526.00 221.23 247.3 1402.9 q0a15
+ 3 1 -42 263.76 310.25 359.00 222.94 253.0 1413.3 q0a15
+ 3 1 -41 287.19 373.88 491.00 233.96 258.7 1423.8 q0a15
+ 3 1 -40 -676.80 492.96 524.00 244.63 264.4 1434.1 q0a15
+ 3 1 -39 5032.00 582.52 1685.00 269.29 270.1 1444.5 q0a15
+ 3 1 -38 745.28 648.54 996.00 295.63 275.7 1454.7 q0a15
+ 3 1 -37 1460.62 617.29 793.00 303.74 281.3 1464.9 q0a15
+ 3 3 -59 -366.09 399.62 345.00 114.68 179.4 1238.4 q0a12
+ 3 3 -26 604.55 240.61 323.00 127.09 318.3 346.7 q0a3
+ 3 5 -65 687.64 176.21 208.00 89.13 167.3 1149.8 q0a12
+ 3 7 -15 1385.22 197.93 795.00 65.14 454.5 206.4 q1a2
+ 3 9 -12 112.88 116.10 107.00 65.76 495.2 223.3 q1a2
+ 3 17 -2 398.75 190.14 355.00 101.60 646.5 272.6 q1a3
+ 3 21 1 1346.12 401.36 1375.00 156.88 716.0 278.9 q1a3
+ 3 23 2 482.77 461.20 410.00 203.54 749.1 277.3 q1a3
+ 3 27 4 -1041.65 625.22 536.00 284.79 681.5 1451.7 q1a15
+ 3 31 5 426.82 336.18 463.00 199.53 668.5 1386.8 q1a15
+ 3 39 5 115.67 356.01 362.00 113.33 620.8 1286.3 q1a13
+ 3 41 5 -264.07 179.31 178.00 93.27 608.3 1252.9 q1a13
+ 3 47 3 333.88 174.56 201.00 76.37 551.0 1156.1 q1a12
+ 3 49 2 96.27 115.07 123.00 77.97 526.3 1123.6 q1a12
+ 4 8 -56 -68.91 122.51 174.00 110.28 271.9 1229.4 q0a13
+ 4 8 -30 -720.94 450.47 474.00 240.94 397.0 74.7 q1a0
+ 4 8 -29 1178.13 385.74 743.00 218.51 402.2 84.7 q1a0
+ 4 10 -62 115.46 170.25 148.00 92.22 262.4 1141.2 q0a13
+ 4 10 -23 1540.36 245.66 1049.00 169.73 459.0 131.3 q1a0
+ 4 12 -19 39.86 174.71 220.00 163.55 505.3 157.9 q1a0
+ 4 34 -2 -605.29 443.77 438.00 172.86 573.2 1370.8 q1a14
+ 4 36 -2 41.43 278.63 379.00 163.24 560.7 1339.1 q1a14
+ 4 38 -2 -76.78 176.34 219.00 139.44 547.9 1306.9 q1a14
+ 4 42 -3 -387.62 240.54 239.00 93.14 510.7 1272.1 q1a12
+ 4 44 -4 102.48 122.04 143.00 83.48 486.2 1241.8 q1a12
+ 4 48 -6 -215.45 135.15 149.00 79.13 435.4 1179.0 q1a12
+ 4 50 -7 95.45 107.04 119.00 73.48 409.0 1146.5 q1a12
+ 5 15 -31 3713.61 451.95 1461.00 237.21 490.9 10.5 q1a0
+ 5 15 -30 -489.78 576.68 628.00 262.02 496.0 20.8 q1a0
+ 5 17 -26 39.49 818.87 671.00 306.87 543.1 48.2 q1a0
+ 5 17 -25 -614.85 785.62 650.00 335.38 548.0 58.3 q1a0
+ 5 21 -19 4209.59 583.61 1908.00 286.29 629.2 92.5 q1a1
+ 5 23 -17 1765.08 593.24 892.00 267.69 666.8 99.6 q1a1
+ 5 25 -15 -113.63 619.20 530.00 279.52 704.6 106.7 q1a1
+ 5 27 -14 -182.12 473.14 609.00 243.10 738.3 103.8 q1a1
+ 5 31 -12 728.10 224.56 449.00 166.67 481.3 1460.5 q1a14
+ 5 33 -12 -304.90 273.03 306.00 165.96 468.1 1429.7 q1a14
+ 5 35 -12 6.60 191.23 253.00 142.07 454.5 1398.4 q1a14
+ 5 37 -12 -88.15 280.33 371.00 140.45 440.8 1366.6 q1a14
+ 5 39 -12 95.52 186.35 208.00 120.44 426.8 1334.2 q1a14
+ 5 47 -16 85.59 126.00 156.00 77.58 539.9 776.8 q1a8
+ 5 49 -17 -285.62 123.25 126.00 77.83 507.9 804.5 q1a8
+ 5 51 -20 56.75 104.84 126.00 74.25 482.5 857.2 q1a8
+ 5 53 -23 242.25 111.16 122.00 71.34 456.1 912.0 q1a8
+ 5 53 -22 -17.21 105.27 125.00 72.82 452.4 899.4 q1a8
+ 5 55 -26 215.36 106.02 105.00 54.01 429.2 941.8 q1a10
+ 5 57 -32 111.43 111.01 125.00 58.17 412.1 1042.0 q1a10
+ 5 57 -31 170.99 106.41 134.00 56.61 408.3 1028.2 q1a10
+ 6 24 -47 -42.57 205.52 250.00 109.46 569.6 586.4 q1a6
+ 6 24 -45 -398.03 159.98 205.00 129.08 589.9 576.1 q1a7
+ 6 24 -44 -72.70 164.16 204.00 128.89 601.5 571.0 q1a7
+ 6 24 -43 -315.05 205.22 258.00 131.84 613.0 566.0 q1a7
+ 6 26 -52 86.77 104.76 185.00 94.39 492.3 582.6 q1a6
+ 6 26 -51 -119.66 122.89 163.00 97.91 504.5 577.4 q1a6
+ 6 26 -35 -703.18 433.20 373.00 151.51 687.2 525.2 q1a5
+ 6 26 -34 67.58 380.02 409.00 154.42 698.4 520.5 q1a5
+ 6 26 -33 -803.21 475.81 431.00 163.21 709.4 515.8 q1a5
+ 6 28 -55 138.94 142.14 150.00 93.06 436.6 568.0 q1a6
+ 6 28 -54 18.06 169.66 187.00 94.84 449.2 562.6 q1a6
+ 6 28 -31 619.06 298.20 467.00 142.37 716.6 476.7 q1a5
+ 6 28 -30 -84.82 384.13 439.00 155.49 727.6 472.1 q1a5
+ 6 30 -29 449.35 316.11 398.00 141.32 723.9 437.3 q1a5
+ 6 30 -28 194.00 385.70 382.00 149.00 734.9 432.9 q1a5
+ 6 32 -28 -158.50 235.38 271.00 132.50 720.1 402.2 q1a5
+ 6 32 -27 470.49 263.00 402.00 127.85 731.2 397.7 q1a5
+ 6 36 -26 49.23 311.67 358.00 98.30 766.8 811.5 q1a9
+ 6 38 -27 159.22 153.47 152.00 85.34 738.9 838.4 q1a9
+ 6 38 -26 -148.60 238.32 279.00 97.11 734.6 826.9 q1a9
+ 6 40 -28 144.81 161.57 221.00 87.84 710.2 865.9 q1a9
+ 6 40 -27 -97.21 155.22 201.00 89.62 706.0 854.3 q1a9
+ 6 42 -29 64.24 118.54 180.00 84.24 680.8 894.2 q1a9
+ 6 42 -28 -183.16 123.63 133.00 83.11 676.6 882.3 q1a9
+ 6 46 -35 -215.86 110.86 131.00 79.49 637.1 975.6 q1a11
+ 6 46 -34 -61.81 120.39 132.00 73.42 632.9 962.9 q1a11
+ 6 46 -33 -235.36 136.34 135.00 77.99 628.7 950.3 q1a11
+ 6 48 -43 -52.39 99.62 101.00 69.76 635.5 1099.8 q1a11
+ 6 48 -42 12.62 120.13 142.00 71.99 631.1 1086.3 q1a11
+ 6 48 -41 -24.09 110.46 123.00 73.72 626.8 1072.9 q1a11
+ 6 48 -40 -185.91 114.34 118.00 72.18 622.4 1059.5 q1a11
+ 6 48 -39 -115.95 178.56 257.00 73.47 618.1 1046.3 q1a11
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035049_16fa7.h5
+Image serial number: 20
+hit = 1
+indexed_by = none
+photon_energy_eV = 9511.631956
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998596
+hdf5/LCLS/photon_energy_eV = 9511.631956
+average_camera_length = 0.152001 m
+num_peaks = 24
+peak_resolution = 3.659748 nm^-1 or 2.732429 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 179.50 22.98 2.41 950.95 q0a0
+ 410.91 143.50 1.64 1341.27 q1a0
+1255.72 84.60 1.98 1344.09 q3a0
+1335.50 140.84 1.82 646.47 q3a0
+ 87.50 214.28 1.17 1367.31 q0a2
+ 122.50 251.66 1.06 2638.75 q0a2
+ 14.50 253.73 0.92 2432.55 q0a2
+ 130.06 324.50 0.76 385.86 q0a2
+ 243.50 216.12 1.62 470.97 q0a3
+ 242.64 325.50 1.29 1666.62 q0a3
+ 250.28 357.50 1.27 1092.60 q0a3
+ 494.50 214.14 1.18 931.07 q1a2
+ 550.50 218.89 1.30 248.22 q1a2
+ 893.50 276.88 0.89 1064.56 q2a2
+ 818.45 283.28 0.72 5331.76 q2a2
+1092.03 221.25 1.88 1552.23 q2a3
+1213.43 248.95 0.93 5211.64 q3a2
+1294.14 268.45 0.98 6836.65 q3a2
+1282.50 290.23 0.85 1854.04 q3a2
+1324.07 292.13 0.99 1362.39 q3a2
+1220.50 318.82 0.56 574.11 q3a2
+1380.18 292.50 1.24 1185.76 q3a3
+1384.97 331.66 1.16 4495.96 q3a3
+ 730.13 844.13 3.66 360.31 q1a9
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035214_1e678.h5
+Image serial number: 23
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9501.521852
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9501.521852
+average_camera_length = 0.152001 m
+num_peaks = 23
+peak_resolution = 3.327423 nm^-1 or 3.005329 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 115.02 27.02 2.30 1285.60 q0a0
+ 43.50 59.94 2.10 2318.58 q0a0
+ 316.75 84.13 2.48 3808.96 q0a1
+ 343.43 106.05 2.48 1799.24 q0a1
+ 698.93 56.07 2.55 534.94 q1a1
+ 632.11 98.35 2.19 3842.62 q1a1
+ 839.50 56.02 2.09 1057.57 q2a0
+ 859.50 85.97 1.95 581.90 q2a0
+1006.87 70.94 2.27 1781.21 q2a1
+1292.50 123.14 1.82 1410.54 q3a0
+1443.15 71.85 2.40 828.30 q3a1
+ 221.17 338.50 1.16 1027.30 q0a3
+ 465.78 202.82 1.20 1838.34 q1a2
+ 804.50 324.78 0.49 11715.03 q2a2
+1212.29 249.67 0.92 7374.46 q3a2
+1333.03 254.36 1.17 3401.98 q3a2
+1252.50 265.75 0.89 1865.01 q3a2
+1219.26 274.34 0.79 8086.75 q3a2
+1291.50 339.89 0.68 1750.05 q3a2
+ 333.50 508.93 3.02 373.33 q0a5
+1082.96 1246.50 3.33 665.19 q2a13
+ 214.18 1453.89 2.44 1224.55 q0a15
+1298.61 1454.77 2.65 2236.69 q3a14
+End of peak list
+--- Begin crystal
+Cell parameters 6.17806 12.36425 16.74517 nm, 89.85682 90.41054 90.58139 deg
+astar = -0.0566044 +0.1417911 -0.0538043 nm^-1
+bstar = -0.0588600 -0.0015192 +0.0554546 nm^-1
+cstar = +0.0354521 +0.0291412 +0.0382161 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00135 nm^-1
+predict_refine/final_residual = 2.853602e-07
+predict_refine/det_shift x = -0.033 y = 0.012 mm
+diffraction_resolution_limit = 2.55 nm^-1 or 3.93 A
+num_reflections = 116
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -22 -36 -17 -337.46 157.04 163.00 47.66 1339.7 1039.9 q3a10
+ -20 -22 -23 -317.19 158.53 156.00 69.19 1305.3 403.7 q3a4
+ -20 -18 -29 -49.10 99.23 110.00 64.90 1266.3 496.5 q3a4
+ -19 -37 -5 89.10 110.33 128.00 53.10 1295.3 870.7 q3a8
+ -18 -40 0 186.65 102.23 108.00 48.15 1228.4 810.3 q3a8
+ -18 -18 -20 41.55 138.95 258.00 80.05 1399.5 464.2 q3a5
+ -18 -8 -38 180.94 108.10 151.00 68.06 1279.5 682.9 q3a6
+ -17 -35 0 195.80 118.65 133.00 50.80 1326.1 764.5 q3a8
+ -16 -24 -6 5.37 156.84 136.00 74.01 1534.7 751.8 q3a9
+ -16 -14 -18 -786.45 388.71 351.00 116.05 1481.9 526.5 q3a5
+ -16 -8 -28 107.38 120.45 143.00 88.62 1419.2 636.4 q3a7
+ -16 -2 -42 258.58 129.61 200.00 71.95 1112.4 1172.6 q2a13
+ -13 -15 -7 209.92 187.25 350.00 147.92 1450.7 57.8 q3a1
+ -13 -1 -30 7.13 235.82 290.00 140.32 1155.9 1329.6 q2a15
+ -13 5 -47 210.77 236.00 213.00 70.11 962.8 1231.3 q2a12
+ -12 -34 12 -211.07 218.36 235.00 64.67 1340.1 1256.8 q3a12
+ -12 -28 8 -100.05 236.52 310.00 107.45 1322.6 1342.1 q3a14
+ -12 -22 3 2311.79 363.30 750.00 128.41 1298.6 1454.0 q3a14
+ -12 -18 -1 -232.81 382.89 466.00 173.81 1514.0 119.0 q3a1
+ -12 -12 -8 -79.73 600.14 679.00 197.69 1397.5 82.4 q3a1
+ -12 2 -33 412.86 184.43 244.00 135.51 1090.3 1339.1 q2a15
+ -10 -6 -11 1424.83 259.61 1096.00 128.70 1291.4 123.1 q3a0
+ -9 -25 12 898.88 194.68 695.00 122.12 1428.7 1392.2 q3a15
+ -9 -7 -7 -179.93 194.85 215.00 108.79 1317.7 172.8 q3a0
+ -9 -5 -10 -152.26 190.61 302.00 120.86 1276.3 156.2 q3a0
+ -9 5 -29 -459.36 438.84 470.00 184.07 1054.4 1451.9 q2a15
+ -8 -16 6 740.00 325.81 380.00 107.43 1489.9 241.8 q3a3
+ -7 -37 23 235.41 151.42 205.00 57.75 1544.5 1197.6 q3a13
+ -7 -35 22 -174.69 181.81 146.00 67.69 1538.8 1235.2 q3a13
+ -6 -38 25 -87.05 149.72 114.00 59.45 167.8 725.4 q0a6
+ -6 -22 15 -111.73 627.04 692.00 213.53 1527.3 1444.8 q3a15
+ -6 4 -18 59.45 115.88 264.00 74.71 1055.9 314.5 q2a3
+ -6 14 -45 306.04 165.79 231.00 107.12 802.6 1426.0 q2a14
+ -6 16 -54 36.26 90.13 95.00 61.14 1068.6 787.7 q2a9
+ -5 -35 25 -6.18 154.54 198.00 74.58 222.5 697.9 q0a7
+ -5 -33 24 -298.27 153.83 172.00 81.47 259.4 704.3 q0a7
+ -5 -3 -4 1826.34 168.12 1450.00 58.61 1251.8 266.5 q3a2
+ -5 -1 -7 7308.27 283.59 4740.00 55.52 1211.1 250.0 q3a2
+ -5 19 -68 63.47 81.72 87.00 44.58 977.1 951.8 q2a11
+ -3 19 -54 -139.73 160.53 125.00 56.71 1154.2 857.8 q2a9
+ -3 21 -70 217.20 72.03 87.00 44.20 1018.8 1026.1 q2a11
+ -2 -28 25 -114.95 378.65 349.00 107.55 354.9 618.3 q0a7
+ -2 0 -3 2594.59 846.63 2033.00 195.36 1195.3 348.6 q3a2
+ -2 22 -72 153.62 75.01 73.00 42.38 1030.4 1076.7 q2a11
+ -1 -31 28 214.85 127.85 128.00 78.35 303.0 571.2 q0a7
+ -1 -17 18 593.55 156.47 557.00 116.05 104.7 134.2 q0a0
+ -1 15 -32 1589.91 308.96 708.00 176.25 1007.8 70.5 q2a1
+ -1 19 -46 -160.73 264.13 281.00 86.83 1103.4 443.5 q2a5
+ 0 -18 20 -100.41 244.51 299.00 131.21 142.4 119.0 q0a0
+ 0 12 -22 -177.13 158.94 183.00 107.53 926.0 166.6 q2a0
+ 0 14 -27 922.27 299.16 380.00 143.83 954.7 108.4 q2a0
+ 0 20 -47 -259.12 152.71 165.00 78.88 1070.6 463.8 q2a5
+ 1 -19 22 916.96 424.20 607.00 162.84 180.5 103.7 q0a0
+ 1 -5 8 156.01 115.07 300.00 59.39 99.0 325.3 q0a2
+ 1 7 -10 989.08 133.83 586.00 51.65 834.0 263.2 q2a2
+ 1 19 -40 52.73 297.58 323.00 106.45 1131.2 537.6 q2a5
+ 2 -42 36 -97.75 86.53 100.00 53.75 107.0 446.9 q0a4
+ 2 22 -50 -107.85 166.43 225.00 69.38 993.3 497.8 q2a5
+ 3 15 -24 670.09 214.92 543.00 127.32 859.1 86.6 q2a0
+ 3 23 -52 -60.81 156.85 166.00 57.51 951.2 511.5 q2a4
+ 4 -22 27 540.19 188.12 235.00 139.81 289.8 61.5 q0a1
+ 4 14 -20 67.04 160.81 203.00 113.35 810.8 115.6 q2a0
+ 4 16 -25 999.05 232.63 546.00 148.79 838.4 56.7 q2a0
+ 4 20 -37 698.50 294.23 422.00 97.50 1108.6 608.4 q2a7
+ 5 -21 27 3246.56 380.05 1296.00 152.44 316.6 83.4 q0a1
+ 5 -5 12 848.73 166.40 589.00 70.47 221.4 340.0 q0a3
+ 5 -1 7 1089.61 174.11 780.00 49.99 416.0 249.8 q1a2
+ 5 19 -32 -208.79 404.69 380.00 116.87 1149.0 664.8 q2a7
+ 6 -20 27 1591.89 333.28 668.00 153.51 343.3 105.3 q0a1
+ 6 -6 14 656.05 133.04 420.00 73.55 259.2 326.3 q0a3
+ 7 -47 41 -12.94 58.76 67.00 38.94 288.8 1088.5 q0a11
+ 7 1 6 1842.59 179.96 742.00 42.21 464.6 203.1 q1a2
+ 8 -24 31 -238.20 217.24 244.00 112.80 40.3 1449.0 q0a14
+ 8 26 -56 -30.20 82.30 112.00 52.13 797.5 599.7 q2a6
+ 9 -41 40 53.14 75.62 72.00 40.26 250.8 956.0 q0a11
+ 9 -9 19 1462.00 438.19 515.00 136.00 371.0 290.2 q0a3
+ 9 19 -27 -262.66 338.25 360.00 134.91 734.8 1354.2 q1a15
+ 9 23 -40 72.66 127.89 168.00 77.09 979.2 728.3 q2a7
+ 10 -46 42 21.60 151.30 123.00 39.60 185.0 1054.4 q0a10
+ 10 -20 29 751.12 328.65 403.00 123.88 123.8 1408.5 q0a14
+ 10 20 -29 130.73 140.13 371.00 116.03 717.9 1312.9 q1a15
+ 11 -45 42 -66.66 118.30 100.00 38.46 153.8 1028.3 q0a10
+ 11 9 -4 161.73 231.22 241.00 139.29 658.0 177.3 q1a1
+ 11 23 -38 -25.49 129.33 130.00 61.89 738.8 1211.3 q1a13
+ 12 -44 42 84.04 77.81 76.00 36.16 122.6 1002.2 q0a10
+ 12 -36 39 95.18 146.05 171.00 56.42 177.5 868.7 q0a8
+ 12 -30 36 68.10 85.55 133.00 59.10 214.5 754.9 q0a9
+ 12 -12 23 31.65 230.78 276.00 137.15 277.8 1396.3 q0a15
+ 12 22 -34 -86.82 81.61 97.00 63.14 687.7 1244.4 q1a13
+ 13 3 6 378.96 472.67 465.00 182.84 550.6 66.1 q1a0
+ 13 7 0 3712.21 453.71 1992.00 182.59 632.2 99.2 q1a1
+ 13 15 -15 433.46 498.71 508.00 144.22 561.5 1439.2 q1a14
+ 14 16 -17 -495.42 289.45 328.00 122.89 542.8 1398.9 q1a14
+ 15 -35 39 -17.45 91.82 99.00 52.05 75.9 828.9 q0a8
+ 15 -33 38 -75.99 102.30 90.00 56.39 90.9 790.0 q0a8
+ 15 -31 37 -130.40 109.88 107.00 56.60 105.6 751.9 q0a8
+ 15 9 -3 388.42 288.28 509.00 152.11 699.7 56.6 q1a1
+ 16 -16 27 146.43 130.96 156.00 75.17 240.7 1267.8 q0a13
+ 16 22 -33 255.86 127.61 136.00 52.96 565.0 1189.2 q1a12
+ 17 -33 38 12.12 103.31 97.00 53.88 17.6 774.0 q0a8
+ 17 -3 14 -75.61 308.59 453.00 110.01 701.2 653.5 q1a7
+ 17 1 9 75.39 245.47 325.00 116.01 732.9 573.9 q1a7
+ 18 -26 34 -14.36 138.55 106.00 61.76 78.5 1125.4 q0a12
+ 18 16 -17 -367.54 147.51 162.00 89.15 420.7 1339.9 q1a14
+ 19 -19 29 -281.46 131.27 119.00 71.66 216.8 1144.1 q0a13
+ 19 -5 16 -117.79 143.03 177.00 96.59 621.6 667.4 q1a7
+ 19 5 3 -254.48 183.89 209.00 97.28 704.0 489.5 q1a5
+ 20 2 7 352.75 128.48 155.00 78.25 646.3 538.8 q1a5
+ 22 -6 16 15.46 137.35 161.00 72.34 517.1 643.4 q1a6
+ 22 18 -24 166.25 79.88 115.00 49.75 512.3 777.2 q1a8
+ 23 -3 12 -46.06 94.61 113.00 67.06 508.4 565.8 q1a6
+ 24 4 2 20.59 123.62 123.00 63.21 536.5 421.3 q1a4
+ 24 12 -12 50.18 70.71 79.00 54.42 650.7 911.1 q1a9
+ 27 11 -13 52.00 70.71 89.00 48.00 597.7 996.3 q1a11
+ 28 6 -5 -180.05 117.34 144.00 50.45 709.8 1083.5 q1a11
+ 29 13 -20 -125.86 72.61 70.00 40.26 466.2 1046.4 q1a10
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035144_1bcf0.h5
+Image serial number: 22
+hit = 1
+indexed_by = none
+photon_energy_eV = 9508.566905
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9508.566905
+average_camera_length = 0.152001 m
+num_peaks = 20
+peak_resolution = 4.106821 nm^-1 or 2.434973 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 132.50 13.95 2.39 989.15 q0a0
+ 404.50 128.88 1.72 906.69 q1a0
+1265.08 63.52 2.09 2196.88 q3a0
+1188.45 119.35 1.77 5972.89 q3a0
+ 97.50 199.29 1.27 1877.51 q0a2
+ 173.50 201.33 1.43 1861.51 q0a2
+ 37.50 257.97 0.90 3594.74 q0a2
+ 71.89 355.89 0.42 92.65 q0a2
+ 311.07 309.50 1.66 1291.91 q0a3
+ 425.70 250.12 0.92 1724.27 q1a2
+ 476.94 329.96 0.57 2070.20 q1a2
+ 942.76 235.59 1.23 3822.01 q2a2
+ 805.50 303.21 0.60 603.22 q2a2
+ 909.50 329.01 0.74 744.01 q2a2
+1343.93 339.50 0.93 1402.96 q3a2
+1218.98 342.02 0.43 180.39 q3a2
+ 751.50 755.94 3.30 745.36 q1a9
+1310.04 798.96 4.11 102.29 q3a8
+ 741.50 1341.01 2.72 469.99 q1a15
+1150.50 1309.89 2.87 963.54 q2a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035215_1e732.h5
+Image serial number: 24
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9516.205073
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9516.205073
+average_camera_length = 0.152001 m
+num_peaks = 14
+peak_resolution = 4.110233 nm^-1 or 2.432952 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 129.64 139.34 1.77 1690.93 q0a0
+ 671.17 175.83 2.00 367.91 q1a1
+1031.32 107.27 2.18 1264.94 q2a1
+1446.50 36.98 2.56 632.25 q3a1
+1389.21 41.80 2.40 2452.45 q3a1
+ 131.90 221.58 1.23 3233.04 q0a2
+ 158.03 310.06 0.93 1112.32 q0a2
+ 559.50 311.66 0.96 2095.98 q1a2
+ 702.86 230.87 1.85 1405.56 q1a3
+1095.50 264.83 1.79 1218.86 q2a3
+1187.50 222.01 1.07 1144.77 q3a2
+1376.21 352.50 1.08 1645.62 q3a3
+ 355.16 468.16 3.02 452.09 q0a5
+1310.02 798.98 4.11 165.04 q3a8
+End of peak list
+--- Begin crystal
+Cell parameters 6.09408 12.35237 16.82624 nm, 89.73161 89.94176 90.54879 deg
+astar = +0.0714826 +0.0832176 -0.1220423 nm^-1
+bstar = +0.0334245 +0.0509686 +0.0532884 nm^-1
+cstar = +0.0475231 -0.0354945 +0.0037172 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00216 nm^-1
+predict_refine/final_residual = 3.723018e-07
+predict_refine/det_shift x = 0.002 y = -0.003 mm
+diffraction_resolution_limit = 2.18 nm^-1 or 4.59 A
+num_reflections = 192
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -11 -49 -21 108.59 76.63 68.00 38.25 983.0 997.1 q2a11
+ -11 -49 4 81.68 89.25 81.00 48.95 803.6 757.4 q2a8
+ -11 -47 -1 -64.18 82.31 93.00 50.29 873.2 787.3 q2a8
+ -11 -47 0 198.93 97.64 87.00 46.74 866.1 776.9 q2a8
+ -10 -44 -32 -165.55 121.44 85.00 34.87 1149.0 1046.4 q2a11
+ -10 -42 -29 411.18 122.77 170.00 37.49 1155.6 987.9 q2a11
+ -10 -42 12 262.45 96.73 193.00 59.87 890.3 1181.1 q2a12
+ -10 -40 8 77.69 205.63 249.00 63.64 869.7 1240.3 q2a12
+ -10 -38 -18 28.97 127.43 188.00 51.90 1132.9 854.4 q2a9
+ -9 -39 21 169.60 116.43 102.00 63.31 1013.0 1171.0 q2a13
+ -9 -37 18 -70.38 124.83 138.00 66.86 1000.6 1222.9 q2a13
+ -9 -35 14 415.73 201.26 199.00 70.82 979.1 1280.1 q2a13
+ -9 -33 -25 -150.52 126.17 106.00 64.56 1047.8 432.9 q2a5
+ -9 -33 8 477.36 205.32 287.00 103.77 942.3 1321.7 q2a14
+ -9 -31 -16 61.41 198.91 244.00 82.71 1156.5 397.1 q2a5
+ -9 -31 -2 325.41 162.41 256.00 105.42 865.7 1415.8 q2a14
+ -9 -31 -1 328.74 163.44 278.00 103.62 875.1 1409.1 q2a14
+ -9 -31 0 -11.07 170.18 258.00 111.25 884.5 1402.4 q2a14
+ -8 -36 27 326.79 129.38 233.00 67.47 1107.2 1181.6 q2a13
+ -8 -34 24 173.72 191.51 216.00 72.72 1093.6 1232.9 q2a13
+ -8 -32 -37 -54.18 230.11 238.00 57.06 946.0 541.0 q2a4
+ -8 -30 -33 -273.75 161.74 154.00 69.59 1006.4 536.9 q2a5
+ -8 -30 16 194.39 193.36 189.00 108.56 1049.1 1317.2 q2a15
+ -8 -28 -27 -221.67 213.53 240.00 81.67 1086.9 519.3 q2a5
+ -8 -26 -17 208.84 178.58 175.00 123.27 1066.6 8.2 q2a1
+ -8 -26 1 84.97 581.70 459.00 172.78 945.7 1469.1 q2a14
+ -7 -35 34 27.32 179.98 209.00 82.05 1300.8 723.6 q3a6
+ -7 -33 -48 -14.30 80.45 85.00 50.70 822.2 595.9 q2a6
+ -7 -31 -45 109.76 91.63 91.00 48.64 879.6 597.0 q2a6
+ -7 -29 -42 106.57 118.91 128.00 55.52 935.1 598.0 q2a6
+ -7 -27 -38 -286.57 134.85 147.00 73.09 995.5 592.0 q2a7
+ -7 -27 21 358.07 211.72 242.00 131.96 1129.4 1332.6 q2a15
+ -7 -25 -33 -102.51 116.48 126.00 78.52 1066.3 579.4 q2a7
+ -7 -25 16 403.67 345.10 393.00 155.33 1097.9 1392.2 q2a15
+ -7 -21 -13 402.40 311.22 407.00 166.40 1024.5 98.3 q2a1
+ -7 -21 -12 1046.37 467.17 1207.00 183.52 1031.1 107.4 q2a1
+ -7 -21 -11 103.06 261.39 319.00 161.75 1037.7 116.4 q2a1
+ -7 -21 -10 139.00 422.35 488.00 170.00 1044.3 125.5 q2a1
+ -7 -21 -9 271.30 323.61 459.00 161.95 1050.9 134.5 q2a1
+ -7 -21 -8 36.68 199.81 370.00 152.29 1057.4 143.5 q2a1
+ -7 -21 -7 55.52 403.38 472.00 171.23 1064.0 152.5 q2a1
+ -7 -21 -6 149.12 395.13 425.00 169.88 1070.6 161.5 q2a1
+ -7 -21 -5 827.18 268.99 515.00 164.26 1077.1 170.5 q2a1
+ -6 -36 42 -72.43 106.29 111.00 67.54 1232.4 636.8 q3a6
+ -6 -34 40 -330.57 124.25 125.00 75.46 1279.6 643.7 q3a6
+ -6 -30 35 -108.64 139.37 155.00 93.36 1373.6 666.3 q3a7
+ -6 -28 32 2.37 200.95 272.00 103.38 1423.4 681.8 q3a7
+ -6 -24 25 62.70 375.34 462.00 141.70 1525.7 720.6 q3a7
+ -6 -18 -21 62.58 359.04 534.00 176.15 929.4 60.2 q2a0
+ -6 -18 5 1246.69 334.96 943.00 100.82 1097.0 265.5 q2a3
+ -5 -35 47 -57.85 123.84 146.00 67.65 1217.3 564.4 q3a6
+ -5 -33 45 -26.86 89.89 117.00 68.26 1265.0 572.4 q3a6
+ -5 -19 -39 66.93 181.80 255.00 86.80 1081.9 713.3 q2a7
+ -5 -15 -25 -106.69 260.83 422.00 144.85 858.3 58.3 q2a0
+ -5 -15 8 -212.31 221.67 241.00 82.31 1071.2 324.3 q2a3
+ -4 -22 -53 -109.49 105.03 100.00 52.89 735.3 1157.0 q1a13
+ -4 -20 33 665.17 443.24 442.00 141.10 1542.1 594.8 q3a7
+ -4 -18 29 620.30 457.78 479.00 165.73 1284.9 13.3 q3a0
+ -4 -16 24 354.81 222.01 280.00 147.84 1252.3 70.8 q3a0
+ -4 -14 18 158.95 151.11 210.00 117.41 1211.6 133.4 q3a0
+ -4 -12 -26 375.77 258.64 394.00 128.05 807.6 83.5 q2a0
+ -3 -15 30 903.00 662.89 548.00 208.00 1325.9 53.2 q3a0
+ -3 -13 25 791.78 250.95 548.00 141.74 1292.9 109.9 q3a0
+ -3 -11 -35 -219.23 507.37 433.00 164.19 741.6 1426.4 q1a15
+ -3 -11 19 414.82 125.44 385.00 106.66 1252.0 171.8 q3a0
+ -3 -9 10 1012.41 154.37 491.00 57.09 1186.4 222.3 q3a2
+ -2 -30 57 -28.57 92.89 116.00 60.17 1241.4 408.4 q3a4
+ -2 -28 55 34.66 117.88 159.00 65.54 1289.2 419.5 q3a4
+ -2 -26 53 121.55 122.79 123.00 66.05 1335.5 430.2 q3a4
+ -2 -22 48 39.69 145.28 202.00 78.23 1428.0 460.2 q3a5
+ -2 -16 -55 -350.42 110.37 109.00 57.74 626.9 1214.7 q1a13
+ -2 -14 35 2562.57 252.82 1139.00 148.91 1388.6 41.9 q3a1
+ -2 -10 25 44.29 188.36 223.00 111.65 1324.4 155.1 q3a0
+ -2 -8 -35 -501.24 502.76 423.00 173.21 697.8 1460.9 q1a15
+ -2 -6 -25 -6.32 142.67 176.00 79.29 699.8 339.5 q1a3
+ -2 -6 9 1239.78 136.48 1031.00 51.84 1209.0 272.4 q3a2
+ -1 -23 54 156.28 103.09 115.00 70.08 1378.0 387.6 q3a5
+ -1 -19 49 -7.46 109.95 151.00 81.78 1471.6 418.6 q3a5
+ -1 -17 46 130.20 213.70 246.00 91.87 1519.8 438.0 q3a5
+ -1 -15 -59 131.03 128.35 105.00 48.77 571.0 1189.4 q1a12
+ -1 -13 39 838.00 189.65 468.00 139.71 1446.3 37.1 q3a1
+ -1 -11 35 -311.41 348.65 452.00 171.78 1420.2 88.3 q3a1
+ -1 -9 30 -165.35 194.10 247.00 141.21 1386.0 144.7 q3a1
+ -1 -5 17 48.82 174.39 193.00 63.74 1297.4 244.4 q3a2
+ -1 -3 -22 151.29 94.46 147.00 67.64 640.5 316.2 q1a3
+ -1 -3 6 -272.63 161.26 124.00 66.95 1214.2 334.7 q3a2
+ 0 -12 -59 258.88 137.11 178.00 51.12 524.7 1228.2 q1a12
+ 0 -4 23 868.52 163.54 1033.00 73.42 1366.5 228.9 q3a3
+ 0 -2 -31 1619.83 273.88 682.00 96.39 703.4 230.7 q1a3
+ 0 -2 15 -121.56 133.56 114.00 57.89 1310.9 300.7 q3a2
+ 0 0 -17 230.62 167.34 112.00 43.38 567.4 306.3 q1a2
+ 0 0 -16 1930.56 213.97 1674.00 50.27 558.7 312.8 q1a2
+ 1 -25 64 107.89 88.45 100.00 52.51 1465.4 987.4 q3a11
+ 1 -23 62 123.97 76.28 85.00 53.23 1478.8 939.8 q3a11
+ 1 -17 55 282.99 209.06 233.00 68.61 1525.7 825.8 q3a9
+ 1 -11 -62 42.64 82.22 92.00 49.13 471.7 1213.0 q1a12
+ 1 -9 42 73.78 242.35 317.00 135.37 1527.5 86.0 q3a1
+ 1 -7 -54 -195.37 138.28 149.00 85.99 500.4 1310.1 q1a14
+ 1 -7 38 4.33 504.62 454.00 185.20 1500.3 136.7 q3a1
+ 2 -28 70 -109.46 97.30 91.00 52.66 1387.7 1081.4 q3a11
+ 2 -14 55 -94.82 105.12 110.00 65.42 1493.7 775.3 q3a9
+ 2 -10 -65 134.09 84.75 105.00 46.71 417.4 1197.3 q1a12
+ 2 -8 45 198.28 212.92 255.00 109.28 1247.6 1465.4 q3a14
+ 2 0 -41 121.84 357.38 343.00 146.51 759.9 134.9 q1a1
+ 2 0 25 -89.46 145.78 180.00 78.38 1435.3 283.3 q3a3
+ 2 2 -33 585.35 200.08 609.00 142.22 670.4 175.0 q1a1
+ 2 2 17 1605.83 162.09 1241.00 68.92 1375.9 354.8 q3a3
+ 2 4 -20 627.23 129.27 344.00 46.02 543.8 218.6 q1a2
+ 2 4 4 785.15 125.14 617.00 57.24 71.2 335.8 q0a2
+ 3 -15 60 112.29 106.44 100.00 57.91 1426.3 816.6 q3a9
+ 3 -5 44 -329.03 277.24 321.00 125.27 1301.4 1443.3 q3a14
+ 4 -22 71 -313.57 205.30 284.00 50.17 1311.8 974.6 q3a10
+ 4 -18 67 -415.65 166.68 142.00 55.85 1343.4 905.8 q3a8
+ 4 -10 -73 -20.85 97.29 96.00 46.65 415.0 795.8 q1a8
+ 4 -6 50 87.62 131.65 192.00 91.99 1259.3 1371.1 q3a14
+ 4 2 32 -464.50 591.92 377.00 192.50 1540.2 285.0 q3a3
+ 4 4 25 -207.87 173.62 199.00 89.96 1487.4 351.1 q3a3
+ 4 8 1 1220.72 166.48 403.00 55.88 157.9 311.0 q0a2
+ 4 8 2 757.34 233.24 810.00 65.56 151.4 302.4 q0a2
+ 5 -21 73 213.26 84.52 79.00 43.14 1261.0 967.6 q3a10
+ 5 -9 -75 -11.71 116.02 127.00 45.91 407.8 847.1 q1a8
+ 5 1 -56 142.55 113.83 161.00 59.05 719.8 764.8 q1a9
+ 5 9 -25 1186.12 209.51 710.00 117.90 518.1 117.4 q1a0
+ 5 9 9 3126.40 215.63 1627.00 63.34 131.3 221.9 q0a2
+ 6 -12 66 -31.93 88.24 91.00 55.33 1287.9 791.5 q3a8
+ 6 2 -58 -31.76 87.98 87.00 55.36 716.6 811.7 q1a9
+ 6 2 42 248.56 149.70 161.00 109.74 1428.3 1375.2 q3a15
+ 6 4 37 52.48 260.28 392.00 144.48 1483.4 1413.3 q3a15
+ 6 6 -47 542.41 297.89 323.00 91.36 767.1 425.0 q1a5
+ 6 6 31 298.64 606.67 475.00 185.03 1543.8 1459.1 q3a15
+ 7 -13 70 49.78 80.32 89.00 51.02 1221.6 828.1 q3a8
+ 7 3 -60 -171.51 115.66 105.00 58.11 713.4 859.8 q1a9
+ 7 5 39 -164.73 167.47 206.00 126.40 1494.4 1371.3 q3a15
+ 7 7 -49 477.88 196.66 368.00 84.33 721.4 423.3 q1a5
+ 7 9 -42 -264.66 360.80 363.00 109.97 759.1 506.7 q1a5
+ 7 9 26 394.07 215.52 490.00 146.16 50.8 68.3 q0a0
+ 7 11 17 1750.00 231.22 1257.00 119.00 129.0 138.3 q0a0
+ 7 13 -17 -476.00 207.25 213.00 125.00 396.1 102.1 q1a0
+ 7 13 0 -339.69 142.26 123.00 75.18 256.1 248.0 q0a3
+ 7 13 1 -271.33 127.18 135.00 76.48 249.4 239.3 q0a3
+ 8 -10 69 -180.65 89.03 82.00 51.85 1198.9 766.6 q3a8
+ 8 8 -51 -54.45 106.52 145.00 70.23 674.7 421.6 q1a5
+ 8 10 -44 598.23 226.88 229.00 90.81 713.7 505.9 q1a5
+ 8 14 -22 132.78 473.49 589.00 172.82 420.3 39.3 q1a0
+ 9 -5 65 2.22 93.14 86.00 51.98 1218.3 1129.2 q3a12
+ 9 -3 -78 -76.69 76.93 68.00 36.69 462.9 1005.0 q1a10
+ 9 -3 62 -166.94 90.30 92.00 56.94 1267.2 1155.6 q3a12
+ 9 1 55 265.82 125.40 130.00 63.86 1365.1 1215.3 q3a13
+ 9 5 47 15.18 214.24 224.00 75.79 1467.6 1280.9 q3a13
+ 9 11 -46 152.65 130.68 173.00 73.88 667.3 505.0 q1a5
+ 9 13 -38 7.88 124.23 174.00 102.37 714.0 568.2 q1a7
+ 9 13 22 993.34 594.02 509.00 181.20 147.2 49.0 q0a0
+ 9 15 10 778.23 229.27 596.00 151.08 242.3 145.7 q0a1
+ 10 0 -76 52.72 95.22 113.00 40.48 527.9 1036.5 q1a10
+ 10 6 -64 -52.11 86.56 91.00 46.51 724.2 967.3 q1a11
+ 10 6 48 -106.74 112.14 169.00 68.77 1485.9 1244.9 q3a13
+ 10 16 -28 -531.94 426.55 421.00 137.12 742.5 693.8 q1a7
+ 10 16 12 -216.70 414.37 500.00 176.61 255.7 105.5 q0a1
+ 11 1 -77 110.47 116.93 128.00 41.73 533.1 1084.4 q1a10
+ 11 7 -65 -301.59 156.05 153.00 50.79 731.4 1011.7 q1a11
+ 11 7 49 301.22 122.15 195.00 62.98 1504.5 1208.2 q3a13
+ 11 11 39 -121.09 126.03 142.00 82.14 276.9 694.2 q0a7
+ 11 17 -30 257.20 149.78 337.00 105.63 697.2 695.6 q1a7
+ 11 17 14 100.76 232.25 257.00 147.21 269.4 64.6 q0a1
+ 12 8 -66 0.35 173.23 231.00 48.85 738.8 1057.1 q1a11
+ 12 8 50 -52.38 182.05 237.00 62.38 1523.4 1170.8 q3a13
+ 12 18 -31 403.65 217.23 358.00 93.78 658.3 706.7 q1a7
+ 13 15 -50 -221.71 159.90 189.00 62.32 504.9 541.4 q1a4
+ 13 15 34 145.54 110.72 129.00 68.85 265.0 586.1 q0a7
+ 13 19 -32 -93.50 180.30 247.00 89.50 618.6 718.1 q1a7
+ 14 18 27 -50.79 147.54 160.00 71.38 297.3 519.0 q0a5
+ 15 15 41 -210.70 132.81 110.00 57.30 152.0 598.8 q0a6
+ 15 19 27 139.31 105.37 132.00 65.93 271.0 490.0 q0a5
+ 16 16 41 -55.11 80.54 81.00 51.51 123.1 570.1 q0a6
+ 16 22 -32 193.01 142.68 125.00 65.35 365.1 1147.9 q0a13
+ 17 21 -42 -202.65 144.06 163.00 67.79 414.9 693.0 q1a6
+ 17 23 -31 -87.67 98.50 120.00 69.20 332.9 1120.6 q0a13
+ 17 23 15 -259.15 188.02 220.00 64.49 375.9 811.4 q0a9
+ 18 24 14 333.38 161.84 284.00 59.85 337.0 828.7 q0a9
+ 19 19 40 215.22 96.93 213.00 47.98 42.1 499.1 q0a4
+ 19 21 33 -44.35 83.10 87.00 50.15 108.3 429.0 q0a4
+ 19 25 12 -50.84 91.72 110.00 56.96 289.8 837.0 q0a9
+ 20 22 32 131.89 111.36 87.00 45.51 87.9 389.5 q0a4
+ 20 24 23 -98.77 96.92 94.00 45.46 354.8 938.7 q0a11
+ 20 26 10 -40.95 104.92 112.00 56.84 241.4 845.4 q0a9
+ 21 27 6 6.32 129.36 113.00 50.05 179.4 834.6 q0a8
+ 22 26 19 -43.47 87.73 82.00 43.32 256.5 959.2 q0a11
+ 22 28 -1 186.96 102.70 100.00 51.96 88.9 794.1 q0a8
+ 22 28 0 -24.76 88.42 92.00 54.12 96.8 803.9 q0a8
+ 24 26 25 77.79 79.53 71.00 40.47 247.7 1079.9 q0a11
+ 26 28 19 -89.84 65.71 63.00 36.89 126.7 1084.6 q0a10
+ 27 29 14 -115.78 75.57 81.00 35.98 44.9 1066.1 q0a10
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035124_1a01c.h5
+Image serial number: 25
+hit = 1
+indexed_by = none
+photon_energy_eV = 9508.557668
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9508.557668
+average_camera_length = 0.152001 m
+num_peaks = 20
+peak_resolution = 4.107329 nm^-1 or 2.434672 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 453.50 14.70 2.31 1491.38 q1a0
+ 407.66 91.07 1.92 22680.84 q1a0
+1068.25 75.08 2.41 1620.57 q2a1
+1127.77 89.79 2.54 963.39 q2a1
+1031.13 138.68 2.05 1988.66 q2a1
+1283.48 26.74 2.29 4530.65 q3a0
+1219.87 77.13 1.99 265.45 q3a0
+1206.50 113.80 1.80 1030.65 q3a0
+1543.78 127.50 2.52 1354.29 q3a1
+1431.50 171.28 1.97 846.81 q3a1
+ 34.50 337.83 0.46 692.12 q0a2
+ 402.24 242.20 0.96 1691.40 q1a2
+ 760.17 318.50 1.93 903.31 q1a3
+1509.46 353.41 1.77 4862.36 q3a3
+ 322.50 691.05 2.86 608.50 q0a7
+ 622.05 710.95 3.24 317.17 q1a7
+1491.66 633.02 2.84 1373.24 q3a7
+1309.95 799.05 4.11 -403.36 q3a8
+ 55.43 1459.77 2.90 1869.91 q0a14
+ 282.50 1460.05 2.27 1976.62 q0a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035039_160e9.h5
+Image serial number: 27
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9507.388553
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9507.388553
+average_camera_length = 0.152001 m
+num_peaks = 15
+peak_resolution = 2.453308 nm^-1 or 4.076129 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 912.02 52.50 2.17 1890.09 q2a0
+1019.50 98.12 2.19 2079.96 q2a1
+1317.38 48.55 2.23 -998.09 q3a0
+1244.50 102.01 1.88 857.29 q3a0
+1481.77 87.50 2.45 1111.48 q3a1
+1460.10 120.42 2.26 1228.64 q3a1
+ 8.44 283.95 0.76 17705.44 q0a2
+ 146.24 316.23 0.86 1122.16 q0a2
+ 114.18 328.70 0.68 845.31 q0a2
+ 460.83 222.57 1.09 4062.79 q1a2
+ 524.82 241.18 1.12 2532.39 q1a2
+ 486.11 287.25 0.80 9469.26 q1a2
+ 904.62 288.66 0.88 3576.00 q2a2
+1232.50 208.73 1.16 940.91 q3a2
+1035.94 1467.72 2.27 5087.56 q2a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.14083 12.17293 16.89551 nm, 89.40108 90.68344 90.14752 deg
+astar = +0.1212853 +0.0973003 -0.0484231 nm^-1
+bstar = -0.0545908 +0.0568526 -0.0231722 nm^-1
+cstar = +0.0031414 +0.0241206 +0.0539662 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00189 nm^-1
+predict_refine/final_residual = 4.310747e-07
+predict_refine/det_shift x = -0.055 y = -0.030 mm
+diffraction_resolution_limit = 2.26 nm^-1 or 4.43 A
+num_reflections = 176
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -23 15 -40 -107.91 83.65 87.00 57.71 1048.2 1071.7 q2a11
+ -22 -2 -45 -30.15 91.62 114.00 70.35 841.9 863.8 q2a8
+ -22 8 -39 -15.46 97.02 111.00 59.66 1002.5 941.5 q2a11
+ -21 -3 -42 154.70 102.15 116.00 70.70 881.4 812.0 q2a8
+ -21 5 -37 -8.61 118.46 164.00 73.01 1008.1 894.1 q2a9
+ -21 23 -32 306.50 116.05 116.00 64.50 797.6 415.7 q2a4
+ -20 -2 -38 -22.75 139.46 141.00 72.75 948.7 784.0 q2a8
+ -20 22 -29 15.66 81.03 109.00 65.54 854.0 446.5 q2a4
+ -19 -11 -42 97.27 136.55 169.00 79.53 824.1 1149.6 q2a12
+ -19 1 -33 -206.99 138.45 129.00 75.39 1038.8 778.3 q2a9
+ -19 7 -30 12.48 268.25 326.00 83.72 1124.4 841.5 q2a9
+ -19 25 -26 -275.05 105.57 103.00 68.45 851.9 519.7 q2a4
+ -19 27 -26 -367.57 173.88 165.00 75.17 823.2 542.0 q2a4
+ -18 18 -24 -238.67 174.33 183.00 91.54 977.9 476.5 q2a5
+ -17 31 -21 49.23 115.34 114.00 68.97 841.9 630.8 q2a6
+ -16 10 -21 -10.02 360.17 407.00 126.22 1135.8 450.0 q2a5
+ -16 14 -20 -86.34 328.55 316.00 119.54 1090.5 497.5 q2a5
+ -16 34 -19 -160.81 96.45 110.00 71.81 833.2 696.6 q2a6
+ -15 -19 -38 -428.41 144.80 138.00 93.21 1023.5 1177.6 q2a13
+ -15 -5 -26 -586.62 358.36 393.00 173.62 894.3 1393.6 q2a14
+ -14 -4 -23 64.58 423.98 428.00 193.82 913.0 1442.9 q2a14
+ -14 6 -18 -4.58 332.20 472.00 194.18 1078.3 42.5 q2a1
+ -13 -15 -29 -4.14 209.20 230.00 149.74 1042.1 1304.4 q2a15
+ -12 6 -14 2195.85 443.62 1034.00 241.35 1019.3 97.2 q2a1
+ -12 12 -12 -443.98 610.34 573.00 244.78 949.4 35.5 q2a0
+ -12 36 -11 249.44 122.25 261.00 72.56 697.6 1177.8 q1a13
+ -11 -13 -23 1212.94 454.21 589.00 219.06 1075.4 1404.3 q2a15
+ -11 -9 -20 5421.48 624.08 2584.00 249.72 1037.4 1465.2 q2a15
+ -11 13 -10 2140.15 653.89 1019.00 253.65 910.7 51.5 q2a0
+ -10 -4 -15 -75.01 333.47 459.00 147.61 1092.0 219.2 q2a3
+ -9 -7 -15 190.70 391.28 418.00 156.70 1104.8 272.6 q2a3
+ -9 41 -7 165.50 146.26 135.00 69.50 562.5 1194.7 q1a12
+ -8 -28 -32 250.00 160.73 219.00 119.00 1402.9 621.2 q3a7
+ -8 -8 -14 -106.79 304.89 307.00 125.59 1091.7 306.2 q2a3
+ -8 46 -7 -74.54 102.15 100.00 63.34 476.0 1146.3 q1a12
+ -7 -17 -19 612.83 481.27 520.00 229.57 1196.5 50.3 q3a0
+ -7 41 -4 -180.70 165.91 172.00 78.30 511.3 1252.4 q1a12
+ -6 -38 -42 84.80 120.11 161.00 85.80 1237.9 483.1 q3a4
+ -6 -34 -36 -159.94 242.15 278.00 97.94 1340.1 532.9 q3a4
+ -6 -26 -26 -159.34 436.84 551.00 174.54 1506.1 594.0 q3a7
+ -6 -24 -24 132.99 537.90 478.00 198.61 1541.6 614.7 q3a7
+ -6 -8 -11 162.76 125.78 319.00 93.64 1040.3 353.3 q2a3
+ -6 30 -1 -253.73 352.07 395.00 165.53 612.4 1396.7 q1a15
+ -5 -41 -45 -135.10 123.59 143.00 84.90 1189.7 418.0 q3a4
+ -5 -17 -16 907.01 373.69 722.00 180.39 1243.6 103.1 q3a0
+ -5 -13 -13 834.20 179.71 483.00 139.20 1205.0 161.7 q3a0
+ -5 1 -5 3590.73 225.05 2617.00 75.47 904.4 290.0 q2a2
+ -5 33 0 307.64 343.35 424.00 149.76 556.9 1385.2 q1a14
+ -4 -22 -19 -263.06 736.55 1126.00 297.06 1316.4 49.5 q3a0
+ -4 18 1 550.74 200.77 414.00 101.86 687.3 294.3 q1a3
+ -4 40 0 -332.52 162.91 167.00 103.72 449.9 1319.2 q1a14
+ -3 -19 -15 919.59 249.54 592.00 172.21 1309.7 122.4 q3a0
+ -3 -11 -9 1074.65 177.39 809.00 74.15 1232.2 209.2 q3a2
+ -3 5 -1 696.35 161.69 333.00 69.85 810.3 297.1 q2a2
+ -3 17 2 -94.79 156.82 226.00 91.59 653.3 282.9 q1a3
+ -2 -44 -45 269.84 168.11 228.00 71.96 1513.3 1068.6 q3a11
+ -2 -32 -27 636.62 273.81 405.00 124.38 1502.7 461.7 q3a5
+ -2 -18 -13 169.10 260.60 352.00 148.10 1322.8 161.3 q3a0
+ -2 -8 -6 106.88 144.32 175.00 72.12 1226.0 272.0 q3a2
+ -2 36 3 224.01 212.71 240.00 131.39 450.7 1422.7 q1a14
+ -1 -33 -27 405.45 250.12 397.00 125.95 1509.0 426.1 q3a5
+ 0 -34 -27 311.70 211.32 242.00 116.70 1515.3 390.3 q3a5
+ 0 -28 -20 -58.91 307.16 410.00 194.71 1469.9 47.2 q3a1
+ 0 -26 -18 573.67 314.99 467.00 209.93 1448.3 81.4 q3a1
+ 0 -24 -16 881.04 472.13 552.00 229.16 1427.0 114.9 q3a1
+ 0 -8 -4 291.16 123.86 284.00 74.04 1271.0 316.2 q3a2
+ 0 18 5 2185.84 284.57 906.00 73.65 594.9 205.3 q1a3
+ 1 -47 -46 8.11 148.65 220.00 67.49 1387.7 1064.0 q3a11
+ 1 -27 -18 1070.44 371.91 894.00 218.56 1482.6 87.6 q3a1
+ 1 -25 -16 1196.95 656.91 1070.00 264.45 1461.0 121.2 q3a1
+ 1 -11 -5 78.16 196.44 223.00 76.04 1322.6 298.1 q3a2
+ 1 9 4 9552.61 323.87 3972.00 52.99 485.0 287.8 q1a2
+ 1 13 5 2532.39 208.67 1191.00 57.01 524.5 241.3 q1a2
+ 1 33 6 374.66 261.96 352.00 177.54 735.8 34.9 q1a1
+ 1 47 3 2.77 86.86 102.00 70.03 671.3 860.8 q1a9
+ 2 -42 -36 -67.11 107.12 128.00 78.51 1444.8 914.6 q3a9
+ 2 -40 -33 -117.04 211.80 307.00 81.84 1474.2 865.3 q3a9
+ 2 -28 -18 -140.26 395.44 485.00 210.86 1517.2 93.9 q3a1
+ 2 -26 -16 1910.20 529.29 554.00 240.20 1495.2 127.6 q3a1
+ 2 -18 -9 436.29 158.63 565.00 97.91 1411.8 223.3 q3a3
+ 2 10 5 50.61 119.86 108.00 54.99 472.4 255.1 q1a2
+ 2 22 7 100.24 268.27 368.00 173.36 590.4 143.7 q1a1
+ 2 30 7 82.77 202.90 263.00 188.03 677.6 48.8 q1a1
+ 2 60 -2 109.55 72.27 87.00 53.05 485.4 1056.0 q1a10
+ 3 -45 -40 -305.43 124.33 133.00 71.83 1370.9 943.1 q3a11
+ 3 -19 -9 71.45 138.22 171.00 105.95 1445.1 230.1 q3a3
+ 3 -15 -6 1335.07 202.93 1372.00 97.33 1404.5 286.8 q3a3
+ 3 -5 0 -111.49 171.91 164.00 77.89 31.6 304.2 q0a2
+ 3 -3 1 442.71 121.36 136.00 68.09 56.5 323.5 q0a2
+ 3 -1 2 256.41 118.94 248.00 75.79 81.4 342.8 q0a2
+ 3 11 6 3861.71 237.34 2262.00 55.09 459.8 222.2 q1a2
+ 3 51 3 -219.79 138.02 118.00 66.59 661.9 940.2 q1a11
+ 4 -42 -34 -158.14 120.15 126.00 76.74 1393.8 862.6 q3a9
+ 4 -40 -31 -289.26 144.20 166.00 78.86 1424.0 814.3 q3a9
+ 4 -34 -23 324.02 188.92 251.00 121.78 1189.0 1406.5 q3a14
+ 4 -16 -6 934.04 167.21 720.00 96.16 1437.6 293.8 q3a3
+ 4 0 3 885.38 198.55 508.00 77.01 113.8 330.0 q0a2
+ 4 34 8 -349.58 472.28 358.00 152.18 760.5 477.0 q1a5
+ 4 40 7 -329.76 138.27 133.00 97.36 684.0 403.3 q1a5
+ 5 -45 -38 19.34 185.71 174.00 74.46 1321.0 916.8 q3a8
+ 5 -23 -11 954.24 722.62 502.00 302.36 1534.3 212.1 q3a3
+ 5 1 4 1027.74 200.25 504.00 74.86 146.3 317.1 q0a2
+ 5 15 8 253.68 156.26 384.00 126.92 454.0 162.5 q1a0
+ 5 25 9 1954.56 583.12 611.00 244.44 556.5 43.2 q1a0
+ 5 49 5 -223.36 163.69 196.00 68.76 741.8 961.4 q1a11
+ 6 -28 -15 844.76 420.14 461.00 176.64 1339.8 1429.8 q3a14
+ 6 2 5 202.77 219.67 237.00 72.03 179.0 304.1 q0a2
+ 6 18 9 -331.84 211.04 236.00 164.04 461.2 105.8 q1a0
+ 7 -17 -5 105.85 426.08 394.00 171.35 1518.0 340.7 q3a3
+ 7 1 5 170.80 252.62 333.00 81.13 186.9 271.7 q0a2
+ 7 15 9 565.35 260.38 367.00 150.85 408.4 120.6 q1a0
+ 8 -28 -14 179.56 268.55 317.00 164.44 1377.3 1379.8 q3a15
+ 8 -10 0 -26.90 220.80 296.00 135.10 68.2 169.3 q0a0
+ 8 20 10 1367.99 380.19 559.00 205.61 435.7 39.3 q1a0
+ 8 44 8 151.55 231.44 281.00 88.05 534.7 446.6 q1a4
+ 9 -23 -9 -400.12 415.88 441.00 212.12 1476.0 1412.3 q3a15
+ 9 -9 1 -41.60 157.56 199.00 145.40 101.1 155.6 q0a0
+ 9 -7 2 -440.39 186.48 241.00 142.99 126.5 175.3 q0a0
+ 9 41 9 72.27 254.72 255.00 90.53 552.4 508.8 q1a4
+ 9 45 8 100.79 147.78 210.00 81.41 494.7 457.1 q1a4
+ 11 -27 -12 185.73 173.51 207.00 133.47 1452.5 1314.3 q3a15
+ 11 -13 -1 2231.76 310.92 579.00 190.64 86.5 66.1 q0a0
+ 11 3 7 -419.85 328.96 299.00 128.65 289.1 198.0 q0a3
+ 11 23 11 -1241.61 577.66 428.00 189.01 741.4 731.6 q1a7
+ 11 29 11 -91.38 181.73 228.00 130.38 664.5 667.9 q1a7
+ 11 43 9 19.94 128.27 218.00 81.06 472.8 531.3 q1a4
+ 12 -32 -17 42.05 202.65 210.00 89.55 1386.2 1250.4 q3a13
+ 12 -10 1 -108.60 598.55 509.00 236.40 145.9 72.0 q0a0
+ 12 0 6 99.46 307.49 552.00 202.34 271.4 172.1 q0a1
+ 12 32 11 80.18 179.64 236.00 118.42 601.2 658.8 q1a7
+ 13 -33 -18 143.20 118.76 137.00 77.20 1386.9 1208.1 q3a13
+ 13 13 10 -83.14 463.62 465.00 216.74 268.1 1426.3 q0a15
+ 13 33 11 418.62 303.60 304.00 97.38 566.4 671.7 q1a6
+ 14 20 11 -100.99 268.28 358.00 173.39 314.1 1316.0 q0a15
+ 14 40 10 169.19 127.33 136.00 81.81 440.2 615.0 q1a6
+ 15 -33 -18 15.19 109.41 118.00 70.81 1423.6 1148.5 q3a13
+ 15 -15 -2 -465.04 440.45 401.00 148.84 358.3 604.3 q0a7
+ 15 13 10 -28.35 364.53 524.00 182.15 219.0 1383.2 q0a15
+ 15 33 11 33.50 200.09 234.00 98.50 516.9 720.7 q1a6
+ 16 -32 -17 -78.84 98.55 112.00 70.04 1459.8 1132.1 q3a13
+ 16 0 6 408.94 288.37 473.00 183.06 352.0 71.3 q0a1
+ 17 -29 -14 -42.84 124.37 123.00 72.04 1530.3 1143.5 q3a13
+ 17 3 7 -458.85 296.40 323.00 159.65 70.7 1467.9 q0a14
+ 17 23 11 -42.67 155.04 165.00 95.54 269.7 1234.1 q0a13
+ 17 29 11 -17.85 116.32 152.00 90.65 332.9 1150.9 q0a13
+ 19 -23 -9 55.15 165.91 148.00 78.65 149.4 646.1 q0a6
+ 19 -9 1 211.45 175.36 199.00 96.95 312.9 471.6 q0a5
+ 19 -7 2 -87.35 246.12 281.00 110.15 334.5 444.9 q0a5
+ 19 -3 4 -64.55 281.72 298.00 110.95 377.7 391.6 q0a5
+ 19 17 10 98.23 286.35 334.00 101.97 158.8 1267.7 q0a12
+ 20 -28 -14 285.75 115.53 138.00 66.25 48.0 708.6 q0a6
+ 20 -26 -12 129.99 84.97 141.00 67.61 77.0 675.0 q0a6
+ 20 -10 0 94.02 150.80 195.00 87.78 272.2 465.1 q0a5
+ 20 0 5 1045.14 259.45 319.00 92.26 378.6 754.4 q0a9
+ 20 20 10 -86.62 180.11 165.00 85.62 162.3 1202.4 q0a12
+ 21 -17 -5 -29.15 148.06 194.00 73.35 161.5 544.1 q0a4
+ 21 -11 -1 -25.95 110.41 155.00 84.55 230.5 458.4 q0a5
+ 21 1 5 -335.89 205.51 224.00 91.49 343.4 772.8 q0a9
+ 22 -26 -13 -296.09 128.05 111.00 67.43 7.7 637.9 q0a6
+ 23 -17 -6 112.01 106.12 118.00 69.39 95.7 503.7 q0a4
+ 23 -11 -2 130.89 131.34 124.00 67.51 170.0 416.5 q0a4
+ 23 1 4 -110.01 89.27 110.00 76.61 298.4 832.9 q0a9
+ 23 15 8 86.25 132.22 137.00 79.75 25.2 1197.3 q0a12
+ 24 -20 -9 -65.69 140.19 133.00 68.69 20.0 529.2 q0a4
+ 24 -16 -6 2.82 94.09 114.00 65.58 73.4 468.5 q0a4
+ 24 -10 -2 -188.11 117.99 116.00 69.51 148.8 380.8 q0a4
+ 24 0 3 194.60 94.00 231.00 71.60 289.1 875.4 q0a9
+ 25 -15 -6 -106.43 113.09 123.00 63.83 50.6 432.5 q0a4
+ 25 -7 -1 -31.39 139.27 192.00 65.99 365.1 960.9 q0a11
+ 26 -14 -6 -138.40 102.80 111.00 62.60 27.3 395.7 q0a4
+ 26 10 5 -308.64 130.49 152.00 75.24 101.1 832.0 q0a8
+ 27 9 4 133.24 99.47 125.00 67.36 88.8 876.4 q0a8
+ 28 -8 -4 28.72 78.06 96.00 56.48 310.0 1083.3 q0a11
+ 29 5 1 29.64 78.23 120.00 52.76 93.6 966.1 q0a10
+ 30 8 1 99.79 99.48 122.00 54.41 19.2 970.4 q0a10
+ 31 5 -1 -94.43 96.44 108.00 50.83 35.9 1045.3 q0a10
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035050_17001.h5
+Image serial number: 19
+hit = 1
+indexed_by = none
+photon_energy_eV = 9505.628995
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998596
+hdf5/LCLS/photon_energy_eV = 9505.628995
+average_camera_length = 0.152001 m
+num_peaks = 135
+peak_resolution = 4.109392 nm^-1 or 2.433450 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 52.29 12.20 2.34 1412.09 q0a0
+ 73.76 23.78 2.29 1684.57 q0a0
+ 159.64 35.52 2.32 1679.88 q0a0
+ 147.47 95.22 2.01 1619.01 q0a0
+ 99.50 125.06 1.80 1098.11 q0a0
+ 120.74 130.03 1.80 1526.54 q0a0
+ 100.50 169.12 1.57 1053.46 q0a0
+ 229.64 75.28 2.28 4562.60 q0a1
+ 258.26 97.20 2.26 2420.09 q0a1
+ 300.28 109.28 2.33 3363.34 q0a1
+ 285.68 119.54 2.24 5801.53 q0a1
+ 218.95 153.80 1.90 865.06 q0a1
+ 568.17 33.54 2.34 2139.51 q1a0
+ 423.80 58.97 2.08 1943.68 q1a0
+ 460.50 140.00 1.67 1394.77 q1a0
+ 617.57 58.03 2.33 3665.80 q1a1
+ 748.79 67.21 2.66 1217.35 q1a1
+ 630.36 131.20 2.04 2168.60 q1a1
+ 638.03 133.81 2.05 3901.06 q1a1
+ 753.47 143.11 2.41 2371.40 q1a1
+ 656.41 150.14 2.04 1721.68 q1a1
+ 925.50 13.15 2.38 642.70 q2a0
+ 874.01 52.52 2.13 6302.01 q2a0
+ 951.24 129.97 1.86 729.69 q2a0
+ 900.79 148.92 1.67 2190.26 q2a0
+1076.27 66.73 2.47 1949.75 q2a1
+1060.75 85.25 2.35 128.68 q2a1
+1009.37 112.84 2.09 2456.35 q2a1
+1020.95 111.74 2.13 966.46 q2a1
+1244.92 74.83 2.02 637.41 q3a0
+1373.62 135.48 1.94 3780.02 q3a1
+ 111.50 194.85 1.31 1004.50 q0a2
+ 132.77 195.50 1.35 1338.76 q0a2
+ 10.85 202.13 1.20 2285.29 q0a2
+ 15.07 221.64 1.09 8379.94 q0a2
+ 70.85 238.08 1.03 2526.92 q0a2
+ 103.50 255.04 1.00 1402.93 q0a2
+ 155.70 271.21 1.07 8025.76 q0a2
+ 176.74 281.50 1.11 924.16 q0a2
+ 89.77 290.92 0.79 1485.60 q0a2
+ 179.91 323.50 0.98 1730.49 q0a2
+ 162.79 336.21 0.87 201.89 q0a2
+ 140.93 344.31 0.74 957.26 q0a2
+ 72.27 344.50 0.48 849.56 q0a2
+ 54.05 348.50 0.42 1538.90 q0a2
+ 156.99 352.79 0.79 17963.20 q0a2
+ 134.78 359.92 0.67 1710.82 q0a2
+ 285.17 221.50 1.77 1122.96 q0a3
+ 220.19 243.50 1.43 1034.61 q0a3
+ 370.81 259.83 2.05 1806.84 q0a3
+ 210.03 268.50 1.30 595.31 q0a3
+ 283.80 292.50 1.57 904.29 q0a3
+ 234.37 304.68 1.30 1789.60 q0a3
+ 260.88 349.50 1.34 1224.29 q0a3
+ 532.83 209.50 1.29 1468.11 q1a2
+ 431.50 215.84 1.10 5273.59 q1a2
+ 464.47 217.64 1.12 6296.56 q1a2
+ 487.50 228.05 1.10 718.76 q1a2
+ 428.38 235.65 0.99 6069.30 q1a2
+ 498.11 248.50 1.02 988.88 q1a2
+ 519.50 267.79 0.98 926.56 q1a2
+ 437.57 275.76 0.78 16121.80 q1a2
+ 421.66 277.58 0.76 12189.05 q1a2
+ 561.79 280.50 1.08 1273.48 q1a2
+ 413.03 289.63 0.70 3865.11 q1a2
+ 412.70 295.16 0.67 -322.04 q1a2
+ 404.74 297.41 0.66 3428.48 q1a2
+ 475.50 298.08 0.72 752.32 q1a2
+ 544.36 301.27 0.93 1289.52 q1a2
+ 485.50 310.76 0.68 940.71 q1a2
+ 510.11 314.50 0.75 458.78 q1a2
+ 442.50 317.86 0.56 3983.85 q1a2
+ 422.50 322.96 0.51 1123.50 q1a2
+ 552.20 327.50 0.87 621.39 q1a2
+ 509.59 339.92 0.65 8392.72 q1a2
+ 481.50 342.20 0.53 2270.23 q1a2
+ 407.72 342.70 0.41 7279.97 q1a2
+ 489.23 351.78 0.52 4248.84 q1a2
+ 483.81 360.50 0.47 292.78 q1a2
+ 541.88 360.86 0.74 2514.29 q1a2
+ 683.27 207.73 1.83 999.00 q1a3
+ 649.12 331.50 1.35 855.30 q1a3
+ 790.50 194.95 1.20 1300.38 q2a2
+ 808.50 220.94 1.05 19312.50 q2a2
+ 844.45 220.12 1.08 7255.60 q2a2
+ 784.50 224.24 1.04 2435.61 q2a2
+ 818.83 223.50 1.04 1192.96 q2a2
+ 793.13 225.50 1.03 154.72 q2a2
+ 881.50 239.14 1.04 1904.38 q2a2
+ 891.93 241.50 1.06 22426.36 q2a2
+ 837.04 248.50 0.92 2751.84 q2a2
+ 876.66 260.24 0.93 5201.84 q2a2
+ 808.51 271.27 0.78 15126.57 q2a2
+ 851.11 281.32 0.77 6501.29 q2a2
+ 808.50 291.20 0.67 1018.31 q2a2
+ 809.50 299.08 0.63 1157.29 q2a2
+ 887.14 305.14 0.75 969.44 q2a2
+ 940.02 323.50 0.89 917.95 q2a2
+ 833.29 329.50 0.49 5048.60 q2a2
+ 890.11 338.93 0.62 7404.06 q2a2
+ 923.19 350.72 0.74 1521.46 q2a2
+ 950.51 352.75 0.87 4506.65 q2a2
+ 867.37 354.18 0.47 12247.84 q2a2
+ 923.03 358.50 0.72 -15.61 q2a2
+ 880.04 361.50 0.50 1377.94 q2a2
+1089.31 228.69 1.85 2240.52 q2a3
+ 979.34 277.04 1.23 2558.41 q2a3
+1068.83 298.50 1.58 474.44 q2a3
+1146.48 304.00 1.95 4568.71 q2a3
+ 981.91 345.54 1.06 7769.89 q2a3
+1308.86 209.50 1.30 862.24 q3a2
+1316.50 220.21 1.27 1677.51 q3a2
+1227.24 239.26 0.99 2615.46 q3a2
+1238.50 246.06 0.97 1097.54 q3a2
+1224.92 263.50 0.86 2792.26 q3a2
+1187.50 266.52 0.82 8852.90 q3a2
+1303.50 272.05 1.00 2197.90 q3a2
+1186.12 272.50 0.79 -4020.85 q3a2
+1183.50 275.01 0.78 895.93 q3a2
+1289.13 274.50 0.94 1108.84 q3a2
+1247.50 291.96 0.75 812.75 q3a2
+1331.50 307.04 0.97 1982.27 q3a2
+1201.01 313.56 0.57 7555.35 q3a2
+1210.12 316.50 0.56 746.44 q3a2
+1322.83 326.50 0.87 1190.54 q3a2
+1297.50 329.20 0.75 1051.68 q3a2
+1468.82 260.50 1.73 627.75 q3a3
+1474.36 276.96 1.72 6100.14 q3a3
+1218.07 540.07 4.11 710.19 q3a4
+1326.38 844.67 4.17 16606.11 q3a8
+1512.00 956.50 4.12 491.39 q3a11
+ 658.72 1426.09 2.43 5347.90 q1a15
+1479.50 1397.11 2.51 1035.55 q3a15
+1508.15 1414.14 2.39 1741.05 q3a15
+1432.55 1470.48 2.24 2511.10 q3a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035112_18fc0.h5
+Image serial number: 29
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9503.441602
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9503.441602
+average_camera_length = 0.152001 m
+num_peaks = 24
+peak_resolution = 4.104949 nm^-1 or 2.436084 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 132.96 27.04 2.32 459.40 q0a0
+ 133.80 58.98 2.17 1041.54 q0a0
+ 668.75 89.13 2.33 2711.10 q1a1
+ 992.25 22.00 2.45 13188.61 q2a1
+1105.77 73.99 2.53 1761.04 q2a1
+ 999.17 78.67 2.21 9435.43 q2a1
+1055.26 104.48 2.26 4663.17 q2a1
+1219.56 43.54 2.16 3832.84 q3a0
+1386.27 119.05 2.05 1517.93 q3a1
+ 46.50 228.77 1.06 1944.09 q0a2
+ 110.98 303.26 0.78 2207.06 q0a2
+ 314.18 198.60 1.96 3721.04 q0a3
+ 240.99 293.50 1.36 625.79 q0a3
+ 547.03 243.32 1.17 2686.40 q1a2
+ 504.50 265.25 0.95 1454.41 q1a2
+ 677.29 201.37 1.83 1781.95 q1a3
+ 820.93 302.50 0.61 2013.68 q2a2
+ 906.83 326.05 0.74 7047.35 q2a2
+1245.64 306.16 0.67 2260.69 q3a2
+1043.06 649.50 3.09 558.93 q2a7
+1309.98 799.02 4.11 74.30 q3a8
+ 282.24 1392.17 2.58 3380.39 q0a15
+ 922.67 1368.72 2.95 874.94 q2a14
+1434.87 1412.05 2.50 1989.14 q3a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.17015 12.25605 16.99923 nm, 90.13268 90.84869 90.21061 deg
+astar = +0.0629968 -0.1477326 +0.0218968 nm^-1
+bstar = -0.0723753 -0.0336928 -0.0168539 nm^-1
+cstar = +0.0145744 -0.0031770 -0.0569104 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00219 nm^-1
+predict_refine/final_residual = 6.251109e-07
+predict_refine/det_shift x = 0.009 y = -0.011 mm
+diffraction_resolution_limit = 2.59 nm^-1 or 3.86 A
+num_reflections = 187
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -28 10 11 25.36 81.70 85.00 48.24 659.5 1078.0 q1a11
+ -27 15 9 -7.09 100.58 94.00 45.29 591.9 1003.2 q1a11
+ -27 23 9 38.91 74.64 65.00 36.29 452.5 959.1 q1a10
+ -26 12 8 110.91 93.59 76.00 46.29 660.6 978.7 q1a11
+ -25 11 7 42.47 68.83 79.00 45.73 693.8 944.6 q1a11
+ -24 -2 9 582.29 120.61 169.00 58.91 508.1 479.9 q1a4
+ -23 -15 14 -152.71 111.22 125.00 65.91 446.1 676.2 q1a6
+ -23 -5 9 -18.31 134.78 157.00 64.31 525.4 540.2 q1a4
+ -22 30 4 233.90 100.13 86.00 42.90 427.0 750.2 q1a8
+ -21 -17 13 -178.68 171.60 225.00 74.08 508.2 729.3 q1a6
+ -21 1 5 -174.71 137.67 188.00 76.91 637.8 472.3 q1a5
+ -21 5 4 42.84 130.54 151.00 71.96 663.6 411.0 q1a5
+ -20 -20 14 -111.76 120.46 127.00 69.36 358.3 1147.8 q0a13
+ -20 -2 5 -217.30 168.50 183.00 83.70 653.1 530.7 q1a5
+ -20 28 2 59.21 109.10 105.00 51.59 407.8 1200.5 q1a12
+ -19 -13 9 -57.62 154.13 210.00 91.62 610.1 684.6 q1a7
+ -19 -11 8 42.05 163.40 244.00 91.55 624.9 653.1 q1a7
+ -19 -9 7 113.74 140.23 180.00 90.86 639.6 621.8 q1a7
+ -19 33 2 -215.12 122.03 90.00 47.12 470.1 1131.0 q1a12
+ -18 -6 5 176.43 120.01 171.00 95.17 694.2 587.1 q1a7
+ -18 16 0 -108.91 159.43 179.00 94.71 407.3 1398.2 q1a14
+ -18 18 0 -60.81 138.52 150.00 90.81 418.6 1367.2 q1a14
+ -18 22 0 205.39 136.39 114.00 70.01 441.5 1304.4 q1a14
+ -17 29 0 79.91 105.59 147.00 54.29 513.6 1234.1 q1a12
+ -16 6 0 236.44 156.13 200.00 128.56 692.8 29.0 q1a1
+ -15 -39 27 -154.16 114.48 123.00 58.96 54.3 755.0 q0a8
+ -15 9 -1 -259.88 300.88 386.00 146.88 724.2 77.3 q1a1
+ -14 2 0 962.77 376.22 412.00 166.03 610.3 66.1 q1a1
+ -14 6 -1 2661.44 314.50 1513.00 154.56 668.2 90.1 q1a1
+ -13 -21 10 216.92 199.08 261.00 132.68 275.8 1352.0 q0a15
+ -13 -3 1 765.17 462.25 619.00 179.43 529.6 65.8 q1a0
+ -13 9 -2 -153.60 519.88 455.00 191.40 699.3 137.5 q1a1
+ -13 35 -1 -93.21 89.45 102.00 56.41 671.9 1197.8 q1a13
+ -12 -20 9 3495.54 249.91 1902.00 144.66 281.9 1390.4 q0a15
+ -12 -4 1 297.50 239.56 304.00 131.50 503.9 89.2 q1a0
+ -12 24 -3 373.02 156.94 173.00 110.78 635.2 1361.1 q1a15
+ -12 32 -2 219.38 95.08 112.00 60.62 683.6 1263.0 q1a13
+ -12 40 0 -173.00 93.26 101.00 54.00 734.6 1127.1 q1a13
+ -11 -47 35 109.46 66.12 77.00 49.34 103.6 956.6 q0a10
+ -11 -31 17 -123.02 160.64 169.00 98.22 85.9 1335.2 q0a14
+ -11 -19 8 200.25 486.33 556.00 176.75 287.8 1428.2 q0a15
+ -11 27 -3 121.04 159.88 170.00 106.16 682.5 1329.2 q1a15
+ -10 -50 39 32.00 57.76 90.00 48.00 99.4 1052.0 q0a10
+ -10 -48 36 146.25 78.51 87.00 47.75 127.6 992.1 q0a10
+ -10 -8 2 1138.14 166.62 779.00 104.26 423.9 122.6 q1a0
+ -10 10 -3 2030.31 224.92 1143.00 86.69 677.2 202.4 q1a3
+ -9 9 -3 -17.95 160.13 193.00 73.47 650.9 224.5 q1a3
+ -9 39 -1 449.03 173.46 157.00 59.77 951.5 717.3 q2a6
+ -9 45 1 76.93 102.45 114.00 54.67 845.1 674.1 q2a6
+ -8 18 -4 -599.89 441.76 315.00 133.49 765.6 306.2 q1a3
+ -8 36 -2 -140.88 216.97 290.00 86.88 1013.6 708.6 q2a7
+ -7 -49 37 72.19 86.28 95.00 49.81 218.9 1050.4 q0a11
+ -7 -47 34 -205.88 88.69 85.00 53.88 243.8 992.1 q0a11
+ -7 -37 22 33.66 134.09 128.00 66.54 344.6 783.2 q0a9
+ -7 -15 5 -222.50 282.45 334.00 100.50 308.7 287.5 q0a3
+ -7 -13 4 654.50 152.93 393.00 84.50 296.0 317.2 q0a3
+ -7 -11 3 351.18 108.62 469.00 78.42 283.4 346.8 q0a3
+ -7 3 -2 2712.50 223.00 1147.00 52.50 546.2 244.4 q1a2
+ -7 17 -4 1248.88 263.41 497.00 94.12 738.7 327.9 q1a3
+ -7 19 -4 -165.61 390.25 336.00 126.01 767.1 340.1 q1a3
+ -7 21 -4 649.63 595.73 524.00 184.35 759.7 1472.1 q1a15
+ -7 31 -3 124.32 393.24 387.00 117.08 1107.0 713.2 q2a7
+ -6 -20 8 3744.30 297.65 2329.00 112.30 313.2 198.9 q0a3
+ -6 16 -4 339.15 158.57 191.00 77.65 712.0 349.4 q1a3
+ -6 18 -4 293.98 225.60 361.00 91.22 740.2 361.6 q1a3
+ -6 36 -2 286.66 158.05 341.00 89.54 1042.2 650.5 q2a7
+ -5 -49 37 182.14 86.61 115.00 49.26 287.9 1072.6 q0a11
+ -5 -27 13 1.51 280.48 368.00 161.89 331.6 99.6 q0a1
+ -5 -23 10 -649.08 447.75 524.00 179.68 304.2 167.2 q0a1
+ -5 -13 4 682.26 135.75 357.00 75.14 240.3 294.7 q0a3
+ -5 -11 3 849.43 138.18 522.00 75.17 227.9 324.2 q0a3
+ -5 3 -2 787.30 162.81 678.00 47.81 522.6 299.0 q1a2
+ -5 19 -4 515.99 180.10 273.00 107.63 783.1 117.6 q2a0
+ -5 21 -4 713.11 292.97 622.00 134.49 795.4 89.1 q2a0
+ -5 31 -3 764.57 373.60 481.00 119.83 1134.4 656.5 q2a7
+ -4 -46 33 -215.12 162.80 177.00 55.12 353.8 1001.8 q0a11
+ -4 -28 14 -103.06 225.66 378.00 158.06 309.9 70.3 q0a1
+ -4 -18 7 407.95 126.20 137.00 77.45 244.2 207.1 q0a3
+ -4 0 -1 184.40 93.94 119.00 44.40 469.0 308.2 q1a2
+ -3 -41 27 -152.98 121.48 127.00 65.78 216.6 383.7 q0a5
+ -3 -29 15 750.01 190.99 411.00 135.39 288.0 40.8 q0a1
+ -3 -21 9 129.58 157.40 201.00 131.82 235.0 176.3 q0a1
+ -3 47 2 -353.28 187.40 227.00 59.48 900.8 503.6 q2a4
+ -3 49 3 35.29 80.64 87.00 52.91 863.5 485.4 q2a4
+ -3 53 5 -187.20 124.85 106.00 54.80 785.8 447.4 q2a4
+ -2 -40 26 50.93 99.74 133.00 65.67 227.1 423.2 q0a5
+ -2 -22 10 -418.44 257.73 297.00 142.44 213.5 147.8 q0a1
+ -2 -2 0 3026.59 491.38 1041.00 186.27 417.4 350.3 q1a2
+ -1 -43 30 -50.81 91.25 100.00 55.81 145.0 427.7 q0a4
+ -1 -27 14 -75.80 370.72 621.00 171.20 217.5 51.3 q0a1
+ -1 -15 6 -110.91 121.69 119.00 68.71 146.1 216.9 q0a2
+ -1 -9 3 2287.59 187.63 905.00 61.21 110.1 305.5 q0a2
+ -1 7 -2 1683.24 178.00 667.00 58.36 819.5 303.9 q2a2
+ -1 15 -3 44.26 138.55 114.00 61.14 868.4 194.2 q2a2
+ -1 25 -3 71.73 396.01 568.00 165.47 931.7 82.3 q2a0
+ -1 43 1 -174.79 139.39 141.00 69.59 996.7 478.2 q2a5
+ 0 4 -1 -1997.83 1310.24 877.00 438.43 828.5 357.4 q2a2
+ 0 30 -2 13155.88 432.57 4926.00 151.12 991.2 22.0 q2a1
+ 0 42 1 61.94 94.57 119.00 66.06 1027.6 457.0 q2a5
+ 1 -43 31 -63.71 104.13 116.00 56.91 114.0 489.0 q0a4
+ 1 27 -2 9938.98 537.46 4593.00 184.22 998.4 78.8 q2a1
+ 2 -44 33 -44.49 90.85 104.00 53.89 70.6 511.2 q0a4
+ 2 -40 28 291.26 172.16 179.00 58.14 169.7 543.3 q0a4
+ 2 -24 13 -26.60 431.43 543.00 177.40 117.2 63.8 q0a0
+ 2 -18 9 279.88 116.05 169.00 111.12 81.4 161.3 q0a0
+ 2 -6 3 209.73 1117.52 1486.00 81.47 11.4 310.8 q0a2
+ 2 8 -1 7229.94 298.61 2520.00 58.06 906.5 327.6 q2a2
+ 2 42 2 -249.71 127.99 111.00 66.91 1055.0 396.7 q2a5
+ 3 -45 35 -76.00 110.81 106.00 54.00 26.2 534.0 q0a4
+ 3 -23 13 -222.39 223.00 327.00 153.99 83.2 66.0 q0a0
+ 3 -17 9 186.19 132.69 168.00 105.81 47.9 163.4 q0a0
+ 3 27 -1 4663.17 437.85 2491.00 170.43 1055.2 104.3 q2a1
+ 3 33 0 524.54 178.31 426.00 139.66 1099.9 15.8 q2a1
+ 4 -36 25 244.73 113.40 131.00 75.47 223.4 604.0 q0a7
+ 4 -34 23 -187.14 136.40 151.00 85.74 265.0 617.2 q0a7
+ 4 -32 21 195.68 147.34 195.00 91.92 305.7 630.2 q0a7
+ 4 -16 9 234.27 109.28 147.00 103.53 14.5 165.5 q0a0
+ 4 0 2 2302.05 180.77 1085.00 56.47 1244.5 307.7 q3a2
+ 4 4 1 907.19 145.82 577.00 57.81 1189.5 283.7 q3a2
+ 4 30 0 2042.01 272.34 818.00 156.39 1106.1 73.4 q2a1
+ 4 58 11 -74.59 100.81 101.00 39.79 985.6 1100.7 q2a11
+ 5 -37 27 -432.91 204.80 164.00 66.57 186.2 627.1 q0a6
+ 5 -31 21 -399.82 207.68 247.00 98.42 307.9 665.5 q0a7
+ 5 -11 7 -111.04 111.11 131.00 74.84 1412.5 344.5 q3a3
+ 5 -1 3 -18.35 76.29 110.00 59.72 1271.9 286.2 q3a2
+ 5 15 0 -14.00 133.60 203.00 75.00 1030.4 270.6 q2a3
+ 5 25 0 1226.31 539.35 506.00 193.69 1098.3 158.6 q2a1
+ 5 45 5 -85.31 108.68 105.00 59.31 1099.4 866.5 q2a9
+ 6 -38 29 -79.04 151.55 143.00 63.84 145.2 650.7 q0a6
+ 6 12 1 153.40 118.11 184.00 74.40 1039.1 325.0 q2a3
+ 6 48 7 18.21 93.29 116.00 58.59 1035.7 905.3 q2a9
+ 6 52 9 -6.21 85.85 94.00 47.41 990.5 951.8 q2a11
+ 7 -23 16 787.75 482.01 489.00 158.25 1540.3 1410.0 q3a15
+ 7 -17 12 468.30 574.29 708.00 168.30 1534.6 322.8 q3a3
+ 7 1 4 1019.81 140.76 841.00 61.19 1271.6 218.6 q3a2
+ 7 29 2 -82.01 415.00 421.00 147.61 898.5 1468.1 q2a14
+ 7 41 5 -71.80 94.84 115.00 62.20 1074.8 772.9 q2a9
+ 8 -28 21 218.01 163.90 191.00 118.37 1539.6 1302.1 q3a15
+ 8 -10 9 427.81 141.57 172.00 77.19 1441.3 254.7 q3a3
+ 8 30 3 -294.54 215.05 219.00 127.34 897.2 1429.6 q2a14
+ 8 44 7 80.21 83.54 113.00 57.59 1011.6 809.1 q2a9
+ 9 -23 18 555.54 248.96 394.00 129.66 1481.9 1376.1 q3a15
+ 9 9 4 -1.88 174.87 202.00 109.88 1188.0 140.9 q3a0
+ 9 35 5 80.38 140.78 157.00 96.62 835.8 1355.2 q2a14
+ 10 -24 20 -9.66 175.59 215.00 112.46 1457.4 1339.3 q3a15
+ 10 -20 17 1985.24 238.93 844.00 130.36 1435.6 1410.2 q3a15
+ 10 4 6 776.86 156.41 606.00 117.74 1272.0 142.8 q3a0
+ 10 30 5 878.82 238.27 703.00 122.58 924.2 1366.6 q2a14
+ 10 44 9 161.80 110.03 110.00 52.80 945.8 782.1 q2a8
+ 10 54 14 38.50 80.05 78.00 40.50 821.1 937.4 q2a10
+ 11 -5 10 120.09 194.16 251.00 136.71 1413.7 166.3 q3a1
+ 11 9 6 185.10 230.73 266.00 139.10 1216.6 81.6 q3a0
+ 12 -34 32 62.99 115.04 115.00 48.61 1447.1 1118.3 q3a13
+ 12 -28 26 -138.94 119.81 109.00 63.94 1416.2 1249.2 q3a13
+ 12 -22 21 281.93 151.28 182.00 108.67 1385.2 1336.9 q3a15
+ 12 -2 10 1826.41 320.66 728.00 147.79 1385.5 118.9 q3a1
+ 12 10 7 3346.99 443.26 2306.00 172.61 1217.5 44.3 q3a0
+ 13 33 9 140.76 212.84 233.00 77.64 921.0 1267.2 q2a12
+ 13 45 13 -334.65 134.58 99.00 55.85 823.7 758.3 q2a8
+ 13 47 14 88.86 107.07 95.00 53.74 797.6 793.4 q2a8
+ 14 14 9 683.94 506.73 423.00 157.06 1533.8 712.4 q3a7
+ 15 -9 17 276.24 194.29 331.00 129.97 1544.7 64.0 q3a1
+ 15 9 11 81.44 515.94 435.00 151.56 1536.0 625.4 q3a7
+ 15 29 11 -151.20 141.35 147.00 75.80 1007.1 1233.1 q2a13
+ 16 -22 27 -17.94 97.16 118.00 57.94 1256.7 1277.2 q3a12
+ 16 -18 24 245.77 133.06 138.00 80.03 1237.3 1324.7 q3a14
+ 16 26 12 16.40 112.01 132.00 75.40 1066.6 1224.3 q2a13
+ 16 36 14 20.31 94.97 112.00 64.69 918.0 1125.0 q2a12
+ 17 -21 28 -56.15 89.59 134.00 55.35 1216.5 1271.7 q3a12
+ 17 -17 25 -111.43 119.67 158.00 84.83 1197.6 1319.8 q3a14
+ 17 1 16 -393.76 436.78 340.00 123.36 1520.2 501.3 q3a5
+ 17 29 14 151.11 115.21 111.00 64.49 1037.8 1158.3 q2a13
+ 18 14 15 -305.64 190.18 218.00 100.24 1394.8 645.2 q3a7
+ 18 24 15 -0.14 136.26 138.00 70.74 1128.4 1166.7 q2a13
+ 19 -11 25 -61.09 107.48 116.00 63.29 1476.8 781.9 q3a9
+ 19 -3 21 32.57 114.00 128.00 77.83 1473.0 397.7 q3a5
+ 20 -22 35 -99.40 118.64 124.00 50.60 1238.9 768.8 q3a8
+ 20 6 20 -12.74 130.11 162.00 78.14 1376.3 515.0 q3a5
+ 21 -11 29 -97.30 97.08 99.00 57.70 1425.2 859.7 q3a9
+ 22 -20 38 2.93 77.44 85.00 48.67 1214.9 862.8 q3a8
+ 22 -12 32 -197.64 141.64 173.00 56.24 1376.5 897.6 q3a9
+ 22 6 24 -120.40 162.85 186.00 64.60 1297.9 470.2 q3a4
+ 23 3 27 47.97 93.09 108.00 58.23 1275.5 398.0 q3a4
+ 23 7 26 -149.66 129.89 166.00 59.46 1246.3 461.3 q3a4
+ 24 8 28 256.64 113.14 120.00 58.76 1193.0 452.1 q3a4
+ 26 -14 44 58.12 67.42 96.00 38.88 1192.8 1059.0 q3a10
+ 26 -10 41 -127.15 79.52 76.00 44.35 1281.7 1073.8 q3a10
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035135_1af88.h5
+Image serial number: 26
+hit = 1
+indexed_by = none
+photon_energy_eV = 9498.117577
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9498.117577
+average_camera_length = 0.152001 m
+num_peaks = 98
+peak_resolution = 4.102711 nm^-1 or 2.437413 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 150.71 105.11 1.97 1117.54 q0a0
+ 51.78 158.00 1.59 2303.94 q0a0
+ 204.50 33.04 2.41 1368.80 q0a1
+ 303.50 166.06 2.12 1353.05 q0a1
+ 296.86 172.50 2.08 1269.69 q0a1
+ 454.06 37.05 2.19 2000.88 q1a0
+ 539.53 76.36 2.08 2426.48 q1a0
+ 561.28 101.21 2.00 719.68 q1a0
+ 679.73 106.92 2.28 2177.79 q1a1
+ 627.88 108.50 2.13 715.80 q1a1
+ 679.91 139.09 2.16 474.79 q1a1
+ 834.50 39.06 2.17 889.47 q2a0
+1114.09 124.22 2.38 910.70 q2a1
+1064.66 139.14 2.15 1093.99 q2a1
+1105.85 162.62 2.21 1908.90 q2a1
+ 991.50 164.07 1.82 1546.45 q2a1
+1253.33 93.50 1.93 1036.35 q3a0
+1257.50 102.18 1.89 816.36 q3a0
+1407.78 90.50 2.23 723.00 q3a1
+1448.50 105.90 2.28 425.22 q3a1
+1429.25 127.04 2.14 2006.07 q3a1
+ 105.77 251.50 1.02 3397.02 q0a2
+ 18.21 266.50 0.85 1185.28 q0a2
+ 125.14 281.50 0.92 1307.44 q0a2
+ 131.83 285.29 0.93 3873.74 q0a2
+ 142.50 293.93 0.93 1436.02 q0a2
+ 182.50 303.95 1.05 506.14 q0a2
+ 8.06 319.88 0.57 1430.99 q0a2
+ 182.99 320.89 1.00 4936.26 q0a2
+ 78.53 339.24 0.52 9987.24 q0a2
+ 175.93 338.50 0.92 643.03 q0a2
+ 160.50 347.12 0.82 767.62 q0a2
+ 92.50 357.89 0.49 779.54 q0a2
+ 159.08 361.50 0.78 1202.11 q0a2
+ 330.90 239.50 1.91 1179.57 q0a3
+ 320.50 265.87 1.80 1252.25 q0a3
+ 247.50 308.91 1.35 706.95 q0a3
+ 248.92 324.50 1.32 949.94 q0a3
+ 234.50 341.96 1.21 547.84 q0a3
+ 275.78 345.66 1.42 2805.91 q0a3
+ 403.50 193.99 1.22 634.29 q1a2
+ 536.50 223.94 1.23 1073.77 q1a2
+ 436.50 227.19 1.04 2475.06 q1a2
+ 521.50 228.92 1.16 1329.04 q1a2
+ 413.50 248.89 0.92 776.68 q1a2
+ 444.50 255.11 0.89 -752.53 q1a2
+ 449.96 260.04 0.87 711.06 q1a2
+ 479.88 270.52 0.86 18023.12 q1a2
+ 504.50 270.93 0.92 1555.61 q1a2
+ 415.50 282.34 0.74 1574.85 q1a2
+ 413.95 287.86 0.71 1822.85 q1a2
+ 538.66 291.72 0.94 2955.95 q1a2
+ 542.88 301.02 0.92 1527.95 q1a2
+ 560.84 341.30 0.87 2154.83 q1a2
+ 567.01 355.18 0.87 1897.80 q1a2
+ 811.74 195.59 1.19 2379.14 q2a2
+ 822.06 210.50 1.11 786.12 q2a2
+ 801.28 249.19 0.90 4870.90 q2a2
+ 907.63 262.08 1.00 2940.84 q2a2
+ 940.50 272.97 1.07 304.39 q2a2
+ 931.04 281.24 1.00 1126.90 q2a2
+ 830.96 287.91 0.70 3689.45 q2a2
+ 955.83 302.73 1.03 3780.62 q2a2
+ 864.50 321.05 0.60 6483.01 q2a2
+ 910.59 331.00 0.74 2064.71 q2a2
+ 839.11 336.02 0.46 3620.96 q2a2
+ 872.50 352.70 0.50 2399.99 q2a2
+ 912.98 357.50 0.67 4344.86 q2a2
+1002.66 316.82 1.22 4290.35 q2a3
+ 994.77 356.32 1.11 1610.29 q2a3
+1321.50 206.16 1.35 1593.02 q3a2
+1321.50 225.12 1.26 545.43 q3a2
+1259.89 238.98 1.04 5021.05 q3a2
+1334.69 241.98 1.23 6499.95 q3a2
+1347.50 242.91 1.27 1081.26 q3a2
+1298.89 249.50 1.08 3528.05 q3a2
+1183.41 257.69 0.88 3159.74 q3a2
+1329.90 261.03 1.13 3384.91 q3a2
+1252.55 263.46 0.90 9087.53 q3a2
+1213.16 263.50 0.85 -2186.54 q3a2
+1303.00 266.28 1.02 762.54 q3a2
+1210.50 267.05 0.83 6507.99 q3a2
+1212.55 268.52 0.82 6414.15 q3a2
+1184.62 275.69 0.78 1732.05 q3a2
+1242.34 279.28 0.80 2522.33 q3a2
+1337.14 290.50 1.05 1144.04 q3a2
+1349.83 318.66 1.01 2098.23 q3a2
+1323.44 349.56 0.80 4866.86 q3a2
+1321.18 353.83 0.78 3091.38 q3a2
+1533.88 258.37 2.04 1367.62 q3a3
+1383.85 302.50 1.23 1587.25 q3a3
+1377.60 331.64 1.13 3848.96 q3a3
+1377.05 345.50 1.10 672.11 q3a3
+1119.85 718.50 2.71 383.38 q2a7
+1309.97 799.03 4.10 142.14 q3a8
+ 623.00 1447.00 2.40 1105.26 q1a15
+1410.99 1418.50 2.52 708.60 q3a15
+1441.91 1455.91 2.29 772.72 q3a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035029_15255.h5
+Image serial number: 30
+hit = 1
+indexed_by = none
+photon_energy_eV = 9504.253552
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9504.253552
+average_camera_length = 0.152001 m
+num_peaks = 16
+peak_resolution = 4.104987 nm^-1 or 2.436061 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 18.50 13.93 2.33 116.74 q0a0
+ 208.11 156.50 1.86 741.90 q0a1
+ 12.18 229.34 1.05 1760.69 q0a2
+ 33.67 253.66 0.92 1257.05 q0a2
+ 140.93 297.50 0.91 1703.98 q0a2
+ 127.17 308.50 0.82 1330.36 q0a2
+ 463.50 240.34 1.00 1004.06 q1a2
+ 496.89 317.50 0.69 2045.19 q1a2
+ 894.09 344.50 0.62 3120.98 q2a2
+1179.50 282.20 0.74 8187.56 q3a2
+1344.00 282.50 1.10 1398.69 q3a2
+1225.50 285.37 0.74 3866.45 q3a2
+1217.99 294.50 0.68 852.69 q3a2
+1319.50 304.85 0.92 1443.40 q3a2
+1400.96 273.50 1.39 616.50 q3a3
+1310.19 799.14 4.10 -121.18 q3a8
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035059_17d54.h5
+Image serial number: 31
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9498.820662
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9498.820662
+average_camera_length = 0.152001 m
+num_peaks = 33
+peak_resolution = 4.569930 nm^-1 or 2.188217 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 134.22 171.50 1.61 1324.69 q0a0
+ 221.98 85.14 2.21 2242.67 q0a1
+ 402.16 64.48 2.05 2942.60 q1a0
+ 419.50 97.10 1.88 1697.35 q1a0
+ 665.82 128.36 2.16 2702.96 q1a1
+ 786.27 14.27 2.29 1994.55 q2a0
+ 895.85 156.10 1.63 1409.40 q2a0
+1302.26 101.44 1.95 3293.40 q3a0
+ 17.52 241.09 0.99 11919.25 q0a2
+ 19.00 270.50 0.83 1165.73 q0a2
+ 112.63 309.14 0.76 16898.35 q0a2
+ 145.95 351.36 0.74 12778.81 q0a2
+ 516.50 252.90 1.04 2224.45 q1a2
+ 457.21 259.29 0.89 4169.17 q1a2
+ 532.91 274.15 1.00 3609.58 q1a2
+ 444.36 291.37 0.70 11592.55 q1a2
+ 430.87 323.27 0.51 7487.90 q1a2
+ 477.25 348.60 0.49 15944.49 q1a2
+ 908.26 251.95 1.05 3169.44 q2a2
+ 880.52 269.67 0.89 2935.46 q2a2
+ 852.33 287.13 0.74 5599.78 q2a2
+ 793.99 291.50 0.67 1117.74 q2a2
+1116.90 246.76 1.93 3599.54 q2a3
+1001.28 319.09 1.21 2694.27 q2a3
+1282.50 197.80 1.29 1865.68 q3a2
+1181.53 237.31 0.99 18709.14 q3a2
+1198.71 265.37 0.83 7242.24 q3a2
+1179.50 267.06 0.83 721.64 q3a2
+1255.50 277.89 0.83 789.03 q3a2
+1281.20 294.01 0.83 2198.42 q3a2
+1515.69 329.40 1.82 5541.29 q3a3
+ 320.50 638.82 2.88 1185.88 q0a7
+ 321.50 1077.92 4.57 657.21 q0a11
+End of peak list
+--- Begin crystal
+Cell parameters 6.12376 12.32621 16.94071 nm, 88.57260 89.57178 90.51911 deg
+astar = +0.0146713 +0.1598937 +0.0298136 nm^-1
+bstar = +0.0803991 -0.0047473 -0.0099923 nm^-1
+cstar = -0.0079827 +0.0109832 -0.0574673 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00206 nm^-1
+predict_refine/final_residual = 8.807216e-07
+predict_refine/det_shift x = -0.035 y = -0.038 mm
+diffraction_resolution_limit = 2.21 nm^-1 or 4.52 A
+num_reflections = 203
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -25 9 5 6.91 180.81 215.00 88.29 1185.9 645.2 q3a6
+ -25 11 5 42.11 124.06 152.00 86.49 1181.3 610.9 q3a6
+ -25 13 5 -262.06 149.26 182.00 85.06 1176.6 576.4 q3a6
+ -24 10 4 -34.98 101.29 164.00 84.78 1225.9 624.4 q3a6
+ -24 12 4 -35.64 116.75 133.00 83.24 1221.4 590.5 q3a6
+ -24 24 5 -258.91 124.40 121.00 78.71 1189.4 407.4 q3a4
+ -23 -33 20 -95.15 101.62 88.00 53.35 827.7 956.5 q2a10
+ -23 -29 17 -47.51 101.47 129.00 67.11 831.7 892.8 q2a8
+ -23 -23 13 -83.27 114.20 102.00 69.47 835.9 766.4 q2a8
+ -23 -13 8 -35.73 109.52 126.00 84.53 908.9 1148.5 q2a12
+ -23 1 4 -201.88 168.14 234.00 90.88 1147.5 1134.7 q2a13
+ -23 11 3 38.02 110.75 141.00 87.78 1264.9 604.1 q3a6
+ -23 13 3 189.21 122.05 136.00 83.59 1260.6 570.5 q3a6
+ -23 23 4 29.76 147.90 142.00 79.64 1234.5 424.8 q3a4
+ -21 -29 15 366.82 123.98 196.00 66.58 915.4 866.6 q2a8
+ -21 -19 9 -669.01 199.51 211.00 90.61 817.0 1229.7 q2a12
+ -21 -17 8 30.38 107.57 158.00 81.62 853.8 1229.0 q2a12
+ -21 21 2 66.66 155.42 169.00 85.54 1320.7 458.2 q3a4
+ -21 39 7 117.57 167.37 183.00 63.83 1341.7 1013.3 q3a10
+ -20 -34 18 -343.29 149.01 121.00 60.09 953.1 937.3 q2a10
+ -20 -24 11 -195.02 140.01 125.00 73.22 955.3 755.2 q2a8
+ -20 36 5 144.06 116.63 111.00 66.94 1400.9 959.7 q3a11
+ -19 -35 18 197.18 103.38 112.00 57.42 989.4 947.2 q2a11
+ -19 11 0 229.60 170.95 193.00 114.60 1413.9 592.2 q3a7
+ -18 -28 12 -30.29 86.51 103.00 72.09 1028.1 814.2 q2a9
+ -18 34 3 -119.65 108.78 126.00 77.85 1441.0 901.9 q3a9
+ -17 -41 22 -96.26 79.67 96.00 56.86 1065.2 1066.0 q2a11
+ -17 -33 15 195.39 89.52 119.00 73.01 1065.5 907.7 q2a9
+ -17 -5 1 175.79 226.47 305.00 173.41 1080.2 1335.4 q2a15
+ -17 7 -1 610.95 406.13 516.00 159.45 1490.9 649.8 q3a7
+ -17 29 1 310.91 265.81 317.00 83.29 1531.2 851.3 q3a9
+ -16 -10 2 297.11 291.85 317.00 181.49 1004.4 1374.7 q2a15
+ -16 34 2 -36.52 103.88 124.00 79.72 1442.4 827.5 q3a9
+ -15 -43 23 -345.69 179.18 128.00 56.69 1141.4 1093.8 q2a11
+ -15 -41 21 -341.61 156.19 138.00 56.01 1141.0 1043.2 q2a11
+ -15 -39 19 -274.43 191.08 240.00 57.83 1140.5 994.1 q2a11
+ -15 -33 14 244.89 181.80 216.00 70.51 1137.6 889.3 q2a9
+ -15 35 2 -327.44 138.39 133.00 77.44 1424.5 794.1 q3a9
+ -14 -6 0 -22.39 468.76 485.00 240.99 1077.8 1436.2 q2a15
+ -14 -2 -1 383.85 689.89 573.00 279.35 1140.3 1431.4 q2a15
+ -14 36 2 -284.88 125.80 121.00 80.88 1406.8 760.8 q3a9
+ -13 -43 22 -43.15 110.58 134.00 64.35 816.5 389.7 q2a4
+ -13 -27 9 -366.03 262.43 278.00 117.27 1155.8 377.8 q2a5
+ -13 -7 0 -1244.56 773.68 591.00 278.56 1066.2 1469.5 q2a15
+ -13 -3 -1 -832.24 803.73 586.00 305.64 1128.4 1464.7 q2a15
+ -13 21 -2 -28.51 196.10 281.00 179.11 1481.1 19.7 q3a1
+ -12 -38 17 16.18 161.90 212.00 72.42 943.2 421.1 q2a4
+ -12 -24 7 59.01 205.09 351.00 174.39 1134.5 21.3 q2a1
+ -12 -16 3 -1174.49 701.80 560.00 267.89 1144.0 157.9 q2a1
+ -12 -8 0 -879.81 753.24 540.00 270.81 1153.7 259.3 q2a3
+ -12 28 -1 184.11 215.66 285.00 142.49 1199.6 1446.7 q3a14
+ -12 40 3 26.14 148.18 202.00 78.26 1175.4 1261.9 q3a12
+ -11 -5 -1 201.36 590.89 443.00 183.24 1125.9 309.5 q2a3
+ -11 9 -3 3477.26 452.51 835.00 195.14 1302.3 102.5 q3a0
+ -11 11 -3 2021.12 541.01 832.00 219.88 1332.7 99.6 q3a0
+ -11 15 -3 1395.75 522.99 499.00 237.66 1390.8 93.8 q3a1
+ -10 -36 15 -110.02 205.13 219.00 91.22 997.0 486.7 q2a5
+ -10 -28 9 -92.91 471.43 393.00 145.71 1154.8 476.9 q2a5
+ -10 -12 1 68.45 287.57 313.00 136.95 1086.6 204.2 q2a3
+ -10 8 -3 -18.04 202.48 281.00 162.90 1289.7 134.9 q3a0
+ -10 16 -3 75.05 488.06 524.00 227.55 1408.3 123.8 q3a1
+ -9 -35 14 208.80 129.29 210.00 88.80 1024.5 518.4 q2a5
+ -9 -31 11 222.34 384.36 360.00 124.46 1103.5 512.9 q2a5
+ -9 -23 6 -337.14 276.89 382.00 198.74 1040.3 54.9 q2a1
+ -9 -17 3 414.41 378.99 525.00 199.79 1048.7 155.4 q2a1
+ -9 -9 0 89.59 188.04 330.00 102.21 1059.5 254.6 q2a3
+ -9 7 -3 304.94 161.19 389.00 143.06 1277.3 167.0 q3a0
+ -9 17 -3 -9.30 248.36 370.00 194.70 1425.7 153.5 q3a1
+ -9 29 -1 186.26 380.05 384.00 167.14 1295.8 1427.0 q3a14
+ -9 43 4 66.59 94.58 159.00 74.21 1273.1 1204.8 q3a12
+ -9 45 5 5.09 96.93 116.00 72.71 1269.4 1165.2 q3a12
+ -8 -12 1 249.41 189.36 191.00 99.79 1025.2 211.3 q2a3
+ -7 -23 6 -388.49 476.38 482.00 240.89 978.1 63.9 q2a1
+ -7 -21 5 -632.59 539.72 575.00 238.79 981.3 97.5 q2a1
+ -7 -19 4 -224.94 428.55 430.00 192.94 984.4 130.7 q2a1
+ -7 -17 3 554.56 199.10 231.00 160.44 987.4 163.5 q2a1
+ -7 -9 0 316.50 132.29 156.00 89.50 998.8 261.2 q2a3
+ -7 7 -3 1920.47 193.65 1068.00 76.58 1282.6 199.1 q3a2
+ -6 -36 15 43.61 165.88 153.00 101.99 1019.7 590.1 q2a7
+ -6 -32 12 -171.26 209.57 226.00 121.86 1098.3 582.3 q2a7
+ -6 0 -2 18684.48 451.09 9262.00 72.95 1180.9 237.5 q3a2
+ -6 10 -3 115.91 185.89 212.00 81.29 1329.5 225.8 q3a2
+ -6 14 -3 187.86 143.82 173.00 92.74 1386.4 221.3 q3a3
+ -6 32 0 151.73 214.87 240.00 156.47 1384.7 1373.5 q3a15
+ -5 -11 1 699.61 187.24 458.00 75.99 939.0 236.2 q2a2
+ -5 1 -2 7141.30 296.74 4914.00 78.30 1198.2 266.1 q3a2
+ -4 -44 23 -35.06 124.57 153.00 70.06 852.5 676.8 q2a6
+ -4 -42 21 -61.01 127.45 209.00 77.61 899.7 670.9 q2a6
+ -4 -40 19 -165.07 243.80 231.00 82.67 945.6 665.1 q2a6
+ -4 -30 11 -95.39 452.20 435.00 160.99 1143.6 641.4 q2a7
+ -4 -20 5 275.90 206.22 402.00 154.90 894.4 124.7 q2a0
+ -3 -35 15 200.60 146.91 228.00 110.60 1051.0 684.5 q2a7
+ -3 -31 12 -238.49 557.09 428.00 163.89 1128.2 675.0 q2a7
+ -3 5 -2 618.62 136.19 511.00 72.99 1261.8 321.0 q3a2
+ -3 29 0 -181.79 607.93 518.00 218.59 1482.1 1418.6 q3a15
+ -2 -38 18 -29.48 157.78 210.00 101.28 991.8 725.3 q2a7
+ -2 -14 3 438.48 156.48 225.00 74.72 844.7 197.3 q2a2
+ -2 -8 1 5201.86 256.37 1804.00 76.74 853.6 289.3 q2a2
+ -2 42 5 -584.85 225.54 267.00 91.65 1505.5 1216.8 q3a13
+ -2 44 6 258.00 129.27 177.00 78.00 1504.6 1178.3 q3a13
+ -2 46 7 -100.04 96.28 123.00 74.84 1503.7 1138.9 q3a13
+ -1 41 5 67.86 195.94 198.00 85.74 1538.9 1233.6 q3a13
+ 0 -38 19 -24.91 280.38 315.00 86.71 744.7 1239.7 q1a13
+ 0 -14 4 496.59 138.13 243.00 72.21 784.3 201.3 q2a2
+ 0 10 -1 1042.55 169.13 462.00 73.05 19.6 272.3 q0a2
+ 0 12 -1 11788.89 374.45 2933.00 79.70 17.9 242.7 q0a2
+ 0 14 -1 -276.76 154.60 162.00 79.97 16.1 212.9 q0a2
+ 1 -31 14 -189.11 280.57 350.00 161.51 734.2 1353.1 q1a15
+ 1 -25 10 -757.78 707.96 498.00 258.98 750.0 1461.1 q1a15
+ 1 19 0 149.69 151.58 247.00 136.31 42.4 164.4 q0a0
+ 1 33 3 -356.61 399.03 378.00 151.01 356.8 704.9 q0a7
+ 1 43 7 287.09 235.04 238.00 80.71 179.7 705.3 q0a6
+ 1 45 8 275.54 164.58 214.00 74.66 140.6 705.0 q0a6
+ 2 -30 14 88.69 235.08 344.00 165.31 704.7 1372.7 q1a15
+ 2 -22 9 100.00 446.80 412.00 150.56 754.7 318.2 q1a3
+ 2 -16 6 274.27 138.70 161.00 83.53 656.8 330.9 q1a3
+ 2 -4 2 15966.26 423.68 7791.00 68.14 476.1 350.4 q1a2
+ 2 22 1 489.91 175.30 231.00 154.29 71.4 116.0 q0a0
+ 3 -41 24 -29.07 108.76 106.00 68.67 630.7 1176.0 q1a13
+ 3 -33 17 -153.82 220.69 189.00 126.42 662.4 1316.4 q1a15
+ 3 -29 14 40.20 368.24 485.00 163.20 675.4 1392.2 q1a15
+ 3 -1 2 7503.28 313.44 3535.00 61.08 429.8 324.0 q1a2
+ 3 7 1 17040.10 433.60 7359.00 84.10 113.2 311.1 q0a2
+ 3 35 5 670.56 241.52 532.00 123.44 317.5 640.2 q0a7
+ 3 51 13 -149.30 130.76 122.00 68.19 7.9 631.0 q0a6
+ 4 -42 26 -213.61 130.63 127.00 68.38 589.9 1151.4 q1a13
+ 4 -40 24 -351.85 190.80 241.00 74.65 599.8 1197.5 q1a13
+ 4 -38 22 277.93 153.14 193.00 76.67 609.3 1242.3 q1a13
+ 4 -32 17 -416.04 207.43 204.00 141.84 632.8 1336.4 q1a15
+ 4 -2 3 11555.08 375.73 8060.00 59.33 443.2 292.0 q1a2
+ 4 4 2 13307.90 398.19 6234.00 75.06 146.8 353.6 q0a2
+ 5 -43 28 -15.06 119.24 115.00 64.06 551.3 1126.3 q1a12
+ 5 -41 26 -164.38 154.84 140.00 65.38 561.8 1173.2 q1a12
+ 5 -39 24 -174.04 261.93 300.00 75.84 572.0 1218.9 q1a12
+ 5 -7 5 2480.53 209.06 1449.00 65.42 516.8 254.0 q1a2
+ 5 -3 4 4088.47 235.51 2755.00 57.58 456.6 259.8 q1a2
+ 5 21 3 -98.33 290.38 303.00 164.93 165.8 124.5 q0a0
+ 5 43 10 -59.07 149.55 139.00 74.67 167.2 568.7 q0a6
+ 6 -42 28 -228.79 120.20 121.00 68.59 520.0 1148.4 q1a12
+ 6 -40 26 -101.69 181.08 207.00 70.69 530.9 1194.9 q1a12
+ 6 -38 24 -145.16 156.66 155.00 66.79 541.5 1240.1 q1a12
+ 6 -32 19 -501.98 313.41 375.00 136.78 567.5 1335.1 q1a14
+ 7 27 6 50.06 172.10 252.00 178.94 227.2 23.5 q0a1
+ 7 43 12 87.30 172.84 217.00 76.30 158.3 524.7 q0a4
+ 7 45 13 238.15 162.62 176.00 74.65 118.4 521.7 q0a4
+ 8 22 6 -576.73 434.67 501.00 224.53 260.1 100.9 q0a1
+ 9 -21 15 1317.24 499.46 475.00 215.36 734.9 119.1 q1a1
+ 9 -15 12 -266.45 334.50 499.00 193.05 635.4 136.2 q1a1
+ 9 -7 9 558.35 169.88 658.00 138.85 512.5 153.8 q1a0
+ 9 -3 8 19.07 158.62 180.00 124.33 451.6 160.4 q1a0
+ 9 21 7 61.21 527.90 510.00 246.59 293.9 113.8 q0a1
+ 10 20 8 -115.88 720.03 550.00 248.88 327.9 126.8 q0a1
+ 10 38 13 -141.14 115.84 132.00 83.74 238.4 423.6 q0a5
+ 10 44 16 -142.76 98.91 101.00 70.36 123.3 410.9 q0a4
+ 11 -43 36 186.76 94.08 100.00 57.64 397.1 786.6 q1a8
+ 11 -25 20 -188.12 266.53 294.00 136.12 416.9 1459.5 q1a14
+ 11 5 9 -236.06 673.45 491.00 208.06 368.9 328.1 q0a3
+ 12 -4 12 1324.02 358.81 679.00 195.78 464.3 56.1 q1a0
+ 12 0 11 3404.05 446.47 996.00 198.55 402.6 63.0 q1a0
+ 13 -39 35 -46.54 72.35 121.00 58.34 483.6 843.0 q1a8
+ 13 -37 33 -22.32 144.95 137.00 64.92 531.2 828.1 q1a8
+ 13 3 12 1195.08 700.89 587.00 281.32 375.6 1438.3 q0a15
+ 13 47 22 -39.18 108.24 160.00 56.58 329.1 1073.0 q0a11
+ 14 -40 38 -201.75 115.41 124.00 60.75 449.1 898.3 q1a8
+ 14 -32 30 35.11 95.69 142.00 67.49 634.2 837.1 q1a9
+ 14 16 13 -1514.05 659.20 585.00 201.45 174.3 1408.5 q0a14
+ 14 34 17 -32.65 140.11 137.00 79.85 325.4 843.0 q0a9
+ 14 46 23 112.60 81.43 100.00 51.60 289.2 1059.1 q0a11
+ 15 -31 31 -33.01 96.56 101.00 65.61 649.2 875.0 q1a9
+ 15 -9 18 -698.99 423.59 430.00 154.39 739.8 584.8 q1a7
+ 15 3 15 -1024.67 558.78 452.00 220.07 373.4 1364.3 q0a15
+ 15 35 19 41.44 127.46 181.00 75.56 282.0 867.5 q0a9
+ 15 45 24 -206.20 116.10 120.00 53.80 249.2 1045.1 q0a11
+ 16 -26 29 -243.19 220.23 239.00 74.19 745.4 890.2 q1a9
+ 16 -20 25 33.90 148.82 139.00 88.90 662.7 422.6 q1a5
+ 16 10 16 -55.10 241.79 274.00 158.90 261.8 1331.0 q0a15
+ 16 12 16 125.70 207.27 250.00 160.70 230.0 1331.5 q0a15
+ 16 22 17 36.57 207.06 195.00 115.83 69.7 1327.2 q0a14
+ 16 40 23 43.64 94.92 97.00 54.76 223.6 946.1 q0a11
+ 17 -37 41 11.28 87.65 102.00 50.52 494.4 994.1 q1a10
+ 17 -31 35 45.14 114.74 117.00 61.26 635.0 941.2 q1a11
+ 17 31 21 272.31 156.91 229.00 76.69 206.0 804.6 q0a9
+ 18 -40 47 4.60 100.86 106.00 43.60 397.0 1086.4 q1a10
+ 18 -26 33 366.75 135.14 175.00 62.25 733.9 955.3 q1a11
+ 18 -8 23 282.26 161.68 191.00 110.14 619.3 597.9 q1a7
+ 18 18 20 521.35 179.72 257.00 93.85 129.0 1274.4 q0a12
+ 18 24 21 261.71 126.46 181.00 82.09 26.4 1267.8 q0a12
+ 18 28 22 -279.76 171.38 145.00 79.36 170.9 755.5 q0a8
+ 18 34 24 -313.25 202.95 176.00 76.25 155.2 868.2 q0a8
+ 18 42 28 50.81 98.96 106.00 50.19 122.0 1007.9 q0a10
+ 19 -1 23 -15.85 254.18 281.00 112.65 590.3 712.8 q1a7
+ 19 5 22 75.88 259.04 351.00 104.12 337.2 1228.8 q0a13
+ 19 19 22 -61.06 171.19 199.00 91.06 108.3 1229.8 q0a12
+ 20 -18 32 -126.75 110.27 164.00 73.75 490.5 441.4 q1a4
+ 20 18 24 297.34 128.68 236.00 84.46 121.3 1183.9 q0a12
+ 20 24 25 133.85 102.15 155.00 82.35 15.9 1175.5 q0a12
+ 20 28 26 105.79 124.46 118.00 73.41 77.0 767.5 q0a8
+ 20 38 30 -253.07 107.21 87.00 53.67 39.4 940.5 q0a10
+ 21 7 26 352.27 120.47 225.00 88.53 301.5 1137.6 q0a13
+ 21 17 26 214.34 136.01 184.00 86.46 134.5 1137.0 q0a12
+ 21 23 27 -37.32 114.69 135.00 79.92 28.1 1127.7 q0a12
+ 21 27 28 146.64 100.80 107.00 68.76 28.4 755.6 q0a8
+ 21 33 30 -120.46 117.47 115.00 64.66 8.1 872.7 q0a8
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035215_1e870.h5
+Image serial number: 33
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9507.324720
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9507.324720
+average_camera_length = 0.152001 m
+num_peaks = 28
+peak_resolution = 4.106570 nm^-1 or 2.435122 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 148.38 114.01 1.92 3417.30 q0a0
+ 183.21 120.78 1.96 1243.30 q0a0
+ 534.74 74.82 2.09 799.88 q1a0
+ 566.26 83.04 2.10 926.66 q1a0
+ 838.50 117.91 1.77 1353.36 q2a0
+ 867.35 134.77 1.70 1798.93 q2a0
+1119.09 136.73 2.35 1807.43 q2a1
+ 550.50 200.26 1.38 1130.29 q1a2
+ 501.54 232.23 1.11 5863.33 q1a2
+ 475.71 255.68 0.94 1292.70 q1a2
+ 457.73 263.50 0.87 2580.24 q1a2
+ 488.50 271.76 0.88 2402.14 q1a2
+ 518.41 280.15 0.92 6262.76 q1a2
+ 434.16 307.50 0.61 1087.32 q1a2
+ 849.43 230.73 1.03 9348.54 q2a2
+ 922.16 235.07 1.17 3527.88 q2a2
+ 949.31 282.50 1.07 2549.30 q2a2
+1002.50 347.84 1.16 1773.05 q2a3
+1283.66 256.18 1.01 1437.10 q3a2
+1174.59 260.34 0.86 5289.70 q3a2
+1204.50 268.76 0.81 1562.95 q3a2
+1235.50 277.05 0.80 684.81 q3a2
+1260.50 357.60 0.49 4667.58 q3a2
+1374.50 287.21 1.23 1011.94 q3a3
+1309.99 799.01 4.11 170.79 q3a8
+ 595.50 1458.21 2.42 1282.30 q1a15
+ 687.00 1463.00 2.21 1744.88 q1a15
+1524.25 1446.78 2.22 1286.29 q3a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.14538 12.31074 16.97988 nm, 89.06648 90.72643 91.04663 deg
+astar = +0.0386268 -0.1248035 -0.0970772 nm^-1
+bstar = +0.0776497 +0.0037313 +0.0236388 nm^-1
+cstar = -0.0122664 -0.0382567 +0.0430793 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00227 nm^-1
+predict_refine/final_residual = 6.449719e-07
+predict_refine/det_shift x = 0.017 y = 0.043 mm
+diffraction_resolution_limit = 2.34 nm^-1 or 4.27 A
+num_reflections = 242
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -15 -41 -51 1.20 29.86 27.00 12.20 448.5 1097.0 q1a10
+ -15 -39 -50 34.74 34.79 57.00 12.86 492.1 1077.3 q1a10
+ -15 -37 -49 29.64 62.23 42.00 12.76 534.4 1058.2 q1a10
+ -15 -33 -48 83.94 52.06 50.00 15.06 611.3 1035.3 q1a11
+ -15 -21 -48 20.17 45.46 43.00 16.43 488.0 394.5 q1a4
+ -14 -44 -46 50.42 40.48 33.00 11.11 395.5 1014.9 q1a10
+ -14 -38 -43 22.09 48.51 37.00 14.71 523.9 961.5 q1a10
+ -14 -14 -44 41.53 148.24 148.00 20.40 565.6 515.4 q1a4
+ -14 -8 -48 -80.25 88.78 100.00 23.25 527.1 592.3 q1a6
+ -14 -2 -54 19.90 46.73 47.00 20.90 462.0 702.4 q1a6
+ -13 -21 -36 107.51 70.38 52.00 20.89 663.3 397.5 q1a5
+ -13 -17 -37 19.78 50.58 56.00 22.76 656.7 464.3 q1a5
+ -13 -9 -41 -126.47 67.57 53.00 30.42 621.8 570.5 q1a7
+ -13 -5 -44 30.72 57.26 58.00 27.92 592.7 639.2 q1a7
+ -12 -38 -32 14.78 63.31 51.00 16.76 539.6 816.8 q1a8
+ -12 -34 -31 -17.63 55.57 53.00 19.65 611.3 801.0 q1a9
+ -12 -20 -31 -127.89 87.39 76.00 27.30 736.5 415.6 q1a5
+ -12 -14 -33 -134.29 114.59 112.00 29.56 720.7 513.8 q1a5
+ -12 -8 -36 -8.33 54.72 70.00 31.46 695.2 583.9 q1a7
+ -12 -4 -39 80.43 58.54 67.00 31.48 667.2 651.4 q1a7
+ -12 4 -47 -24.90 93.58 92.00 24.59 353.8 1217.5 q0a13
+ -12 10 -56 -5.61 42.87 39.00 20.38 230.6 1117.3 q0a13
+ -11 -45 -30 52.86 50.01 39.00 14.74 407.3 782.2 q1a8
+ -11 -5 -33 195.47 120.57 152.00 35.58 747.1 630.8 q1a7
+ -11 -1 -36 -90.82 91.04 80.00 35.65 719.7 697.5 q1a7
+ -11 1 -38 -95.32 80.00 69.00 34.82 700.5 732.4 q1a7
+ -11 13 -54 -151.87 91.63 80.00 23.49 184.7 1163.4 q0a12
+ -10 -38 -23 -127.79 82.88 83.00 18.59 419.1 1252.8 q1a12
+ -10 -22 -22 168.65 106.69 106.00 43.72 768.4 56.2 q1a1
+ -10 -14 -24 -70.95 98.72 103.00 51.47 640.6 42.3 q1a1
+ -10 6 -38 154.70 88.33 85.00 45.70 333.6 1326.2 q0a15
+ -10 14 -49 73.85 101.49 81.00 20.35 179.3 1241.3 q0a12
+ -10 18 -57 212.58 66.82 49.00 17.82 83.5 1150.3 q0a12
+ -9 -41 -20 -16.03 38.41 38.00 17.23 468.2 1201.4 q1a12
+ -9 -37 -19 137.39 59.83 55.00 19.01 480.4 1275.2 q1a12
+ -9 -31 -18 35.24 59.13 63.00 27.97 493.0 1352.4 q1a14
+ -9 -17 -19 -39.27 97.61 100.00 54.31 687.8 106.4 q1a1
+ -9 -9 -22 611.05 190.72 405.00 57.63 565.2 82.8 q1a0
+ -9 -7 -23 945.99 181.07 439.00 53.59 533.7 74.6 q1a0
+ -9 5 -32 405.56 168.14 363.00 56.15 357.1 1404.1 q0a15
+ -9 7 -34 44.04 100.74 97.00 49.04 322.3 1385.7 q0a15
+ -9 11 -39 -17.38 82.47 82.00 44.54 248.0 1337.9 q0a15
+ -9 17 -48 -32.25 71.39 104.00 22.41 127.9 1273.6 q0a12
+ -9 19 -52 -18.78 47.85 49.00 20.63 80.1 1229.6 q0a12
+ -8 -12 -17 215.71 113.75 208.00 46.03 609.2 145.7 q1a1
+ -8 -4 -21 -195.44 74.68 74.00 43.15 487.1 113.2 q1a0
+ -8 10 -33 109.22 87.72 93.00 47.63 273.3 1415.8 q0a15
+ -8 16 -41 272.89 98.66 76.00 37.51 160.8 1339.1 q0a14
+ -8 18 -44 18.86 80.28 97.00 34.59 119.4 1308.9 q0a14
+ -8 22 -52 132.64 66.77 89.00 20.44 22.9 1250.7 q0a12
+ -7 -31 -11 241.16 91.52 78.00 34.77 595.2 1358.1 q1a15
+ -7 -29 -11 51.16 106.96 97.00 39.04 595.3 1391.2 q1a15
+ -7 -27 -11 -146.74 122.20 130.00 40.14 595.5 1423.8 q1a15
+ -7 -25 -11 1179.03 222.12 873.00 48.73 595.6 1456.1 q1a15
+ -7 -3 -18 73.25 58.41 65.00 36.34 472.2 159.2 q1a0
+ -7 13 -32 -312.27 166.44 171.00 55.82 224.4 1445.8 q0a15
+ -7 21 -44 31.73 76.43 61.00 30.74 64.2 1329.6 q0a14
+ -7 29 -64 101.51 67.69 61.00 14.89 36.2 878.0 q0a8
+ -6 -38 -9 28.87 55.53 47.00 20.33 634.1 1267.8 q1a13
+ -6 -32 -8 -102.19 75.00 60.00 35.49 642.5 1343.9 q1a15
+ -6 -30 -8 42.09 88.55 86.00 36.71 642.3 1377.1 q1a15
+ -6 -8 -12 1132.20 123.86 765.00 18.87 550.2 200.4 q1a2
+ -6 -6 -13 124.28 69.95 67.00 19.08 519.4 192.2 q1a2
+ -6 6 -21 63.65 69.53 80.00 29.88 317.3 329.4 q0a3
+ -5 -41 -7 -29.85 51.88 46.00 19.65 674.4 1216.5 q1a13
+ -5 -31 -5 6.03 75.73 70.00 38.77 689.2 1363.0 q1a15
+ -5 -29 -5 8.22 56.69 59.00 37.98 688.7 1395.8 q1a15
+ -5 -27 -5 -16.03 114.02 118.00 48.23 688.3 1428.1 q1a15
+ -5 -25 -5 1500.28 204.63 460.00 45.52 687.8 1460.1 q1a15
+ -5 -17 -6 142.19 71.71 65.00 27.51 683.5 270.5 q1a3
+ -5 17 -29 302.91 196.26 191.00 57.25 366.0 166.7 q0a1
+ -5 23 -38 -133.65 103.78 110.00 39.85 39.2 1430.3 q0a14
+ -5 29 -50 8.65 52.67 47.00 17.15 242.0 821.8 q0a9
+ -5 33 -62 -2.75 39.16 33.00 14.34 103.5 932.5 q0a10
+ -4 -44 -5 -50.62 61.19 46.00 20.62 715.6 1163.8 q1a13
+ -4 -14 -4 17.33 37.30 63.00 27.67 636.2 306.5 q1a3
+ -4 -6 -7 6270.32 255.50 3406.00 17.18 517.9 281.1 q1a2
+ -4 -4 -8 2344.27 162.17 1611.00 17.71 487.4 272.9 q1a2
+ -4 -2 -9 2570.94 168.66 1889.00 17.76 457.0 264.6 q1a2
+ -4 4 -13 87.16 62.46 52.00 21.49 210.8 362.7 q0a3
+ -4 8 -16 158.88 69.32 159.00 25.12 235.4 298.9 q0a3
+ -4 22 -32 -0.16 136.26 123.00 47.23 372.2 73.3 q0a1
+ -4 30 -47 20.18 40.30 33.00 17.14 294.9 833.6 q0a9
+ -4 32 -52 61.10 57.88 44.00 16.10 240.3 893.5 q0a9
+ -4 34 -58 58.70 68.27 49.00 15.70 173.8 936.5 q0a10
+ -4 36 -65 -16.36 35.55 29.00 14.76 85.6 1019.9 q0a10
+ -3 -21 0 -47.79 110.19 85.00 31.59 741.4 361.5 q1a3
+ -3 -9 -3 291.24 92.97 48.00 11.97 562.0 333.6 q1a2
+ -3 1 -8 444.55 95.04 198.00 17.66 410.0 292.5 q1a2
+ -3 17 -22 109.23 116.56 120.00 52.61 264.6 172.9 q0a1
+ -3 21 -27 206.91 97.44 133.00 55.29 307.2 97.6 q0a1
+ -3 25 -33 -213.78 108.22 92.00 51.24 360.6 14.7 q0a1
+ -3 33 -49 16.71 57.17 68.00 18.09 294.1 905.0 q0a9
+ -2 -44 0 -45.79 79.98 67.00 20.59 928.7 730.3 q2a6
+ -2 -36 2 12.00 51.88 64.00 29.00 1069.4 720.5 q2a7
+ -2 -18 2 41.10 63.34 57.00 31.94 785.1 165.8 q2a0
+ -2 10 -12 151.41 86.53 61.00 19.36 165.6 265.8 q0a2
+ -2 18 -20 108.84 98.10 86.00 51.23 227.3 156.6 q0a1
+ -2 22 -25 -92.77 98.52 98.00 53.61 269.2 81.1 q0a1
+ -2 30 -38 78.73 63.85 49.00 22.29 324.1 378.8 q0a5
+ -2 36 -52 -102.50 54.21 35.00 15.50 282.2 958.6 q0a11
+ -1 -31 5 274.40 135.46 109.00 32.40 1155.5 678.1 q2a7
+ -1 -27 5 -194.16 118.19 110.00 52.96 835.2 27.5 q2a0
+ -1 -25 5 53.50 99.33 91.00 47.50 833.8 59.2 q2a0
+ -1 -13 3 421.12 76.80 224.00 20.88 812.2 214.5 q2a2
+ -1 -7 1 371.41 98.47 524.00 21.79 794.3 304.7 q2a2
+ -1 11 -10 579.62 90.68 438.00 19.38 129.4 249.4 q0a2
+ -1 17 -16 -51.99 110.12 101.00 36.04 176.9 175.2 q0a0
+ -1 25 -26 -297.32 118.28 96.00 49.21 256.8 23.4 q0a1
+ -1 31 -36 -4.77 50.79 45.00 22.61 306.6 418.7 q0a5
+ -1 33 -40 10.28 64.52 51.00 20.52 255.1 380.0 q0a5
+ 0 -46 4 -18.65 42.07 45.00 18.85 895.4 646.5 q2a6
+ 0 -32 7 362.07 190.69 253.00 36.33 1141.0 638.7 q2a7
+ 0 -22 7 -43.96 74.04 83.00 43.10 869.1 107.9 q2a0
+ 0 -12 5 9385.52 312.97 6253.00 20.27 848.1 231.5 q2a2
+ 0 -4 2 24739.22 568.79 8702.00 64.24 821.7 351.7 q2a2
+ 1 -49 5 -29.08 49.03 40.00 17.68 838.3 609.0 q2a6
+ 1 -43 7 -112.74 83.12 53.00 20.14 953.8 601.5 q2a6
+ 1 -39 8 -159.54 74.27 48.00 29.34 1023.3 599.0 q2a7
+ 1 -33 9 -85.66 102.06 134.00 35.46 1126.4 598.8 q2a7
+ 1 -23 9 -67.16 103.94 152.00 46.96 907.6 94.3 q2a0
+ 1 21 -15 -154.19 113.31 118.00 50.49 126.8 103.4 q0a0
+ 1 25 -20 -127.10 150.49 133.00 54.06 167.0 27.0 q0a0
+ 1 31 -29 86.71 64.20 50.00 24.09 316.2 525.1 q0a5
+ 1 37 -41 160.64 69.28 46.00 15.76 162.0 412.5 q0a4
+ 2 -46 8 -10.35 52.99 56.00 20.15 898.7 563.6 q2a6
+ 2 -22 11 102.84 138.79 133.00 43.96 944.3 111.8 q2a0
+ 2 -12 9 3668.06 204.43 1151.00 21.94 921.7 236.2 q2a2
+ 2 -6 7 672.29 105.10 619.00 20.91 903.0 326.3 q2a2
+ 2 4 2 4645.24 221.99 4215.00 18.36 1259.2 359.2 q3a2
+ 2 24 -16 -59.57 113.83 122.00 56.17 113.2 46.8 q0a0
+ 3 -27 13 499.26 130.92 376.00 53.14 985.0 34.8 q2a1
+ 3 -25 13 20.25 139.46 151.00 57.75 982.6 66.7 q2a1
+ 3 -9 10 2621.73 192.69 2065.00 19.29 949.1 283.8 q2a2
+ 3 7 2 173.49 71.49 72.00 14.11 1308.7 338.4 q3a2
+ 3 17 -6 -65.38 89.41 76.00 37.38 13.9 171.8 q0a0
+ 3 19 -8 181.07 84.26 73.00 38.33 29.2 137.0 q0a0
+ 3 37 -34 17.06 72.57 65.00 15.94 174.4 523.1 q0a4
+ 3 41 -43 -21.08 42.30 41.00 15.68 53.9 436.2 q0a4
+ 4 -48 11 -9.86 45.93 41.00 19.26 861.9 510.2 q2a4
+ 4 -18 14 101.90 86.57 181.00 45.41 1005.9 177.8 q2a1
+ 4 -10 12 353.90 83.15 193.00 25.90 984.3 271.6 q2a3
+ 4 -2 9 5214.84 239.75 3829.00 16.96 1173.4 260.9 q3a2
+ 4 0 8 1567.19 139.14 970.00 16.81 1203.8 269.3 q3a2
+ 4 2 7 678.58 99.31 401.00 17.82 1234.2 277.7 q3a2
+ 4 16 -3 -67.78 57.04 57.00 23.98 1453.9 355.7 q3a3
+ 4 22 -9 174.15 97.66 130.00 47.65 14.8 81.3 q0a0
+ 4 36 -29 -48.76 58.90 51.00 24.97 201.5 563.0 q0a7
+ 4 42 -42 101.20 62.02 55.00 16.87 27.6 468.7 q0a4
+ 5 -21 16 261.26 102.08 245.00 54.14 1047.8 133.6 q2a1
+ 5 -15 15 -238.18 100.37 66.00 32.58 1034.2 198.4 q2a3
+ 5 -11 14 61.81 65.09 113.00 27.19 1022.8 259.2 q2a3
+ 5 -5 12 1773.58 147.77 1149.00 26.89 1003.1 349.8 q2a3
+ 5 5 7 1437.10 130.18 683.00 17.10 1283.7 256.6 q3a2
+ 5 11 3 1028.88 111.75 575.00 20.12 1375.1 288.0 q3a3
+ 5 17 -2 -128.71 90.81 96.00 28.91 1474.2 326.1 q3a3
+ 5 19 -4 29.56 150.58 135.00 35.15 1509.0 341.2 q3a3
+ 5 21 -6 -71.77 224.88 139.00 41.61 1544.1 356.5 q3a3
+ 6 -46 15 43.17 54.92 46.00 18.43 903.5 429.1 q2a4
+ 6 -38 17 88.88 61.31 48.00 22.12 1048.9 432.9 q2a5
+ 6 -6 14 145.95 63.62 97.00 27.53 1041.6 337.9 q2a3
+ 6 6 8 36.11 70.52 68.00 18.49 1303.1 226.8 q3a2
+ 6 12 4 303.59 78.84 205.00 23.21 1394.9 258.2 q3a3
+ 6 20 -3 -328.84 257.35 189.00 46.04 1529.6 311.3 q3a3
+ 7 -21 19 2184.70 232.53 540.00 58.70 1118.9 138.1 q2a1
+ 7 -15 18 197.71 129.65 106.00 43.09 1104.2 204.1 q2a3
+ 7 -11 17 -111.01 77.73 67.00 33.61 1092.3 265.4 q2a3
+ 7 7 9 55.28 81.90 62.00 18.52 1322.6 196.8 q3a2
+ 7 33 -17 78.44 61.57 55.00 28.85 268.1 732.3 q0a7
+ 7 35 -20 -134.92 71.52 60.00 27.20 222.9 708.2 q0a7
+ 7 39 -27 -87.95 74.97 68.00 21.55 124.8 650.2 q0a6
+ 7 41 -31 -12.94 51.33 44.00 18.94 68.1 615.6 q0a6
+ 8 16 4 4.79 85.05 89.00 30.41 1469.7 212.5 q3a3
+ 8 26 -6 -100.61 85.76 76.00 39.01 1470.4 1395.3 q3a15
+ 8 38 -23 168.05 87.18 65.00 20.55 148.4 708.0 q0a6
+ 9 -39 21 -30.05 79.09 55.00 15.45 1142.6 876.8 q2a9
+ 9 -29 22 -39.51 80.30 72.00 35.11 784.5 1448.2 q2a14
+ 9 -27 22 1.65 87.53 94.00 36.15 817.6 1452.3 q2a14
+ 9 -25 22 100.64 78.18 64.00 35.76 850.2 1456.3 q2a14
+ 9 -3 17 92.97 130.25 108.00 42.23 1175.2 113.6 q3a0
+ 9 23 -1 -1.97 101.61 181.00 44.77 1409.3 1446.8 q3a15
+ 9 35 -16 72.88 83.01 90.00 20.12 1522.0 1230.0 q3a13
+ 10 -44 21 -34.04 54.48 51.00 16.84 1098.6 942.6 q2a11
+ 10 -40 22 53.25 71.62 60.00 17.75 1103.2 894.3 q2a9
+ 10 -32 23 -91.00 81.93 81.00 23.00 1117.4 752.2 q2a9
+ 10 -22 23 -510.72 181.17 185.00 47.52 901.0 1427.9 q2a14
+ 10 0 17 -134.57 211.00 292.00 47.17 1225.6 91.0 q3a0
+ 10 2 16 -89.51 109.21 127.00 46.11 1256.8 99.5 q3a0
+ 10 4 15 87.75 102.36 98.00 44.66 1287.9 108.0 q3a0
+ 10 28 -5 -33.03 71.87 76.00 33.23 1414.2 1346.1 q3a15
+ 10 38 -19 -12.78 55.96 43.00 16.98 1520.2 1152.2 q3a13
+ 11 -51 20 57.90 40.26 34.00 14.90 1050.7 1085.2 q2a11
+ 11 -21 24 11.53 145.14 153.00 40.27 919.8 1395.2 q2a14
+ 11 -15 23 141.65 105.51 104.00 45.15 1012.2 1412.8 q2a15
+ 11 39 -19 33.99 43.55 43.00 16.61 1494.3 1120.3 q3a13
+ 12 -34 25 32.78 57.21 49.00 18.02 1038.9 783.8 q2a9
+ 12 -20 25 77.18 110.85 109.00 37.42 938.7 1362.2 q2a14
+ 12 -10 23 -180.45 130.28 119.00 53.05 1094.1 1393.7 q2a15
+ 12 22 4 -303.72 157.06 115.00 40.52 1300.2 1445.9 q3a14
+ 12 26 0 148.50 103.93 116.00 32.50 1329.4 1371.5 q3a14
+ 12 32 -7 -41.84 78.53 65.00 22.04 1377.4 1278.2 q3a13
+ 13 -45 24 -53.91 52.74 44.00 15.71 978.1 962.3 q2a11
+ 13 -41 25 -22.56 64.06 49.00 17.56 985.3 911.2 q2a9
+ 13 -35 26 35.78 58.92 64.00 18.02 998.4 800.1 q2a9
+ 13 -21 26 86.22 89.09 72.00 35.98 925.6 1323.9 q2a14
+ 13 -7 23 -182.59 177.42 189.00 51.79 1145.5 1370.3 q2a15
+ 14 -48 24 -46.40 64.88 49.00 12.60 934.9 1024.8 q2a10
+ 14 14 13 193.85 82.93 80.00 42.35 1471.1 21.8 q3a1
+ 14 36 -10 25.19 61.17 46.00 16.81 1347.8 1170.5 q3a12
+ 14 38 -13 63.35 48.60 40.00 16.85 1367.0 1121.7 q3a13
+ 15 -23 28 0.09 51.93 44.00 22.71 898.1 1272.6 q2a12
+ 16 -12 27 224.91 88.96 161.00 28.29 1079.4 1273.4 q2a13
+ 16 2 22 13.51 65.41 63.00 31.89 1474.3 614.6 q3a7
+ 16 4 21 -34.39 83.91 79.00 31.99 1483.5 582.1 q3a7
+ 16 30 0 198.09 59.32 56.00 16.71 1219.1 1284.5 q3a12
+ 16 34 -5 4.34 40.78 36.00 16.46 1254.5 1196.9 q3a12
+ 17 -37 29 45.78 55.46 40.00 18.02 839.7 832.9 q2a8
+ 17 -13 28 43.91 62.44 54.00 24.29 1067.6 1233.2 q2a13
+ 17 21 10 -14.99 76.51 48.00 19.39 1522.3 757.2 q3a9
+ 18 -34 30 -36.75 51.56 44.00 17.75 809.0 775.4 q2a8
+ 18 -22 30 134.79 89.29 68.00 22.41 924.2 1163.6 q2a12
+ 18 -4 26 100.80 68.92 101.00 26.80 1376.8 699.5 q3a7
+ 18 10 19 122.44 61.70 54.00 26.56 1442.7 495.0 q3a5
+ 18 24 8 11.30 54.45 42.00 17.30 1455.2 772.4 q3a9
+ 18 26 6 -136.90 69.88 43.00 17.10 1415.8 758.1 q3a9
+ 19 -17 30 20.04 54.97 48.00 22.16 1009.9 1143.7 q2a13
+ 19 11 19 29.88 48.62 63.00 25.12 1412.4 468.9 q3a5
+ 20 -14 30 124.49 60.18 49.00 20.32 1065.2 1117.1 q2a13
+ 20 -10 29 -93.81 80.44 70.00 23.81 1132.6 1133.6 q2a13
+ 20 -4 27 -250.85 94.34 68.00 23.65 1306.8 686.0 q3a6
+ 21 11 20 78.09 87.48 73.00 21.71 1342.8 449.1 q3a4
+ 23 9 22 -32.86 50.48 44.00 21.26 1256.6 463.3 q3a4
+ 23 19 15 -75.69 50.17 36.00 17.69 1491.6 960.9 q3a11
+ 23 33 1 -21.49 47.36 53.00 13.89 1196.2 888.8 q3a8
+ 24 0 27 56.13 54.67 39.00 16.67 1171.1 586.0 q3a6
+ 24 4 25 119.42 64.24 62.00 20.18 1191.2 541.4 q3a4
+ 24 6 24 -38.94 59.95 52.00 21.94 1201.6 506.0 q3a4
+ 24 24 11 -5.25 52.34 61.00 18.25 1377.5 967.5 q3a11
+ 24 26 9 -85.35 66.45 40.00 16.15 1337.7 953.5 q3a10
+ 24 28 7 -40.31 51.87 43.00 15.31 1294.5 939.4 q3a10
+ 25 31 4 57.27 45.10 33.00 13.53 1208.3 956.5 q3a10
+ 26 16 18 -50.99 70.65 65.00 16.39 1508.1 1097.2 q3a11
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035217_1eafb.h5
+Image serial number: 34
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9521.121104
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9521.121104
+average_camera_length = 0.152001 m
+num_peaks = 17
+peak_resolution = 4.493936 nm^-1 or 2.225221 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 102.50 18.85 2.34 414.66 q0a0
+ 38.50 47.46 2.16 2480.44 q0a0
+ 592.69 99.56 2.09 2051.88 q1a1
+ 612.93 167.07 1.85 1294.32 q1a1
+ 904.50 31.14 2.27 1540.59 q2a0
+1245.91 68.09 2.05 1358.75 q3a0
+1248.50 124.93 1.76 897.11 q3a0
+ 149.50 348.97 0.77 961.75 q0a2
+ 311.50 337.91 1.62 751.64 q0a3
+ 542.40 282.71 1.00 14496.80 q1a2
+1020.68 261.41 1.45 3425.80 q2a3
+1502.21 236.50 1.94 346.06 q3a3
+1463.05 293.50 1.63 873.57 q3a3
+1532.85 618.50 2.65 1684.26 q3a7
+ 321.05 1050.05 4.49 951.79 q0a11
+ 367.24 1379.77 2.55 1471.01 q0a15
+ 924.50 1414.99 2.77 1426.56 q2a14
+End of peak list
+--- Begin crystal
+Cell parameters 6.13662 12.31178 16.89448 nm, 90.57629 89.59942 90.19820 deg
+astar = -0.1176091 +0.1072954 -0.0348151 nm^-1
+bstar = -0.0345707 -0.0537456 -0.0501419 nm^-1
+cstar = -0.0323795 -0.0216545 +0.0445729 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00107 nm^-1
+predict_refine/final_residual = 4.231259e-07
+predict_refine/det_shift x = -0.015 y = 0.078 mm
+diffraction_resolution_limit = 2.57 nm^-1 or 3.89 A
+num_reflections = 103
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -26 22 -31 -64.26 84.53 90.00 44.86 1207.4 994.8 q3a10
+ -24 12 -35 193.18 111.92 105.00 53.42 1185.1 809.5 q3a8
+ -22 6 -36 -84.11 100.75 101.00 54.51 1197.7 1131.8 q3a12
+ -22 20 -19 247.14 104.61 135.00 60.26 1426.1 908.2 q3a9
+ -21 25 -12 -113.14 166.62 207.00 61.74 1536.4 943.8 q3a11
+ -21 33 -7 -108.55 126.27 138.00 69.95 1196.2 405.0 q3a4
+ -20 14 -19 12.93 106.58 102.00 61.67 1449.9 778.0 q3a9
+ -20 18 -15 81.02 161.20 173.00 66.78 1502.5 841.1 q3a9
+ -20 32 -5 56.04 105.92 125.00 68.16 1234.2 441.8 q3a4
+ -20 34 -4 -1.66 131.50 139.00 70.46 1199.7 460.6 q3a4
+ -19 3 -30 359.09 236.09 394.00 67.71 1287.9 1255.2 q3a12
+ -18 -4 -39 40.70 102.17 108.00 60.70 1419.2 1161.9 q3a13
+ -15 -7 -35 -421.01 204.90 217.00 80.61 1503.7 1259.5 q3a13
+ -15 21 -1 87.91 339.68 345.00 125.29 1495.4 532.1 q3a5
+ -15 29 4 -11.69 145.83 165.00 98.69 1374.8 586.1 q3a7
+ -15 33 6 166.82 140.01 171.00 79.58 1314.7 625.3 q3a6
+ -14 -8 -34 -6.81 292.86 265.00 91.51 1531.9 1287.3 q3a13
+ -13 -17 -53 -113.60 113.12 94.00 57.40 68.1 573.9 q0a6
+ -13 -5 -26 -267.12 242.18 381.00 150.12 1490.4 1366.2 q3a15
+ -13 1 -17 21.19 436.69 425.00 190.81 1394.4 1467.3 q3a15
+ -13 15 -2 625.52 345.20 446.00 174.28 1393.4 33.7 q3a1
+ -13 23 4 662.55 379.35 449.00 136.05 1499.5 595.5 q3a7
+ -12 22 5 1864.39 342.58 797.00 143.01 1530.6 618.5 q3a7
+ -12 38 13 65.85 147.67 160.00 76.35 1140.7 1143.1 q2a13
+ -11 -19 -52 51.97 106.44 138.00 62.27 117.5 540.3 q0a4
+ -11 1 -13 11.05 533.06 825.00 171.55 1503.4 237.9 q3a3
+ -11 7 -6 -419.14 254.43 333.00 159.96 1421.8 177.8 q3a1
+ -11 9 -4 347.01 285.16 439.00 155.39 1397.0 149.5 q3a1
+ -11 17 3 366.33 622.32 573.00 229.07 1307.1 37.0 q3a0
+ -10 -22 -59 -8.05 91.65 95.00 57.45 50.1 444.6 q0a4
+ -10 -14 -36 -110.66 180.64 204.00 104.46 317.0 623.8 q0a7
+ -10 -6 -21 335.86 608.08 461.00 237.74 1543.1 1467.1 q3a15
+ -10 -4 -18 62.46 615.75 395.00 209.15 1544.2 327.9 q3a3
+ -10 2 -10 -4.24 147.23 200.00 93.03 1455.3 236.9 q3a3
+ -9 -21 -52 -46.75 135.50 136.00 62.75 155.4 475.3 q0a4
+ -9 -9 -24 430.92 379.66 553.00 187.68 34.9 46.4 q0a0
+ -9 -1 -12 1168.05 194.85 568.00 92.47 1463.8 295.0 q3a3
+ -9 11 1 190.73 174.92 220.00 129.47 1312.4 151.9 q3a0
+ -9 17 6 1326.35 292.36 684.00 167.85 1244.3 68.8 q3a0
+ -9 35 16 -193.84 170.85 207.00 89.04 1073.9 1245.6 q2a13
+ -9 41 18 -470.27 149.77 133.00 76.47 1013.5 1150.9 q2a13
+ -8 -20 -46 -111.75 127.51 148.00 77.75 240.5 498.0 q0a5
+ -8 14 5 1064.55 206.34 615.00 134.05 1247.5 126.0 q3a0
+ -7 5 -2 1689.60 195.91 1399.00 65.60 1324.3 237.0 q3a2
+ -7 7 0 -114.01 171.49 156.00 66.61 1300.0 209.2 q3a2
+ -4 -28 -64 -58.41 81.74 80.00 50.21 255.1 1004.1 q0a11
+ -4 34 21 -24.91 270.90 364.00 123.71 938.9 1322.0 q2a14
+ -4 40 23 7.48 143.16 196.00 77.72 875.1 1259.4 q2a12
+ -4 44 24 12.25 104.72 136.00 71.75 831.7 1196.1 q2a12
+ -3 -29 -66 46.20 112.73 111.00 48.20 203.9 1008.9 q0a11
+ -3 -17 -29 -208.29 502.25 646.00 199.09 254.8 93.7 q0a1
+ -3 -15 -25 -133.31 270.93 324.00 170.31 216.5 134.7 q0a1
+ -3 -5 -9 206.94 105.75 475.00 67.06 54.9 271.9 q0a2
+ -3 51 26 -114.90 94.86 108.00 60.94 783.1 763.8 q2a8
+ -2 -26 -51 -206.34 168.65 188.00 70.54 322.9 837.7 q0a9
+ -2 -22 -39 50.24 172.54 211.00 146.53 376.9 7.9 q0a1
+ -2 30 21 1176.98 335.89 715.00 150.22 925.4 1414.5 q2a14
+ -1 15 13 3353.86 238.56 2473.00 82.74 1021.6 261.8 q2a3
+ -1 21 17 193.49 432.13 446.00 155.11 1101.5 196.5 q2a3
+ -1 33 23 -81.61 245.13 361.00 124.01 865.6 1389.6 q2a14
+ 0 -32 -75 106.82 86.48 89.00 40.58 14.0 1064.4 q0a10
+ 0 14 13 399.20 172.16 607.00 87.20 991.7 246.9 q2a3
+ 1 -25 -43 -352.00 189.69 202.00 115.00 18.4 1382.6 q0a14
+ 1 -13 -17 -15.60 130.51 139.00 83.40 241.6 258.0 q0a3
+ 1 35 25 -300.02 207.31 268.00 110.22 788.8 1397.0 q2a14
+ 2 -22 -34 -737.77 472.29 438.00 160.89 129.7 1444.3 q0a14
+ 3 7 9 1315.06 153.98 947.00 58.94 850.7 251.8 q2a2
+ 3 35 26 638.57 189.38 365.00 76.83 1144.9 753.5 q2a9
+ 4 10 12 257.71 130.01 410.00 70.56 872.7 192.6 q2a2
+ 5 -27 -45 194.00 116.82 148.00 73.86 77.9 1284.4 q0a12
+ 5 -5 -3 2153.72 177.11 2148.00 49.48 478.2 258.8 q1a2
+ 5 1 4 506.10 193.10 697.00 54.10 556.8 344.9 q1a2
+ 5 5 8 1138.55 180.25 1127.00 65.05 788.3 227.2 q2a2
+ 5 33 26 71.43 150.71 159.00 91.17 1127.3 385.9 q2a5
+ 5 39 28 -163.26 181.89 193.00 67.86 1124.5 855.3 q2a9
+ 5 43 29 -7.84 83.26 104.00 63.04 1064.8 904.2 q2a9
+ 6 -2 1 14476.41 426.00 7593.00 58.79 542.0 284.2 q1a2
+ 8 18 19 1459.19 554.98 1231.00 190.81 902.0 31.0 q2a0
+ 8 34 27 22.55 123.88 134.00 72.05 1034.8 429.1 q2a5
+ 9 -19 -24 354.20 561.12 1027.00 183.20 367.4 1375.6 q0a15
+ 10 -20 -26 -110.41 272.38 273.00 153.21 370.1 1331.3 q0a15
+ 10 2 6 162.31 152.35 165.00 86.69 683.0 262.6 q1a3
+ 10 44 30 104.69 128.85 174.00 47.31 1149.6 1034.5 q2a11
+ 11 -5 -2 1294.33 214.33 658.00 139.07 612.7 167.9 q1a1
+ 11 21 21 219.48 327.96 331.00 125.72 1114.1 634.9 q2a7
+ 12 -8 -6 2051.88 401.05 958.00 192.12 592.3 99.3 q1a1
+ 12 18 19 108.99 448.55 405.00 136.61 1125.8 695.1 q2a7
+ 13 -15 -17 -601.40 446.91 427.00 150.60 758.2 621.5 q1a7
+ 14 -24 -36 -96.18 153.14 134.00 76.58 367.1 1153.6 q0a13
+ 14 38 28 -202.59 104.88 98.00 57.79 818.5 496.7 q2a4
+ 16 -16 -20 -283.39 160.25 150.00 99.99 658.4 575.7 q1a7
+ 16 18 18 -31.71 275.22 294.00 81.91 752.5 1269.8 q1a13
+ 18 -22 -34 49.99 115.27 129.00 70.61 451.5 656.5 q1a6
+ 19 13 13 -151.55 157.23 136.00 71.95 612.6 1260.0 q1a13
+ 20 -10 -13 139.76 130.35 123.00 75.64 656.6 420.0 q1a5
+ 21 11 10 26.30 159.57 168.00 64.30 534.1 1237.0 q1a12
+ 22 -10 -15 32.76 106.01 125.00 75.03 590.0 377.2 q1a5
+ 22 -2 -4 151.29 95.04 113.00 62.91 691.0 789.5 q1a9
+ 22 12 10 235.34 133.28 170.00 57.46 519.3 1197.9 q1a12
+ 27 3 -4 11.11 86.47 113.00 55.49 497.6 881.0 q1a8
+ 28 0 -9 53.18 75.90 79.00 47.42 518.7 946.8 q1a10
+ 29 3 -7 158.78 88.33 74.00 42.02 444.8 935.9 q1a10
+ 30 -2 -15 -8.20 81.65 108.00 45.80 499.2 1077.2 q1a10
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035210_1e0c3.h5
+Image serial number: 32
+hit = 1
+indexed_by = none
+photon_energy_eV = 9510.823454
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9510.823454
+average_camera_length = 0.152001 m
+num_peaks = 18
+peak_resolution = 3.437976 nm^-1 or 2.908688 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 177.90 30.50 2.37 363.40 q0a0
+ 43.66 91.15 1.94 1458.04 q0a0
+ 284.85 96.15 2.34 761.07 q0a1
+ 226.66 125.97 2.05 1959.05 q0a1
+1133.79 71.85 2.63 1221.36 q2a1
+1192.36 46.62 2.14 2704.67 q3a0
+ 50.34 232.03 1.04 4750.40 q0a2
+ 60.97 232.50 1.05 1989.45 q0a2
+ 747.78 277.70 1.94 2172.86 q1a3
+ 744.13 332.50 1.83 2615.44 q1a3
+ 687.74 351.50 1.52 2195.16 q1a3
+1334.58 299.64 1.01 3280.83 q3a2
+1226.50 328.87 0.51 1350.38 q3a2
+1102.89 650.89 2.81 472.29 q2a7
+1142.12 797.88 3.44 678.30 q2a9
+ 903.50 1285.93 3.43 507.46 q2a12
+ 740.86 1330.14 2.78 637.26 q1a15
+1242.86 1465.14 2.79 169.51 q3a14
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035138_1b40b.h5
+Image serial number: 35
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9513.960660
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9513.960660
+average_camera_length = 0.152001 m
+num_peaks = 24
+peak_resolution = 4.109684 nm^-1 or 2.433277 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 109.82 118.50 1.85 2098.41 q0a0
+ 481.50 71.47 2.04 1921.68 q1a0
+ 670.95 103.05 2.28 489.60 q1a1
+1449.50 24.09 2.62 999.12 q3a1
+1374.27 45.00 2.35 725.46 q3a1
+ 465.17 203.50 1.19 1855.55 q1a2
+ 550.50 206.74 1.35 873.46 q1a2
+ 553.26 253.30 1.15 5001.33 q1a2
+ 471.33 295.73 0.72 7204.60 q1a2
+ 513.50 339.94 0.66 974.45 q1a2
+ 704.50 238.29 1.83 1163.69 q1a3
+1212.50 303.02 0.63 937.62 q3a2
+1299.93 352.18 0.69 1982.56 q3a2
+1502.73 251.80 1.91 1070.43 q3a3
+ 354.53 639.24 2.73 1290.25 q0a7
+ 351.13 681.13 2.72 781.76 q0a7
+1309.95 799.05 4.11 450.35 q3a8
+ 216.12 1404.12 2.66 781.79 q0a15
+ 713.09 1454.50 2.21 737.93 q1a15
+ 902.78 1429.06 2.77 1509.26 q2a14
+1009.16 1461.16 2.36 1066.81 q2a15
+1050.50 1461.11 2.27 1545.64 q2a15
+1454.04 1444.96 2.32 825.55 q3a15
+1423.93 1458.50 2.32 808.97 q3a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.13167 12.34941 16.88617 nm, 90.08546 89.89776 90.14522 deg
+astar = +0.1174439 -0.1122843 +0.0140370 nm^-1
+bstar = -0.0229555 -0.0330904 -0.0702507 nm^-1
+cstar = +0.0373539 +0.0355892 -0.0290711 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00228 nm^-1
+predict_refine/final_residual = 7.875569e-07
+predict_refine/det_shift x = 0.004 y = -0.006 mm
+diffraction_resolution_limit = 2.66 nm^-1 or 3.76 A
+num_reflections = 212
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -29 9 18 11.34 50.83 38.00 20.46 511.6 1060.2 q1a10
+ -28 8 17 130.30 83.29 131.00 21.81 546.6 1019.9 q1a10
+ -27 5 23 19.51 50.53 52.00 23.91 639.1 1058.0 q1a11
+ -27 11 6 -117.51 78.21 89.00 24.83 479.8 900.6 q1a8
+ -25 3 22 -86.95 71.06 56.00 25.84 707.5 991.8 q1a11
+ -24 10 0 53.91 73.53 64.00 24.96 541.8 765.8 q1a8
+ -23 -1 30 -53.67 68.59 56.00 28.67 474.9 407.4 q1a4
+ -23 3 15 45.84 67.63 59.00 26.49 718.0 895.9 q1a9
+ -23 13 -8 -59.35 64.78 64.00 26.15 438.1 1194.8 q1a12
+ -22 16 -15 -30.36 62.35 56.00 25.76 533.7 1151.1 q1a12
+ -21 7 0 208.87 82.60 72.00 40.33 399.0 1323.4 q1a14
+ -21 15 -15 79.10 88.97 132.00 28.10 553.7 1188.8 q1a12
+ -20 8 -4 -98.36 107.99 79.00 38.76 460.0 1316.9 q1a14
+ -20 14 -15 -22.69 84.69 69.00 25.69 573.2 1225.5 q1a12
+ -19 -1 17 34.36 72.46 75.00 39.73 700.7 426.0 q1a5
+ -19 13 -15 -96.13 93.25 77.00 32.33 589.2 1261.4 q1a13
+ -19 15 -18 -10.08 65.58 56.00 29.68 622.0 1224.8 q1a13
+ -19 17 -21 -120.80 73.96 57.00 29.20 655.4 1187.5 q1a13
+ -18 -6 36 47.67 77.78 77.00 36.33 540.1 581.0 q1a6
+ -18 -4 26 -107.33 84.96 75.00 40.99 636.1 528.0 q1a5
+ -18 -2 18 -55.99 140.79 143.00 45.41 713.4 463.4 q1a5
+ -18 16 -21 105.16 62.55 56.00 29.04 673.4 1224.0 q1a13
+ -17 -7 38 55.86 86.76 118.00 35.51 544.5 625.1 q1a6
+ -17 1 7 104.60 111.31 147.00 67.60 755.7 32.7 q1a1
+ -17 3 2 -14.73 90.91 96.00 53.42 463.3 1466.6 q1a14
+ -16 -8 41 -36.32 104.65 115.00 37.21 538.6 676.2 q1a6
+ -16 -4 21 -80.48 174.12 236.00 52.44 729.1 543.0 q1a5
+ -16 0 8 -108.18 135.22 145.00 73.47 719.2 44.4 q1a1
+ -16 4 -2 301.25 177.06 165.00 57.75 521.4 1459.2 q1a14
+ -16 8 -10 177.22 106.23 120.00 57.98 596.5 1381.2 q1a15
+ -16 12 -17 -153.28 106.78 92.00 51.48 668.2 1307.1 q1a15
+ -16 18 -26 89.79 100.64 73.00 30.41 767.5 1227.2 q1a13
+ -16 22 -31 -248.61 116.95 97.00 37.01 917.2 706.4 q2a6
+ -15 -7 32 109.11 73.15 79.00 43.77 648.1 629.6 q1a7
+ -15 1 4 345.67 177.25 185.00 77.80 727.4 102.3 q1a1
+ -15 9 -13 141.46 108.07 111.00 58.34 645.9 1379.7 q1a15
+ -14 -8 35 -46.21 77.17 113.00 50.62 642.5 679.3 q1a7
+ -14 -6 25 -37.01 166.87 195.00 56.96 736.5 599.0 q1a7
+ -14 0 5 -165.88 216.24 299.00 83.41 691.6 113.3 q1a1
+ -14 24 -35 -101.41 81.89 79.00 33.21 925.6 618.5 q2a6
+ -14 32 -43 3.94 73.06 66.00 30.06 786.0 522.8 q2a4
+ -13 -9 38 -156.24 89.56 91.00 47.27 636.8 729.0 q1a7
+ -13 -5 19 80.61 161.86 171.00 75.13 552.3 7.7 q1a0
+ -13 9 -15 125.81 169.47 263.00 73.19 704.1 1415.5 q1a15
+ -12 -10 43 12.13 50.36 64.00 39.07 353.9 1242.5 q0a13
+ -12 8 -14 1171.69 210.66 537.00 79.31 713.2 1452.2 q1a15
+ -12 34 -46 -63.06 91.17 85.00 31.06 799.6 436.8 q2a4
+ -11 -11 50 -5.53 67.22 63.00 36.68 271.0 1197.3 q0a13
+ -11 3 -5 1153.52 185.99 868.00 50.52 704.8 238.2 q1a3
+ -11 29 -42 127.42 75.69 72.00 30.18 909.2 489.0 q2a4
+ -10 -6 19 1915.01 175.18 1207.00 71.59 480.6 71.5 q1a0
+ -10 12 -22 76.45 145.11 200.00 84.95 814.0 12.8 q2a0
+ -9 -9 31 -186.95 282.71 413.00 96.82 380.8 1394.8 q0a15
+ -9 -7 22 -240.50 165.15 191.00 77.07 433.4 66.4 q1a0
+ -9 11 -21 105.06 175.18 197.00 82.94 822.3 49.3 q2a0
+ -9 13 -24 28.74 139.63 131.00 82.86 854.8 16.4 q2a0
+ -9 25 -39 -62.18 79.89 93.00 39.58 1017.0 500.6 q2a5
+ -9 27 -41 13.06 76.49 77.00 37.94 985.4 469.8 q2a5
+ -9 39 -51 -77.65 74.53 64.00 25.85 1105.2 1097.6 q2a11
+ -8 -12 54 187.67 118.77 172.00 36.80 167.8 1230.0 q0a12
+ -8 -12 55 101.35 128.82 111.00 35.85 159.0 1220.0 q0a12
+ -8 -2 5 893.45 140.48 757.00 30.93 550.1 206.8 q1a2
+ -8 0 0 4188.25 268.79 2625.00 31.65 589.5 251.6 q1a3
+ -8 22 -36 -140.86 167.41 156.00 49.26 1087.3 524.0 q2a5
+ -8 40 -52 43.15 47.81 49.00 25.65 1063.3 1088.6 q2a11
+ -7 -9 29 385.03 387.53 405.00 112.88 351.5 1455.7 q0a15
+ -7 -1 2 4954.40 247.54 2755.00 27.83 552.7 253.6 q1a2
+ -7 7 -15 -226.51 105.84 117.00 57.11 800.3 157.7 q2a0
+ -7 33 -47 -0.85 65.63 65.00 26.65 1152.9 946.0 q2a11
+ -7 41 -53 40.39 54.82 61.00 26.01 1021.0 1079.5 q2a11
+ -6 -10 34 1588.78 171.30 571.00 82.56 288.8 1433.8 q0a15
+ -6 -8 24 -299.01 195.31 164.00 57.35 359.5 350.4 q0a3
+ -6 -4 10 1911.10 160.69 898.00 23.14 464.4 203.9 q1a2
+ -6 8 -17 -43.21 83.48 96.00 57.41 840.1 161.2 q2a0
+ -6 34 -48 -55.81 73.28 65.00 28.81 1113.3 936.8 q2a11
+ -6 38 -51 101.67 59.82 46.00 25.93 1047.8 1001.6 q2a11
+ -5 -11 40 501.07 187.83 414.00 77.96 217.0 1402.9 q0a15
+ -5 11 -22 -67.49 96.48 108.00 62.89 912.3 133.3 q2a0
+ -5 13 -25 338.62 290.75 275.00 77.38 945.1 101.4 q2a0
+ -5 19 -33 -137.43 148.79 138.00 73.83 1037.7 8.5 q2a1
+ -4 -12 49 -111.37 86.09 106.00 61.11 120.6 1344.4 q0a14
+ -4 -2 4 7231.00 274.42 4793.00 22.86 470.4 296.9 q1a2
+ -4 0 -1 817.71 117.95 484.00 26.37 512.4 341.1 q1a2
+ -4 34 -48 17.70 52.40 61.00 32.70 1068.0 912.3 q2a9
+ -3 -11 40 -363.52 256.19 230.00 82.11 176.1 1447.6 q0a14
+ -3 -7 20 -32.11 72.51 83.00 39.27 261.7 318.2 q0a3
+ -3 11 -22 162.66 128.19 117.00 50.09 953.5 177.5 q2a0
+ -3 13 -25 -131.74 145.93 173.00 72.14 983.6 146.1 q2a1
+ -3 19 -33 160.77 101.13 163.00 80.03 1079.9 54.6 q2a1
+ -2 -12 50 248.50 94.26 104.00 53.50 67.1 1381.6 q0a14
+ -2 -12 77 -44.03 72.17 64.00 28.23 47.6 914.0 q0a8
+ -2 -8 24 35.30 77.71 72.00 39.44 274.3 264.4 q0a3
+ -2 16 -29 -319.65 257.27 358.00 90.85 1051.9 123.5 q2a1
+ -2 20 -34 91.52 207.52 291.00 79.28 1115.6 63.9 q2a1
+ -2 44 -55 67.34 45.47 40.00 22.46 852.3 990.7 q2a10
+ -1 -9 29 74.62 105.58 113.00 50.38 294.7 202.4 q0a3
+ -1 21 -35 -177.93 190.34 174.00 75.33 1151.6 73.3 q2a1
+ -1 37 -50 -248.70 107.34 78.00 29.30 955.0 878.4 q2a8
+ 0 22 -36 217.61 123.76 152.00 60.99 854.2 1467.5 q2a14
+ 0 30 -44 95.12 96.95 74.00 35.88 1049.3 748.1 q2a9
+ 0 36 -49 181.41 94.71 64.00 25.79 951.0 835.9 q2a8
+ 0 40 -52 58.91 60.53 59.00 29.29 880.2 897.0 q2a8
+ 1 -11 44 153.92 156.39 168.00 69.08 375.7 59.4 q0a1
+ 1 -11 83 -17.75 43.82 42.00 22.75 58.6 1035.0 q0a10
+ 1 -9 31 15.15 183.07 216.00 82.18 266.6 171.5 q0a1
+ 1 7 -14 486.09 136.44 391.00 29.71 957.9 309.4 q2a2
+ 1 13 -24 248.36 97.76 81.00 46.24 1060.2 213.0 q2a3
+ 1 35 -48 91.40 102.65 104.00 28.40 947.2 794.2 q2a8
+ 1 39 -51 -76.40 56.12 52.00 29.60 876.9 853.4 q2a8
+ 2 -6 19 357.85 96.00 425.00 33.49 148.7 222.4 q0a2
+ 2 12 -22 -199.18 92.75 74.00 47.58 1060.8 253.3 q2a3
+ 3 -11 50 23.00 116.50 88.00 40.00 379.9 385.6 q0a5
+ 3 -11 77 142.41 84.39 63.00 23.79 179.3 1011.9 q0a10
+ 3 -11 78 18.14 70.16 84.00 24.26 168.6 1023.8 q0a10
+ 3 -9 34 -240.42 273.20 355.00 98.25 246.0 104.2 q0a1
+ 3 3 -5 890.36 116.28 520.00 32.01 1211.2 304.8 q3a2
+ 3 5 -9 328.43 103.76 410.00 33.52 1175.8 266.7 q3a2
+ 3 7 -13 39.25 77.00 82.00 39.75 989.3 358.9 q2a3
+ 3 25 -38 -10.51 91.99 113.00 59.11 889.3 1362.1 q2a14
+ 3 27 -40 -111.15 91.89 77.00 51.35 861.5 1329.1 q2a14
+ 4 0 3 1816.44 167.66 879.00 34.56 1299.0 353.9 q3a2
+ 4 22 -34 346.80 185.44 168.00 72.80 958.9 1394.3 q2a14
+ 4 38 -49 -144.91 86.92 74.00 31.71 833.3 752.5 q2a8
+ 5 35 -46 -95.31 80.16 74.00 38.31 805.7 1181.8 q2a12
+ 6 -10 51 91.07 69.47 85.00 36.96 302.9 448.5 q0a5
+ 6 -10 52 -43.45 62.62 62.00 34.52 293.2 440.1 q0a5
+ 6 -10 76 79.51 49.07 46.00 23.89 266.1 1076.5 q0a11
+ 6 -8 35 -695.48 527.36 491.00 106.89 187.0 32.4 q0a0
+ 6 -6 25 -713.40 576.27 719.00 85.03 106.0 119.1 q0a0
+ 6 12 -19 -28.04 194.01 230.00 59.84 1125.3 360.4 q2a3
+ 6 16 -25 -765.89 352.53 338.00 117.49 1095.6 1461.1 q2a15
+ 6 28 -39 -188.46 147.86 131.00 43.66 931.5 1285.5 q2a12
+ 6 30 -41 -146.80 107.80 111.00 40.20 903.7 1250.7 q2a12
+ 7 -9 45 -67.63 189.77 175.00 47.71 337.2 523.5 q0a5
+ 7 -7 32 136.31 216.35 191.00 89.36 138.8 37.8 q0a0
+ 7 -5 23 37.51 124.96 134.00 68.30 65.7 115.8 q0a0
+ 7 9 -13 58.49 103.15 129.00 59.05 1216.9 160.3 q3a0
+ 7 19 -28 205.45 137.95 153.00 77.95 1081.7 1394.5 q2a15
+ 7 23 -33 345.25 125.03 146.00 63.75 1025.0 1325.5 q2a15
+ 7 33 -43 -35.25 78.28 96.00 38.25 891.7 1179.3 q2a12
+ 8 -4 21 94.63 122.01 127.00 64.62 25.6 112.4 q0a0
+ 8 -2 14 42.90 74.78 85.00 45.86 1468.1 354.4 q3a3
+ 8 2 3 709.75 111.37 415.00 37.60 1374.7 258.9 q3a3
+ 8 8 -10 37.29 74.20 132.00 62.91 1263.4 165.0 q3a0
+ 8 12 -17 6.52 228.14 255.00 75.28 1198.0 91.6 q3a0
+ 8 16 -23 88.34 423.12 362.00 106.46 1153.5 1430.5 q2a15
+ 8 34 -43 -26.81 79.43 82.00 39.81 908.5 1143.1 q2a12
+ 9 -7 38 -163.00 203.18 244.00 58.00 358.2 601.8 q0a7
+ 9 -1 13 155.55 102.93 141.00 48.09 1479.7 320.8 q3a3
+ 9 3 2 30.95 74.92 75.00 40.84 1385.9 225.1 q3a3
+ 9 11 -14 437.68 151.61 458.00 71.82 1245.0 96.3 q3a0
+ 9 19 -26 -342.61 185.69 178.00 81.01 1140.4 1363.1 q2a15
+ 10 -8 54 -93.28 105.97 105.00 32.43 182.5 523.5 q0a4
+ 10 -6 36 -25.72 297.89 621.00 63.83 354.6 643.4 q0a7
+ 10 -4 26 -246.10 167.87 178.00 87.43 16.2 27.7 q0a0
+ 10 0 12 -230.04 177.91 194.00 56.10 1491.3 286.9 q3a3
+ 10 10 -11 256.49 214.98 282.00 78.32 1292.0 101.0 q3a0
+ 11 -7 49 107.96 71.99 71.00 39.78 207.2 563.7 q0a7
+ 11 -5 34 -313.10 287.80 282.00 60.33 350.9 685.1 q0a7
+ 11 1 11 1272.89 192.39 501.00 63.33 1503.0 252.8 q3a3
+ 11 25 -31 -18.69 125.78 134.00 46.69 1119.7 1253.7 q2a13
+ 12 -6 46 103.18 71.85 86.00 39.69 213.7 614.7 q0a7
+ 12 8 -4 521.99 228.93 315.00 85.04 1391.0 115.7 q3a1
+ 12 16 -18 -800.19 313.38 269.00 80.49 1544.7 641.8 q3a7
+ 12 26 -31 -22.19 171.00 162.00 46.19 1137.8 1219.5 q2a13
+ 13 -5 44 142.99 96.71 109.00 39.45 210.0 658.0 q0a7
+ 13 -1 23 531.11 138.13 315.00 70.67 1483.2 1394.4 q3a15
+ 13 1 16 1003.16 137.81 393.00 72.51 1424.7 1456.5 q3a15
+ 13 9 -4 -146.93 223.16 258.00 88.73 1410.1 85.7 q3a1
+ 13 11 -8 1244.90 206.02 522.00 86.41 1373.7 45.3 q3a1
+ 13 17 -18 386.95 124.41 283.00 61.45 1512.9 623.0 q3a7
+ 13 23 -26 -83.24 100.62 105.00 51.64 1403.6 707.0 q3a7
+ 14 8 0 -399.00 289.40 353.00 90.14 1466.0 95.8 q3a1
+ 14 10 -4 -99.67 139.75 167.00 81.01 1429.6 55.2 q3a1
+ 14 12 -8 -40.45 142.39 169.00 79.09 1393.0 14.4 q3a1
+ 15 1 22 483.86 113.69 303.00 60.59 1418.9 1359.9 q3a15
+ 15 9 0 132.03 190.04 261.00 79.69 1486.0 65.2 q3a1
+ 15 11 -4 1009.96 155.32 476.00 67.65 1449.4 24.3 q3a1
+ 15 23 -23 96.99 79.87 81.00 45.61 1374.8 637.8 q3a7
+ 15 29 -30 -126.36 77.21 71.00 38.76 1264.6 717.6 q3a6
+ 16 -2 41 28.41 94.00 120.00 31.36 1543.4 1182.3 q3a13
+ 16 2 22 51.28 98.10 100.00 60.85 1389.2 1337.7 q3a15
+ 16 16 -11 -107.79 258.74 262.00 59.59 1495.2 526.1 q3a5
+ 16 26 -25 -112.59 121.11 111.00 40.79 1307.0 641.6 q3a6
+ 17 -1 41 -26.96 64.19 73.00 33.35 1513.2 1157.4 q3a13
+ 17 1 30 -46.90 73.40 80.00 36.57 1425.0 1267.0 q3a13
+ 17 7 10 -116.36 108.09 95.00 55.42 1256.0 1425.2 q3a14
+ 17 9 5 -54.18 114.61 108.00 57.64 1209.0 1470.7 q3a14
+ 17 15 -7 20.34 179.88 173.00 52.46 1505.5 468.4 q3a5
+ 17 25 -22 40.79 83.75 89.00 37.41 1312.3 590.2 q3a6
+ 18 6 16 43.25 86.74 97.00 51.75 1277.8 1348.1 q3a14
+ 18 18 -10 -168.38 84.70 79.00 44.38 1434.0 476.4 q3a5
+ 18 20 -13 -47.78 97.00 81.00 42.98 1394.6 505.8 q3a5
+ 19 3 31 18.18 88.20 74.00 34.36 1369.6 1208.6 q3a13
+ 19 5 23 -99.66 106.71 87.00 37.61 1305.8 1286.7 q3a12
+ 19 9 11 137.97 89.62 114.00 50.08 1198.4 1371.9 q3a14
+ 19 25 -18 116.65 70.10 71.00 34.15 1285.4 536.4 q3a4
+ 20 4 32 108.95 83.49 72.00 29.21 1347.0 1173.2 q3a12
+ 20 6 24 -45.55 70.24 87.00 33.71 1279.7 1252.7 q3a12
+ 20 10 12 135.09 70.44 98.00 44.04 1171.3 1339.6 q3a14
+ 20 12 7 -49.44 75.65 68.00 34.66 1485.8 752.8 q3a9
+ 20 18 -5 -62.61 82.63 87.00 40.01 1414.9 386.4 q3a5
+ 20 26 -17 9.71 62.44 70.00 35.09 1253.1 506.1 q3a4
+ 21 13 8 34.18 66.77 59.00 31.22 1453.1 780.9 q3a9
+ 21 27 -16 49.68 61.50 62.00 33.92 1219.9 475.0 q3a4
+ 23 23 -5 -128.33 112.44 107.00 31.93 1532.0 992.4 q3a11
+ 24 22 0 -47.01 64.37 80.00 29.61 1458.1 978.2 q3a11
+ 25 17 14 -78.49 81.80 120.00 30.68 1295.1 891.3 q3a8
+ 25 27 -5 -14.94 67.18 70.00 29.94 1483.4 1101.1 q3a11
+ 26 26 0 106.68 69.20 155.00 26.78 1406.0 1087.4 q3a11
+ 28 24 12 -77.92 54.90 47.00 24.32 1225.5 1050.7 q3a10
+ 28 26 8 39.64 45.84 49.00 23.76 1267.5 1102.0 q3a10
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035216_1e9ed.h5
+Image serial number: 36
+hit = 1
+indexed_by = none
+photon_energy_eV = 9496.262566
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9496.262566
+average_camera_length = 0.152001 m
+num_peaks = 12
+peak_resolution = 2.389889 nm^-1 or 4.184295 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 13.99 26.50 2.27 277.06 q0a0
+ 855.50 96.93 1.88 1844.07 q2a0
+1192.50 15.92 2.30 1606.98 q3a0
+ 82.86 213.50 1.17 3174.76 q0a2
+ 27.87 270.50 0.82 504.55 q0a2
+ 133.83 302.28 0.87 3071.16 q0a2
+ 916.18 360.50 0.68 1124.61 q2a2
+1305.50 211.24 1.28 1414.45 q3a2
+1194.74 215.46 1.10 6655.51 q3a2
+1194.50 301.70 0.63 1377.99 q3a2
+1482.78 276.50 1.76 1247.05 q3a3
+ 243.50 1450.33 2.39 1547.89 q0a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035231_1fdd3.h5
+Image serial number: 38
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9501.237896
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9501.237896
+average_camera_length = 0.152001 m
+num_peaks = 14
+peak_resolution = 2.498856 nm^-1 or 4.001831 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 110.50 152.83 1.67 775.28 q0a0
+ 249.50 115.05 2.15 1322.55 q0a1
+ 283.50 119.77 2.23 1013.34 q0a1
+ 594.50 9.33 2.50 1386.84 q1a1
+ 801.50 50.47 2.10 2412.61 q2a0
+ 895.14 102.02 1.90 2777.29 q2a0
+1284.83 114.50 1.86 1523.01 q3a0
+1457.51 136.77 2.19 2301.94 q3a1
+ 527.50 298.42 0.87 7311.78 q1a2
+ 511.50 328.98 0.69 2633.12 q1a2
+ 997.57 307.50 1.22 7822.08 q2a3
+1521.26 338.74 1.84 217.28 q3a3
+ 683.14 1425.27 2.39 1356.35 q1a15
+1140.38 1413.57 2.38 2270.60 q2a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.11754 12.39051 16.90174 nm, 90.59255 90.24474 90.41087 deg
+astar = -0.0177321 +0.1537150 +0.0527236 nm^-1
+bstar = +0.0119059 -0.0241101 +0.0761026 nm^-1
+cstar = +0.0582211 +0.0089211 -0.0056312 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00089 nm^-1
+predict_refine/final_residual = 5.622035e-07
+predict_refine/det_shift x = 0.025 y = -0.077 mm
+diffraction_resolution_limit = 2.24 nm^-1 or 4.47 A
+num_reflections = 85
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -23 3 -8 -80.66 133.50 156.00 80.97 1272.5 717.3 q3a6
+ -23 3 33 94.76 90.49 89.00 56.66 1449.6 951.0 q3a11
+ -22 2 -17 37.08 103.83 117.00 76.55 1088.4 1148.7 q2a13
+ -22 4 -1 -44.58 197.03 202.00 85.75 1321.3 635.7 q3a6
+ -20 -12 -61 34.10 78.05 83.00 42.10 807.2 1014.1 q2a10
+ -20 -10 -57 225.75 94.39 79.00 43.25 820.5 940.5 q2a10
+ -20 0 54 74.14 102.03 110.00 54.94 1188.8 840.8 q3a8
+ -20 2 45 -97.77 159.41 138.00 63.89 1319.0 850.7 q3a8
+ -19 -3 -40 128.75 145.65 293.00 71.66 788.5 1217.8 q2a12
+ -19 5 21 112.50 121.69 140.00 87.50 1456.2 417.3 q3a5
+ -17 -13 -64 -260.34 116.85 103.00 46.54 922.8 1055.9 q2a10
+ -16 -8 -54 -88.39 175.66 204.00 62.99 983.0 904.3 q2a9
+ -16 -4 -44 -53.49 115.85 111.00 63.68 1003.4 752.5 q2a9
+ -16 -2 -38 -68.93 136.79 157.00 98.96 817.8 1302.8 q2a14
+ -16 0 -31 -172.03 157.77 205.00 117.82 909.5 1314.4 q2a14
+ -16 0 56 222.19 101.26 112.00 55.81 1184.9 1128.5 q3a12
+ -15 1 52 -120.00 84.32 102.00 56.00 1214.2 1195.1 q3a12
+ -14 -8 -54 165.52 102.04 133.00 63.05 1056.6 901.9 q2a9
+ -14 -4 -44 -37.87 100.60 112.00 69.67 1073.9 752.6 q2a9
+ -14 -2 -38 -8.40 139.04 195.00 113.07 816.9 1372.0 q2a14
+ -14 0 -31 -661.49 332.66 356.00 146.95 907.2 1382.3 q2a14
+ -14 0 56 196.76 99.15 115.00 53.64 1256.0 1147.7 q3a12
+ -13 -13 -64 151.06 82.83 92.00 48.94 1075.2 1044.8 q2a11
+ -13 5 0 285.83 377.68 487.00 198.68 1246.7 47.1 q3a0
+ -13 5 25 914.15 319.07 474.00 159.12 1523.8 80.4 q3a1
+ -12 4 34 -31.56 287.21 295.00 141.89 1285.7 1420.3 q3a14
+ -11 -15 -67 -61.06 126.57 115.00 43.06 1144.7 1099.9 q2a11
+ -11 -3 -40 -36.20 223.86 369.00 134.80 786.8 1469.7 q2a14
+ -11 3 -15 909.05 687.13 460.00 221.59 1155.8 292.0 q2a3
+ -11 3 40 -74.20 212.18 288.00 127.39 1328.2 1354.3 q3a14
+ -11 5 5 66.45 271.31 300.00 152.30 1294.0 116.4 q3a0
+ -11 5 20 1841.37 604.36 1298.00 228.52 1456.6 136.8 q3a1
+ -9 -15 -66 -255.99 112.39 109.00 58.39 805.1 393.6 q2a4
+ -9 3 -12 217.51 289.07 297.00 101.97 1089.8 319.2 q2a3
+ -8 -2 59 -54.92 89.69 101.00 62.20 1464.6 1153.8 q3a13
+ -7 -13 -61 -194.53 100.82 112.00 59.73 891.5 469.3 q2a4
+ -7 -11 -57 508.43 167.37 214.00 59.17 958.2 472.3 q2a4
+ -7 -1 54 255.46 177.33 199.00 70.22 1485.0 1229.6 q3a13
+ -7 1 45 -205.60 191.05 211.00 132.40 1463.8 1318.1 q3a15
+ -7 3 32 45.57 447.47 438.00 197.66 1437.3 1472.6 q3a15
+ -6 -14 -62 149.62 91.72 110.00 55.38 871.0 503.7 q2a4
+ -6 -6 -44 -453.24 418.56 336.00 128.27 1143.9 515.8 q2a5
+ -6 2 -12 7740.70 307.13 6089.00 79.05 998.0 308.3 q2a3
+ -5 -11 -55 163.24 135.95 195.00 79.36 980.4 541.6 q2a5
+ -4 -4 60 373.19 164.73 170.00 65.51 154.8 708.2 q0a6
+ -4 2 29 2052.59 399.69 801.00 134.68 1521.9 341.3 q3a3
+ -3 -1 -21 179.01 140.31 139.00 70.61 918.5 195.7 q2a2
+ -2 -4 -31 2384.49 374.13 1083.00 151.85 893.8 102.5 q2a0
+ -1 -1 39 781.65 265.01 527.00 170.78 70.4 18.8 q0a0
+ -1 1 6 14095.48 812.16 8757.00 185.62 8.1 351.8 q0a2
+ -1 1 19 545.48 126.82 209.00 64.81 29.1 213.0 q0a2
+ 0 -10 -45 -573.11 423.27 414.00 136.70 1104.5 683.0 q2a7
+ 1 -9 65 -290.19 169.71 220.00 67.19 109.1 541.3 q0a4
+ 1 -7 -34 2550.82 379.16 2075.00 184.47 799.2 51.2 q2a0
+ 1 -1 28 611.01 167.10 521.00 128.61 108.9 153.1 q0a0
+ 3 -9 -35 668.88 833.00 739.00 235.88 753.5 1435.6 q1a15
+ 3 -7 -28 -152.07 404.94 341.00 125.94 746.0 344.7 q1a3
+ 3 -3 -7 2483.10 211.08 1379.00 52.16 510.8 329.9 q1a2
+ 4 -6 -20 507.84 144.18 345.00 76.66 657.9 308.5 q1a3
+ 4 -4 -8 7063.89 291.08 6507.00 53.06 527.0 299.0 q1a2
+ 5 -11 -35 450.29 379.33 394.00 168.14 685.6 1421.8 q1a15
+ 5 -7 -20 44.44 149.46 160.00 77.97 664.1 275.5 q1a3
+ 5 -5 33 1262.55 424.31 786.00 195.09 249.0 114.9 q0a1
+ 6 -20 -54 -18.56 138.40 147.00 60.56 632.8 1164.3 q1a13
+ 6 -10 53 115.42 128.96 137.00 78.11 294.5 412.6 q0a5
+ 6 -8 -20 57.91 177.44 325.00 88.33 670.3 242.2 q1a3
+ 6 -6 33 1036.71 404.71 790.00 197.99 283.3 119.3 q0a1
+ 7 -15 -40 31.21 193.74 224.00 125.53 612.3 1338.9 q1a15
+ 9 -13 -26 277.57 424.55 474.00 197.66 763.8 164.6 q1a1
+ 10 -12 41 -309.42 239.93 453.00 127.25 36.9 1422.7 q0a14
+ 10 -10 -3 653.85 195.73 559.00 140.62 507.4 118.6 q1a0
+ 11 -13 39 328.40 155.62 204.00 117.97 64.9 1390.5 q0a14
+ 11 -11 24 -770.06 538.21 480.00 211.88 235.8 1439.8 q0a15
+ 12 -14 -12 -636.20 360.29 423.00 189.45 620.8 50.0 q1a1
+ 12 -12 8 -145.66 361.95 514.00 192.65 398.7 28.9 q1a0
+ 12 -12 17 1404.55 438.30 494.00 210.09 319.2 1418.7 q0a15
+ 13 -15 -9 1474.52 235.94 819.00 160.42 594.1 9.0 q1a1
+ 14 -26 66 -80.91 93.63 92.00 39.71 21.5 991.9 q0a10
+ 15 -31 -47 -198.50 110.95 96.00 53.50 443.6 846.2 q1a8
+ 15 -25 -34 -65.18 96.82 99.00 59.72 652.3 808.3 q1a9
+ 15 -25 59 199.08 135.85 136.00 59.20 27.1 906.8 q0a8
+ 15 -19 -13 -248.90 339.00 305.00 123.67 731.5 493.6 q1a5
+ 15 -19 38 194.46 98.02 135.00 76.54 91.7 1249.1 q0a12
+ 15 -17 2 -583.87 396.57 393.00 140.69 720.1 641.1 q1a7
+ 21 -29 4 214.85 115.40 146.00 70.49 414.0 606.9 q1a6
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035032_156de.h5
+Image serial number: 37
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 4
+photon_energy_eV = 9513.558696
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9513.558696
+average_camera_length = 0.152001 m
+num_peaks = 24
+peak_resolution = 4.616073 nm^-1 or 2.166343 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 17.50 14.15 2.33 5676.17 q0a0
+ 456.42 51.09 2.13 4001.71 q1a0
+ 616.50 78.96 2.23 2601.56 q1a1
+ 901.39 56.67 2.13 4055.92 q2a0
+1204.50 171.82 1.50 478.26 q3a0
+ 69.27 237.06 1.03 26872.15 q0a2
+ 293.67 288.33 1.62 1416.54 q0a3
+ 406.80 202.38 1.18 8999.01 q1a2
+ 409.72 228.24 1.03 1573.73 q1a2
+ 471.42 240.33 1.01 4434.00 q1a2
+ 546.50 258.34 1.11 2167.10 q1a2
+ 431.43 267.33 0.82 14632.16 q1a2
+ 815.50 202.89 1.15 841.35 q2a2
+ 796.01 208.50 1.12 1308.46 q2a2
+ 861.21 276.03 0.81 4683.19 q2a2
+ 931.23 301.77 0.93 978.75 q2a2
+ 855.22 306.50 0.65 2478.56 q2a2
+1274.73 279.50 0.88 2330.62 q3a2
+1293.93 302.50 0.84 360.55 q3a2
+ 757.88 814.50 3.49 412.59 q1a9
+1310.07 798.93 4.11 -129.05 q3a8
+ 180.97 993.50 4.62 353.06 q0a10
+ 126.93 1281.50 3.46 422.49 q0a12
+ 281.12 1386.75 2.61 1850.74 q0a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.18346 12.14485 17.08652 nm, 90.43754 90.51423 90.09992 deg
+astar = +0.0296497 -0.1589110 +0.0049300 nm^-1
+bstar = +0.0731646 +0.0145804 +0.0348505 nm^-1
+cstar = -0.0241614 -0.0033929 +0.0532019 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00170 nm^-1
+predict_refine/final_residual = 3.489117e-07
+predict_refine/det_shift x = 0.044 y = -0.028 mm
+diffraction_resolution_limit = 2.23 nm^-1 or 4.48 A
+num_reflections = 165
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -26 -20 -10 125.26 209.50 244.00 66.14 737.2 1094.4 q1a11
+ -25 -37 -5 24.99 81.16 96.00 51.61 408.9 1041.7 q1a10
+ -25 -21 -8 -408.48 248.44 268.00 76.28 722.6 1045.3 q1a11
+ -24 -26 -5 -84.46 107.23 126.00 69.66 633.5 993.9 q1a11
+ -23 -37 -2 54.97 115.28 120.00 52.23 427.2 946.3 q1a10
+ -23 -13 -8 58.54 156.40 170.00 85.66 529.4 438.3 q1a4
+ -23 -11 -9 -279.85 374.07 410.00 97.65 524.3 474.2 q1a4
+ -22 -2 -13 -172.76 179.04 207.00 95.36 538.6 610.6 q1a6
+ -22 2 -16 336.94 194.65 421.00 97.06 522.6 684.8 q1a6
+ -21 -25 -1 -164.60 105.46 117.00 74.40 668.3 892.9 q1a9
+ -21 15 -27 -44.54 118.57 149.00 91.34 204.4 1122.8 q0a13
+ -20 -24 0 -17.75 82.36 101.00 73.75 691.5 854.1 q1a9
+ -20 18 -29 -63.27 145.98 157.00 95.47 145.8 1145.9 q0a12
+ -19 -39 3 -138.61 118.12 119.00 65.01 420.4 801.9 q1a8
+ -19 -37 3 56.36 111.05 105.00 64.24 459.9 802.6 q1a8
+ -19 1 -11 -20.44 151.44 229.00 131.44 645.1 664.9 q1a7
+ -19 15 -24 131.73 157.52 155.00 96.47 213.2 1208.1 q0a13
+ -18 -36 4 96.30 119.16 137.00 64.30 486.8 763.9 q1a8
+ -18 -10 -3 -305.69 454.08 376.00 140.69 716.5 504.2 q1a5
+ -18 30 -44 262.62 140.07 130.00 68.38 33.5 867.3 q0a8
+ -17 -17 1 -227.04 287.95 345.00 131.90 769.0 390.0 q1a5
+ -17 -3 -6 58.77 412.81 455.00 165.03 732.4 597.4 q1a7
+ -17 19 -26 517.79 211.36 351.00 102.41 137.2 1263.4 q0a12
+ -16 -40 6 141.50 116.37 116.00 66.50 413.5 1126.3 q1a12
+ -16 -38 6 -39.15 111.57 126.00 67.35 411.9 1164.9 q1a12
+ -16 -36 6 32.25 143.61 144.00 72.75 410.3 1202.8 q1a12
+ -16 -28 5 -215.43 162.09 182.00 114.83 400.5 1319.5 q1a14
+ -16 0 -7 521.15 632.03 470.00 208.65 757.9 650.5 q1a7
+ -16 12 -17 -121.00 248.98 267.00 171.00 281.1 1313.0 q0a15
+ -15 -29 6 -143.77 139.56 161.00 104.97 437.3 1307.7 q1a14
+ -15 11 -15 363.98 362.73 627.00 206.22 300.5 1353.5 q0a15
+ -15 13 -17 -31.09 231.36 316.00 171.29 262.1 1344.0 q0a15
+ -15 15 -19 -345.19 255.55 350.00 178.19 223.3 1334.5 q0a15
+ -15 35 -49 291.50 92.96 268.00 59.50 110.3 975.8 q0a10
+ -14 4 -8 -504.52 389.54 507.00 219.72 406.1 8.3 q1a0
+ -14 12 -15 1074.39 324.44 710.00 203.01 281.6 1383.9 q0a15
+ -14 14 -17 -56.64 330.22 427.00 197.24 243.4 1374.6 q0a15
+ -14 24 -29 -185.94 236.72 226.00 127.94 33.2 1317.5 q0a14
+ -14 28 -35 -55.85 141.56 139.00 81.65 222.2 779.1 q0a9
+ -14 38 -54 13.43 80.17 98.00 56.17 115.0 1079.2 q0a10
+ -13 -11 2 -248.19 469.67 484.00 231.19 650.5 85.3 q1a1
+ -13 -9 1 1530.83 506.81 1199.00 250.57 617.9 80.2 q1a1
+ -13 1 -5 4304.50 406.57 2229.00 216.50 455.6 51.5 q1a0
+ -13 21 -24 746.33 225.26 504.00 152.07 103.8 1373.0 q0a14
+ -12 -42 9 -325.27 123.58 113.00 70.29 561.1 1117.2 q1a12
+ -12 -36 9 -223.51 220.20 204.00 79.11 551.9 1229.3 q1a12
+ -12 -14 4 1554.55 596.05 589.00 264.05 695.4 124.9 q1a1
+ -12 -4 -1 -573.09 416.29 529.00 214.29 536.3 99.0 q1a0
+ -12 2 -5 728.83 332.91 627.00 196.57 436.4 80.6 q1a0
+ -12 20 -22 298.35 327.46 516.00 180.85 125.3 1413.0 q0a14
+ -12 30 -36 -7.56 200.71 293.00 83.56 282.8 824.3 q0a9
+ -12 36 -47 -136.49 134.25 168.00 67.89 225.8 982.6 q0a11
+ -11 -21 7 98.11 592.37 505.00 211.49 555.9 1463.2 q1a14
+ -11 -15 5 -460.80 653.86 530.00 269.20 707.5 159.0 q1a1
+ -11 -3 -1 364.74 202.21 418.00 166.86 516.8 127.7 q1a0
+ -11 3 -5 1031.09 247.49 629.00 164.71 417.5 109.4 q1a0
+ -11 19 -20 297.42 549.12 519.00 211.18 146.3 1452.2 q0a14
+ -11 35 -44 152.93 108.28 122.00 63.67 276.2 943.2 q0a11
+ -10 -34 10 -523.41 248.37 310.00 101.21 612.2 1277.4 q1a13
+ -10 -2 -1 735.69 180.20 397.00 145.31 497.5 156.1 q1a0
+ -10 36 -45 -101.55 86.06 97.00 65.95 305.1 971.8 q0a11
+ -9 7 -7 -122.64 274.17 297.00 130.24 314.0 344.0 q0a3
+ -9 21 -21 380.25 316.70 521.00 199.75 371.3 108.3 q0a1
+ -8 -36 11 229.07 218.23 273.00 89.33 681.5 1254.5 q1a13
+ -8 10 -9 1683.30 206.02 1091.00 117.30 294.0 289.2 q0a3
+ -8 18 -17 286.51 732.93 638.00 301.89 325.7 167.6 q0a1
+ -7 -13 6 148.64 173.34 259.00 95.76 658.3 249.4 q1a3
+ -7 -3 1 216.80 150.07 130.00 57.80 503.3 221.5 q1a2
+ -7 3 -3 8798.45 332.71 4997.00 57.95 405.7 203.0 q1a2
+ -7 21 -20 -1120.02 609.42 550.00 251.22 307.5 104.9 q0a1
+ -7 31 -34 -9.90 129.04 136.00 90.10 289.5 403.9 q0a5
+ -6 -24 10 34.21 727.80 551.00 275.59 715.7 1440.1 q1a15
+ -6 -6 3 1808.85 249.31 1205.00 68.35 546.6 259.9 q1a2
+ -6 2 -2 -80.39 172.38 189.00 56.99 418.0 235.8 q1a2
+ -6 14 -12 -83.04 130.12 181.00 107.84 248.3 210.7 q0a3
+ -6 30 -32 154.38 169.91 213.00 103.62 313.8 443.3 q0a5
+ -5 1 -1 14561.25 407.44 8559.00 57.75 430.3 268.4 q1a2
+ -5 19 -17 -13.16 448.81 518.00 225.96 237.2 139.7 q0a1
+ -5 29 -30 -532.33 405.19 369.00 133.93 337.5 482.0 q0a5
+ -5 37 -44 -74.77 131.11 156.00 71.97 109.9 428.1 q0a4
+ -5 39 -48 -224.73 132.71 128.00 71.53 41.1 411.6 q0a4
+ -4 -44 12 22.56 115.31 127.00 78.44 894.3 704.1 q2a6
+ -4 -34 12 396.01 324.01 363.00 134.37 1070.1 732.9 q2a7
+ -4 -16 8 654.21 200.68 421.00 99.59 690.6 346.7 q1a3
+ -3 -33 12 -66.04 372.44 494.00 143.84 1093.1 704.8 q2a7
+ -3 -5 3 1786.05 216.84 1468.00 58.55 516.5 344.5 q1a2
+ -3 33 -36 -97.14 258.67 298.00 97.74 224.6 523.0 q0a5
+ -2 -32 12 -624.29 560.12 491.00 178.09 1115.9 677.1 q2a7
+ -2 -26 11 2017.88 473.15 705.00 226.12 821.6 21.5 q2a0
+ -2 -22 10 -674.46 347.34 417.00 195.66 810.3 85.4 q2a0
+ -2 22 -20 2452.69 530.09 634.00 246.31 161.6 67.0 q0a0
+ -1 -47 12 9.68 117.32 132.00 69.92 857.2 596.1 q2a6
+ -1 -13 7 938.20 153.77 556.00 74.20 814.4 202.4 q2a2
+ -1 7 -5 992.02 157.11 849.00 79.78 80.4 311.3 q0a2
+ 0 -46 12 -15.39 103.38 128.00 72.99 883.0 567.0 q2a6
+ 0 -22 10 -649.67 311.04 321.00 189.07 869.4 96.6 q2a0
+ 1 -27 11 835.05 642.16 611.00 247.55 914.4 22.8 q2a0
+ 1 -19 9 6.58 176.74 233.00 152.82 889.8 149.5 q2a0
+ 1 -9 5 4595.61 251.56 1809.00 76.99 860.2 276.1 q2a2
+ 1 -7 4 2535.70 200.29 1783.00 79.70 854.2 307.3 q2a2
+ 1 21 -19 836.61 433.46 659.00 212.99 68.5 70.8 q0a0
+ 2 -28 11 397.56 469.90 486.00 227.44 947.7 12.6 q2a0
+ 2 -14 7 379.60 152.53 179.00 84.60 904.3 204.7 q2a2
+ 2 -2 1 -252.85 1104.36 823.00 310.65 1173.3 352.8 q3a2
+ 3 23 -22 5183.83 535.41 3359.00 238.57 16.0 14.5 q0a0
+ 4 -48 11 150.07 122.42 142.00 70.33 870.5 453.1 q2a4
+ 4 34 -39 -38.44 181.14 217.00 81.44 147.8 713.6 q0a6
+ 5 -35 11 628.14 320.80 323.00 121.26 1109.0 479.1 q2a5
+ 5 -27 10 -362.27 325.36 434.00 221.47 1032.0 47.3 q2a1
+ 6 -10 4 60.31 180.59 198.00 102.69 1004.9 293.1 q2a3
+ 6 -8 3 56.73 136.25 160.00 99.47 998.5 324.5 q2a3
+ 7 -33 10 146.53 457.96 523.00 144.42 1156.1 424.7 q2a5
+ 7 -9 3 155.30 138.47 160.00 100.30 1031.1 316.2 q2a3
+ 7 23 -24 -14.51 260.72 321.00 180.11 1466.2 1381.4 q3a15
+ 8 20 -21 -69.27 406.35 448.00 210.47 1427.0 1435.1 q3a15
+ 8 24 -26 -17.56 222.41 321.00 154.56 1438.4 1347.9 q3a15
+ 9 -27 8 124.70 425.89 455.00 202.70 1155.7 73.9 q2a1
+ 9 -23 7 -90.12 563.06 646.00 255.12 1140.2 138.4 q2a1
+ 9 21 -23 -497.56 312.88 345.00 193.56 1399.1 1402.4 q3a15
+ 9 33 -41 -292.26 144.95 147.00 76.86 1430.6 1121.8 q3a13
+ 10 -48 8 -180.93 101.08 133.00 62.33 1071.5 977.8 q2a11
+ 11 -3 -3 -129.56 197.90 273.00 172.56 1225.6 114.9 q3a0
+ 11 9 -12 -464.77 354.83 388.00 228.97 1427.7 149.3 q3a1
+ 11 17 -20 -255.45 607.61 499.00 230.05 1329.4 1462.7 q3a14
+ 12 -42 7 254.01 112.03 197.00 74.39 1036.5 878.3 q2a9
+ 12 -40 7 123.89 136.73 189.00 79.51 1048.1 841.9 q2a9
+ 12 -38 7 9.68 93.80 129.00 79.92 1059.4 806.3 q2a9
+ 12 -28 6 -44.02 319.53 441.00 149.22 851.0 1398.5 q2a14
+ 12 -20 4 1964.59 400.53 502.00 213.25 977.5 1432.7 q2a15
+ 12 -10 0 -865.81 723.10 598.00 305.81 1136.9 1470.0 q2a15
+ 12 30 -39 -187.71 190.17 223.00 84.91 1325.4 1161.0 q3a12
+ 13 -23 4 -281.69 443.96 445.00 188.69 940.5 1387.7 q2a14
+ 13 3 -9 2401.76 697.33 678.00 297.64 1346.6 70.2 q3a0
+ 13 9 -14 447.44 414.39 506.00 228.56 1450.8 86.4 q3a1
+ 13 21 -27 192.05 205.28 219.00 135.55 1274.2 1347.9 q3a14
+ 14 -52 4 -71.69 86.39 100.00 51.69 894.5 1034.4 q2a10
+ 14 -14 0 488.34 292.80 466.00 218.46 1091.1 1391.5 q2a15
+ 14 -6 -4 -306.33 503.38 592.00 244.93 1205.5 10.8 q3a0
+ 14 10 -16 226.59 367.82 513.00 210.21 1481.9 56.7 q3a1
+ 14 20 -27 375.77 159.89 206.00 125.03 1238.5 1354.4 q3a14
+ 15 -45 4 -201.39 190.64 247.00 75.99 908.3 913.9 q2a8
+ 15 19 -27 -326.61 208.99 224.00 130.01 1202.6 1361.0 q3a14
+ 16 -52 2 146.70 93.89 93.00 48.70 812.6 1022.2 q2a10
+ 16 -12 -3 -535.84 421.70 440.00 209.04 1143.3 1332.6 q2a15
+ 17 -43 2 111.70 98.05 102.00 69.70 844.4 861.3 q2a8
+ 17 -5 -8 -1347.64 519.67 442.00 200.24 1494.8 648.7 q3a7
+ 17 7 -17 218.14 498.71 445.00 171.26 1530.2 463.2 q3a5
+ 17 15 -25 -228.62 177.98 204.00 100.62 1514.7 750.6 q3a9
+ 18 -18 -3 349.36 248.79 278.00 113.24 1065.7 1264.8 q2a13
+ 19 -31 -1 259.09 145.18 144.00 79.71 858.9 1159.8 q2a12
+ 19 -3 -12 -227.40 206.96 201.00 133.60 1430.6 588.0 q3a7
+ 19 13 -26 211.04 187.16 207.00 91.16 1519.9 828.0 q3a9
+ 19 21 -36 241.30 170.28 131.00 77.30 1332.6 817.2 q3a8
+ 19 23 -39 88.16 103.64 134.00 75.04 1277.4 816.2 q3a8
+ 20 -20 -5 384.69 140.04 164.00 92.31 1054.1 1180.7 q2a13
+ 21 1 -18 206.77 164.41 250.00 107.03 1367.2 512.2 q3a5
+ 21 21 -40 -31.84 110.87 152.00 77.04 1278.8 900.3 q3a8
+ 21 23 -43 -26.84 107.50 129.00 71.04 1221.0 900.5 q3a8
+ 22 0 -19 -15.48 197.01 189.00 96.28 1327.4 513.1 q3a4
+ 23 -1 -20 481.68 179.19 192.00 89.92 1283.5 514.1 q3a4
+ 23 9 -29 -46.52 204.73 214.00 79.72 1522.9 968.3 q3a11
+ 23 15 -36 49.36 112.55 120.00 72.24 1380.4 962.5 q3a11
+ 24 -10 -16 72.76 151.17 166.00 98.64 1209.3 636.0 q3a6
+ 24 14 -37 59.81 117.20 123.00 71.19 1377.1 1009.2 q3a11
+ 25 -1 -24 153.40 142.81 195.00 89.40 1195.5 473.3 q3a4
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035155_1cc11.h5
+Image serial number: 40
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 2
+photon_energy_eV = 9501.718951
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9501.718951
+average_camera_length = 0.152001 m
+num_peaks = 28
+peak_resolution = 3.176093 nm^-1 or 3.148522 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 145.35 18.50 2.38 68.51 q0a0
+ 470.50 11.95 2.33 1455.20 q1a0
+ 477.88 50.27 2.15 2204.11 q1a0
+ 429.50 56.91 2.09 1021.01 q1a0
+ 697.96 84.04 2.43 308.70 q1a1
+ 662.19 171.11 1.98 889.96 q1a1
+ 883.05 48.17 2.16 1015.02 q2a0
+1321.48 47.87 2.23 1418.44 q3a0
+ 106.15 309.50 0.74 973.72 q0a2
+ 298.50 214.86 1.85 1162.01 q0a3
+ 366.02 261.56 2.02 4508.09 q0a3
+ 493.85 240.93 1.05 4471.19 q1a2
+ 460.04 254.50 0.92 4323.72 q1a2
+ 519.07 280.50 0.92 1745.93 q1a2
+ 793.50 325.74 0.48 1011.56 q2a2
+ 846.08 328.50 0.52 718.85 q2a2
+ 912.11 331.50 0.74 736.34 q2a2
+1059.50 197.76 1.82 1519.35 q2a3
+1207.50 203.76 1.17 2129.71 q3a2
+1307.50 220.14 1.24 437.86 q3a2
+1211.50 225.16 1.05 1472.68 q3a2
+1286.76 256.50 1.01 2596.10 q3a2
+1339.42 297.81 1.03 6373.28 q3a2
+1181.89 302.78 0.63 4844.66 q3a2
+1303.97 326.70 0.78 1160.95 q3a2
+1172.43 342.32 0.42 4644.02 q3a2
+ 336.15 543.50 2.95 691.61 q0a5
+1445.50 539.04 3.17 388.50 q3a5
+End of peak list
+--- Begin crystal
+Cell parameters 6.19546 12.20876 16.70929 nm, 89.50255 89.82749 90.59593 deg
+astar = -0.0347920 -0.0568880 +0.1470001 nm^-1
+bstar = -0.0470346 +0.0653463 +0.0150943 nm^-1
+cstar = -0.0470289 -0.0292693 -0.0226616 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00292 nm^-1
+predict_refine/final_residual = 4.179324e-07
+predict_refine/det_shift x = 0.000 y = -0.002 mm
+diffraction_resolution_limit = 2.14 nm^-1 or 4.66 A
+num_reflections = 303
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -21 5 -61 -104.96 83.46 84.00 43.16 34.3 1012.5 q0a10
+ -20 4 -60 -36.09 69.01 67.00 41.29 81.9 991.0 q0a10
+ -19 -5 -61 34.15 95.53 113.00 42.65 220.5 1084.6 q0a11
+ -19 -1 -60 -299.26 177.95 163.00 48.86 175.4 1027.1 q0a10
+ -19 5 -58 -62.95 74.23 71.00 44.55 106.3 938.2 q0a10
+ -18 -4 -59 -45.60 80.77 82.00 45.40 242.1 1030.4 q0a11
+ -18 8 -55 -88.75 118.42 156.00 55.75 108.3 883.3 q0a8
+ -18 10 -54 80.76 99.35 97.00 55.64 87.2 852.0 q0a8
+ -18 12 -53 -82.12 109.39 99.00 59.12 66.2 820.8 q0a8
+ -17 -7 -58 125.95 89.79 198.00 47.45 310.1 1033.6 q0a11
+ -17 -3 -57 -24.44 81.62 79.00 45.44 262.9 978.1 q0a11
+ -16 -14 -57 -76.97 98.27 91.00 50.77 26.1 379.2 q0a4
+ -16 4 -53 -190.40 184.17 175.00 63.60 216.1 871.1 q0a9
+ -16 12 -49 312.91 123.25 122.00 56.29 137.1 750.0 q0a8
+ -15 -17 -55 162.16 108.95 110.00 52.04 30.4 449.2 q0a4
+ -15 -15 -55 -16.85 93.71 102.00 50.65 54.6 422.7 q0a4
+ -15 -13 -55 -1.55 79.03 80.00 47.95 78.5 396.6 q0a4
+ -15 -7 -54 -291.00 164.73 142.00 52.00 373.6 955.0 q0a11
+ -15 1 -52 96.25 82.05 117.00 57.75 281.6 876.5 q0a9
+ -15 39 -21 -70.14 125.48 137.00 71.06 401.4 640.8 q1a6
+ -14 -20 -53 -170.16 105.40 97.00 55.96 34.7 517.9 q0a4
+ -14 -18 -53 -255.70 118.34 103.00 55.30 58.6 491.4 q0a4
+ -14 -16 -53 -69.69 90.82 98.00 52.69 82.3 465.1 q0a4
+ -14 -14 -53 16.46 96.02 119.00 55.34 105.8 439.1 q0a4
+ -14 26 -34 -205.93 118.96 109.00 69.33 261.9 1167.8 q0a13
+ -14 28 -32 138.86 118.15 119.00 72.74 299.9 1151.3 q0a13
+ -14 34 -25 202.58 95.20 143.00 66.89 477.3 722.8 q1a6
+ -14 44 -9 -95.75 126.07 189.00 60.34 412.1 488.5 q1a4
+ -13 3 -47 205.80 126.93 143.00 66.80 323.5 777.6 q0a9
+ -13 5 -46 359.04 114.30 104.00 62.16 303.7 748.6 q0a9
+ -13 11 -43 -175.57 150.08 166.00 96.17 49.4 1308.9 q0a14
+ -13 17 -39 327.52 255.71 331.00 86.28 143.4 1281.2 q0a12
+ -13 21 -36 117.31 148.69 165.00 74.69 206.0 1245.4 q0a13
+ -13 29 -28 251.37 145.03 202.00 76.65 356.2 1180.8 q0a13
+ -13 41 -11 -39.21 133.11 146.00 60.41 471.1 536.2 q1a4
+ -13 43 -7 24.43 77.53 101.00 56.57 461.3 474.8 q1a4
+ -13 51 14 -27.97 94.23 87.00 44.90 593.5 1061.7 q1a11
+ -13 53 22 -93.49 62.97 70.00 39.68 474.6 1058.2 q1a10
+ -12 -30 -47 -75.91 95.16 96.00 56.71 10.9 691.9 q0a6
+ -12 -10 -48 76.21 104.08 135.00 67.59 229.3 450.2 q0a5
+ -12 2 -45 -230.85 179.17 197.00 72.65 365.4 755.1 q0a9
+ -12 10 -41 256.15 181.16 185.00 102.65 70.5 1351.4 q0a14
+ -12 12 -40 283.93 159.52 181.00 99.67 98.8 1331.9 q0a14
+ -12 40 -9 169.40 122.16 103.00 61.40 518.5 522.2 q1a4
+ -12 42 -5 -125.91 113.61 103.00 62.71 509.3 461.4 q1a4
+ -12 46 4 194.55 138.63 135.00 50.66 762.8 1005.1 q1a11
+ -12 48 10 88.68 75.74 76.00 49.21 674.7 1007.9 q1a11
+ -12 50 17 -143.06 117.95 91.00 47.76 574.1 1007.0 q1a10
+ -12 52 26 -96.32 83.02 74.00 41.82 439.5 998.4 q1a10
+ -11 -21 -46 173.05 146.76 160.00 62.55 146.9 590.1 q0a6
+ -11 -13 -46 -56.46 118.91 161.00 68.66 231.7 515.0 q0a5
+ -11 -7 -45 284.40 109.35 137.00 72.40 303.7 445.5 q0a5
+ -11 3 -42 -272.22 247.71 325.00 119.76 7.0 1451.4 q0a14
+ -11 5 -41 -316.65 276.50 356.00 116.85 35.1 1431.8 q0a14
+ -11 9 -39 -332.71 194.69 261.00 115.91 91.2 1392.9 q0a14
+ -11 11 -38 71.43 254.35 307.00 122.17 119.1 1373.6 q0a14
+ -11 19 -32 132.26 182.79 198.00 120.14 244.2 1304.3 q0a15
+ -11 29 -22 449.19 246.25 347.00 98.81 623.2 720.1 q1a7
+ -11 45 7 -250.00 109.49 94.00 53.00 739.7 953.5 q1a11
+ -11 47 13 -50.01 103.07 86.00 47.63 652.1 955.3 q1a11
+ -10 -10 -43 176.05 197.52 228.00 82.55 305.4 509.3 q0a5
+ -10 6 -38 124.93 187.71 202.00 116.67 83.7 1452.7 q0a14
+ -10 18 -30 28.81 169.43 196.00 136.19 262.5 1345.9 q0a15
+ -10 30 -17 -38.56 287.88 412.00 100.56 654.6 657.7 q1a7
+ -10 36 -8 219.91 149.07 236.00 81.96 618.6 543.6 q1a5
+ -10 40 0 -306.83 135.81 130.00 74.83 602.5 425.2 q1a5
+ -9 -31 -39 -194.69 109.49 116.00 61.69 1521.4 1142.5 q3a13
+ -9 -27 -40 -431.65 259.93 266.00 68.85 168.2 729.1 q0a6
+ -9 -17 -41 -23.35 128.67 136.00 80.15 265.9 594.0 q0a7
+ -9 -1 -38 345.90 201.22 312.00 145.90 325.1 34.1 q0a1
+ -9 21 -24 170.00 295.50 384.00 155.29 351.9 1356.7 q0a15
+ -9 39 3 34.73 118.89 106.00 68.45 651.0 402.4 q1a5
+ -9 47 31 150.00 84.78 83.00 49.00 446.0 855.4 q1a8
+ -8 -34 -35 -34.35 101.07 105.00 60.15 1446.0 1160.7 q3a13
+ -8 -20 -38 196.38 117.41 146.00 87.62 275.6 661.4 q0a7
+ -8 -18 -38 75.12 212.55 303.00 94.88 296.5 636.1 q0a7
+ -8 -16 -38 -144.25 157.07 204.00 94.25 317.2 611.0 q0a7
+ -8 -14 -38 266.16 185.94 230.00 98.04 337.7 586.1 q0a7
+ -8 -4 -36 537.21 197.96 335.00 139.59 263.3 35.4 q0a1
+ -8 2 -34 374.27 430.51 492.00 175.53 325.6 108.9 q0a1
+ -8 4 -33 1515.09 421.70 514.00 166.71 344.6 135.9 q0a1
+ -8 6 -32 767.21 444.43 542.00 192.59 363.7 162.9 q0a1
+ -8 16 -25 596.96 594.75 502.00 208.90 306.2 1430.4 q0a15
+ -8 24 -17 -344.74 570.67 405.00 171.16 768.1 699.7 q1a7
+ -8 28 -12 675.09 379.36 384.00 130.61 742.3 618.2 q1a7
+ -8 30 -9 1065.92 231.53 356.00 112.55 731.3 572.2 q1a7
+ -8 38 6 76.41 98.28 145.00 77.64 698.6 380.0 q1a5
+ -8 42 18 194.99 87.60 88.00 53.65 650.2 823.5 q1a9
+ -8 44 26 -69.80 109.16 126.00 52.87 542.1 814.1 q1a8
+ -7 -43 -27 104.68 85.19 93.00 50.92 1260.8 1140.3 q3a12
+ -7 -27 -34 254.71 342.17 354.00 84.09 1524.8 1265.3 q3a13
+ -7 -19 -35 -76.95 364.06 381.00 114.55 326.6 677.4 q0a7
+ -7 -17 -35 -542.45 417.90 373.00 121.05 347.0 652.4 q0a7
+ -7 -15 -35 561.96 286.60 379.00 108.84 367.2 627.5 q0a7
+ -7 -1 -32 -114.38 374.90 480.00 185.38 264.6 109.6 q0a1
+ -7 1 -31 1518.44 311.13 513.00 174.56 283.6 136.4 q0a1
+ -7 33 1 -193.71 470.16 491.00 114.63 758.5 474.4 q1a5
+ -7 39 16 -207.60 100.34 103.00 61.40 701.9 772.7 q1a9
+ -7 41 23 -143.67 94.61 95.00 58.20 606.0 766.7 q1a9
+ -6 -62 -3 -31.79 81.68 85.00 44.59 1192.0 1093.1 q3a10
+ -6 -60 -6 8.53 73.99 94.00 45.32 1193.8 1029.0 q3a10
+ -6 -58 -9 112.84 84.53 83.00 44.96 1195.4 967.0 q3a10
+ -6 -52 -16 159.14 101.16 103.00 54.26 1215.0 836.1 q3a8
+ -6 -50 -18 -156.24 100.77 118.00 55.64 1223.8 788.9 q3a8
+ -6 -32 -29 120.45 111.39 132.00 68.91 1419.0 1268.9 q3a13
+ -6 -10 -31 84.00 424.02 424.00 186.00 140.5 45.4 q0a0
+ -6 -2 -29 127.36 401.31 414.00 167.24 223.5 136.8 q0a1
+ -6 0 -28 319.90 182.38 245.00 141.06 242.4 163.3 q0a1
+ -6 6 -25 881.14 181.28 442.00 97.26 298.9 215.0 q0a3
+ -6 12 -21 1373.58 358.65 488.00 126.89 350.1 302.5 q0a3
+ -6 22 -11 2146.76 316.89 819.00 165.66 477.2 50.5 q1a0
+ -6 30 1 -123.03 183.09 198.00 133.08 655.5 8.2 q1a1
+ -6 40 30 -337.83 128.58 100.00 55.83 397.5 1243.1 q1a12
+ -5 -41 -21 -56.88 74.74 85.00 55.88 1238.3 1251.8 q3a12
+ -5 -27 -27 -208.35 167.59 169.00 119.15 1464.8 1327.2 q3a15
+ -5 -15 -28 184.09 231.80 441.00 161.32 51.5 35.0 q0a0
+ -5 -13 -28 515.34 245.37 273.00 158.46 76.0 54.2 q0a0
+ -5 -7 -27 -46.95 267.78 391.00 143.55 143.5 118.6 q0a0
+ -5 3 -23 47.44 138.17 197.00 84.85 239.4 214.3 q0a3
+ -5 13 -16 297.61 293.45 518.00 96.76 322.5 361.8 q0a3
+ -5 17 -12 267.63 158.29 206.00 118.11 431.0 121.4 q1a0
+ -5 19 -10 -105.78 170.88 209.00 124.34 465.9 107.2 q1a0
+ -5 23 -5 -1345.37 542.53 454.00 193.29 545.3 82.8 q1a0
+ -5 29 5 193.30 207.04 294.00 147.01 688.0 56.2 q1a1
+ -5 37 29 -59.73 112.65 105.00 59.40 450.8 1285.5 q1a12
+ -4 -58 2 -92.37 114.42 123.00 50.58 1332.7 1059.8 q3a10
+ -4 -54 -4 78.68 96.58 90.00 52.21 1331.7 939.5 q3a10
+ -4 -50 -9 90.09 142.55 123.00 52.71 1338.2 862.0 q3a8
+ -4 -48 -11 -242.46 191.52 198.00 60.66 1345.3 815.6 q3a8
+ -4 -28 -23 -62.66 164.52 194.00 120.91 1419.5 1364.2 q3a15
+ -4 -22 -24 14.77 502.52 461.00 180.39 1502.4 1416.2 q3a15
+ -4 -12 -24 -377.11 208.49 225.00 133.51 55.7 108.3 q0a0
+ -4 6 -17 -71.53 110.48 156.00 74.60 231.2 299.7 q0a3
+ -4 10 -14 35.06 92.58 126.00 74.20 263.2 360.0 q0a3
+ -4 18 -6 -124.79 120.70 166.00 115.79 498.4 153.1 q1a0
+ -4 26 6 427.80 444.80 465.00 186.23 674.2 113.6 q1a1
+ -4 28 10 -237.92 426.14 401.00 176.69 730.0 108.0 q1a1
+ -4 36 41 133.27 103.30 105.00 54.12 540.3 1158.6 q1a12
+ -4 36 42 31.03 126.66 133.00 53.73 545.3 1146.4 q1a12
+ -4 36 43 -75.61 98.28 97.00 55.38 550.4 1134.1 q1a12
+ -3 -47 -7 -91.53 95.91 118.00 61.68 1404.8 832.5 q3a9
+ -3 -45 -9 -362.89 128.64 146.00 65.49 1411.0 787.5 q3a9
+ -3 -35 -16 40.13 164.01 226.00 107.08 1278.6 1363.1 q3a14
+ -3 -33 -17 -96.41 276.71 264.00 121.21 1312.2 1375.8 q3a14
+ -3 -27 -19 -84.24 306.17 346.00 143.64 1400.7 1420.5 q3a15
+ -3 -23 -20 738.15 450.52 458.00 172.41 1457.8 1452.0 q3a15
+ -3 -21 -20 1207.76 603.39 747.00 188.64 1483.0 1471.2 q3a15
+ -3 -13 -20 -39.83 147.85 200.00 116.51 11.5 142.9 q0a0
+ -3 23 7 901.36 225.21 512.00 149.77 660.7 169.9 q1a1
+ -3 25 11 -197.49 588.72 454.00 202.28 715.8 164.8 q1a1
+ -3 29 21 -204.90 303.70 279.00 125.67 547.2 1418.2 q1a14
+ -3 31 29 88.05 161.16 185.00 97.84 561.4 1316.4 q1a14
+ -3 33 41 28.41 113.54 113.00 57.22 593.2 1190.8 q1a13
+ -3 33 42 114.96 100.00 102.00 56.96 598.3 1178.9 q1a13
+ -3 33 43 128.00 92.91 104.00 57.86 603.5 1166.9 q1a13
+ -3 33 44 -13.01 85.96 83.00 53.55 608.8 1154.8 q1a13
+ -2 -48 0 -110.15 86.93 161.00 63.55 1468.4 903.0 q3a9
+ -2 -42 -6 -93.88 109.97 143.00 70.12 1484.7 768.0 q3a9
+ -2 -18 -16 86.76 347.69 372.00 116.27 1500.1 305.3 q3a3
+ -2 -16 -16 82.30 186.71 221.00 96.24 1481.5 329.9 q3a3
+ -2 -10 -15 -211.48 115.79 102.00 61.52 11.2 192.1 q0a2
+ -2 -6 -14 410.91 108.93 141.00 57.57 53.5 236.0 q0a2
+ -2 10 -4 4349.54 228.46 2274.00 47.48 459.2 255.6 q1a2
+ -2 12 -2 4404.40 258.56 1512.00 52.83 493.5 242.2 q1a2
+ -2 16 3 910.65 162.61 632.00 48.80 571.6 219.8 q1a2
+ -2 20 9 -307.33 176.58 155.00 86.33 657.3 202.0 q1a3
+ -2 22 13 941.26 304.22 415.00 118.95 711.9 197.7 q1a3
+ -2 26 23 365.70 254.75 320.00 125.27 605.9 1423.8 q1a15
+ -2 28 30 433.70 150.95 169.00 106.58 616.2 1333.8 q1a15
+ -2 28 31 -65.48 147.08 174.00 105.89 621.3 1323.0 q1a15
+ -2 30 45 -21.72 89.11 95.00 55.87 668.7 1175.0 q1a13
+ -2 30 46 140.97 80.91 91.00 57.10 674.1 1163.1 q1a13
+ -2 30 47 -26.19 84.03 84.00 55.27 679.6 1151.0 q1a13
+ -2 30 48 51.49 90.94 93.00 56.83 685.0 1138.9 q1a13
+ -2 30 49 -16.33 80.32 91.00 54.46 690.6 1126.7 q1a13
+ -1 -49 8 89.60 120.65 123.00 59.60 1541.3 955.0 q3a11
+ -1 -45 3 -869.95 252.54 206.00 73.63 1542.1 881.1 q3a9
+ -1 -19 -11 -26.10 185.20 269.00 92.33 1458.1 255.9 q3a3
+ -1 -17 -11 224.24 127.65 143.00 78.12 1439.7 280.6 q3a3
+ -1 -15 -11 -69.94 120.95 121.00 75.37 1421.5 305.1 q3a3
+ -1 3 -4 1765.47 438.46 806.00 132.47 405.8 349.4 q1a2
+ -1 7 -1 82.80 110.43 117.00 48.23 465.3 318.0 q1a2
+ -1 9 1 -20.16 100.18 106.00 50.94 499.5 304.7 q1a2
+ -1 17 12 -177.60 204.92 220.00 79.40 662.6 265.8 q1a3
+ -1 23 26 771.06 180.12 346.00 131.37 671.7 1419.1 q1a15
+ -1 25 34 -175.68 168.39 179.00 115.05 688.4 1318.6 q1a15
+ 0 -50 19 -270.35 122.80 115.00 67.15 1212.0 427.7 q3a4
+ 0 -48 15 -126.79 94.94 102.00 67.53 1278.9 414.1 q3a4
+ 0 -46 12 -36.80 146.33 144.00 70.12 1335.1 409.5 q3a4
+ 0 -44 9 23.18 101.38 146.00 78.71 1386.6 405.0 q3a5
+ 0 -26 -4 -606.74 536.03 474.00 205.22 1455.1 145.9 q3a1
+ 0 -12 -5 6997.90 317.71 4253.00 47.19 1339.4 299.3 q3a2
+ 0 -8 -4 -46.09 128.37 130.00 60.21 1296.1 341.9 q3a2
+ 0 -6 -3 14.00 95.42 103.00 59.43 1270.4 360.4 q3a2
+ 0 8 7 -240.42 161.27 141.00 51.87 548.5 358.6 q1a2
+ 0 20 30 -235.30 535.07 452.00 164.70 742.1 1404.1 q1a15
+ 0 20 31 -288.38 441.58 402.00 161.03 747.4 1393.7 q1a15
+ 0 22 54 188.64 125.55 151.00 62.99 907.2 683.9 q2a6
+ 0 22 55 195.65 169.33 189.00 68.88 895.1 677.8 q2a6
+ 0 22 56 93.14 102.06 115.00 60.59 883.0 671.7 q2a6
+ 0 22 57 -233.09 165.96 221.00 64.53 870.7 665.5 q2a6
+ 1 -47 24 61.55 131.93 158.00 66.52 1219.8 518.2 q3a4
+ 1 -45 20 -142.79 139.71 171.00 73.53 1285.8 503.1 q3a4
+ 1 -41 14 77.66 117.92 143.00 79.39 1392.0 491.5 q3a5
+ 1 -25 2 -583.50 412.58 398.00 176.07 1385.9 116.0 q3a1
+ 1 -17 1 511.43 141.14 166.00 63.52 1325.6 195.7 q3a2
+ 1 -15 1 370.96 159.22 576.00 69.10 1307.9 220.4 q3a2
+ 1 -13 1 -7.30 133.89 151.00 59.99 1290.3 245.0 q3a2
+ 1 -9 2 156.83 101.02 97.00 58.17 1247.2 287.9 q3a2
+ 1 -7 3 421.65 124.83 238.00 57.82 1221.6 306.4 q3a2
+ 1 -5 4 292.44 143.58 235.00 62.97 1196.0 324.9 q3a2
+ 1 1 8 906.61 140.53 449.00 62.64 845.9 329.6 q2a2
+ 1 5 12 69.80 111.26 108.00 61.15 819.9 261.0 q2a2
+ 1 7 14 16.66 106.58 102.00 59.93 806.8 226.4 q2a2
+ 1 13 25 -113.31 187.37 310.00 127.72 792.8 103.1 q2a0
+ 1 15 30 112.40 487.79 511.00 186.97 795.2 37.3 q2a0
+ 1 15 67 -140.57 117.52 142.00 56.17 811.2 519.5 q2a4
+ 1 17 38 659.14 447.08 432.00 127.92 1131.1 701.8 q2a7
+ 1 17 39 914.58 397.19 418.00 118.42 1120.4 696.1 q2a7
+ 1 17 40 1606.48 222.00 324.00 105.11 1109.7 690.4 q2a7
+ 1 17 58 -151.37 106.89 99.00 62.99 907.6 581.3 q2a6
+ 1 17 59 209.00 102.96 116.00 59.71 895.5 574.8 q2a6
+ 2 -44 32 -70.09 99.53 108.00 70.86 1201.5 608.2 q3a6
+ 2 -44 33 202.90 144.95 168.00 70.41 1192.5 617.8 q3a6
+ 2 -42 27 -34.91 98.81 114.00 73.32 1276.3 581.3 q3a6
+ 2 -40 23 -202.82 172.88 159.00 80.71 1339.7 564.6 q3a6
+ 2 -32 14 -193.06 199.95 214.00 121.39 1519.8 562.1 q3a7
+ 2 -28 11 502.91 280.29 428.00 160.37 1330.8 13.8 q3a0
+ 2 -26 10 1231.62 691.68 810.00 220.38 1321.2 47.1 q3a0
+ 2 -22 9 -137.84 220.47 296.00 156.96 1293.8 105.8 q3a0
+ 2 -18 8 -306.39 171.03 233.00 123.13 1267.0 163.3 q3a0
+ 2 -12 9 2077.58 172.60 1392.00 58.66 1206.9 203.4 q3a2
+ 2 -2 14 334.49 166.12 286.00 66.03 924.0 297.3 q2a2
+ 2 0 16 119.88 124.74 121.00 63.10 911.1 262.8 q2a2
+ 2 2 18 59.21 116.46 127.00 62.42 898.1 228.2 q2a2
+ 2 6 24 94.40 136.88 168.00 111.52 882.6 168.3 q2a0
+ 2 8 28 244.09 158.82 202.00 123.79 880.4 113.7 q2a0
+ 2 8 69 138.55 97.38 93.00 52.95 853.9 398.0 q2a4
+ 2 10 33 963.52 508.17 720.00 182.83 883.8 48.1 q2a0
+ 2 10 64 198.81 109.96 117.00 57.49 899.7 463.1 q2a4
+ 2 12 42 83.04 229.81 281.00 113.12 1132.0 605.4 q2a7
+ 2 12 43 65.14 360.24 440.00 123.92 1121.3 599.4 q2a7
+ 2 12 44 -537.00 363.83 425.00 111.00 1110.6 593.4 q2a7
+ 2 12 45 -338.54 253.98 325.00 108.52 1099.8 587.3 q2a7
+ 3 -37 34 213.91 172.96 258.00 79.39 1296.7 704.8 q3a6
+ 3 -37 35 -134.49 123.01 114.00 75.91 1288.2 714.5 q3a6
+ 3 -33 27 246.23 136.69 183.00 95.69 1408.8 677.1 q3a7
+ 3 -31 24 698.12 213.88 261.00 110.63 1459.9 668.4 q3a7
+ 3 -29 22 260.04 405.85 429.00 131.77 1502.3 668.9 q3a7
+ 3 -27 21 -300.97 465.95 386.00 154.18 1536.8 678.2 q3a7
+ 3 -23 19 -86.10 388.03 450.00 182.86 1208.2 23.6 q3a0
+ 3 -21 18 825.35 352.39 491.00 168.18 1199.4 56.7 q3a0
+ 3 -19 18 410.03 308.95 385.00 156.06 1182.0 82.8 q3a0
+ 3 -13 18 -479.71 176.92 167.00 94.65 1087.3 349.9 q2a3
+ 3 -11 19 21.30 170.04 225.00 86.24 1068.4 324.0 q2a3
+ 3 -11 78 -17.59 77.64 73.00 40.79 857.7 978.6 q2a10
+ 3 -9 20 286.99 112.26 120.00 76.39 1049.4 298.1 q2a3
+ 3 -9 77 -61.47 82.61 81.00 43.27 899.2 982.9 q2a10
+ 3 -7 21 128.40 147.60 187.00 77.52 1030.6 272.3 q2a3
+ 3 -7 76 -171.28 114.64 83.00 44.48 940.1 987.1 q2a10
+ 3 -5 74 125.46 85.77 85.00 45.34 985.8 978.4 q2a11
+ 3 -1 70 -119.16 70.71 75.00 46.96 1079.7 961.6 q2a11
+ 3 1 30 -93.46 169.12 266.00 138.38 984.2 150.2 q2a1
+ 3 1 67 -112.74 99.61 97.00 50.14 1132.8 941.2 q2a11
+ 3 3 34 147.81 349.10 453.00 186.84 982.8 94.9 q2a1
+ 3 3 35 137.51 447.86 532.00 199.28 988.8 85.0 q2a1
+ 3 5 53 286.28 123.70 246.00 80.83 1072.8 464.6 q2a5
+ 3 5 54 -23.10 130.70 178.00 79.43 1061.7 457.8 q2a5
+ 3 5 55 -128.77 138.19 150.00 80.08 1050.5 451.0 q2a5
+ 3 5 56 -91.81 126.77 120.00 74.51 1039.2 444.2 q2a5
+ 4 -28 41 -259.52 179.62 244.00 82.11 1056.6 1228.6 q2a13
+ 4 -28 42 -100.75 113.69 128.00 79.75 1046.6 1220.6 q2a13
+ 4 -28 43 -37.62 92.11 157.00 77.85 1036.6 1212.5 q2a13
+ 4 -28 44 -35.99 114.52 118.00 74.35 1026.5 1204.4 q2a13
+ 4 -28 53 200.09 128.46 139.00 69.04 935.3 1129.0 q2a12
+ 4 -28 54 73.03 111.49 142.00 64.90 924.5 1120.3 q2a12
+ 4 -26 38 -127.97 261.57 306.00 94.92 1068.2 1280.8 q2a13
+ 4 -24 35 -181.90 165.68 207.00 135.14 1079.6 1304.4 q2a15
+ 4 -24 61 -43.68 113.69 122.00 67.08 810.3 1121.2 q2a12
+ 4 -22 33 -235.99 210.18 266.00 149.59 1081.0 1346.6 q2a15
+ 4 -22 34 -225.10 254.26 343.00 141.47 1071.5 1339.4 q2a15
+ 4 -20 32 122.00 340.00 413.00 158.14 1073.0 1381.0 q2a15
+ 4 -20 33 -45.25 201.43 280.00 146.64 1063.6 1373.9 q2a15
+ 4 -18 32 -226.06 387.74 422.00 169.88 1055.7 1407.9 q2a15
+ 4 -18 64 49.80 102.39 95.00 55.80 874.7 764.0 q2a8
+ 4 -18 65 12.07 97.21 110.00 56.33 866.0 775.6 q2a8
+ 4 -16 32 -578.52 327.20 349.00 175.17 1038.5 1434.6 q2a15
+ 4 -16 64 132.19 99.22 107.00 54.81 905.4 781.6 q2a8
+ 4 -16 65 10.69 104.05 125.00 58.31 896.9 793.3 q2a8
+ 4 -14 32 -927.10 508.50 509.00 204.04 1021.5 1461.0 q2a15
+ 4 -14 33 318.28 608.64 548.00 190.01 1012.0 1454.3 q2a15
+ 4 -14 64 136.90 121.08 124.00 56.90 935.8 799.1 q2a8
+ 4 -10 61 -4.41 84.25 113.00 61.25 1016.8 799.0 q2a9
+ 4 -10 62 254.16 98.02 101.00 57.04 1008.9 810.5 q2a9
+ 4 -8 37 642.00 562.88 507.00 197.14 1149.0 154.6 q2a1
+ 4 -8 38 -810.75 483.15 404.00 185.75 1155.6 144.7 q2a1
+ 4 -8 58 -87.86 156.37 237.00 68.26 1069.1 782.1 q2a9
+ 4 -8 59 -23.89 86.30 99.00 61.49 1061.4 793.4 q2a9
+ 4 -6 41 192.07 326.46 381.00 159.79 1149.0 98.2 q2a1
+ 4 -6 42 -465.40 316.86 316.00 156.19 1155.7 88.1 q2a1
+ 4 -6 54 144.55 170.27 169.00 71.38 1127.2 754.7 q2a9
+ 4 -6 55 161.89 152.73 158.00 69.70 1119.9 765.7 q2a9
+ 4 -6 56 -34.55 114.42 120.00 70.71 1112.5 776.7 q2a9
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035050_16fe9.h5
+Image serial number: 39
+hit = 1
+indexed_by = none
+photon_energy_eV = 9513.548647
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998596
+hdf5/LCLS/photon_energy_eV = 9513.548647
+average_camera_length = 0.152001 m
+num_peaks = 43
+peak_resolution = 4.176929 nm^-1 or 2.394103 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 225.34 92.28 2.19 2830.58 q0a1
+ 320.69 160.21 2.21 3216.88 q0a1
+ 485.50 92.87 1.94 1249.18 q1a0
+ 877.86 84.22 1.97 3168.77 q2a0
+1391.87 122.83 2.05 2182.27 q3a1
+ 43.50 286.88 0.74 817.51 q0a2
+ 185.50 287.84 1.12 600.97 q0a2
+ 122.50 294.43 0.86 3528.74 q0a2
+ 150.89 298.19 0.95 3643.44 q0a2
+ 173.29 361.50 0.86 1846.65 q0a2
+ 202.13 325.50 1.10 937.03 q0a3
+ 515.23 249.50 1.05 1932.21 q1a2
+ 417.85 254.50 0.89 1222.81 q1a2
+ 477.17 259.50 0.92 737.74 q1a2
+ 442.06 292.50 0.69 558.50 q1a2
+ 715.74 212.50 1.95 1136.18 q1a3
+ 900.19 237.47 1.10 7354.75 q2a2
+ 922.50 257.98 1.07 598.96 q2a2
+ 826.69 272.79 0.78 1344.76 q2a2
+ 892.91 280.50 0.88 146.84 q2a2
+ 927.89 300.35 0.92 6218.94 q2a2
+ 815.36 300.50 0.62 1813.93 q2a2
+ 787.61 305.50 0.60 3932.91 q2a2
+ 956.50 320.31 0.98 1169.94 q2a2
+ 955.50 330.03 0.95 268.26 q2a2
+ 820.50 337.15 0.43 -260.71 q2a2
+ 958.30 361.26 0.89 2088.41 q2a2
+1031.96 248.50 1.54 777.51 q2a3
+1078.02 261.50 1.71 749.84 q2a3
+1006.63 327.28 1.22 1876.59 q2a3
+1181.50 201.01 1.18 1032.36 q3a2
+1224.50 213.26 1.13 874.20 q3a2
+1202.87 248.87 0.92 897.31 q3a2
+1282.50 279.79 0.90 2040.15 q3a2
+1197.50 289.02 0.70 1161.19 q3a2
+1252.50 294.11 0.75 1290.00 q3a2
+1178.06 336.50 0.45 936.69 q3a2
+1521.29 264.50 1.97 4003.42 q3a3
+1455.81 328.50 1.53 714.59 q3a3
+1476.23 361.23 1.59 1188.89 q3a3
+ 550.50 848.03 4.18 457.05 q1a8
+1011.72 1470.03 2.31 4442.83 q2a15
+1255.88 1460.50 2.76 473.14 q3a14
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035146_1be6d.h5
+Image serial number: 41
+hit = 1
+indexed_by = none
+photon_energy_eV = 9507.505659
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9507.505659
+average_camera_length = 0.152001 m
+num_peaks = 21
+peak_resolution = 4.106349 nm^-1 or 2.435253 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 36.08 19.08 2.30 504.99 q0a0
+ 500.50 74.12 2.05 662.72 q1a0
+ 911.04 119.50 1.84 1569.32 q2a0
+1110.80 118.50 2.38 1186.61 q2a1
+1409.50 81.03 2.27 706.50 q3a1
+ 111.50 248.05 1.05 1207.39 q0a2
+ 476.50 209.14 1.18 1122.19 q1a2
+ 417.50 217.73 1.09 3150.00 q1a2
+ 730.94 289.83 1.83 831.26 q1a3
+ 804.11 311.50 0.56 883.70 q2a2
+ 837.47 315.35 0.57 9871.95 q2a2
+ 872.97 324.50 0.62 1438.57 q2a2
+ 913.74 329.50 0.76 1258.99 q2a2
+ 914.20 333.50 0.75 1792.14 q2a2
+1330.20 291.50 1.02 2376.05 q3a2
+1279.92 298.50 0.80 1528.07 q3a2
+1300.81 354.83 0.68 994.00 q3a2
+1399.30 348.24 1.20 1540.46 q3a3
+1276.50 720.98 3.78 473.03 q3a6
+1310.05 798.95 4.11 -75.47 q3a8
+1088.50 1440.84 2.30 612.62 q2a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035026_14f46.h5
+Image serial number: 42
+hit = 1
+indexed_by = none
+photon_energy_eV = 9514.548822
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9514.548822
+average_camera_length = 0.152001 m
+num_peaks = 14
+peak_resolution = 3.742388 nm^-1 or 2.672091 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 179.91 22.50 2.41 1833.31 q0a0
+ 726.15 151.11 2.28 950.15 q1a1
+ 843.50 51.89 2.11 1255.79 q2a0
+1395.35 70.47 2.29 1327.69 q3a1
+ 37.88 223.68 1.08 1349.85 q0a2
+ 61.19 305.15 0.66 1293.71 q0a2
+ 348.82 326.50 1.82 435.29 q0a3
+ 358.80 330.99 1.86 2177.89 q0a3
+ 459.99 288.58 0.74 17460.40 q1a2
+ 796.00 221.59 1.05 3766.33 q2a2
+1215.17 325.50 0.51 1876.45 q3a2
+1301.50 333.93 0.75 1350.57 q3a2
+ 742.92 877.92 3.74 514.75 q1a9
+1472.50 1379.52 2.60 1703.55 q3a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035125_1a232.h5
+Image serial number: 44
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9516.446433
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9516.446433
+average_camera_length = 0.152001 m
+num_peaks = 17
+peak_resolution = 4.110349 nm^-1 or 2.432884 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 96.31 32.04 2.27 2440.04 q0a0
+ 539.86 109.50 1.92 297.64 q1a0
+ 677.17 114.90 2.25 786.43 q1a1
+1077.10 26.50 2.64 760.60 q2a1
+1125.31 140.27 2.36 2262.52 q2a1
+ 172.84 325.50 0.94 1233.99 q0a2
+ 133.71 328.86 0.76 1869.90 q0a2
+ 231.98 268.50 1.39 578.07 q0a3
+ 360.85 329.50 1.87 279.25 q0a3
+ 865.50 276.27 0.83 2217.65 q2a2
+ 863.50 355.84 0.45 1251.02 q2a2
+1242.50 311.87 0.64 1570.41 q3a2
+1310.15 799.14 4.11 631.34 q3a8
+1515.50 1286.00 3.12 745.62 q3a13
+ 666.50 1458.05 2.27 213.19 q1a15
+1113.50 1382.87 2.56 273.69 q2a15
+1469.77 1424.74 2.39 974.05 q3a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.22397 12.27163 16.88890 nm, 90.30087 90.50144 90.52787 deg
+astar = -0.0246954 -0.1089406 +0.1155027 nm^-1
+bstar = -0.0647727 -0.0289440 -0.0400988 nm^-1
+cstar = +0.0345443 -0.0387704 -0.0284569 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00152 nm^-1
+predict_refine/final_residual = 8.991708e-07
+predict_refine/det_shift x = 0.007 y = -0.086 mm
+diffraction_resolution_limit = 2.39 nm^-1 or 4.18 A
+num_reflections = 165
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -24 -38 14 -158.43 67.17 52.00 24.52 63.4 1052.9 q0a10
+ -24 -36 8 -23.83 69.04 65.00 24.83 34.8 964.7 q0a10
+ -22 -36 11 73.05 61.86 78.00 25.55 126.2 960.0 q0a10
+ -21 -27 -9 -109.45 84.22 84.00 42.05 30.7 1163.4 q0a12
+ -21 -9 -35 -81.97 91.14 91.00 42.77 434.4 687.0 q1a6
+ -20 -38 22 54.54 64.14 52.00 27.66 252.3 1062.0 q0a11
+ -20 -36 15 -16.35 65.73 73.00 27.72 216.2 966.2 q0a11
+ -20 -8 -35 -124.71 70.17 69.00 41.91 472.2 668.7 q1a6
+ -20 -4 -39 50.86 88.10 96.00 37.74 458.4 585.7 q1a6
+ -20 22 -56 -0.34 60.06 54.00 25.54 524.7 1091.5 q1a10
+ -19 -33 8 47.34 88.84 79.00 36.46 217.0 875.3 q0a9
+ -19 -27 -6 33.46 94.82 86.00 40.34 28.8 1247.5 q0a12
+ -19 -19 -20 127.44 94.99 90.00 42.56 233.6 1190.7 q0a13
+ -19 -7 -35 -89.00 70.23 66.00 43.00 509.1 650.9 q1a6
+ -19 -5 -37 -29.21 80.76 87.00 43.41 502.4 609.9 q1a6
+ -19 3 -44 117.22 65.78 65.00 35.98 480.2 476.0 q1a4
+ -19 7 -47 -35.36 83.09 63.00 33.76 471.6 396.2 q1a4
+ -18 -38 28 -38.34 96.63 85.00 26.99 355.9 1088.9 q0a11
+ -18 -20 -17 65.68 102.79 96.00 44.92 207.0 1237.3 q0a13
+ -18 -18 -20 1.26 77.04 82.00 46.14 254.0 1225.9 q0a13
+ -17 -35 19 6.33 84.92 67.00 28.07 340.4 945.0 q0a11
+ -17 -31 7 18.86 72.80 62.00 36.41 280.8 815.7 q0a9
+ -17 -29 2 -59.18 92.02 73.00 37.86 258.0 749.3 q0a9
+ -17 -19 -17 28.54 111.22 121.00 48.66 227.5 1271.6 q0a13
+ -16 -8 -30 -104.86 109.86 122.00 59.26 629.1 685.1 q1a7
+ -15 -31 12 29.62 168.05 185.00 39.86 370.5 833.7 q0a9
+ -14 -36 35 14.04 84.22 97.00 34.10 42.4 480.9 q0a4
+ -14 -12 -22 -445.39 171.11 168.00 87.99 369.1 1326.3 q0a15
+ -14 -8 -27 -11.25 183.88 235.00 70.25 706.4 696.1 q1a7
+ -13 -35 35 -84.79 79.60 84.00 34.18 70.5 512.9 q0a4
+ -13 -21 -6 101.90 232.64 209.00 85.41 158.7 1418.4 q0a14
+ -13 -15 -16 62.57 141.63 349.00 88.83 297.8 1379.9 q0a15
+ -13 -9 -24 -281.41 313.55 312.00 88.21 749.3 723.7 q1a7
+ -12 -34 35 64.70 61.43 64.00 33.62 97.9 544.3 q0a4
+ -12 -18 -9 -671.01 371.77 375.00 103.63 220.3 1438.2 q0a15
+ -12 -2 -30 74.27 244.67 218.00 76.53 764.7 592.5 q1a7
+ -12 6 -37 200.49 288.26 328.00 67.11 748.6 471.0 q1a5
+ -11 -29 19 -148.78 116.35 116.00 51.93 313.2 483.6 q0a5
+ -11 -21 -1 -183.13 207.74 190.00 97.53 377.6 143.5 q0a1
+ -10 -28 20 -187.69 151.85 154.00 54.97 327.4 519.9 q0a5
+ -10 -4 -24 -40.04 153.81 247.00 96.84 480.0 42.9 q1a0
+ -10 8 -35 -235.96 123.83 137.00 88.16 700.7 17.0 q1a1
+ -9 -31 38 -69.99 89.62 99.00 37.41 148.0 629.2 q0a6
+ -9 -13 -10 840.75 279.82 440.00 76.74 351.8 286.5 q0a3
+ -9 -11 -13 699.15 345.40 491.00 76.55 362.5 329.9 q0a3
+ -9 -3 -23 -192.45 137.75 152.00 90.05 490.1 78.3 q1a0
+ -9 3 -29 305.89 362.39 454.00 115.51 599.9 63.1 q1a1
+ -9 23 -42 -96.59 91.17 85.00 48.79 436.3 1306.7 q1a14
+ -8 -30 40 17.73 107.70 83.00 36.29 154.1 673.2 q0a6
+ -8 -26 22 60.97 128.84 120.00 59.08 356.0 562.6 q0a7
+ -8 -24 16 -22.59 120.75 139.00 88.77 206.3 9.1 q0a1
+ -8 -20 6 91.85 165.90 194.00 102.82 254.9 129.4 q0a1
+ -8 0 -24 724.99 184.65 496.00 84.61 537.2 108.4 q1a0
+ -8 2 -26 4608.85 371.20 2553.00 103.59 574.6 103.5 q1a0
+ -7 -5 -16 100.49 85.26 114.00 65.11 430.4 163.4 q1a0
+ -6 -28 46 -223.20 98.97 73.00 39.72 1533.8 1158.0 q3a13
+ -6 -22 19 916.38 197.18 612.00 99.44 133.8 27.6 q0a0
+ -6 -12 -3 728.07 115.16 396.00 48.79 232.4 269.6 q0a3
+ -5 -27 51 54.42 62.60 63.00 36.75 1464.9 1134.0 q3a13
+ -5 -21 21 1179.00 194.08 735.00 98.71 93.0 32.8 q0a0
+ -5 -3 -13 60.03 80.07 66.00 30.77 444.7 208.2 q1a2
+ -5 23 -34 -135.39 210.15 293.00 71.99 590.5 1358.7 q1a15
+ -5 31 -37 171.15 101.64 81.00 38.65 605.2 1244.9 q1a13
+ -4 -24 40 959.33 174.51 353.00 51.35 1516.7 1284.2 q3a13
+ -4 -12 4 0.49 91.69 88.00 38.85 145.2 235.1 q0a2
+ -4 -8 -3 1195.33 148.17 808.00 36.38 172.9 326.9 q0a2
+ -4 2 -16 -84.04 114.86 101.00 33.84 527.1 233.3 q1a2
+ -4 4 -18 -81.43 136.19 87.00 33.83 563.7 229.1 q1a2
+ -4 6 -20 -149.63 155.55 139.00 41.88 597.6 224.9 q1a3
+ -4 12 -25 408.45 182.55 390.00 60.95 704.2 218.7 q1a3
+ -4 18 -29 890.14 184.84 582.00 83.26 626.1 1459.5 q1a15
+ -4 26 -33 193.64 128.21 111.00 61.76 635.0 1320.4 q1a15
+ -4 36 -36 -159.36 78.75 57.00 35.76 660.8 1170.2 q1a13
+ -3 -23 45 143.44 94.42 108.00 44.34 1450.0 1262.2 q3a13
+ -3 -11 6 384.94 92.04 438.00 39.63 105.8 239.2 q0a2
+ -3 -7 -1 2063.63 172.61 834.00 38.62 133.6 330.8 q0a2
+ -3 27 -31 125.99 113.99 106.00 61.61 677.3 1317.7 q1a15
+ -3 33 -33 -89.49 81.51 88.00 40.89 692.1 1239.8 q1a13
+ -2 20 -25 556.30 339.64 414.00 102.30 708.1 1453.6 q1a15
+ -2 26 -28 367.55 109.08 276.00 73.05 716.5 1350.5 q1a15
+ -1 -19 43 346.61 106.16 126.00 63.95 1403.2 1319.6 q3a15
+ -1 -17 33 1124.41 242.25 458.00 93.15 1471.3 1424.3 q3a15
+ -1 -15 26 839.65 361.72 371.00 93.68 1543.6 329.9 q3a3
+ -1 -7 7 2322.67 168.01 2176.00 37.19 38.0 289.8 q0a2
+ -1 7 -12 191.90 150.12 137.00 27.90 573.7 347.7 q1a2
+ 0 -16 38 127.32 118.84 145.00 76.61 1406.7 1404.6 q3a15
+ 0 30 -24 -181.10 148.94 131.00 61.90 1098.2 726.1 q2a7
+ 0 46 -27 -31.78 67.43 65.00 34.98 817.1 654.6 q2a6
+ 1 -7 17 309.17 94.37 381.00 48.10 1375.8 313.5 q3a3
+ 1 9 -7 -40.53 67.21 67.00 35.84 821.8 258.4 q2a2
+ 1 33 -22 45.30 98.75 123.00 55.30 1064.3 672.9 q2a7
+ 1 37 -23 24.90 96.63 89.00 46.90 995.2 656.9 q2a7
+ 1 45 -24 -155.61 74.80 62.00 33.01 855.5 614.5 q2a6
+ 1 47 -24 -177.01 82.24 63.00 34.61 818.8 601.2 q2a6
+ 2 -14 66 -98.40 81.05 63.00 36.60 1297.8 770.0 q3a8
+ 2 -14 67 -17.96 61.59 69.00 36.16 1287.6 780.3 q3a8
+ 2 -8 26 -90.77 102.06 98.00 54.46 1443.1 232.9 q3a3
+ 2 0 9 1585.10 137.02 988.00 37.67 1240.9 314.1 q3a2
+ 2 10 -4 785.26 129.29 708.00 40.02 867.9 260.7 q2a2
+ 2 12 -6 539.46 107.11 404.00 34.38 864.6 224.1 q2a2
+ 2 24 -15 261.51 146.57 147.00 91.95 864.7 43.0 q2a0
+ 2 26 -16 107.46 133.72 134.00 88.22 868.6 9.1 q2a0
+ 3 -11 50 79.17 101.98 113.00 60.30 1220.3 1389.2 q3a14
+ 3 -11 74 8.22 57.69 57.00 34.98 1260.9 898.2 q3a8
+ 3 11 -1 749.93 127.50 464.00 36.80 914.2 263.1 q2a2
+ 3 13 -3 791.50 126.96 645.00 39.21 911.0 226.4 q2a2
+ 3 19 -8 233.90 138.72 132.00 71.14 907.9 148.8 q2a0
+ 3 27 -13 -139.27 208.47 201.00 96.74 916.8 10.9 q2a0
+ 3 35 -16 170.94 106.72 93.00 50.06 1068.2 573.4 q2a7
+ 4 -8 48 -201.51 129.05 133.00 70.52 1200.2 1448.8 q3a14
+ 4 -8 77 -64.03 70.10 66.00 33.23 1276.6 948.8 q3a10
+ 4 -6 87 73.24 62.67 75.00 29.36 1183.8 1096.6 q3a10
+ 4 38 -13 1.14 92.50 108.00 47.26 1037.6 537.7 q2a5
+ 5 -5 47 247.31 115.82 164.00 83.97 1543.5 11.8 q3a1
+ 5 -1 31 -83.00 190.38 169.00 98.29 1378.6 124.1 q3a1
+ 5 21 -1 -235.34 161.00 190.00 91.39 1007.3 158.0 q2a1
+ 5 27 -5 188.72 161.99 182.00 100.72 1013.8 53.5 q2a1
+ 5 29 -6 -159.07 127.42 145.00 89.27 1018.8 19.4 q2a1
+ 5 45 -10 154.25 153.70 174.00 33.75 942.0 441.7 q2a4
+ 5 47 -10 -43.20 63.98 60.00 32.80 906.8 425.9 q2a4
+ 5 49 -10 50.34 68.15 59.00 30.46 870.7 409.6 q2a4
+ 6 2 32 472.31 372.15 619.00 121.01 1347.6 78.9 q3a0
+ 6 4 27 182.20 204.48 377.00 96.63 1290.3 107.5 q3a0
+ 6 22 3 75.75 177.10 330.00 105.41 1063.2 165.3 q2a1
+ 6 28 -1 -64.80 157.20 207.00 95.20 1070.7 60.4 q2a1
+ 6 30 -2 657.50 151.24 526.00 88.50 1076.1 26.2 q2a1
+ 6 54 -5 126.76 83.04 67.00 23.47 1125.7 1081.8 q2a11
+ 7 1 51 -220.13 116.95 139.00 57.92 1478.6 439.2 q3a5
+ 7 1 74 34.71 48.55 54.00 36.09 1447.1 1044.0 q3a11
+ 7 5 34 1055.35 203.54 387.00 99.32 1320.3 24.3 q3a0
+ 7 7 29 60.93 232.87 331.00 111.04 1262.7 53.6 q3a0
+ 7 9 25 -122.20 164.60 178.00 98.23 1212.6 73.8 q3a0
+ 7 25 6 2044.38 435.23 1337.00 117.85 1125.3 139.8 q2a1
+ 7 49 -1 4.20 65.38 55.00 27.20 1114.3 963.7 q2a11
+ 7 55 0 151.43 59.32 51.00 24.48 1048.0 1072.2 q2a11
+ 8 4 58 -38.46 76.69 92.00 50.72 1367.1 424.9 q3a5
+ 8 4 60 -87.31 88.29 104.00 47.03 1348.7 407.9 q3a4
+ 8 4 61 -36.93 112.39 103.00 45.04 1337.8 399.3 q3a4
+ 8 4 62 -21.83 76.34 80.00 44.30 1326.9 390.7 q3a4
+ 8 4 63 102.37 101.10 100.00 47.42 1315.9 381.9 q3a4
+ 8 12 28 520.61 220.07 270.00 105.44 1190.7 10.4 q3a0
+ 8 26 11 104.04 200.85 268.00 88.04 924.0 1463.9 q2a14
+ 8 38 5 -118.69 126.04 113.00 40.36 1135.0 773.0 q2a9
+ 8 44 4 154.34 89.90 77.00 33.61 1093.3 875.7 q2a9
+ 8 46 4 36.94 67.18 71.00 34.76 1075.5 909.8 q2a9
+ 8 54 5 -43.00 74.44 74.00 26.86 989.0 1023.6 q2a11
+ 9 11 42 -140.92 104.08 121.00 60.75 1454.3 611.6 q3a7
+ 9 15 32 -339.54 399.59 362.00 88.52 1516.4 729.4 q3a7
+ 9 21 23 155.31 123.07 141.00 83.36 1056.6 1380.0 q2a15
+ 9 27 17 201.11 249.35 202.00 82.77 942.8 1387.0 q2a14
+ 9 31 14 -144.55 140.00 163.00 65.87 869.1 1382.3 q2a14
+ 9 33 13 -145.36 106.30 106.00 61.84 834.2 1375.1 q2a14
+ 9 35 12 201.09 118.13 108.00 58.18 798.9 1367.8 q2a14
+ 9 43 10 32.77 62.87 58.00 35.31 1027.9 825.8 q2a9
+ 9 57 12 20.83 45.33 53.00 23.57 866.5 1044.2 q2a10
+ 10 14 51 169.52 92.13 97.00 45.52 1324.9 589.2 q3a6
+ 10 16 43 94.00 161.83 215.00 59.71 1387.0 672.4 q3a7
+ 10 18 38 94.99 115.92 143.00 59.96 1419.4 732.2 q3a7
+ 11 19 57 30.80 85.94 90.00 40.80 1195.0 614.3 q3a6
+ 11 19 58 59.46 79.85 84.00 43.34 1183.2 606.5 q3a6
+ 11 19 59 -120.32 100.87 85.00 43.78 1171.2 598.7 q3a6
+ 11 21 47 -164.19 113.90 118.00 49.15 1287.7 714.2 q3a6
+ 11 23 42 -60.18 172.75 148.00 46.92 1143.8 1174.9 q2a13
+ 11 25 38 21.91 176.71 228.00 49.82 1090.2 1198.2 q2a13
+ 11 33 29 259.55 121.89 166.00 41.09 923.5 1216.2 q2a12
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035135_1af8e.h5
+Image serial number: 28
+hit = 1
+indexed_by = none
+photon_energy_eV = 9501.308614
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9501.308614
+average_camera_length = 0.152001 m
+num_peaks = 213
+peak_resolution = 2.555310 nm^-1 or 3.913420 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 153.88 28.50 2.34 -83.70 q0a0
+ 140.32 54.14 2.20 2347.98 q0a0
+ 178.62 91.21 2.09 2420.10 q0a0
+ 38.50 119.07 1.79 1063.69 q0a0
+ 177.58 119.05 1.95 3130.88 q0a0
+ 182.34 157.50 1.78 673.25 q0a0
+ 85.50 167.99 1.56 765.65 q0a0
+ 244.50 38.89 2.47 1619.93 q0a1
+ 276.71 55.01 2.48 3206.14 q0a1
+ 205.77 138.30 1.94 1396.77 q0a1
+ 301.39 156.72 2.15 6609.21 q0a1
+ 531.50 44.18 2.23 785.61 q1a0
+ 453.87 100.79 1.87 2913.71 q1a0
+ 517.21 103.21 1.92 602.35 q1a0
+ 505.02 110.80 1.87 3514.77 q1a0
+ 498.50 119.11 1.82 287.41 q1a0
+ 505.50 128.03 1.78 1806.01 q1a0
+ 515.40 137.73 1.75 2350.54 q1a0
+ 481.50 169.24 1.54 2428.58 q1a0
+ 615.65 47.73 2.37 2057.00 q1a1
+ 633.50 69.86 2.31 388.95 q1a1
+ 912.54 24.78 2.30 3046.15 q2a0
+ 835.50 70.74 2.01 2049.54 q2a0
+ 893.79 89.35 1.96 4214.83 q2a0
+ 957.18 110.59 1.97 2348.67 q2a0
+1058.50 58.92 2.45 944.97 q2a1
+1057.85 116.84 2.22 2064.06 q2a1
+ 990.94 158.94 1.84 3708.67 q2a1
+1060.09 160.19 2.06 2210.54 q2a1
+1256.04 60.85 2.09 2807.10 q3a0
+1268.76 66.50 2.08 2272.96 q3a0
+1269.25 69.36 2.06 4668.34 q3a0
+1251.96 107.00 1.86 2126.75 q3a0
+1172.05 131.04 1.71 1505.56 q3a0
+1212.50 134.96 1.69 1323.16 q3a0
+ 18.16 202.76 1.19 1276.07 q0a2
+ 29.71 202.98 1.19 2873.02 q0a2
+ 70.50 213.91 1.15 -2914.10 q0a2
+ 64.32 216.52 1.13 8265.97 q0a2
+ 116.13 221.50 1.19 878.19 q0a2
+ 118.50 229.81 1.15 1062.32 q0a2
+ 60.50 238.01 1.02 1898.27 q0a2
+ 117.80 238.50 1.11 985.64 q0a2
+ 105.74 241.50 1.07 3816.27 q0a2
+ 52.91 246.50 0.96 1355.60 q0a2
+ 133.93 247.50 1.11 1088.68 q0a2
+ 183.94 248.50 1.26 687.96 q0a2
+ 56.12 253.50 0.93 807.35 q0a2
+ 138.50 254.26 1.09 988.84 q0a2
+ 43.50 258.13 0.90 1156.94 q0a2
+ 129.50 261.00 1.03 953.15 q0a2
+ 49.67 264.49 0.86 36038.61 q0a2
+ 95.50 266.04 0.92 486.74 q0a2
+ 28.12 269.69 0.83 1620.76 q0a2
+ 32.90 269.50 0.83 396.85 q0a2
+ 123.50 276.98 0.94 639.62 q0a2
+ 36.50 284.87 0.75 270.24 q0a2
+ 154.50 286.78 1.00 937.91 q0a2
+ 168.24 290.35 1.04 5881.46 q0a2
+ 133.50 291.84 0.91 775.15 q0a2
+ 54.84 292.74 0.72 2593.79 q0a2
+ 160.50 298.15 0.98 415.11 q0a2
+ 17.50 298.83 0.67 1236.77 q0a2
+ 96.97 301.50 0.75 577.49 q0a2
+ 155.31 307.37 0.93 1380.32 q0a2
+ 164.50 306.82 0.97 1056.98 q0a2
+ 12.50 311.92 0.61 916.62 q0a2
+ 121.99 312.50 0.78 857.55 q0a2
+ 21.09 313.50 0.59 811.54 q0a2
+ 46.50 329.97 0.51 729.03 q0a2
+ 89.44 346.66 0.52 9658.86 q0a2
+ 83.50 355.00 0.47 -45.60 q0a2
+ 171.07 354.72 0.86 -1630.95 q0a2
+ 165.27 356.99 0.82 5589.90 q0a2
+ 340.95 211.31 2.03 634.57 q0a3
+ 346.19 215.03 2.05 3346.75 q0a3
+ 319.86 227.50 1.90 1588.84 q0a3
+ 294.03 229.12 1.78 2457.44 q0a3
+ 206.50 257.87 1.33 801.44 q0a3
+ 345.74 266.33 1.92 4933.16 q0a3
+ 311.00 272.72 1.74 5585.45 q0a3
+ 350.28 283.03 1.90 2770.67 q0a3
+ 210.20 311.50 1.17 1752.94 q0a3
+ 214.97 343.50 1.12 1176.98 q0a3
+ 221.07 349.35 1.14 2034.45 q0a3
+ 218.66 361.24 1.10 1585.71 q0a3
+ 515.50 206.24 1.26 1657.61 q1a2
+ 411.50 217.12 1.09 426.20 q1a2
+ 410.63 227.80 1.04 2658.84 q1a2
+ 433.50 227.96 1.04 813.15 q1a2
+ 567.71 228.89 1.30 6724.94 q1a2
+ 502.05 232.50 1.10 947.82 q1a2
+ 405.50 249.11 0.92 484.79 q1a2
+ 429.84 250.16 0.92 2281.34 q1a2
+ 529.07 255.50 1.07 269.53 q1a2
+ 417.50 259.80 0.86 2421.11 q1a2
+ 481.09 260.99 0.92 15772.61 q1a2
+ 484.39 261.20 0.92 15714.65 q1a2
+ 530.82 266.50 1.02 64.39 q1a2
+ 485.02 285.50 0.80 5005.45 q1a2
+ 570.50 286.18 1.09 1539.51 q1a2
+ 460.47 295.33 0.70 6504.26 q1a2
+ 510.50 295.97 0.83 1122.26 q1a2
+ 525.50 299.61 0.86 4101.12 q1a2
+ 422.37 302.34 0.63 3933.23 q1a2
+ 520.77 304.50 0.83 853.75 q1a2
+ 414.91 306.96 0.60 6037.21 q1a2
+ 569.79 316.38 0.99 2532.48 q1a2
+ 423.50 335.90 0.44 1071.23 q1a2
+ 505.33 357.50 0.57 1533.54 q1a2
+ 736.50 324.67 1.80 1203.50 q1a3
+ 647.12 350.50 1.31 816.94 q1a3
+ 790.50 212.88 1.10 1006.54 q2a2
+ 958.88 220.50 1.35 673.97 q2a2
+ 866.66 234.35 1.04 4240.11 q2a2
+ 834.50 237.99 0.97 559.53 q2a2
+ 791.08 241.08 0.95 1133.40 q2a2
+ 799.64 240.69 0.95 2440.51 q2a2
+ 906.50 250.94 1.05 1692.99 q2a2
+ 936.50 259.14 1.11 1311.29 q2a2
+ 904.50 265.09 0.98 1376.25 q2a2
+ 920.98 278.50 0.98 1043.46 q2a2
+ 882.50 290.96 0.80 4524.62 q2a2
+ 923.50 295.15 0.92 1325.90 q2a2
+ 933.50 298.84 0.95 593.86 q2a2
+ 954.34 298.95 1.03 1659.48 q2a2
+ 859.87 304.50 0.67 1488.46 q2a2
+ 926.16 306.50 0.89 369.92 q2a2
+ 801.50 311.85 0.56 2201.70 q2a2
+ 791.37 313.50 0.55 2471.84 q2a2
+ 856.50 318.83 0.59 1187.88 q2a2
+ 787.15 329.23 0.47 2657.99 q2a2
+ 851.30 328.77 0.53 1975.40 q2a2
+ 950.96 330.50 0.92 831.66 q2a2
+ 820.50 331.98 0.45 1886.20 q2a2
+ 844.62 340.50 0.45 2029.35 q2a2
+ 896.88 340.56 0.65 4151.60 q2a2
+ 932.95 345.29 0.80 5128.01 q2a2
+ 944.10 344.50 0.85 2986.80 q2a2
+ 850.50 350.00 0.43 836.75 q2a2
+ 909.16 350.50 0.67 655.12 q2a2
+ 898.50 353.04 0.61 1086.75 q2a2
+ 902.98 361.50 0.61 825.31 q2a2
+1086.69 271.50 1.73 1444.27 q2a3
+1065.50 322.12 1.52 589.46 q2a3
+1040.12 338.50 1.37 530.85 q2a3
+ 980.50 345.91 1.05 347.59 q2a3
+ 981.50 349.99 1.05 3156.11 q2a3
+1096.50 352.88 1.64 1266.62 q2a3
+1017.82 354.50 1.23 1314.55 q2a3
+ 984.95 360.50 1.05 449.65 q2a3
+ 994.98 360.50 1.10 1685.30 q2a3
+1272.95 202.23 1.25 1169.48 q3a2
+1212.70 204.23 1.17 1649.65 q3a2
+1288.54 212.43 1.23 10106.10 q3a2
+1260.09 227.40 1.10 4595.34 q3a2
+1229.50 229.22 1.05 1629.01 q3a2
+1336.50 234.18 1.27 1000.12 q3a2
+1177.50 234.86 1.00 2189.46 q3a2
+1218.99 234.84 1.01 3140.99 q3a2
+1289.13 243.36 1.08 11737.97 q3a2
+1190.22 248.69 0.92 1058.05 q3a2
+1278.50 254.99 1.00 1074.46 q3a2
+1249.58 258.50 0.92 3131.08 q3a2
+1213.74 261.50 0.86 1632.66 q3a2
+1320.85 265.50 1.08 667.64 q3a2
+1298.79 266.50 1.01 1290.04 q3a2
+1220.50 273.88 0.80 527.80 q3a2
+1181.12 275.15 0.78 12842.99 q3a2
+1196.50 278.40 0.76 2707.04 q3a2
+1225.50 284.67 0.74 2176.01 q3a2
+1321.17 286.16 1.00 4783.47 q3a2
+1290.03 289.50 0.88 647.10 q3a2
+1228.50 297.19 0.68 1325.20 q3a2
+1200.12 297.50 0.65 707.24 q3a2
+1320.93 299.50 0.95 780.65 q3a2
+1217.50 304.31 0.63 1524.19 q3a2
+1190.99 304.50 0.62 1397.00 q3a2
+1282.50 309.58 0.76 7127.70 q3a2
+1326.07 311.50 0.93 1318.44 q3a2
+1345.90 313.78 1.01 408.19 q3a2
+1218.50 316.00 0.57 2219.65 q3a2
+1332.28 323.14 0.92 752.30 q3a2
+1249.82 329.19 0.57 31296.44 q3a2
+1202.39 334.22 0.45 6617.19 q3a2
+1287.50 335.09 0.68 3427.59 q3a2
+1302.74 337.50 0.74 1387.94 q3a2
+1326.83 338.50 0.85 644.80 q3a2
+1340.86 345.81 0.90 1235.62 q3a2
+1333.83 347.91 0.86 5838.95 q3a2
+1346.50 349.01 0.92 465.31 q3a2
+1301.50 356.10 0.68 -1613.25 q3a2
+1306.35 356.78 0.70 6407.64 q3a2
+1368.15 260.85 1.29 366.42 q3a3
+1402.06 267.50 1.41 1013.11 q3a3
+1476.50 278.83 1.72 869.31 q3a3
+1401.93 283.59 1.36 2852.71 q3a3
+1379.11 308.23 1.19 2550.42 q3a3
+1400.87 312.50 1.28 1048.50 q3a3
+1420.93 325.50 1.35 743.01 q3a3
+1371.11 327.50 1.10 859.94 q3a3
+1481.28 348.22 1.63 3016.55 q3a3
+1457.06 350.50 1.50 1180.12 q3a3
+1407.50 351.94 1.24 1277.41 q3a3
+1369.72 357.74 1.04 2809.34 q3a3
+ 363.79 598.50 2.72 1705.23 q0a7
+ 693.06 1248.50 3.31 321.30 q1a13
+ 708.93 1275.50 3.17 446.53 q1a13
+ 317.73 1458.56 2.22 2420.83 q0a15
+ 636.06 1420.06 2.50 951.46 q1a15
+1065.15 1394.45 2.56 1970.95 q2a15
+1400.94 1373.50 2.74 618.01 q3a15
+1542.36 1387.15 2.50 2081.14 q3a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035038_15fc0.h5
+Image serial number: 43
+hit = 1
+indexed_by = none
+photon_energy_eV = 9490.145320
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9490.145320
+average_camera_length = 0.152001 m
+num_peaks = 27
+peak_resolution = 2.390173 nm^-1 or 4.183797 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 149.75 16.80 2.39 508.25 q0a0
+ 265.15 111.20 2.21 1633.36 q0a1
+ 120.27 205.15 1.28 1998.51 q0a2
+ 118.79 260.24 1.01 1429.57 q0a2
+ 57.50 272.78 0.83 1412.70 q0a2
+ 147.21 304.50 0.91 693.85 q0a2
+ 120.50 320.28 0.74 1192.26 q0a2
+ 87.22 323.65 0.62 2852.25 q0a2
+ 22.52 338.43 0.45 3578.95 q0a2
+ 118.50 350.11 0.62 928.64 q0a2
+ 533.27 240.50 1.14 2456.90 q1a2
+ 528.00 245.50 1.11 1102.39 q1a2
+ 545.10 250.50 1.14 729.03 q1a2
+ 503.50 256.95 0.99 1068.66 q1a2
+ 450.50 260.27 0.87 2522.12 q1a2
+ 405.45 267.19 0.82 3092.33 q1a2
+ 442.50 266.69 0.83 2106.59 q1a2
+ 554.50 306.25 0.95 1549.41 q1a2
+ 564.96 309.40 0.99 4839.36 q1a2
+ 428.28 326.10 0.50 979.71 q1a2
+ 957.69 345.42 0.92 2843.24 q2a2
+1009.78 359.50 1.18 730.75 q2a3
+1280.50 255.03 1.00 1532.41 q3a2
+1257.50 279.72 0.83 3061.20 q3a2
+1309.50 300.39 0.90 2830.10 q3a2
+1287.50 335.13 0.68 1161.23 q3a2
+1331.50 340.64 0.86 1097.86 q3a2
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035132_1abbf.h5
+Image serial number: 45
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9497.194563
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9497.194563
+average_camera_length = 0.152001 m
+num_peaks = 47
+peak_resolution = 4.102209 nm^-1 or 2.437711 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 58.05 68.30 2.06 2076.91 q0a0
+ 154.50 78.97 2.10 1252.44 q0a0
+ 137.50 133.98 1.80 1060.82 q0a0
+ 246.88 136.50 2.06 695.76 q0a1
+ 318.50 147.91 2.24 745.06 q0a1
+ 518.20 138.50 1.74 800.26 q1a0
+ 453.50 171.95 1.50 2020.29 q1a0
+ 595.29 166.89 1.79 1343.66 q1a1
+ 933.98 37.50 2.27 1356.98 q2a0
+ 928.53 72.74 2.09 1189.86 q2a0
+1025.50 58.03 2.37 602.35 q2a1
+1073.50 86.77 2.38 819.82 q2a1
+1323.20 134.83 1.82 2054.81 q3a0
+1429.91 127.83 2.13 2742.45 q3a1
+1374.50 146.19 1.90 1051.06 q3a1
+ 132.05 197.23 1.34 1552.60 q0a2
+ 61.50 217.19 1.13 2229.11 q0a2
+ 142.91 235.50 1.19 1591.70 q0a2
+ 107.89 245.50 1.05 1175.79 q0a2
+ 72.50 255.03 0.94 5615.34 q0a2
+ 154.16 274.20 1.05 1479.39 q0a2
+ 137.50 320.09 0.81 977.80 q0a2
+ 17.30 345.50 0.42 8494.40 q0a2
+ 445.50 223.59 1.06 3567.42 q1a2
+ 558.57 247.67 1.19 4220.30 q1a2
+ 520.80 267.50 0.98 1758.98 q1a2
+ 430.50 297.78 0.65 5427.42 q1a2
+ 542.76 322.07 0.85 9403.45 q1a2
+ 665.50 242.10 1.65 683.72 q1a3
+ 810.50 243.89 0.93 1242.01 q2a2
+ 916.62 284.61 0.94 5409.62 q2a2
+ 876.50 325.95 0.62 1086.64 q2a2
+ 923.25 353.37 0.73 1983.29 q2a2
+1078.14 200.05 1.89 993.51 q2a3
+1114.50 227.97 1.96 1243.69 q2a3
+1315.50 254.15 1.11 797.11 q3a2
+1325.34 297.43 0.98 6818.14 q3a2
+1287.21 309.50 0.78 923.47 q3a2
+1452.14 199.50 1.84 539.79 q3a3
+1414.63 352.00 1.28 2911.92 q3a3
+1541.97 677.50 2.57 769.99 q3a7
+1309.99 799.01 4.10 392.16 q3a8
+ 277.11 1386.01 2.62 2762.70 q0a15
+ 366.88 1403.18 2.43 1408.71 q0a15
+ 661.02 1438.50 2.36 827.64 q1a15
+1410.87 1455.10 2.35 1589.45 q3a15
+1452.98 1455.68 2.27 1127.09 q3a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.16309 12.29192 16.87967 nm, 90.44160 89.75038 90.26677 deg
+astar = +0.1304788 -0.0274614 +0.0924624 nm^-1
+bstar = +0.0430400 +0.0528995 -0.0443650 nm^-1
+cstar = -0.0164492 +0.0441786 +0.0358841 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00493 nm^-1
+predict_refine/final_residual = 5.618210e-06
+predict_refine/det_shift x = 0.006 y = -0.053 mm
+diffraction_resolution_limit = 2.45 nm^-1 or 4.09 A
+num_reflections = 486
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -25 9 36 18.47 51.92 53.00 22.73 408.7 883.2 q1a8
+ -25 15 40 -69.99 53.43 37.00 19.39 436.9 980.0 q1a10
+ -25 17 41 84.74 43.79 33.00 17.86 446.3 1020.6 q1a10
+ -25 19 42 9.36 31.41 43.00 18.24 455.8 1061.9 q1a10
+ -23 -23 -1 -60.61 61.40 55.00 28.01 793.7 580.5 q2a6
+ -23 11 37 -30.41 52.22 48.00 24.21 496.3 891.4 q1a8
+ -22 -26 -7 94.38 66.99 64.00 25.62 815.8 511.6 q2a4
+ -22 -18 7 3.41 35.76 44.00 26.75 858.0 705.9 q2a6
+ -22 -10 18 -10.40 58.13 53.00 25.60 642.4 1137.2 q1a13
+ -22 -8 20 -29.90 52.34 53.00 26.94 601.9 1146.4 q1a13
+ -22 2 30 -91.00 85.33 62.00 27.69 399.3 1193.4 q1a12
+ -22 16 40 -64.15 65.45 52.00 19.35 558.7 946.8 q1a10
+ -22 18 41 -41.79 85.45 58.00 20.59 568.8 985.6 q1a10
+ -21 -35 -32 52.30 84.37 64.00 17.81 962.0 1089.6 q2a10
+ -21 -33 -25 -35.79 41.15 38.00 22.59 1066.1 1074.4 q2a11
+ -21 -27 -10 -36.99 55.58 49.00 26.37 848.6 467.9 q2a4
+ -21 -25 -6 -110.77 63.21 55.00 26.61 859.0 529.3 q2a4
+ -21 -23 -2 -28.05 58.65 58.00 26.53 870.0 562.9 q2a6
+ -21 -19 5 -91.99 68.45 59.00 30.39 890.2 671.3 q2a6
+ -21 -17 8 -121.15 88.52 94.00 30.35 899.8 720.2 q2a6
+ -21 -15 11 20.14 71.76 84.00 26.26 766.8 1149.8 q1a13
+ -21 -11 16 102.14 60.42 54.00 27.04 678.7 1168.7 q1a13
+ -21 -7 21 0.66 71.59 65.00 28.54 590.6 1187.5 q1a13
+ -21 -5 23 -89.38 100.68 114.00 26.38 553.4 1196.8 q1a12
+ -21 -3 25 -13.95 57.55 65.00 26.55 512.9 1206.2 q1a12
+ -21 -1 27 -104.99 66.04 48.00 27.39 472.3 1215.6 q1a12
+ -21 9 35 19.03 84.90 69.00 24.77 561.1 820.2 q1a8
+ -21 17 40 51.61 50.80 49.00 21.99 597.8 947.1 q1a11
+ -21 21 42 -89.03 66.30 56.00 22.23 618.7 1024.8 q1a11
+ -21 23 43 -32.41 63.67 62.00 22.21 629.3 1064.6 q1a11
+ -20 -34 -29 71.07 57.97 56.00 22.04 1008.9 1041.4 q2a11
+ -20 -32 -23 -48.00 64.12 70.00 22.00 1100.0 1028.6 q2a11
+ -20 -28 -13 26.69 50.34 54.00 26.31 881.0 424.6 q2a4
+ -20 -18 6 38.80 73.72 57.00 29.13 931.2 685.9 q2a6
+ -20 -10 17 -107.76 68.04 70.00 28.36 666.5 1209.0 q1a13
+ -20 14 38 -23.28 55.43 50.00 25.48 618.4 900.1 q1a9
+ -20 24 43 2.40 39.55 46.00 22.40 671.7 1064.0 q1a11
+ -19 -37 -42 8.25 44.50 37.00 19.75 815.6 1023.5 q2a10
+ -19 -35 -34 92.70 71.03 53.00 18.70 941.4 1009.1 q2a10
+ -19 -33 -27 -44.26 49.66 40.00 22.86 1044.0 996.3 q2a11
+ -19 -31 -21 -87.31 74.88 53.00 22.64 1132.8 984.6 q2a11
+ -19 -29 -16 86.44 70.72 62.00 26.85 913.2 381.6 q2a4
+ -19 -25 -7 -11.78 87.61 78.00 29.24 933.0 514.1 q2a4
+ -19 -11 15 -11.67 84.38 82.00 30.07 701.8 1239.2 q1a13
+ -19 -7 20 -56.09 93.93 110.00 30.29 615.6 1257.6 q1a13
+ -19 -3 24 114.05 94.68 69.00 26.14 539.8 1276.2 q1a12
+ -19 -1 26 18.76 58.94 56.00 27.64 500.1 1285.6 q1a12
+ -19 13 37 -38.71 51.92 48.00 26.91 648.5 864.8 q1a9
+ -19 15 38 108.24 51.87 55.00 25.36 658.7 901.0 q1a9
+ -19 25 43 -88.35 108.67 129.00 24.15 713.3 1063.4 q1a11
+ -18 -36 -39 7.09 41.72 44.00 21.18 869.8 976.4 q2a10
+ -18 -32 -25 32.89 45.13 52.00 22.78 1077.9 952.8 q2a11
+ -18 -12 13 -36.67 104.85 100.00 33.54 736.4 1268.8 q1a13
+ -18 -8 18 -72.63 70.64 105.00 32.65 651.0 1287.1 q1a13
+ -18 2 28 -5.40 91.63 86.00 33.60 458.0 1306.0 q1a14
+ -18 4 30 98.64 72.25 92.00 34.76 418.1 1315.4 q1a14
+ -18 8 33 -35.70 79.90 69.00 27.30 658.1 755.1 q1a9
+ -18 14 37 6.15 46.13 50.00 27.65 688.0 865.9 q1a9
+ -18 16 38 -113.28 68.03 75.00 28.48 698.6 901.9 q1a9
+ -18 24 42 -60.23 97.93 76.00 23.39 742.9 1023.9 q1a11
+ -18 26 43 -19.22 114.92 85.00 25.02 754.4 1062.8 q1a11
+ -17 -25 -9 55.08 79.35 75.00 33.20 1000.8 489.4 q2a5
+ -17 -23 -5 -267.53 115.50 99.00 38.13 1009.5 547.8 q2a5
+ -17 -19 2 196.66 84.93 68.00 36.09 1027.9 625.0 q2a7
+ -17 5 30 153.46 78.46 77.00 36.34 416.0 1353.6 q1a14
+ -17 9 33 -55.97 57.77 52.00 28.77 696.6 757.0 q1a9
+ -17 15 37 -105.69 84.44 60.00 28.69 727.0 867.0 q1a9
+ -17 17 38 -75.30 100.39 105.00 25.70 737.8 902.7 q1a9
+ -16 -34 -35 -40.63 87.89 59.00 24.65 944.6 916.2 q2a8
+ -16 -32 -28 0.43 56.49 54.00 27.48 1044.0 906.8 q2a9
+ -16 -30 -22 142.32 101.97 75.00 23.79 1130.2 897.8 q2a9
+ -16 -28 -17 142.64 75.82 61.00 30.42 1022.7 377.7 q2a5
+ -16 -24 -8 67.55 65.54 60.00 35.13 1039.6 506.5 q2a5
+ -16 -16 6 73.63 74.27 82.00 42.35 1074.5 686.2 q2a7
+ -16 -10 14 -99.94 88.96 93.00 48.84 719.9 1317.0 q1a15
+ -16 -4 21 202.01 110.07 121.00 46.39 597.9 1343.9 q1a15
+ -16 -2 23 -203.76 173.03 199.00 48.36 562.5 1353.2 q1a14
+ -16 0 25 489.54 107.14 218.00 41.66 524.0 1362.4 q1a14
+ -16 6 30 -106.38 108.15 96.00 42.38 413.8 1391.4 q1a14
+ -16 10 33 -92.03 69.17 58.00 29.23 734.6 758.8 q1a9
+ -16 16 37 6.04 90.06 85.00 27.16 765.5 868.1 q1a9
+ -15 -35 -41 -15.00 48.68 45.00 25.86 861.8 883.4 q2a8
+ -15 -33 -33 -20.26 75.59 67.00 26.03 977.1 875.0 q2a9
+ -15 -31 -27 -13.65 47.26 51.00 28.28 1065.1 866.5 q2a9
+ -15 -29 -21 186.28 100.89 67.00 24.28 1149.8 858.3 q2a9
+ -15 -27 -16 -18.05 73.04 61.00 33.53 1061.5 396.3 q2a5
+ -15 -19 0 81.22 73.23 81.00 43.24 1094.7 598.5 q2a7
+ -15 -11 12 319.74 110.96 118.00 47.86 753.3 1344.9 q1a15
+ -15 -5 19 -22.53 145.99 202.00 49.73 632.5 1371.7 q1a15
+ -15 -3 21 -199.76 132.50 155.00 51.97 594.5 1380.9 q1a15
+ -15 -1 23 5.85 136.14 120.00 46.35 559.4 1390.1 q1a14
+ -15 1 25 -228.93 118.54 101.00 47.33 521.1 1399.4 q1a14
+ -15 7 30 -60.61 99.89 110.00 43.01 411.7 1428.6 q1a14
+ -14 -34 -39 -129.94 65.99 70.00 27.24 899.3 842.2 q2a8
+ -14 -32 -32 -13.00 62.15 68.00 28.00 999.2 834.7 q2a9
+ -14 -26 -15 -87.53 92.40 76.00 38.13 1099.4 414.5 q2a5
+ -14 -24 -11 332.08 146.20 171.00 39.20 1107.3 472.6 q2a5
+ -14 -10 12 302.32 140.02 187.00 56.97 749.0 1381.4 q1a15
+ -14 -6 17 114.88 96.47 98.00 50.12 666.5 1398.9 q1a15
+ -14 -4 19 -22.00 80.57 78.00 52.00 628.9 1408.1 q1a15
+ -14 2 25 132.97 122.71 124.00 47.23 518.3 1435.9 q1a14
+ -14 8 30 -122.45 125.63 125.00 48.05 409.6 1465.3 q1a14
+ -14 14 34 -93.69 82.95 76.00 34.69 727.8 383.6 q1a5
+ -14 28 41 140.31 56.83 56.00 24.69 480.9 464.6 q1a4
+ -13 -35 -47 187.54 66.47 63.00 24.78 788.6 807.5 q2a8
+ -13 -33 -38 -76.64 82.72 96.00 27.56 922.7 801.9 q2a8
+ -13 -31 -31 59.25 52.44 86.00 27.34 1020.7 795.5 q2a9
+ -13 -23 -10 196.25 149.51 138.00 41.75 1143.9 489.5 q2a5
+ -13 -21 -6 501.20 187.96 173.00 46.63 1151.2 545.9 q2a5
+ -13 -5 17 136.07 95.26 200.00 56.33 662.7 1434.8 q1a15
+ -13 1 23 -280.15 218.02 280.00 58.35 553.4 1462.5 q1a14
+ -13 3 25 153.55 133.51 169.00 54.05 515.6 1471.9 q1a14
+ -13 17 35 66.45 70.96 71.00 33.95 692.3 431.5 q1a5
+ -13 19 36 -171.29 82.37 61.00 32.09 657.9 442.9 q1a5
+ -13 21 37 -135.96 82.51 74.00 33.16 623.1 454.5 q1a5
+ -13 25 39 -74.10 98.42 113.00 28.90 554.7 478.2 q1a4
+ -12 -34 -45 3.55 57.61 59.00 25.09 827.7 767.6 q2a8
+ -12 -32 -37 -137.60 107.07 82.00 28.40 945.4 762.7 q2a8
+ -12 -30 -30 -36.20 77.09 54.00 28.13 1041.7 757.2 q2a9
+ -12 -28 -24 30.25 83.51 102.00 31.34 1125.3 751.2 q2a9
+ -12 -16 1 240.88 110.15 118.00 66.96 892.3 10.6 q2a0
+ -12 -14 4 56.60 135.13 117.00 71.60 847.1 18.9 q2a0
+ -12 -12 7 345.85 157.62 157.00 68.59 802.1 27.2 q2a0
+ -12 -4 17 295.54 122.13 275.00 58.66 659.0 1470.2 q1a15
+ -12 8 28 31.71 116.37 129.00 60.09 739.5 60.5 q1a1
+ -12 30 40 10.42 60.90 58.00 27.18 486.1 542.6 q1a4
+ -11 -25 -18 57.40 148.97 190.00 58.91 1153.0 8.3 q2a1
+ -11 -17 -2 1512.85 247.93 666.00 76.59 932.3 37.9 q2a0
+ -11 -11 7 424.54 144.16 159.00 62.72 797.5 62.4 q2a0
+ -11 -3 17 -34.00 259.82 265.00 59.88 763.0 248.0 q1a3
+ -11 -1 19 220.74 192.38 176.00 57.86 753.8 211.2 q1a3
+ -11 17 33 -401.30 205.86 174.00 48.70 728.9 494.0 q1a5
+ -11 19 34 10.49 73.69 94.00 37.11 695.3 505.7 q1a5
+ -11 23 36 -14.30 85.23 88.00 32.70 626.8 529.7 q1a5
+ -11 25 37 139.61 75.91 91.00 29.99 591.7 541.9 q1a5
+ -11 33 40 -66.69 75.52 62.00 31.69 454.4 568.8 q1a6
+ -10 -32 -43 123.70 75.89 61.00 29.70 796.7 1189.3 q2a12
+ -10 -28 -28 -238.34 110.65 106.00 45.80 804.1 1370.7 q2a14
+ -10 -26 -23 42.37 101.43 92.00 48.01 810.2 1440.8 q2a14
+ -10 -24 -18 202.48 133.94 131.00 59.09 1146.0 44.8 q2a1
+ -10 -22 -13 -26.99 95.77 141.00 65.45 1079.3 50.9 q2a1
+ -10 -20 -9 699.89 131.28 288.00 65.70 1023.7 58.0 q2a1
+ -10 -16 -2 1180.89 228.57 595.00 75.68 926.9 73.1 q2a0
+ -10 -10 7 -2.01 110.47 111.00 53.61 793.0 97.2 q2a0
+ -10 -6 12 -210.76 163.31 161.00 42.24 745.3 324.8 q1a3
+ -10 30 38 -42.88 78.04 76.00 32.88 528.6 579.0 q1a6
+ -10 34 39 -83.58 74.88 58.00 31.18 459.8 608.7 q1a6
+ -9 -31 -42 -24.01 76.76 77.00 31.63 834.4 1212.2 q2a12
+ -9 -27 -28 60.09 87.22 85.00 46.43 841.1 1378.9 q2a14
+ -9 -21 -13 826.27 124.52 556.00 70.83 1072.9 86.4 q2a1
+ -9 -19 -9 -65.73 122.96 124.00 74.42 1017.7 93.1 q2a1
+ -9 -15 -2 6.91 147.50 126.00 58.82 921.6 107.8 q2a0
+ -9 -13 1 -72.01 92.36 102.00 56.59 877.0 115.7 q2a0
+ -9 -11 4 -27.41 75.66 84.00 53.78 832.7 123.6 q2a0
+ -9 -9 7 111.51 108.20 128.00 46.89 788.6 131.5 q2a0
+ -9 -5 12 84.56 81.52 69.00 33.44 711.1 320.7 q1a3
+ -9 -3 14 -125.00 131.31 163.00 36.00 701.9 284.5 q1a3
+ -9 5 22 84.95 97.18 146.00 64.45 664.1 165.7 q1a1
+ -9 23 34 -261.50 108.65 80.00 46.50 665.4 563.1 q1a7
+ -9 31 37 -65.47 91.54 78.00 34.27 533.8 618.0 q1a6
+ -8 -30 -42 -40.91 50.43 50.00 32.32 872.7 1222.1 q2a12
+ -8 -28 -34 62.82 76.27 72.00 42.92 873.8 1304.7 q2a14
+ -8 -26 -28 42.74 85.02 84.00 48.84 877.5 1387.1 q2a14
+ -8 -20 -13 1101.33 156.84 562.00 71.67 1066.5 121.4 q2a1
+ -8 -18 -9 349.35 135.13 147.00 67.12 1011.7 127.9 q2a1
+ -8 -14 -2 340.97 104.07 114.00 49.10 916.3 142.1 q2a0
+ -8 -12 1 213.29 85.71 166.00 50.91 872.0 149.9 q2a0
+ -8 -10 4 516.70 99.44 341.00 48.19 828.0 157.7 q2a0
+ -8 -6 9 134.36 69.69 64.00 29.56 684.8 360.2 q1a3
+ -8 0 16 -68.70 93.99 66.00 30.30 658.9 244.5 q1a3
+ -8 2 18 85.61 154.22 181.00 32.99 649.6 208.2 q1a3
+ -8 24 33 -98.38 93.50 108.00 43.38 670.1 600.6 q1a7
+ -8 26 34 78.57 69.96 68.00 41.83 636.1 613.6 q1a7
+ -8 28 35 85.62 88.77 88.00 42.38 601.5 626.8 q1a7
+ -8 34 37 -76.71 73.35 81.00 33.91 502.6 670.7 q1a6
+ -7 -29 -41 -4.69 80.73 63.00 31.77 908.8 1244.2 q2a12
+ -7 -27 -34 67.96 88.29 88.00 46.65 910.5 1313.4 q2a14
+ -7 -25 -28 -293.09 140.04 106.00 56.14 913.5 1395.1 q2a14
+ -7 -3 11 419.00 95.64 265.00 28.86 642.1 320.2 q1a3
+ -7 7 21 1444.20 157.78 776.00 54.20 594.7 167.1 q1a1
+ -7 15 27 188.10 230.88 221.00 74.10 553.8 32.0 q1a0
+ -7 27 33 -6.15 70.04 74.00 42.35 640.8 651.3 q1a7
+ -7 29 34 106.90 68.14 68.00 40.90 606.4 664.7 q1a7
+ -7 35 36 36.89 67.17 69.00 33.51 507.8 709.7 q1a6
+ -6 -28 -41 209.28 120.64 134.00 31.28 945.8 1253.6 q2a12
+ -6 -26 -34 -80.27 131.69 105.00 51.17 946.6 1322.1 q2a14
+ -6 -24 -28 -61.62 214.04 245.00 60.83 949.0 1403.1 q2a14
+ -6 -8 3 288.27 95.39 300.00 30.71 827.3 197.4 q2a2
+ -6 10 22 -183.65 133.48 110.00 53.85 552.5 134.7 q1a0
+ -6 16 26 460.86 136.89 206.00 67.74 517.8 36.4 q1a0
+ -6 30 33 88.86 74.91 106.00 41.74 611.2 702.6 q1a7
+ -5 -29 -51 206.27 80.56 72.00 30.55 985.8 1123.9 q2a13
+ -5 -27 -42 163.55 97.72 82.00 35.52 981.4 1250.8 q2a13
+ -5 -23 -28 -7.63 180.17 193.00 65.30 981.0 1410.9 q2a15
+ -5 -17 -14 -102.95 89.42 81.00 42.63 1057.6 198.2 q2a3
+ -5 -5 5 233.14 105.02 196.00 28.94 787.3 239.5 q2a2
+ -5 1 12 587.90 131.22 559.00 19.90 567.8 284.1 q1a2
+ -5 3 14 4153.38 226.77 2635.00 22.62 558.4 248.3 q1a2
+ -5 5 16 1298.06 138.92 1001.00 21.94 549.0 212.4 q1a2
+ -5 11 21 932.21 132.55 554.00 50.59 517.1 138.8 q1a0
+ -5 15 24 -252.24 167.41 185.00 67.64 494.6 71.7 q1a0
+ -5 17 25 98.18 120.40 119.00 63.42 481.9 40.9 q1a0
+ -5 29 31 -80.35 71.35 72.00 44.15 650.4 726.3 q1a7
+ -5 35 33 -70.56 101.21 72.00 30.56 375.4 1181.8 q0a13
+ -4 -28 -52 29.61 74.13 81.00 32.99 1025.6 1121.3 q2a13
+ -4 -26 -42 -153.64 84.74 87.00 35.56 1017.6 1260.1 q2a13
+ -4 -24 -35 29.38 82.72 93.00 55.83 1016.7 1327.8 q2a15
+ -4 -22 -29 123.44 174.95 215.00 64.44 1017.8 1408.0 q2a15
+ -4 -18 -19 1398.28 164.61 422.00 55.28 1115.3 228.6 q2a3
+ -4 -16 -15 -110.34 86.13 71.00 41.35 1060.6 233.7 q2a3
+ -4 -14 -11 -92.70 74.92 74.00 39.59 1006.7 238.8 q2a3
+ -4 -10 -4 -20.09 100.04 81.00 31.96 912.9 250.8 q2a2
+ -4 -8 -1 -10.19 71.83 64.00 31.49 869.3 257.9 q2a2
+ -4 0 9 9275.95 319.39 3856.00 23.45 542.4 323.3 q1a2
+ -4 2 11 60.00 92.10 79.00 22.00 533.0 287.7 q1a2
+ -4 4 13 -32.46 84.18 64.00 21.85 523.5 252.0 q1a2
+ -4 6 15 -67.22 78.67 53.00 23.02 514.1 216.2 q1a2
+ -4 12 20 260.78 75.33 81.00 48.02 481.8 143.0 q1a0
+ -4 16 23 62.06 81.25 105.00 59.94 459.0 76.0 q1a0
+ -4 18 24 -44.00 131.23 152.00 65.00 446.1 45.3 q1a0
+ -3 -27 -53 49.44 64.78 60.00 33.26 1065.3 1118.7 q2a13
+ -3 -25 -43 -86.82 105.37 101.00 39.08 1055.7 1257.3 q2a13
+ -3 -23 -36 -121.27 116.68 88.00 55.74 1054.0 1325.0 q2a15
+ -3 -21 -30 -51.36 100.01 124.00 62.91 1054.4 1405.1 q2a15
+ -3 -17 -20 132.52 136.86 202.00 53.89 1118.3 264.3 q2a3
+ -3 -11 -8 160.26 120.12 98.00 27.16 959.8 278.6 q2a2
+ -3 -9 -5 5517.82 256.31 3557.00 33.64 916.1 285.6 q2a2
+ -3 -7 -2 1673.73 136.52 1371.00 28.07 872.6 292.6 q2a2
+ -3 -5 1 176.18 67.97 61.00 28.79 829.3 299.6 q2a2
+ -3 -1 6 34.45 70.05 53.00 19.91 517.2 362.2 q1a2
+ -3 1 8 -24.64 77.11 73.00 20.87 507.8 326.8 q1a2
+ -3 7 14 -145.77 81.02 54.00 20.08 479.2 219.9 q1a2
+ -3 13 19 -61.62 70.17 73.00 48.62 446.6 147.2 q1a0
+ -3 19 23 -329.85 153.46 159.00 69.65 410.4 49.7 q1a0
+ -3 21 24 43.04 142.69 131.00 67.16 396.9 18.5 q1a0
+ -3 27 27 -347.10 137.55 108.00 61.90 376.0 1329.9 q0a15
+ -3 35 30 44.35 119.73 158.00 34.85 314.2 1227.4 q0a13
+ -3 39 31 10.67 64.69 57.00 30.93 279.5 1161.6 q0a13
+ -2 -24 -44 11.46 124.68 154.00 39.28 1093.7 1254.6 q2a13
+ -2 -22 -37 65.64 133.07 186.00 58.99 1091.1 1322.2 q2a15
+ -2 -20 -31 -52.45 114.82 128.00 65.66 1090.9 1402.2 q2a15
+ -2 -10 -9 440.39 123.12 154.00 25.05 963.0 313.4 q2a2
+ -2 -8 -6 115.17 90.46 88.00 29.51 919.3 320.3 q2a2
+ -2 -6 -3 1128.90 120.81 577.00 30.29 875.9 327.2 q2a2
+ -2 -4 0 71.86 97.43 87.00 37.06 832.6 334.1 q2a2
+ -2 2 7 84.88 63.80 46.00 18.96 473.2 330.4 q1a2
+ -2 4 9 31.27 57.36 39.00 18.18 463.7 294.9 q1a2
+ -2 6 11 205.55 67.81 48.00 16.38 454.1 259.4 q1a2
+ -2 8 13 3585.05 199.50 3175.00 18.55 444.5 223.6 q1a2
+ -2 14 18 39.18 73.87 78.00 46.42 411.6 151.3 q1a0
+ -2 24 24 611.25 295.55 474.00 75.75 367.6 1399.0 q0a15
+ -2 26 25 86.07 132.59 150.00 62.33 353.6 1367.0 q0a15
+ -2 38 29 176.89 78.25 58.00 31.51 256.8 1202.7 q0a13
+ -1 -23 -46 128.09 133.67 108.00 38.32 1134.4 1239.7 q2a13
+ -1 -21 -38 27.31 181.60 198.00 63.97 1128.1 1319.4 q2a15
+ -1 -19 -32 524.03 184.03 247.00 69.69 1127.2 1399.3 q2a15
+ -1 -15 -22 -289.95 143.62 111.00 49.84 1124.2 335.4 q2a3
+ -1 -11 -14 -100.10 90.31 82.00 38.04 1016.0 343.9 q2a3
+ -1 -7 -7 2062.55 162.15 1178.00 28.21 922.5 354.9 q2a2
+ -1 -5 -4 147.69 78.19 92.00 33.23 879.1 361.7 q2a2
+ -1 3 6 -5.03 92.08 100.00 25.23 438.8 333.9 q1a2
+ -1 5 8 5584.50 249.63 4026.00 20.50 429.2 298.5 q1a2
+ -1 7 10 710.12 116.10 469.00 19.88 419.6 263.0 q1a2
+ -1 31 25 -22.89 100.46 95.00 54.49 284.5 1312.0 q0a15
+ -1 37 27 172.76 80.96 72.00 30.64 234.5 1243.0 q0a13
+ 0 -24 -60 94.44 76.63 112.00 31.26 1204.0 722.3 q3a6
+ 0 -24 -59 -32.82 87.53 96.00 31.51 1217.7 725.6 q3a6
+ 0 12 12 32.70 63.81 66.00 30.70 240.5 361.7 q0a3
+ 0 16 15 -33.94 75.89 73.00 35.94 306.1 338.5 q0a3
+ 0 20 18 0.15 369.52 370.00 57.45 372.8 314.8 q0a3
+ 0 24 20 241.38 169.07 282.00 74.62 306.3 1445.5 q0a15
+ 0 26 21 -228.68 123.61 147.00 67.08 292.0 1414.0 q0a15
+ 0 28 22 2128.28 171.08 851.00 60.52 277.5 1382.0 q0a15
+ 0 30 23 90.64 111.19 109.00 56.76 262.8 1349.6 q0a15
+ 0 36 25 36.40 92.13 84.00 34.40 212.7 1282.5 q0a13
+ 0 42 26 -145.41 82.71 61.00 31.21 157.9 1188.0 q0a12
+ 1 -23 -63 100.81 77.02 65.00 27.19 1173.7 675.0 q3a6
+ 1 -23 -62 165.18 81.10 96.00 29.36 1187.7 678.7 q3a6
+ 1 -19 -42 -70.27 146.54 168.00 47.74 1462.5 711.7 q3a7
+ 1 -13 -25 -193.99 131.77 108.00 54.04 1189.4 106.8 q3a0
+ 1 -7 -13 394.32 97.40 299.00 22.32 1201.5 239.3 q3a2
+ 1 9 7 33.80 89.64 64.00 23.13 168.2 346.9 q0a2
+ 1 19 15 -110.60 99.89 128.00 40.40 332.0 289.8 q0a3
+ 1 31 21 224.45 130.72 118.00 56.95 222.2 1360.2 q0a15
+ 1 33 22 -77.35 101.84 108.00 55.15 206.9 1327.3 q0a15
+ 1 41 24 -159.66 94.47 75.00 32.46 136.3 1229.1 q0a12
+ 2 -20 -53 111.09 100.61 90.00 31.90 1329.5 657.4 q3a6
+ 2 -18 -44 -92.45 102.06 113.00 45.09 1448.2 671.3 q3a7
+ 2 -16 -37 576.11 292.65 411.00 62.67 1540.6 677.8 q3a7
+ 2 -14 -31 167.19 138.22 124.00 63.42 1223.9 38.1 q3a0
+ 2 -10 -22 171.01 79.57 284.00 43.96 1228.5 158.3 q3a0
+ 2 2 -3 8509.30 356.50 3794.00 49.38 15.6 348.4 q0a2
+ 2 14 9 61.99 64.03 70.00 31.63 225.9 289.0 q0a3
+ 2 18 12 175.89 74.10 106.00 35.51 291.4 265.0 q0a3
+ 2 34 20 194.18 123.57 110.00 49.42 168.7 1337.9 q0a14
+ 2 42 22 -29.19 58.58 65.00 30.19 93.1 1239.8 q0a12
+ 3 -19 -57 -83.41 76.98 63.00 32.64 1288.5 607.6 q3a6
+ 3 -19 -56 95.18 61.88 72.00 29.36 1301.4 611.5 q3a6
+ 3 -17 -47 -211.19 133.60 161.00 42.27 1422.2 627.0 q3a7
+ 3 -15 -39 89.34 165.40 119.00 52.07 1526.9 638.0 q3a7
+ 3 -9 -24 154.72 71.06 113.00 46.15 1266.7 145.5 q3a0
+ 3 -3 -13 -10.82 56.26 56.00 21.69 1280.3 268.0 q3a2
+ 3 -1 -10 772.41 114.38 507.00 23.75 1286.7 311.6 q3a2
+ 3 7 0 83.36 60.24 93.00 26.93 82.6 294.5 q0a2
+ 3 9 2 165.82 80.60 255.00 28.53 118.0 284.5 q0a2
+ 3 11 4 1481.45 143.31 431.00 25.64 153.6 274.5 q0a2
+ 3 17 9 95.64 70.92 61.00 32.84 251.1 240.4 q0a3
+ 3 23 13 -118.64 196.17 187.00 62.01 347.4 201.4 q0a3
+ 3 29 16 182.68 174.23 196.00 59.92 178.9 1439.8 q0a14
+ 3 35 18 -44.50 74.68 72.00 48.50 127.2 1348.6 q0a14
+ 3 43 20 -62.61 69.56 59.00 30.01 49.6 1250.6 q0a12
+ 4 -16 -50 -85.39 80.06 65.00 38.95 1395.6 581.9 q3a7
+ 4 -14 -42 -26.45 110.68 125.00 49.66 1502.0 594.3 q3a7
+ 4 -10 -31 -175.01 246.80 230.00 68.96 1305.4 67.4 q3a0
+ 4 -8 -26 183.29 125.34 214.00 48.71 1305.1 132.6 q3a0
+ 4 -2 -15 356.17 112.27 487.00 25.51 1318.2 256.0 q3a2
+ 4 0 -12 6478.87 271.72 4867.00 23.53 1324.6 299.8 q3a2
+ 4 2 -9 166.51 103.84 189.00 18.54 1330.9 343.3 q3a2
+ 4 6 -4 110.12 60.19 52.00 23.88 36.0 266.6 q0a2
+ 4 8 -2 5707.36 243.23 2988.00 25.44 71.3 256.5 q0a2
+ 4 10 0 1185.90 121.90 675.00 28.06 106.8 246.5 q0a2
+ 4 12 2 1635.01 146.23 874.00 28.37 142.4 236.4 q0a2
+ 4 18 7 31.39 83.81 75.00 36.38 240.2 201.7 q0a3
+ 4 26 12 397.65 207.27 253.00 73.72 366.6 174.0 q0a1
+ 4 30 14 -221.90 162.07 163.00 62.10 138.4 1450.6 q0a14
+ 4 36 16 -104.91 79.51 84.00 45.71 85.4 1359.4 q0a14
+ 5 -9 -33 59.08 258.21 269.00 75.24 1344.6 54.1 q3a0
+ 5 9 -4 2118.84 160.35 1448.00 26.49 60.0 218.4 q0a2
+ 5 11 -2 418.52 82.47 273.00 26.05 95.5 208.2 q0a2
+ 5 13 0 1534.65 137.20 621.00 28.99 131.3 198.0 q0a2
+ 5 27 10 63.48 182.67 174.00 67.56 355.5 134.0 q0a1
+ 5 37 14 152.43 83.24 74.00 42.17 43.3 1370.3 q0a14
+ 5 49 16 -23.47 70.84 76.00 27.27 121.1 798.4 q0a8
+ 5 51 16 154.94 58.81 50.00 26.06 89.0 824.2 q0a8
+ 5 53 16 -149.29 66.26 50.00 27.09 56.1 850.6 q0a8
+ 6 -14 -60 -299.96 117.12 81.00 27.35 1292.7 498.0 q3a4
+ 6 -14 -59 -241.43 117.06 92.00 28.91 1305.7 502.8 q3a4
+ 6 -12 -50 -83.68 70.53 60.00 32.22 1427.1 523.8 q3a5
+ 6 -12 -49 -80.44 80.80 94.00 31.11 1438.9 528.2 q3a5
+ 6 -10 -42 -82.63 173.88 145.00 42.71 1532.4 539.2 q3a5
+ 6 -8 -36 -3.08 138.61 130.00 62.25 1385.1 30.3 q3a1
+ 6 -6 -31 42.10 202.48 233.00 72.39 1383.8 96.7 q3a1
+ 6 -4 -27 130.19 171.17 300.00 56.14 1386.4 151.9 q3a1
+ 6 6 -11 2517.33 168.67 1348.00 28.67 1414.4 355.2 q3a3
+ 6 18 1 -37.49 126.40 113.00 49.68 184.0 162.3 q0a0
+ 6 22 4 695.76 162.15 478.00 70.64 246.8 136.2 q0a1
+ 6 34 10 122.90 99.41 112.00 48.06 34.9 1446.9 q0a14
+ 6 36 11 89.75 107.02 112.00 48.25 18.1 1414.3 q0a14
+ 6 48 13 -227.22 110.49 75.00 31.02 168.9 825.1 q0a8
+ 7 -13 -69 25.70 66.28 62.00 22.70 1181.3 417.7 q3a4
+ 7 -13 -68 103.75 60.74 49.00 21.25 1195.4 423.1 q3a4
+ 7 -11 -55 12.11 65.04 57.00 27.30 1376.2 467.5 q3a5
+ 7 -11 -54 -46.00 78.08 78.00 29.00 1388.5 472.3 q3a5
+ 7 -9 -46 365.21 187.79 250.00 38.55 1496.3 489.3 q3a5
+ 7 -3 -30 3142.66 206.51 1022.00 61.99 1429.7 129.2 q3a1
+ 7 3 -19 72.83 71.75 61.00 29.49 1440.8 255.1 q3a3
+ 7 5 -16 -50.15 68.70 69.00 30.55 1446.9 299.4 q3a3
+ 7 11 -9 281.31 85.49 95.00 46.97 28.3 166.1 q0a0
+ 7 17 -3 1043.71 159.36 626.00 58.56 136.3 133.9 q0a0
+ 7 25 3 231.60 122.47 197.00 70.09 265.3 80.6 q0a1
+ 7 27 4 -64.61 96.37 125.00 65.01 295.5 64.5 q0a1
+ 7 29 5 38.81 107.38 115.00 63.19 326.2 48.1 q0a1
+ 7 31 6 269.57 143.78 153.00 58.83 357.3 31.5 q0a1
+ 7 39 9 79.54 78.02 75.00 30.66 333.8 759.2 q0a9
+ 7 45 10 90.00 61.16 64.00 27.57 243.0 826.0 q0a9
+ 7 57 10 -61.38 58.51 54.00 21.38 55.7 963.0 q0a10
+ 7 59 10 37.64 51.29 46.00 19.76 20.7 993.2 q0a10
+ 8 -10 -62 -18.56 64.41 66.00 24.56 1300.4 398.4 q3a4
+ 8 -10 -61 -120.09 86.74 64.00 24.82 1313.5 403.7 q3a4
+ 8 -8 -51 -83.92 63.91 53.00 29.45 1447.6 433.2 q3a5
+ 8 -6 -44 141.89 124.08 123.00 35.68 1541.7 446.5 q3a5
+ 8 -4 -38 66.48 97.20 102.00 54.48 1476.2 39.2 q3a1
+ 8 -2 -33 189.72 218.31 282.00 68.72 1473.8 106.1 q3a1
+ 8 0 -29 -5.93 164.87 195.00 74.20 1475.8 161.7 q3a1
+ 8 4 -22 232.75 151.43 237.00 42.25 1484.2 233.9 q3a3
+ 8 6 -19 376.61 144.95 342.00 41.95 1490.3 278.6 q3a3
+ 8 8 -16 -203.44 136.56 103.00 39.32 1496.3 323.1 q3a3
+ 8 10 -14 551.93 178.19 183.00 38.96 1506.9 358.9 q3a3
+ 8 20 -4 1229.54 188.15 582.00 68.78 153.4 78.7 q0a0
+ 8 24 -1 396.71 126.37 275.00 67.68 216.6 51.5 q0a1
+ 8 40 6 124.45 75.18 69.00 25.87 351.4 808.5 q0a9
+ 8 44 7 106.17 57.89 54.00 27.43 289.2 851.9 q0a9
+ 8 58 7 -21.30 44.49 44.00 20.70 72.8 1020.8 q0a10
+ 9 -5 -49 309.23 89.29 89.00 30.08 1494.1 389.8 q3a5
+ 9 -1 -37 -410.72 169.59 132.00 61.28 1523.2 72.3 q3a1
+ 9 1 -33 -293.95 289.97 295.00 69.63 1524.9 128.9 q3a1
+ 9 5 -25 -134.30 388.17 388.00 70.90 1528.4 212.4 q3a3
+ 9 7 -22 -1017.77 355.47 306.00 78.30 1534.4 257.5 q3a3
+ 9 15 -12 -32.05 193.04 256.00 68.16 32.2 72.0 q0a0
+ 9 17 -10 -97.67 104.65 122.00 67.67 68.5 61.0 q0a0
+ 9 23 -5 -38.01 160.60 164.00 69.37 170.9 22.4 q0a0
+ 9 37 2 42.17 62.92 55.00 30.43 319.9 380.7 q0a5
+ 9 41 3 -90.51 100.50 80.00 26.83 369.3 858.7 q0a9
+ 9 45 4 13.76 71.15 96.00 28.64 306.9 903.6 q0a9
+ 9 57 4 -79.85 58.88 66.00 20.65 124.4 1048.1 q0a10
+ 10 -6 -70 56.81 48.33 60.00 19.19 1473.4 1049.4 q3a11
+ 10 -6 -69 86.26 54.73 53.00 19.14 1479.7 1035.3 q3a11
+ 10 -6 -68 20.30 53.49 45.00 19.30 1485.9 1021.4 q3a11
+ 10 -6 -67 51.09 76.97 77.00 20.71 1492.1 1007.6 q3a11
+ 10 -4 -56 -151.36 151.65 135.00 24.56 1532.3 879.5 q3a9
+ 10 -4 -55 252.51 104.60 83.00 22.89 1537.9 867.3 q3a9
+ 10 0 -42 61.70 123.65 125.00 45.62 1186.4 1464.0 q3a14
+ 10 2 -37 150.28 87.09 98.00 43.57 1254.7 1468.1 q3a14
+ 10 4 -33 -264.99 240.89 202.00 59.35 1311.4 1467.0 q3a14
+ 10 8 -26 -45.65 381.64 508.00 68.01 1410.1 1459.9 q3a15
+ 10 10 -23 1092.87 144.89 618.00 58.53 1455.6 1453.9 q3a15
+ 10 12 -20 -798.75 311.69 231.00 80.36 1500.9 1447.9 q3a15
+ 10 38 -1 -20.20 83.52 66.00 30.80 270.1 398.8 q0a5
+ 10 48 1 -41.35 43.27 40.00 22.15 296.5 956.4 q0a11
+ 10 50 1 71.09 48.05 39.00 21.71 266.8 984.8 q0a11
+ 10 52 1 57.34 69.71 91.00 22.46 236.2 1014.1 q0a11
+ 10 54 1 -51.84 60.73 50.00 22.04 204.8 1044.2 q0a11
+ 10 56 1 -117.67 85.01 60.00 21.07 175.5 1075.1 q0a10
+ 11 -3 -66 -7.75 62.12 48.00 18.75 1439.6 970.4 q3a11
+ 11 -3 -65 58.34 59.97 42.00 18.46 1446.0 957.0 q3a11
+ 11 -3 -64 -28.21 54.21 39.00 19.41 1452.3 943.7 q3a11
+ 11 -1 -55 11.55 60.14 100.00 24.21 1482.2 843.8 q3a9
+ 11 -1 -54 -65.74 67.90 51.00 22.97 1488.1 831.8 q3a9
+ 11 3 -42 122.39 93.77 89.00 40.24 1209.7 1410.7 q3a14
+ 11 5 -37 -14.46 100.38 136.00 46.72 1278.1 1415.4 q3a14
+ 11 7 -33 248.61 148.70 170.00 51.13 1334.9 1414.8 q3a14
+ 11 9 -30 -156.99 133.78 128.00 52.45 1378.4 1408.8 q3a15
+ 11 13 -24 192.79 89.00 97.00 51.47 1470.6 1396.9 q3a15
+ 11 15 -21 50.90 166.67 204.00 58.29 1516.3 1391.0 q3a15
+ 11 19 -17 399.90 199.29 307.00 53.29 380.9 720.9 q0a7
+ 11 21 -15 19.73 173.60 160.00 53.58 369.5 683.6 q0a7
+ 11 23 -13 -90.45 178.22 176.00 47.09 358.1 646.2 q0a7
+ 11 27 -10 108.22 93.08 94.00 41.24 329.3 578.8 q0a7
+ 11 31 -8 71.89 54.93 87.00 32.23 293.2 545.7 q0a5
+ 11 33 -7 -43.18 61.72 58.00 31.92 275.2 514.4 q0a5
+ 11 35 -6 40.29 63.29 56.00 28.91 256.9 482.5 q0a5
+ 11 37 -5 73.42 57.96 52.00 28.18 238.4 450.2 q0a5
+ 11 45 -3 79.90 70.51 56.00 21.90 378.9 961.7 q0a11
+ 11 47 -3 46.01 59.14 40.00 21.59 350.7 989.9 q0a11
+ 12 0 -65 -10.06 52.50 42.00 19.06 1387.0 933.2 q3a11
+ 12 2 -55 -22.71 57.43 61.00 22.91 1425.9 820.1 q3a9
+ 12 2 -54 72.38 56.12 42.00 21.62 1432.1 808.1 q3a9
+ 12 6 -42 78.03 84.60 74.00 35.92 1233.2 1356.7 q3a14
+ 12 8 -38 16.43 90.54 98.00 42.46 1291.5 1356.5 q3a14
+ 12 10 -34 -203.14 146.30 128.00 45.49 1348.9 1356.3 q3a14
+ 12 12 -31 163.29 81.95 80.00 43.97 1392.8 1350.4 q3a15
+ 12 14 -28 11.91 81.49 72.00 45.14 1439.5 1344.6 q3a15
+ 12 16 -25 17.09 90.33 94.00 50.67 1485.9 1338.7 q3a15
+ 12 18 -23 -46.42 95.03 102.00 48.89 1523.2 1327.1 q3a15
+ 12 22 -19 -48.97 99.69 117.00 43.18 316.4 712.7 q0a7
+ 12 24 -17 -40.36 72.50 88.00 40.44 304.7 674.9 q0a7
+ 12 28 -14 81.87 73.47 73.00 36.33 274.9 606.8 q0a7
+ 12 38 -9 127.68 77.90 56.00 23.21 183.4 476.7 q0a4
+ 12 40 -8 -69.71 75.26 64.00 25.91 163.9 443.6 q0a4
+ 12 44 -7 14.99 50.20 46.00 22.61 116.2 383.1 q0a4
+ 13 5 -55 -77.58 64.52 43.00 20.11 1368.9 796.1 q3a9
+ 13 25 -21 -27.31 63.42 74.00 36.23 249.8 704.3 q0a7
+ 13 29 -18 84.32 73.14 72.00 34.22 219.0 635.6 q0a7
+ 13 39 -13 124.12 65.29 145.00 23.88 123.8 504.0 q0a4
+ 13 41 -12 47.60 49.91 47.00 23.60 103.5 470.7 q0a4
+ 13 45 -11 -102.11 62.89 49.00 23.51 53.8 409.9 q0a4
+ 13 47 -11 50.22 48.06 38.00 20.98 24.0 382.2 q0a4
+ 14 6 -71 23.67 52.06 44.00 14.93 1223.5 966.8 q3a10
+ 14 6 -70 233.62 66.41 44.00 13.38 1231.4 952.7 q3a10
+ 14 6 -69 -141.71 78.57 48.00 15.91 1239.3 938.8 q3a10
+ 14 8 -58 -92.51 71.81 52.00 23.11 1293.1 808.0 q3a8
+ 14 8 -57 -88.66 70.39 49.00 21.46 1300.2 795.8 q3a8
+ 14 12 -46 100.46 61.82 58.00 25.28 1238.0 1248.6 q3a12
+ 14 14 -42 -209.04 119.92 117.00 29.90 1298.1 1249.3 q3a12
+ 14 18 -35 -28.00 70.99 87.00 28.00 1402.7 1244.2 q3a13
+ 14 20 -32 -187.70 71.65 54.00 29.73 1450.9 1238.4 q3a13
+ 14 22 -30 116.72 69.10 55.00 27.92 1489.4 1226.1 q3a13
+ 14 24 -28 -125.96 105.97 87.00 28.10 1528.0 1213.6 q3a13
+ 14 28 -24 229.25 95.43 72.00 25.34 177.1 704.4 q0a6
+ 14 32 -21 295.68 77.81 77.00 25.78 144.9 634.2 q0a6
+ 14 34 -20 90.26 57.35 57.00 26.14 124.8 602.8 q0a6
+ 14 36 -19 -94.56 64.51 53.00 27.85 104.5 570.9 q0a6
+ 14 40 -17 52.60 45.83 51.00 22.09 62.5 532.1 q0a4
+ 14 44 -16 -9.78 52.08 61.00 22.98 11.6 472.3 q0a4
+ 15 11 -62 -86.15 64.56 44.00 20.35 1202.7 833.3 q3a8
+ 15 11 -61 10.03 55.51 48.00 19.77 1210.5 820.6 q3a8
+ 15 15 -49 34.89 71.11 68.00 26.70 1229.2 1169.9 q3a12
+ 15 17 -45 35.48 50.45 48.00 24.95 1290.8 1171.3 q3a12
+ 15 21 -38 92.11 54.88 50.00 23.67 1397.9 1167.0 q3a13
+ 15 23 -35 82.80 61.33 56.00 24.88 1447.1 1161.3 q3a13
+ 15 25 -33 21.82 54.76 57.00 25.64 1486.4 1148.4 q3a13
+ 15 27 -31 -11.09 59.81 51.00 25.72 1525.9 1135.5 q3a13
+ 15 33 -26 -62.22 56.13 48.00 27.02 77.4 673.4 q0a6
+ 15 35 -25 63.29 45.97 42.00 24.91 56.5 641.6 q0a6
+ 15 37 -24 -18.70 58.12 49.00 25.81 35.2 609.4 q0a6
+ 15 39 -23 133.60 67.41 70.00 25.60 13.5 576.6 q0a6
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035132_1ab38.h5
+Image serial number: 48
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9513.165945
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9513.165945
+average_camera_length = 0.152001 m
+num_peaks = 36
+peak_resolution = 2.914293 nm^-1 or 3.431364 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 149.95 39.50 2.29 194.83 q0a0
+ 62.50 81.03 2.00 1057.99 q0a0
+ 90.50 134.14 1.74 1144.12 q0a0
+ 127.50 144.06 1.74 836.47 q0a0
+ 59.50 161.07 1.58 1073.40 q0a0
+ 276.47 161.76 2.05 1725.95 q0a1
+ 269.35 170.04 1.99 1263.90 q0a1
+ 486.31 105.69 1.87 881.57 q1a0
+ 756.86 73.70 2.66 1131.55 q1a1
+ 655.30 106.93 2.22 2416.27 q1a1
+ 617.73 112.02 2.09 1484.85 q1a1
+ 721.83 166.70 2.21 1269.75 q1a1
+ 735.51 175.12 2.23 4480.61 q1a1
+ 998.67 50.89 2.34 1727.43 q2a1
+1289.31 74.28 2.07 2347.77 q3a0
+1334.34 93.20 2.05 1398.75 q3a0
+1392.31 109.33 2.11 6341.53 q3a1
+1401.82 156.50 1.93 1388.39 q3a1
+1541.98 160.20 2.41 2904.51 q3a1
+ 88.50 233.16 1.08 2121.71 q0a2
+ 111.90 325.85 0.69 3927.66 q0a2
+ 203.50 288.10 1.21 1316.77 q0a3
+ 460.28 237.46 1.01 12333.06 q1a2
+ 500.84 308.50 0.74 4940.97 q1a2
+ 544.31 311.16 0.89 2641.34 q1a2
+ 528.50 321.04 0.79 913.46 q1a2
+1026.50 268.71 1.46 1853.26 q2a3
+1321.05 241.60 1.19 5712.51 q3a2
+1304.98 334.50 0.76 1485.76 q3a2
+1488.92 204.11 1.98 5628.83 q3a3
+1514.96 263.19 1.94 3822.48 q3a3
+1150.90 466.87 2.91 1389.35 q2a5
+1133.28 642.16 2.68 703.09 q2a7
+1138.75 1429.80 2.31 3839.99 q2a15
+1502.00 1414.73 2.40 3747.91 q3a15
+1439.71 1417.00 2.48 1320.04 q3a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.14282 12.27047 16.86548 nm, 89.83204 90.46168 90.36435 deg
+astar = +0.0159713 -0.0881594 -0.1359292 nm^-1
+bstar = +0.0560989 -0.0466939 +0.0362572 nm^-1
+cstar = -0.0427221 -0.0368249 +0.0182928 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00332 nm^-1
+predict_refine/final_residual = 1.387563e-06
+predict_refine/det_shift x = 0.020 y = -0.036 mm
+diffraction_resolution_limit = 2.66 nm^-1 or 3.76 A
+num_reflections = 295
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -7 -43 -21 112.58 135.46 126.00 54.95 549.1 399.9 q1a4
+ -7 -39 -21 219.43 130.87 165.00 63.24 598.6 452.8 q1a5
+ -7 -37 -22 816.61 132.75 245.00 64.76 614.9 486.2 q1a5
+ -7 -35 -23 -464.07 243.89 257.00 80.04 631.0 519.2 q1a5
+ -7 -31 -28 81.78 122.17 124.00 76.56 636.6 579.7 q1a7
+ -7 -31 -27 86.17 145.90 134.00 77.83 645.4 571.6 q1a7
+ -7 -29 -34 -112.51 134.29 130.00 83.83 608.0 652.4 q1a7
+ -7 -29 -33 52.57 125.49 238.00 84.76 617.0 644.1 q1a7
+ -7 -29 -32 166.78 113.29 188.00 82.56 625.9 635.8 q1a7
+ -7 -29 -31 347.03 111.79 134.00 77.92 634.8 627.5 q1a7
+ -6 -54 -12 191.70 84.96 112.00 38.62 601.4 1011.4 q1a11
+ -6 -46 -8 -86.44 77.21 82.00 50.66 690.0 889.4 q1a9
+ -6 -42 -7 121.89 126.30 127.00 54.23 738.4 829.6 q1a9
+ -6 -36 -8 139.53 172.21 189.00 75.40 757.3 389.2 q1a5
+ -6 -20 -53 -97.50 127.36 124.00 66.50 225.6 1185.4 q0a13
+ -6 -20 -52 -366.18 156.65 171.00 71.31 234.8 1194.7 q0a13
+ -6 -18 -39 96.78 149.65 182.00 121.66 330.4 1308.1 q0a15
+ -6 -18 -38 -569.70 243.30 292.00 134.61 339.0 1316.6 q0a15
+ -6 -18 -37 220.43 188.55 211.00 129.24 347.5 1325.0 q0a15
+ -5 -57 -4 -31.64 65.08 56.00 35.16 485.4 969.3 q1a10
+ -5 -53 -1 57.33 120.74 108.00 46.67 527.4 910.0 q1a8
+ -5 -51 0 -33.91 136.22 113.00 44.75 551.4 873.5 q1a8
+ -5 -47 1 -86.92 89.28 109.00 48.92 601.5 812.5 q1a9
+ -5 -43 2 -1.27 107.32 103.00 52.31 652.2 754.5 q1a9
+ -5 -37 1 -179.92 173.70 171.00 88.24 406.5 1418.3 q1a14
+ -5 -35 1 -314.60 198.85 187.00 95.93 429.0 1444.5 q1a14
+ -5 -31 -1 892.61 216.47 578.00 128.44 757.3 73.5 q1a1
+ -5 -29 -2 -14.90 352.88 455.00 144.96 725.3 87.2 q1a1
+ -5 -25 -5 2331.58 368.94 1177.00 163.25 655.4 106.3 q1a1
+ -5 -23 -7 2249.00 440.39 1157.00 158.57 617.3 111.9 q1a1
+ -5 -19 -12 -182.16 224.28 201.00 123.27 537.5 115.3 q1a0
+ -5 -17 -64 196.40 113.17 103.00 55.40 83.1 1124.6 q0a12
+ -5 -17 -16 948.00 199.00 906.00 117.00 484.9 105.5 q1a0
+ -5 -15 -59 -62.46 196.05 269.00 62.48 113.0 1199.9 q0a12
+ -5 -15 -21 31.60 201.17 215.00 119.93 424.2 88.1 q1a0
+ -5 -15 -20 -10.94 162.80 177.00 116.75 432.2 95.8 q1a0
+ -5 -13 -53 32.37 178.09 216.00 69.89 150.8 1280.6 q0a12
+ -5 -13 -27 1028.34 576.96 444.00 186.07 375.1 1470.4 q0a15
+ -4 -56 5 -120.41 86.90 76.00 41.64 423.5 886.2 q1a8
+ -4 -54 6 -92.09 88.68 85.00 43.25 449.5 849.2 q1a8
+ -4 -52 7 18.91 76.56 70.00 42.68 474.6 813.3 q1a8
+ -4 -50 8 -87.22 72.61 72.00 42.02 499.1 778.4 q1a8
+ -4 -44 9 -242.19 102.94 96.00 54.49 402.4 1284.3 q1a12
+ -4 -40 9 125.27 149.97 126.00 69.40 448.8 1313.5 q1a14
+ -4 -38 9 -202.41 158.44 139.00 75.36 471.2 1341.2 q1a14
+ -4 -34 8 -180.15 185.17 197.00 101.55 506.7 1402.0 q1a14
+ -4 -32 7 95.65 402.32 339.00 113.95 520.0 1435.2 q1a14
+ -4 -26 4 4442.67 532.22 2229.00 174.76 736.0 175.7 q1a1
+ -4 -10 -62 158.31 123.33 117.00 63.77 25.3 1242.7 q0a12
+ -4 -8 -55 -36.20 165.69 155.00 80.88 75.2 1303.4 q0a14
+ -4 -8 -25 47.00 179.98 228.00 92.00 332.1 317.4 q0a3
+ -4 -8 -24 -99.88 215.54 384.00 95.24 324.6 325.5 q0a3
+ -3 -53 13 90.97 79.20 88.00 41.08 403.8 761.7 q1a8
+ -3 -47 15 -1.36 76.79 95.00 47.56 428.5 1187.2 q1a12
+ -3 -45 15 -149.64 92.00 83.00 49.73 452.1 1217.6 q1a12
+ -3 -37 15 215.24 154.02 179.00 83.34 541.8 1305.5 q1a14
+ -3 -23 9 1452.79 308.76 527.00 115.13 739.3 227.7 q1a3
+ -3 -11 -75 -120.69 105.45 98.00 47.69 15.6 824.9 q0a8
+ -3 -9 -72 94.66 90.11 79.00 45.54 74.8 810.6 q0a8
+ -3 -9 -8 12504.06 366.40 7990.00 37.94 459.2 237.6 q1a2
+ -3 -7 -67 122.86 126.00 116.00 51.74 150.8 776.1 q0a8
+ -3 -7 -12 572.87 132.06 123.00 39.66 407.7 227.8 q1a2
+ -3 -5 -18 531.34 125.44 436.00 65.07 239.3 339.7 q0a3
+ -3 -3 -54 359.16 139.31 165.00 89.16 28.4 1379.5 q0a14
+ -3 -3 -26 -12.84 108.63 110.00 73.73 278.5 255.2 q0a3
+ -3 -3 -25 12.08 106.69 131.00 73.65 271.1 263.5 q0a3
+ -2 -48 20 -21.41 99.56 84.00 44.21 470.9 1125.1 q1a12
+ -2 -34 20 481.77 150.52 146.00 87.31 621.9 1304.5 q1a15
+ -2 -20 13 -518.78 290.83 218.00 102.87 734.8 298.5 q1a3
+ -2 -18 11 142.93 136.28 158.00 75.04 696.8 302.7 q1a3
+ -2 -10 2 2447.39 222.77 1141.00 46.91 544.0 312.2 q1a2
+ -2 -8 -79 69.24 103.35 84.00 47.36 20.9 913.0 q0a8
+ -2 -8 -1 5154.28 244.47 3072.00 41.63 500.2 309.4 q1a2
+ -2 -6 -75 7.25 71.96 82.00 45.75 91.0 885.6 q0a8
+ -2 -4 -71 -149.56 189.59 156.00 55.56 158.0 859.5 q0a8
+ -2 -4 -9 207.33 131.60 191.00 39.10 397.6 289.8 q1a2
+ -2 -2 -66 248.19 110.94 156.00 51.81 228.2 824.1 q0a9
+ -2 -2 -14 -437.06 191.73 162.00 58.25 172.8 337.8 q0a2
+ -2 0 -59 191.21 107.33 168.00 58.59 315.4 770.5 q0a9
+ -2 2 -47 708.26 327.22 439.00 118.77 376.3 43.8 q0a1
+ -2 2 -46 455.42 224.47 414.00 123.73 368.3 53.1 q0a1
+ -2 2 -45 36.64 173.54 209.00 126.03 360.4 62.4 q0a1
+ -2 2 -34 1607.39 265.90 996.00 150.87 276.2 161.2 q0a1
+ -2 2 -33 1229.85 194.38 697.00 139.68 268.8 170.0 q0a1
+ -1 -35 25 503.09 115.85 344.00 57.14 663.9 1275.4 q1a13
+ -1 -31 24 310.11 149.09 180.00 97.49 696.1 1310.5 q1a15
+ -1 -17 16 -352.75 207.64 191.00 80.75 723.3 361.5 q1a3
+ -1 -3 -78 -121.16 80.63 70.00 37.96 108.0 935.4 q0a10
+ -1 1 -69 -55.11 70.58 80.00 49.51 245.8 896.7 q0a9
+ -1 1 -11 3659.67 225.37 1424.00 56.19 111.0 327.9 q0a2
+ -1 3 -62 -189.35 244.16 315.00 60.15 333.6 840.3 q0a9
+ -1 3 -18 -64.37 106.30 109.00 58.48 141.6 252.3 q0a2
+ -1 5 -53 29.76 171.66 146.00 74.66 368.0 384.5 q0a5
+ -1 5 -52 173.41 145.65 193.00 71.15 377.7 392.8 q0a5
+ 0 -42 30 131.32 108.55 89.00 45.08 645.0 1126.8 q1a13
+ 0 -40 30 -81.11 93.58 84.00 46.51 666.1 1157.7 q1a13
+ 0 -38 30 38.60 78.94 87.00 51.60 686.7 1187.9 q1a13
+ 0 -18 22 -15.46 247.15 267.00 123.72 797.6 78.2 q2a0
+ 0 -6 10 -78.24 109.61 114.00 51.94 820.4 273.9 q2a2
+ 0 -4 7 665.66 148.69 697.00 50.46 817.3 317.7 q2a2
+ 0 0 -80 -236.89 96.92 79.00 36.49 135.3 1002.6 q0a10
+ 0 6 -64 -58.46 143.04 118.00 49.66 360.9 901.3 q0a9
+ 0 6 -16 2238.55 173.15 1464.00 53.78 86.5 234.5 q0a2
+ 0 8 -55 163.96 110.92 113.00 65.88 309.7 411.7 q0a5
+ 0 8 -54 173.38 110.37 106.00 65.97 319.6 419.9 q0a5
+ 0 8 -26 504.16 180.01 623.00 104.73 137.4 160.6 q0a0
+ 0 8 -25 329.33 123.47 201.00 101.46 130.4 169.3 q0a0
+ 1 -39 34 -96.45 81.06 95.00 52.05 723.2 1134.3 q1a13
+ 1 -29 32 134.12 109.64 121.00 73.04 1051.5 730.8 q2a7
+ 1 -19 27 178.39 303.95 323.00 142.01 839.8 26.1 q2a0
+ 1 -11 21 -543.38 131.57 131.00 98.86 867.7 165.5 q2a0
+ 1 -5 14 -322.66 255.92 299.00 56.20 871.7 255.5 q2a2
+ 1 1 -85 97.47 64.66 66.00 33.73 103.1 1092.4 q0a10
+ 1 3 -81 50.04 116.03 116.00 35.16 173.4 1059.2 q0a10
+ 1 7 -71 -63.69 86.85 83.00 42.69 319.9 974.9 q0a11
+ 1 7 -9 81.95 153.38 168.00 56.41 15.1 276.4 q0a2
+ 1 9 -15 670.32 117.20 341.00 51.71 38.3 208.5 q0a2
+ 1 11 -55 -39.99 88.73 90.00 62.41 270.5 455.7 q0a5
+ 1 11 -54 167.78 100.43 126.00 63.56 280.5 463.9 q0a5
+ 1 11 -26 48.00 133.00 195.00 113.00 95.3 125.7 q0a0
+ 1 11 -25 703.94 147.70 710.00 109.55 88.4 134.4 q0a0
+ 2 -34 37 -557.68 180.55 144.00 61.22 938.7 723.6 q2a6
+ 2 -30 36 461.73 139.81 347.00 71.88 1001.3 693.6 q2a7
+ 2 -24 34 188.66 190.22 317.00 94.54 1098.9 654.1 q2a7
+ 2 -22 33 913.00 333.42 528.00 107.00 1132.6 643.7 q2a7
+ 2 -14 28 -845.03 368.32 415.00 145.18 906.7 76.7 q2a0
+ 2 -4 18 688.43 137.13 326.00 54.09 923.4 236.9 q2a2
+ 2 4 6 -149.63 112.40 90.00 53.30 1193.6 310.6 q3a2
+ 2 8 -77 -19.93 147.35 211.00 41.33 285.2 1071.5 q0a11
+ 2 8 -3 1580.36 188.23 958.00 54.89 1303.8 336.5 q3a2
+ 2 10 -71 214.85 127.55 99.00 40.35 366.7 1017.4 q0a11
+ 2 10 -9 690.88 121.98 203.00 61.12 1368.4 359.4 q3a3
+ 2 12 -64 262.05 99.77 105.00 47.55 155.5 403.0 q0a4
+ 2 14 -53 47.68 95.80 108.00 63.21 251.3 516.2 q0a5
+ 2 14 -52 104.36 120.05 137.00 65.01 261.4 524.1 q0a5
+ 2 14 -28 405.53 172.70 371.00 135.76 66.6 72.7 q0a0
+ 2 14 -27 1012.25 292.01 620.00 133.75 59.7 81.6 q0a0
+ 3 -37 41 -39.84 87.52 89.00 49.04 853.7 704.1 q2a6
+ 3 -31 40 -64.64 174.25 148.00 57.24 952.7 655.4 q2a6
+ 3 -25 38 41.91 119.46 169.00 75.29 1050.0 616.3 q2a7
+ 3 -23 37 309.44 151.19 229.00 83.85 1084.6 606.0 q2a7
+ 3 -21 36 285.40 224.01 293.00 94.93 1118.6 595.9 q2a7
+ 3 -19 35 -374.28 352.72 415.00 109.43 1152.2 585.9 q2a7
+ 3 -13 31 2147.56 456.79 687.00 169.44 953.3 63.6 q2a0
+ 3 7 6 652.20 118.00 548.00 48.55 1227.0 268.9 q3a2
+ 3 15 -62 -6.72 99.28 114.00 48.28 135.7 465.9 q0a4
+ 3 15 -18 -254.31 294.10 255.00 97.23 1497.2 360.3 q3a3
+ 3 15 -17 11.97 195.53 163.00 83.53 1488.5 353.6 q3a3
+ 3 17 -49 109.72 119.36 113.00 65.43 253.0 564.2 q0a7
+ 3 17 -48 29.36 127.30 119.00 68.09 263.1 571.8 q0a7
+ 3 17 -47 -214.91 122.56 110.00 71.86 273.1 579.4 q0a7
+ 3 17 -31 743.10 220.25 539.00 135.81 44.4 9.5 q0a0
+ 4 -34 44 53.04 72.73 75.00 47.16 868.5 634.3 q2a6
+ 4 -30 43 133.01 137.46 115.00 53.39 936.8 605.3 q2a6
+ 4 -24 41 55.41 138.97 117.00 66.79 1035.1 567.3 q2a7
+ 4 -12 34 1488.04 247.61 601.00 153.16 997.5 50.5 q2a1
+ 4 0 22 -80.29 95.21 113.00 67.03 1015.0 251.4 q2a3
+ 4 12 1 5859.30 284.53 3213.00 55.61 1320.2 242.9 q3a2
+ 4 16 -69 -70.97 87.88 84.00 48.77 30.4 429.4 q0a4
+ 4 16 -11 244.93 151.19 442.00 79.94 1454.2 288.2 q3a3
+ 4 18 -60 -73.61 85.65 87.00 49.24 115.9 528.7 q0a4
+ 4 18 -59 174.71 128.50 149.00 53.29 126.7 536.9 q0a4
+ 5 -9 35 -106.55 258.46 316.00 144.77 1048.1 76.5 q2a1
+ 5 1 25 -89.96 129.54 172.00 77.22 1061.5 240.1 q2a3
+ 5 17 -6 8.91 111.52 117.00 68.33 1428.4 229.2 q3a3
+ 5 19 -66 -23.30 96.93 97.00 46.62 21.6 503.0 q0a4
+ 5 19 -14 2814.64 541.83 1429.00 155.27 1515.3 264.8 q3a3
+ 5 21 -55 -43.82 86.72 99.00 50.22 129.5 588.2 q0a6
+ 5 21 -54 103.31 110.96 98.00 52.77 140.3 596.1 q0a6
+ 5 21 -26 -549.16 435.00 393.00 152.94 1511.2 1403.4 q3a15
+ 5 21 -25 3893.13 287.54 1302.00 132.96 1504.4 1412.7 q3a15
+ 6 -30 49 115.27 88.00 94.00 44.71 872.7 547.2 q2a4
+ 6 -14 42 1731.41 353.35 730.00 88.79 1151.1 465.9 q2a5
+ 6 -6 36 -44.59 354.82 491.00 156.79 1098.8 102.6 q2a1
+ 6 -4 34 -216.74 406.95 447.00 171.14 1101.2 141.5 q2a1
+ 6 4 25 -130.09 172.51 258.00 92.43 1104.8 273.6 q2a3
+ 6 6 22 367.18 237.36 257.00 91.51 1100.9 318.4 q2a3
+ 6 8 19 36.19 224.47 245.00 83.96 1097.1 362.9 q2a3
+ 6 10 16 39.58 145.15 168.00 97.27 1187.9 153.5 q3a0
+ 6 12 12 720.86 149.70 728.00 101.47 1240.1 163.1 q3a0
+ 6 14 8 486.50 148.50 280.00 102.21 1292.3 172.7 q3a0
+ 6 20 -9 6213.00 328.57 1933.00 104.00 1489.3 205.2 q3a3
+ 6 22 -18 -347.90 249.65 285.00 133.43 1430.8 1457.4 q3a15
+ 6 24 -44 -123.58 129.99 131.00 68.73 202.3 717.8 q0a7
+ 6 24 -43 -250.51 229.85 285.00 74.83 212.5 725.1 q0a7
+ 6 24 -42 -42.72 180.44 232.00 70.83 222.7 732.4 q0a7
+ 6 24 -37 366.10 258.43 320.00 73.57 1542.5 1287.7 q3a13
+ 7 -31 52 -88.47 110.59 113.00 46.27 823.7 511.3 q2a4
+ 7 -27 51 180.76 145.88 167.00 48.64 894.6 485.0 q2a4
+ 7 -7 40 432.27 233.83 388.00 124.53 1138.9 57.2 q2a1
+ 7 3 30 2448.16 704.88 800.00 189.04 1150.4 224.5 q2a3
+ 7 13 15 -253.51 163.19 197.00 112.46 1229.7 116.0 q3a0
+ 7 15 11 -103.19 159.61 262.00 117.58 1282.2 125.7 q3a0
+ 7 19 1 953.97 200.00 554.00 127.90 1401.1 157.1 q3a1
+ 7 25 -56 -188.28 104.40 111.00 50.43 50.7 653.9 q0a6
+ 7 25 -55 -49.54 104.35 110.00 51.38 61.9 661.7 q0a6
+ 7 25 -25 118.30 153.06 166.00 100.01 1432.6 1355.6 q3a15
+ 7 25 -24 76.54 163.18 203.00 107.38 1426.0 1365.1 q3a15
+ 8 -20 51 -215.75 109.29 96.00 59.75 988.1 405.5 q2a5
+ 8 -18 50 92.40 98.39 96.00 57.40 1024.6 396.9 q2a5
+ 8 -16 49 -270.36 128.25 110.00 59.76 1060.4 388.5 q2a5
+ 8 -6 42 158.13 227.78 223.00 102.67 822.4 1473.0 q2a14
+ 8 4 32 1768.58 352.32 733.00 160.95 1015.7 1463.4 q2a15
+ 8 8 27 -913.74 629.68 451.00 206.14 1099.3 1465.6 q2a15
+ 8 10 24 -308.08 593.09 551.00 197.55 1144.5 1469.6 q2a15
+ 8 14 17 -192.63 218.52 267.00 133.38 1227.3 74.3 q3a0
+ 8 18 9 2058.86 481.16 998.00 163.47 1333.1 93.7 q3a0
+ 8 20 4 6201.22 519.91 3523.00 172.26 1391.6 109.5 q3a1
+ 8 22 -2 805.15 349.10 464.00 157.32 1462.1 131.4 q3a1
+ 8 24 -9 3061.75 402.27 1097.00 151.25 1542.4 159.7 q3a1
+ 9 -27 56 -118.62 95.79 76.00 41.62 835.8 400.9 q2a4
+ 9 -5 44 -316.66 196.25 211.00 98.46 816.2 1428.8 q2a14
+ 9 5 34 36.62 203.50 445.00 141.99 1011.4 1420.2 q2a15
+ 9 9 29 -2212.94 675.86 493.00 195.24 1095.7 1422.8 q2a15
+ 9 11 26 -416.05 886.58 1061.00 208.37 1141.4 1426.9 q2a15
+ 9 23 1 -130.45 198.75 319.00 152.93 1452.9 83.0 q3a1
+ 9 27 -14 -194.30 367.19 339.00 118.27 1305.7 1418.8 q3a14
+ 9 29 -29 113.85 215.59 220.00 69.45 1384.6 1284.1 q3a13
+ 10 -16 54 -222.50 135.85 116.00 50.50 1129.2 903.7 q2a9
+ 10 -8 49 101.88 106.22 113.00 55.12 1104.3 753.3 q2a9
+ 10 -2 44 7.80 128.16 148.00 92.80 850.8 1382.3 q2a14
+ 10 26 -3 922.10 245.69 300.00 127.96 1524.6 62.0 q3a1
+ 10 28 -11 56.30 183.43 241.00 98.16 1256.3 1427.0 q3a14
+ 10 30 -22 19.21 129.34 155.00 92.79 1311.3 1304.0 q3a14
+ 11 -9 52 277.68 95.28 95.00 47.92 1065.3 795.6 q2a9
+ 11 1 44 -354.12 177.69 200.00 96.12 885.6 1335.5 q2a14
+ 11 3 42 190.45 201.11 225.00 101.95 926.0 1334.2 q2a14
+ 11 9 35 594.04 181.50 275.00 107.16 1049.6 1336.1 q2a15
+ 11 17 23 2323.71 386.64 567.00 117.56 1525.4 684.4 q3a7
+ 11 29 -8 392.72 149.11 177.00 96.94 1206.2 1435.3 q3a14
+ 11 31 -18 34.26 139.19 123.00 76.40 1254.2 1321.6 q3a14
+ 12 -22 61 -53.86 80.49 99.00 39.26 1071.1 1043.0 q2a11
+ 12 -20 60 68.40 63.34 79.00 37.40 1063.1 1002.9 q2a11
+ 12 -10 55 -91.78 98.84 95.00 52.98 1025.0 839.5 q2a9
+ 12 20 21 -108.89 227.15 245.00 106.67 1491.0 632.0 q3a7
+ 12 26 7 130.14 371.96 391.00 108.41 1533.7 478.3 q3a5
+ 12 32 -15 56.19 108.90 113.00 76.14 1203.0 1329.5 q3a14
+ 12 34 -34 44.91 102.11 101.00 52.14 1311.6 1143.2 q3a12
+ 12 34 -33 -5.07 85.91 109.00 52.27 1304.8 1154.1 q3a12
+ 12 34 -32 -117.64 88.99 86.00 52.09 1298.1 1164.9 q3a12
+ 13 13 35 -80.44 204.54 247.00 79.56 1096.9 1282.4 q2a13
+ 13 17 29 356.58 169.46 295.00 89.89 1436.0 727.8 q3a7
+ 13 21 22 -334.05 140.45 152.00 92.53 1451.2 625.4 q3a7
+ 13 23 18 -341.96 144.44 146.00 93.35 1461.7 570.0 q3a7
+ 13 29 3 -75.45 192.08 218.00 85.36 1511.1 404.4 q3a5
+ 13 31 -4 45.72 219.44 265.00 65.17 1532.4 759.7 q3a9
+ 13 35 -28 -58.91 77.78 79.00 48.86 1238.4 1182.8 q3a12
+ 13 35 -27 -22.20 85.82 85.00 50.88 1231.8 1193.6 q3a12
+ 14 -10 59 -54.30 133.25 153.00 44.70 942.3 886.1 q2a8
+ 14 -4 55 -84.81 96.37 100.00 48.81 928.6 766.9 q2a8
+ 14 2 50 239.79 88.47 97.00 53.41 841.3 1234.3 q2a12
+ 14 4 48 -161.49 111.07 128.00 57.89 883.5 1233.6 q2a12
+ 14 6 46 -692.24 273.73 199.00 72.64 925.2 1232.9 q2a12
+ 14 12 39 7.47 96.75 95.00 63.73 1053.0 1236.3 q2a13
+ 14 20 27 -227.21 167.92 167.00 88.41 1400.0 674.6 q3a7
+ 14 26 15 95.18 98.57 145.00 75.51 1431.3 534.4 q3a5
+ 14 28 10 64.55 146.33 205.00 78.52 1448.1 469.3 q3a5
+ 14 30 4 -52.36 98.88 115.00 71.91 1470.8 394.4 q3a5
+ 14 34 -11 259.19 102.13 89.00 51.42 1424.5 764.5 q3a9
+ 14 36 -24 207.24 103.55 116.00 49.24 1178.2 1200.9 q3a12
+ 15 -7 59 255.70 92.48 138.00 45.70 890.9 849.1 q2a8
+ 15 -3 56 22.05 79.99 81.00 47.55 884.3 766.7 q2a8
+ 15 3 51 -49.49 95.21 93.00 53.89 842.7 1190.9 q2a12
+ 15 5 49 -8.66 93.20 101.00 57.46 885.4 1190.3 q2a12
+ 15 7 47 -242.88 231.62 303.00 62.88 927.7 1189.8 q2a12
+ 15 13 40 -343.94 122.82 104.00 63.94 1056.9 1193.9 q2a13
+ 15 27 16 -335.45 180.28 175.00 75.29 1390.0 525.8 q3a5
+ 15 29 11 235.18 144.09 201.00 67.08 1406.8 459.9 q3a5
+ 15 33 -1 -102.58 163.23 191.00 59.97 1520.0 847.2 q3a9
+ 15 37 -21 157.41 86.76 84.00 44.22 1282.4 750.4 q3a8
+ 16 -6 60 73.78 77.56 80.00 44.02 845.0 849.9 q2a8
+ 16 4 52 103.21 123.28 96.00 52.59 844.2 1146.3 q2a12
+ 16 6 50 257.46 99.11 233.00 56.34 887.4 1146.0 q2a12
+ 16 8 48 -93.71 146.74 168.00 59.91 930.1 1145.7 q2a12
+ 16 14 41 194.85 111.42 89.00 54.35 1061.0 1150.4 q2a13
+ 16 22 29 131.80 183.16 174.00 68.88 1318.5 661.8 q3a6
+ 16 24 25 62.90 172.01 185.00 69.06 1329.3 604.5 q3a6
+ 16 38 -20 -39.24 107.89 101.00 44.90 1267.6 792.8 q3a8
+ 17 -5 61 -16.51 120.18 147.00 46.11 798.0 850.7 q2a8
+ 17 21 33 -70.50 88.07 144.00 64.50 1269.3 704.5 q3a6
+ 17 25 26 14.50 108.59 124.00 63.50 1285.7 597.2 q3a6
+ 17 37 -8 34.66 87.93 109.00 49.03 1385.9 891.3 q3a9
+ 17 39 -19 149.47 95.79 87.00 44.68 1252.5 836.3 q3a8
+ 18 24 30 -97.75 106.23 105.00 60.75 1235.4 639.4 q3a6
+ 18 30 18 109.86 110.33 160.00 58.96 1268.5 489.5 q3a4
+ 18 32 13 -152.18 121.11 115.00 57.86 1285.7 420.8 q3a4
+ 18 36 1 129.52 83.23 75.00 47.52 1475.1 943.5 q3a11
+ 18 40 -19 -9.62 70.46 74.00 44.83 1225.5 874.6 q3a8
+ 19 23 34 95.80 111.81 126.00 61.80 1183.5 682.9 q3a6
+ 19 37 1 -95.27 84.77 85.00 48.29 1452.2 983.2 q3a11
+ 19 41 -19 -5.94 78.65 78.00 45.24 1197.7 914.1 q3a8
+ 20 38 1 -3.18 65.22 92.00 45.21 1428.6 1024.1 q3a11
+ 21 41 -8 -87.45 93.39 83.00 44.95 1287.6 1025.0 q3a10
+ 22 42 -9 -90.44 75.13 77.00 39.44 1248.2 1062.6 q3a10
+ 23 43 -10 -217.50 89.57 89.00 38.50 1207.2 1101.7 q3a10
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035214_1e681.h5
+Image serial number: 46
+hit = 1
+indexed_by = none
+photon_energy_eV = 9511.588169
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9511.588169
+average_camera_length = 0.152001 m
+num_peaks = 15
+peak_resolution = 3.948810 nm^-1 or 2.532408 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 11.95 13.05 2.34 534.24 q0a0
+ 251.75 98.64 2.23 3578.00 q0a1
+ 986.50 97.10 2.10 1502.62 q2a1
+1262.50 131.19 1.75 521.68 q3a0
+ 148.40 293.11 0.96 5706.65 q0a2
+ 265.50 321.09 1.41 931.60 q0a3
+ 533.50 266.94 1.03 1246.10 q1a2
+ 543.80 351.50 0.77 937.59 q1a2
+ 902.50 237.67 1.10 1835.04 q2a2
+ 808.50 319.94 0.51 7343.44 q2a2
+1210.50 240.83 0.97 706.91 q3a2
+ 485.50 533.92 3.95 329.04 q1a4
+ 669.12 454.50 3.32 219.33 q1a5
+1405.85 664.15 3.22 337.58 q3a7
+ 503.07 1280.50 3.47 957.59 q1a12
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035100_17df9.h5
+Image serial number: 47
+hit = 1
+indexed_by = none
+photon_energy_eV = 9510.069702
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9510.069702
+average_camera_length = 0.152001 m
+num_peaks = 16
+peak_resolution = 2.240995 nm^-1 or 4.462304 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 103.92 38.08 2.24 885.05 q0a0
+ 215.50 116.80 2.06 2015.02 q0a1
+ 238.07 134.00 2.04 1561.00 q0a1
+ 67.60 334.71 0.52 3656.05 q0a2
+ 319.13 206.31 1.96 1943.21 q0a3
+ 429.50 211.81 1.12 1263.85 q1a2
+ 497.99 227.94 1.12 3287.64 q1a2
+ 497.23 258.25 0.97 14938.85 q1a2
+ 533.98 293.00 0.92 2695.33 q1a2
+1078.89 287.50 1.66 1545.88 q2a3
+1015.63 300.50 1.32 1915.73 q2a3
+1227.50 214.65 1.12 2326.44 q3a2
+1312.15 280.50 0.99 2678.02 q3a2
+1320.65 287.02 1.00 2072.88 q3a2
+1319.30 323.50 0.86 2481.46 q3a2
+1322.50 339.35 0.83 1731.31 q3a2
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035032_157c2.h5
+Image serial number: 50
+hit = 1
+indexed_by = none
+photon_energy_eV = 9517.125915
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9517.125915
+average_camera_length = 0.152001 m
+num_peaks = 11
+peak_resolution = 2.802431 nm^-1 or 3.568331 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 97.99 33.99 2.26 1094.19 q0a0
+1252.50 147.81 1.65 1809.06 q3a0
+ 75.33 265.32 0.89 1844.25 q0a2
+ 227.80 220.93 1.55 6719.45 q0a3
+ 403.50 301.01 0.64 1067.74 q1a2
+1289.00 288.54 0.88 11337.44 q3a2
+1392.50 195.66 1.63 1545.55 q3a3
+1518.11 654.50 2.70 1324.85 q3a7
+1534.10 700.28 2.61 1520.76 q3a7
+ 863.90 1451.50 2.80 439.78 q2a14
+1509.39 1434.82 2.30 2816.54 q3a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035150_1c54b.h5
+Image serial number: 51
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9520.392065
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9520.392065
+average_camera_length = 0.152001 m
+num_peaks = 37
+peak_resolution = 4.320822 nm^-1 or 2.314374 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 487.49 30.60 2.26 2913.77 q1a0
+ 634.59 133.07 2.05 2940.76 q1a1
+ 898.34 146.24 1.69 2210.81 q2a0
+1322.07 13.26 2.40 2791.58 q3a0
+1328.50 62.09 2.18 1668.36 q3a0
+1227.50 119.84 1.78 1775.34 q3a0
+1263.06 121.94 1.79 714.64 q3a0
+1312.50 140.84 1.77 715.35 q3a0
+1387.94 114.03 2.08 2829.26 q3a1
+1435.23 134.50 2.13 786.78 q3a1
+ 20.05 259.20 0.89 25598.51 q0a2
+ 170.20 347.03 0.87 1185.29 q0a2
+ 402.50 211.92 1.13 1218.11 q1a2
+ 536.85 274.90 1.01 978.49 q1a2
+ 569.60 292.75 1.07 2731.14 q1a2
+ 517.40 315.94 0.77 10158.50 q1a2
+ 412.50 342.78 0.41 643.07 q1a2
+ 905.37 204.29 1.27 3131.92 q2a2
+ 943.50 226.24 1.28 3500.94 q2a2
+ 887.50 241.93 1.05 2153.62 q2a2
+ 905.86 253.50 1.04 1206.12 q2a2
+ 923.91 265.00 1.05 2006.33 q2a2
+ 865.55 266.49 0.87 13204.21 q2a2
+ 903.28 288.25 0.88 14696.31 q2a2
+ 991.64 300.98 1.21 2694.30 q2a3
+1075.51 314.22 1.59 1837.85 q2a3
+1178.50 264.02 0.84 973.47 q3a2
+1197.95 272.50 0.79 1007.29 q3a2
+1336.27 276.50 1.10 865.34 q3a2
+1313.50 305.69 0.90 3824.62 q3a2
+1214.50 315.36 0.57 7776.91 q3a2
+1401.11 338.50 1.23 978.11 q3a3
+1380.50 350.88 1.10 1282.07 q3a3
+1507.16 353.51 1.75 3349.80 q3a3
+1494.96 1005.96 4.32 415.71 q3a11
+1089.82 1188.81 3.58 507.81 q2a13
+ 363.64 1423.28 2.34 3004.60 q0a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.15991 12.18940 16.95144 nm, 89.58707 90.45023 89.96676 deg
+astar = +0.1009663 +0.0588473 +0.1126887 nm^-1
+bstar = +0.0641291 -0.0272935 -0.0432804 nm^-1
+cstar = +0.0022978 +0.0516726 -0.0283746 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00432 nm^-1
+predict_refine/final_residual = 2.507312e-06
+predict_refine/det_shift x = -0.037 y = 0.021 mm
+diffraction_resolution_limit = 2.25 nm^-1 or 4.44 A
+num_reflections = 392
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -28 -12 -34 -149.65 84.96 82.00 51.85 860.2 1094.7 q2a10
+ -27 -9 -37 -80.32 77.17 92.00 49.92 827.7 1020.0 q2a10
+ -27 -7 -39 -54.97 113.18 121.00 51.77 788.0 995.5 q2a10
+ -26 -18 -25 -28.00 62.60 88.00 56.00 1048.8 1099.8 q2a11
+ -26 -12 -33 -208.11 118.20 100.00 54.51 920.6 1022.4 q2a10
+ -25 -9 -36 -161.34 96.97 94.00 55.54 888.5 950.8 q2a10
+ -24 -14 -29 32.89 75.89 89.00 57.51 1019.6 980.7 q2a11
+ -23 -17 -24 94.09 104.44 97.00 57.18 1112.9 986.5 q2a11
+ -23 -15 -27 -198.55 90.13 89.00 59.95 1068.2 960.8 q2a11
+ -23 -5 -39 204.24 91.19 118.00 69.36 871.3 865.6 q2a8
+ -23 -3 -41 -133.90 105.58 122.00 71.10 833.9 841.4 q2a8
+ -22 -22 -15 52.89 101.09 114.00 67.51 866.5 431.2 q2a4
+ -22 -8 -35 18.20 213.46 242.00 68.20 958.5 871.6 q2a8
+ -22 -6 -37 8.88 124.93 125.00 69.12 922.2 847.9 q2a8
+ -22 0 -43 48.29 134.14 135.00 70.91 811.3 775.7 q2a8
+ -21 -27 -4 88.73 109.94 108.00 62.58 827.6 565.3 q2a6
+ -21 -21 -16 -120.41 146.66 159.00 73.21 911.5 431.8 q2a4
+ -21 -19 -19 151.66 124.28 142.00 68.54 936.8 388.4 q2a4
+ -21 -13 -28 80.41 111.62 155.00 76.79 1082.8 902.5 q2a9
+ -21 -9 -33 83.59 189.09 264.00 75.21 1004.1 854.2 q2a9
+ -20 -26 -5 -37.95 107.79 113.00 67.55 873.1 563.3 q2a6
+ -20 -24 -9 373.39 140.51 233.00 72.01 900.2 537.1 q2a4
+ -20 -22 -13 -260.62 187.36 167.00 76.62 927.8 484.5 q2a4
+ -20 -8 -33 403.46 113.06 160.00 74.34 1016.6 814.2 q2a9
+ -20 2 -43 -208.65 195.78 237.00 85.85 790.4 1154.4 q2a12
+ -19 -27 -1 106.00 108.68 137.00 72.43 887.4 624.4 q2a6
+ -19 -17 -20 246.74 116.79 140.00 80.86 1017.1 399.8 q2a5
+ -19 -9 -31 -31.62 122.45 144.00 81.62 1063.1 798.1 q2a9
+ -19 3 -43 83.95 134.85 137.00 83.45 829.3 1168.4 q2a12
+ -18 -28 3 -35.55 131.33 162.00 75.62 901.5 684.7 q2a6
+ -18 -26 -2 427.67 168.69 379.00 76.46 931.1 621.5 q2a6
+ -18 -24 -6 30.94 188.55 164.00 83.16 957.8 569.2 q2a6
+ -18 -22 -10 -206.65 225.77 236.00 95.12 980.9 544.8 q2a5
+ -18 -18 -17 -11.31 106.34 139.00 90.31 1031.9 451.6 q2a5
+ -18 -12 -26 -166.68 247.12 233.00 89.08 1150.3 806.7 q2a9
+ -18 -8 -31 97.18 99.36 124.00 80.42 1074.6 759.6 q2a9
+ -18 2 -41 62.99 129.55 181.00 84.61 843.6 1217.9 q2a12
+ -18 8 -46 126.49 114.29 138.00 82.32 914.8 1117.4 q2a12
+ -17 -19 -14 374.30 155.11 185.00 92.30 1046.4 502.4 q2a5
+ -17 -5 -33 506.91 188.36 243.00 120.29 788.4 1340.9 q2a14
+ -17 1 -39 -74.35 112.89 125.00 88.15 857.5 1265.9 q2a12
+ -17 3 -41 211.10 180.78 293.00 89.10 881.0 1230.9 q2a12
+ -17 7 -44 405.85 178.78 437.00 91.35 927.9 1167.7 q2a12
+ -16 -30 13 100.25 115.76 119.00 74.59 710.9 1164.9 q1a13
+ -16 -26 2 -158.53 162.41 168.00 100.60 981.5 687.6 q2a7
+ -16 -18 -14 776.40 339.14 347.00 117.40 1084.5 511.1 q2a5
+ -16 -12 -23 -771.19 371.74 418.00 125.15 1156.3 388.0 q2a5
+ -16 -4 -33 -117.05 157.79 194.00 122.45 825.3 1352.2 q2a14
+ -16 -2 -35 -56.96 187.24 192.00 119.16 848.1 1318.6 q2a14
+ -15 -33 27 -158.91 132.59 138.00 68.75 531.5 1136.7 q1a12
+ -15 -31 19 24.23 103.61 113.00 69.46 630.0 1174.0 q1a13
+ -15 -25 2 21.27 134.37 177.00 108.55 1020.6 694.0 q2a7
+ -15 -17 -14 1230.61 527.57 507.00 140.62 1121.9 519.7 q2a5
+ -15 -7 -28 112.61 341.14 381.00 147.99 815.3 1437.2 q2a14
+ -15 5 -40 -154.90 372.11 402.00 105.10 953.0 1264.0 q2a12
+ -15 13 -46 48.16 149.40 148.00 86.04 1045.3 1139.0 q2a13
+ -14 -34 37 -131.32 107.88 108.00 65.68 397.9 1135.3 q1a12
+ -14 -30 19 58.61 147.14 158.00 76.76 625.7 1214.4 q1a13
+ -14 -28 12 46.10 212.24 242.00 83.67 711.6 1247.0 q1a13
+ -14 -24 2 -53.76 170.45 203.00 114.73 1058.8 700.3 q2a7
+ -14 -12 -20 -242.20 252.14 348.00 180.13 1094.7 11.3 q2a1
+ -14 -4 -30 -430.92 252.17 298.00 154.32 873.5 1414.9 q2a14
+ -14 2 -36 147.04 252.39 297.00 142.16 941.9 1316.1 q2a14
+ -14 12 -44 75.96 134.95 147.00 88.84 1056.3 1188.1 q2a13
+ -13 -35 56 77.46 91.27 92.00 49.22 405.2 939.9 q1a10
+ -13 -35 57 -107.76 81.13 86.00 49.97 402.1 954.9 q1a10
+ -13 -35 58 -56.23 88.26 94.00 49.39 399.0 969.9 q1a10
+ -13 -35 59 -38.81 91.40 108.00 47.51 395.9 985.1 q1a10
+ -13 -33 36 -64.15 132.14 126.00 67.45 408.6 1180.3 q1a12
+ -13 -31 26 141.31 121.71 177.00 70.77 536.7 1221.3 q1a12
+ -13 -27 12 6.90 313.03 391.00 96.33 706.6 1285.7 q1a13
+ -13 -23 2 659.36 362.46 420.00 135.93 1096.3 706.5 q2a7
+ -13 11 -42 -205.82 208.99 258.00 101.42 1066.9 1235.8 q2a13
+ -13 21 -48 18.23 179.74 249.00 87.97 1236.2 728.0 q3a6
+ -12 -34 56 94.67 108.93 82.00 47.46 450.6 939.3 q1a10
+ -12 -34 57 -49.18 86.80 81.00 47.58 447.8 954.0 q1a10
+ -12 -32 36 -62.81 141.59 141.00 72.57 406.6 1221.6 q1a12
+ -12 -30 26 -73.57 161.53 170.00 79.24 533.4 1261.1 q1a12
+ -12 -24 7 -78.03 243.69 281.00 155.18 763.3 1323.0 q1a15
+ -12 -22 2 358.33 441.22 409.00 159.20 1133.1 712.6 q2a7
+ -12 -16 -10 -805.58 424.55 496.00 201.58 952.3 12.9 q2a0
+ -12 -14 -13 -913.29 305.53 360.00 208.56 989.2 35.6 q2a1
+ -12 -10 -19 363.16 348.57 453.00 213.04 1068.9 80.9 q2a1
+ -12 -8 -22 286.71 529.01 511.00 220.37 1108.8 103.6 q2a1
+ -12 -2 -29 816.19 615.61 507.00 211.81 942.2 1443.4 q2a14
+ -12 2 -33 565.64 260.83 404.00 176.76 984.5 1379.1 q2a15
+ -12 4 -35 -323.89 252.41 292.00 168.49 1007.5 1346.5 q2a15
+ -12 20 -46 5.89 135.81 164.00 91.51 1286.5 719.2 q3a6
+ -12 22 -47 567.90 132.42 264.00 86.90 1258.2 693.3 q3a6
+ -12 24 -48 -160.51 131.07 137.00 89.11 1229.3 667.0 q3a6
+ -11 -33 56 -19.91 87.74 81.00 51.57 495.0 938.6 q1a10
+ -11 -33 57 15.38 76.90 78.00 50.62 492.4 953.2 q1a10
+ -11 -31 36 -33.68 114.62 133.00 70.01 404.6 1262.2 q1a12
+ -11 -27 19 -323.44 216.08 206.00 132.11 613.6 1303.4 q1a15
+ -11 -25 13 247.99 217.54 254.00 137.59 686.6 1331.8 q1a15
+ -11 5 -34 259.31 270.36 350.00 171.69 1040.9 1365.3 q2a15
+ -11 7 -36 -554.83 276.78 367.00 171.43 1064.0 1332.8 q2a15
+ -11 19 -44 78.16 246.30 259.00 99.04 1335.4 710.8 q3a6
+ -11 21 -45 -235.96 211.36 221.00 97.16 1307.9 685.2 q3a6
+ -11 23 -46 -100.74 116.47 132.00 88.14 1279.9 659.2 q3a6
+ -11 25 -47 -170.61 115.39 136.00 84.01 1251.4 632.7 q3a6
+ -10 -32 56 -337.59 140.24 134.00 58.75 538.5 938.0 q1a10
+ -10 -32 57 -296.43 121.58 99.00 58.52 536.1 952.4 q1a10
+ -10 -32 58 66.89 105.82 118.00 55.70 533.7 966.9 q1a10
+ -10 -32 59 -26.19 116.22 132.00 54.49 531.2 981.6 q1a10
+ -10 -32 60 -43.97 160.81 186.00 55.73 528.8 996.4 q1a10
+ -10 -32 61 55.16 141.33 123.00 56.04 526.3 1011.3 q1a10
+ -10 -32 62 381.74 144.66 223.00 52.86 523.8 1026.4 q1a10
+ -10 -32 63 -29.32 176.40 174.00 57.82 521.3 1041.6 q1a10
+ -10 -32 64 -332.12 169.55 211.00 57.12 518.7 1057.0 q1a10
+ -10 -32 65 16.43 79.83 113.00 51.17 516.2 1072.5 q1a10
+ -10 -32 66 374.09 110.66 273.00 47.71 513.6 1088.2 q1a10
+ -10 -28 27 51.32 204.13 247.00 117.01 515.8 1309.0 q1a14
+ -10 -24 13 293.73 295.09 413.00 152.45 681.9 1368.4 q1a15
+ -10 -22 8 128.96 496.62 481.00 187.96 742.5 1394.2 q1a15
+ -10 -18 -1 -173.85 406.80 497.00 211.38 831.5 34.6 q2a0
+ -10 -16 -5 685.83 504.71 554.00 215.17 880.5 58.1 q2a0
+ -10 -10 -15 1298.33 396.95 495.00 200.54 1004.6 126.1 q2a1
+ -10 -8 -18 518.03 363.17 655.00 217.31 1043.9 148.5 q2a1
+ -10 8 -35 407.12 319.61 389.00 188.88 1097.0 1351.7 q2a15
+ -10 18 -42 -290.45 218.20 226.00 123.05 1379.9 702.5 q3a7
+ -10 22 -44 185.40 210.33 205.00 97.40 1329.0 651.5 q3a6
+ -10 24 -45 -35.98 234.00 320.00 90.78 1301.3 625.4 q3a6
+ -10 32 -48 118.46 146.38 205.00 79.34 1192.7 541.2 q3a4
+ -9 -31 59 -151.69 146.78 144.00 57.77 574.4 980.5 q1a10
+ -9 -31 60 122.36 129.63 106.00 54.24 572.1 995.1 q1a10
+ -9 -31 61 235.03 205.10 230.00 55.73 569.9 1009.9 q1a10
+ -9 -31 62 14.06 140.52 124.00 55.84 567.6 1024.8 q1a10
+ -9 -31 63 -29.35 138.98 162.00 52.72 565.3 1039.8 q1a10
+ -9 -31 64 21.99 143.38 124.00 52.61 563.0 1055.0 q1a10
+ -9 -31 65 -215.38 164.54 123.00 52.38 560.7 1070.3 q1a10
+ -9 -31 66 313.01 131.41 170.00 49.37 558.3 1085.8 q1a10
+ -9 -31 67 -158.82 134.86 120.00 51.42 555.9 1101.4 q1a10
+ -9 -27 28 364.64 166.73 338.00 118.84 501.3 1345.0 q1a14
+ -9 -25 20 415.37 200.73 351.00 140.30 594.8 1375.9 q1a15
+ -9 -23 14 613.06 233.34 390.00 157.37 666.9 1403.1 q1a15
+ -9 -13 -8 55.49 260.61 291.00 169.09 913.1 114.6 q2a0
+ -9 -11 -11 -573.15 259.57 291.00 159.62 952.2 136.8 q2a0
+ -9 -3 -22 -12.35 373.78 347.00 169.72 1097.3 198.1 q2a3
+ -9 9 -34 234.45 532.21 520.00 212.95 1129.6 1370.3 q2a15
+ -9 31 -46 135.95 125.40 150.00 79.45 1244.7 535.8 q3a4
+ -9 35 -47 -25.02 153.31 180.00 79.22 1193.3 476.8 q3a4
+ -8 -28 40 -177.82 122.58 108.00 72.49 667.9 749.4 q1a9
+ -8 -26 29 184.51 164.70 193.00 123.15 487.0 1380.7 q1a14
+ -8 -22 15 -541.45 375.26 581.00 187.66 652.1 1437.3 q1a15
+ -8 -12 -7 1930.43 236.26 1270.00 149.46 897.4 147.3 q2a0
+ -8 -2 -21 71.39 306.97 329.00 125.38 1080.3 230.3 q2a3
+ -8 16 -37 484.45 476.55 436.00 160.95 1478.7 686.2 q3a7
+ -8 30 -44 130.75 228.23 275.00 88.25 1295.3 530.6 q3a4
+ -8 38 -46 132.86 100.66 119.00 74.74 1193.9 411.4 q3a4
+ -7 -27 41 -4.42 87.87 103.00 75.19 704.4 763.3 q1a9
+ -7 -27 42 157.92 108.19 128.00 72.08 702.9 775.8 q1a9
+ -7 -25 30 -166.57 199.26 244.00 131.34 472.8 1415.9 q1a14
+ -7 -21 16 -925.94 673.89 492.00 232.37 637.5 1471.1 q1a15
+ -7 -17 6 -119.59 484.14 459.00 143.15 748.1 349.0 q1a3
+ -7 -7 -12 -284.49 246.62 265.00 91.68 959.4 195.5 q2a2
+ -7 -5 -15 77.40 138.92 162.00 92.40 994.9 217.8 q2a3
+ -7 -1 -20 -299.12 202.38 244.00 111.12 1063.4 262.1 q2a3
+ -7 17 -36 -489.09 513.50 464.00 183.29 1497.9 654.1 q3a7
+ -7 19 -37 -259.91 372.64 477.00 152.71 1472.9 629.1 q3a7
+ -7 33 -43 -45.24 167.24 242.00 90.64 1296.5 467.9 q3a4
+ -6 -26 44 -264.78 186.45 221.00 80.63 737.8 802.0 q1a9
+ -6 -24 32 685.82 203.07 247.00 127.31 447.4 1449.6 q1a14
+ -6 -18 12 544.79 395.98 418.00 141.13 739.3 275.2 q1a3
+ -6 -16 7 893.65 220.11 355.00 102.68 715.4 334.0 q1a3
+ -6 -8 -8 3265.92 240.50 1966.00 78.31 905.0 205.2 q2a2
+ -6 -6 -11 3468.63 273.68 2493.00 83.35 943.3 227.3 q2a2
+ -6 2 -21 1782.81 287.22 1158.00 113.49 1076.8 315.9 q2a3
+ -6 4 -23 271.53 277.85 307.00 127.42 1107.1 338.4 q2a3
+ -6 6 -25 789.10 593.82 470.00 182.10 1137.6 361.1 q2a3
+ -6 32 -41 -9.75 246.70 388.00 91.75 1345.9 463.7 q3a4
+ -6 36 -42 -362.84 286.65 382.00 87.04 1297.8 404.5 q3a4
+ -5 -21 26 -504.01 507.68 472.00 207.41 756.5 135.3 q1a1
+ -5 -1 -15 2547.00 289.90 1342.00 101.00 992.0 302.7 q2a3
+ -5 19 -33 -7.80 542.20 471.00 188.20 1543.5 590.0 q3a7
+ -5 21 -34 452.36 267.26 351.00 144.24 1519.1 564.7 q3a7
+ -5 27 -37 177.84 192.58 311.00 109.96 1443.1 514.4 q3a5
+ -5 29 -38 420.51 185.23 229.00 101.89 1417.2 487.2 q3a5
+ -5 41 -41 2.81 176.47 161.00 71.19 1520.9 997.3 q3a11
+ -4 -20 28 1168.10 482.20 710.00 216.14 723.7 110.5 q1a1
+ -4 -16 15 111.56 160.33 164.00 96.40 674.8 236.0 q1a3
+ -4 -6 -5 13377.76 387.94 8118.00 76.90 864.8 267.7 q2a2
+ -4 -4 -8 14483.44 416.14 7882.00 77.89 902.8 289.7 q2a2
+ -4 -2 -11 617.64 234.35 405.00 72.03 940.8 311.7 q2a2
+ -4 2 -16 628.38 150.12 496.00 88.62 1005.3 355.9 q2a3
+ -4 8 -22 269.00 159.86 196.00 134.00 1204.1 151.6 q3a0
+ -4 10 -24 1754.00 254.34 1007.00 152.00 1226.9 121.1 q3a0
+ -4 18 -30 3351.73 512.98 1409.00 216.47 1321.6 12.6 q3a0
+ -4 30 -36 -73.99 154.83 230.00 104.39 1445.3 454.1 q3a5
+ -4 40 -39 -135.40 122.15 124.00 70.60 1518.8 946.3 q3a11
+ -3 -21 41 219.61 448.02 372.00 137.72 759.0 434.7 q1a5
+ -3 -19 31 -67.00 371.60 506.00 200.00 691.5 74.6 q1a1
+ -3 -11 8 290.76 181.68 142.00 59.59 597.7 318.3 q1a3
+ -3 -7 0 92.76 128.24 119.00 67.94 802.4 276.7 q2a2
+ -3 -1 -9 124.21 194.59 213.00 73.18 916.2 342.6 q2a2
+ -3 13 -24 569.99 236.84 356.00 169.61 1281.3 115.8 q3a0
+ -3 17 -27 1989.28 670.46 1171.00 270.52 1328.9 62.0 q3a0
+ -3 33 -35 -2.23 154.40 140.00 93.03 1447.6 393.0 q3a5
+ -3 43 -37 -198.69 106.00 119.00 66.69 1450.8 937.1 q3a11
+ -3 55 -37 34.32 67.91 74.00 51.08 1233.2 1071.9 q3a10
+ -3 57 -37 -88.38 87.50 83.00 49.38 1192.7 1096.7 q3a10
+ -2 -20 46 117.20 179.40 243.00 110.28 696.6 466.1 q1a5
+ -2 -20 47 235.42 202.30 276.00 104.81 684.1 465.4 q1a5
+ -2 -18 34 1064.25 253.01 445.00 177.65 659.1 38.5 q1a1
+ -2 -16 26 2991.32 370.52 1517.00 207.61 634.6 133.6 q1a1
+ -2 -10 10 2915.76 258.45 1383.00 59.94 569.5 293.9 q1a2
+ -2 -8 6 728.24 170.04 215.00 50.06 547.4 341.7 q1a2
+ -2 2 -10 -29.54 136.87 146.00 71.15 1176.6 291.0 q3a2
+ -2 14 -22 664.85 223.87 592.00 150.59 1312.7 141.1 q3a0
+ -2 38 -34 -234.54 243.38 226.00 84.34 1512.2 868.4 q3a9
+ -2 48 -35 27.86 145.13 153.00 61.74 1348.6 948.8 q3a10
+ -2 52 -35 146.94 83.03 101.00 56.06 1274.3 992.7 q3a10
+ -2 54 -35 -158.91 92.19 87.00 52.71 1235.6 1015.6 q3a10
+ -1 -19 53 -82.56 154.93 186.00 93.26 607.0 496.9 q1a5
+ -1 -19 54 151.82 145.21 233.00 93.51 593.9 496.3 q1a5
+ -1 -19 56 323.30 216.48 262.00 84.81 570.5 495.1 q1a4
+ -1 -19 57 -298.92 239.50 244.00 85.69 557.0 494.4 q1a4
+ -1 -19 68 34.06 163.59 162.00 76.84 401.8 487.3 q1a4
+ -1 -15 29 819.75 497.44 483.00 221.35 602.6 98.3 q1a1
+ -1 -11 17 6.90 210.19 166.00 69.90 560.7 211.3 q1a2
+ -1 -9 12 -553.00 475.28 415.00 72.71 538.5 269.6 q1a2
+ -1 -7 8 10325.06 340.83 5357.00 55.37 516.5 317.4 q1a2
+ -1 -3 1 1365.36 1323.52 1155.00 755.87 791.5 360.2 q2a2
+ -1 1 -5 -1407.11 874.30 819.00 467.27 1185.4 353.4 q3a2
+ -1 3 -8 -4390.41 5280.60 6769.00 156.64 1207.3 315.6 q3a2
+ -1 15 -20 816.62 293.24 550.00 138.99 1344.0 166.3 q3a0
+ -1 19 -23 3269.10 363.77 1301.00 212.10 1389.2 113.4 q3a1
+ -1 41 -32 -78.81 100.85 116.00 72.81 1445.8 858.2 q3a9
+ 0 -14 33 2544.85 657.93 1494.00 260.49 573.7 51.5 q1a0
+ 0 -12 26 344.68 278.66 364.00 149.39 551.1 134.7 q1a0
+ 0 -8 15 -32.63 117.17 104.00 59.38 507.4 235.4 q1a2
+ 0 -4 7 199.85 119.15 125.00 55.49 463.8 331.1 q1a2
+ 0 6 -8 733.45 143.40 433.00 69.34 1260.3 311.2 q3a2
+ 0 22 -22 3.24 485.26 593.00 225.53 1446.0 116.4 q3a1
+ 0 38 -29 249.50 132.04 151.00 75.50 1474.7 785.2 q3a9
+ 0 44 -30 -184.82 141.25 129.00 72.42 1378.0 847.8 q3a9
+ 0 46 -30 40.04 160.51 135.00 70.16 1346.2 866.8 q3a8
+ 0 48 -30 11.89 179.26 177.00 69.51 1310.5 886.4 q3a8
+ 0 50 -30 -133.94 157.87 197.00 70.94 1273.9 906.5 q3a8
+ 1 -15 52 210.73 143.61 169.00 105.60 623.3 562.6 q1a7
+ 1 -15 53 97.27 149.74 193.00 111.69 610.4 562.5 q1a7
+ 1 -15 54 50.09 146.61 175.00 107.90 597.4 562.3 q1a7
+ 1 -11 30 1351.85 344.68 618.00 193.49 519.1 88.7 q1a0
+ 1 -7 18 731.97 168.16 983.00 58.61 476.2 201.0 q1a2
+ 1 -1 6 -1047.88 945.29 943.00 220.88 411.2 344.7 q1a2
+ 1 9 -8 3761.89 253.35 2779.00 68.68 1313.7 306.8 q3a2
+ 1 11 -10 968.10 195.66 786.00 68.71 1336.6 277.6 q3a2
+ 1 15 -14 197.49 144.98 156.00 93.32 1380.1 218.6 q3a3
+ 1 25 -21 -301.09 488.85 446.00 222.29 1503.6 119.4 q3a1
+ 1 27 -22 -270.79 383.33 405.00 187.59 1530.0 96.4 q3a1
+ 1 43 -27 8.05 114.51 160.00 72.55 1375.2 791.9 q3a9
+ 2 -12 45 -134.42 380.53 436.00 155.25 713.6 619.9 q1a7
+ 2 -10 35 3588.89 494.11 1312.00 226.27 486.5 30.8 q1a0
+ 2 -8 27 -89.61 215.89 272.00 147.56 465.4 125.1 q1a0
+ 2 -4 17 42.75 155.45 160.00 58.35 423.2 214.9 q1a2
+ 2 18 -13 133.55 171.51 170.00 95.29 1435.8 222.7 q3a3
+ 2 24 -17 1396.97 617.99 531.00 253.18 1510.8 176.4 q3a1
+ 2 32 -21 125.55 193.51 265.00 130.05 1244.1 1424.7 q3a14
+ 2 34 -22 -386.76 213.54 213.00 130.36 1220.2 1396.5 q3a14
+ 2 38 -23 14.41 159.25 196.00 108.75 1180.0 1336.2 q3a14
+ 3 -11 57 -160.10 294.83 333.00 101.41 564.5 655.2 q1a6
+ 3 -11 58 -413.91 245.36 271.00 98.14 551.2 655.5 q1a6
+ 3 -11 59 161.17 164.50 170.00 90.51 537.8 655.7 q1a6
+ 3 -11 60 321.11 201.12 229.00 88.30 524.3 656.0 q1a6
+ 3 -11 61 -122.48 205.31 269.00 94.05 510.7 656.2 q1a6
+ 3 -11 62 465.68 159.54 332.00 88.21 496.9 656.5 q1a6
+ 3 -11 63 -63.85 208.90 298.00 87.38 483.1 656.7 q1a6
+ 3 -11 64 112.37 103.83 179.00 82.65 469.1 657.0 q1a6
+ 3 -11 65 -28.74 105.92 134.00 82.97 455.0 657.3 q1a6
+ 3 -11 66 -83.63 138.49 180.00 84.65 440.8 657.5 q1a6
+ 3 -11 67 179.14 129.51 172.00 83.04 426.4 657.8 q1a6
+ 3 -11 68 86.14 126.91 238.00 86.04 412.0 658.1 q1a6
+ 3 -9 41 934.44 617.93 448.00 203.34 764.7 675.4 q1a7
+ 3 -7 32 5.00 334.81 499.00 189.00 432.6 68.1 q1a0
+ 3 -5 26 893.32 184.37 660.00 136.61 411.8 139.7 q1a0
+ 3 1 12 1405.63 211.85 529.00 68.19 169.1 348.2 q0a2
+ 3 9 0 25599.07 524.42 8959.00 70.20 17.2 260.1 q0a2
+ 3 19 -10 2.04 245.08 344.00 118.77 1468.1 256.8 q3a3
+ 3 23 -13 535.36 752.29 595.00 238.73 1518.2 205.5 q3a3
+ 3 35 -19 466.04 198.94 248.00 120.16 1256.0 1361.7 q3a14
+ 3 43 -21 -186.59 232.13 278.00 78.79 1174.8 1264.5 q3a12
+ 4 -8 50 -431.10 306.94 380.00 137.86 654.6 710.9 q1a7
+ 4 -8 51 226.77 140.67 194.00 118.92 642.0 711.4 q1a7
+ 4 -8 52 -231.15 263.96 293.00 132.62 629.4 711.9 q1a7
+ 4 -2 25 405.21 211.20 214.00 110.42 318.1 358.3 q0a3
+ 4 0 20 105.60 131.11 140.00 91.17 258.7 337.4 q0a3
+ 4 2 16 -113.38 133.35 148.00 90.03 210.3 316.0 q0a3
+ 4 4 12 -45.06 246.07 266.00 80.80 165.2 294.8 q0a2
+ 4 6 9 700.89 282.28 395.00 79.27 127.2 272.7 q0a2
+ 4 8 6 382.96 129.06 222.00 69.23 89.1 250.6 q0a2
+ 4 10 3 -132.99 130.71 138.00 71.59 51.1 228.6 q0a2
+ 4 12 1 -118.51 125.81 139.00 75.72 22.3 205.2 q0a2
+ 4 20 -7 943.18 424.41 340.00 151.94 1500.6 291.0 q3a3
+ 4 36 -16 -134.82 170.07 224.00 123.42 1291.9 1326.6 q3a14
+ 4 46 -18 15.15 105.97 110.00 68.65 1195.4 1192.5 q3a12
+ 4 48 -18 190.65 125.20 118.00 69.15 1178.4 1156.4 q3a12
+ 5 -3 37 1608.70 733.89 1280.00 288.58 363.9 1421.1 q0a15
+ 5 -1 30 914.41 647.23 498.00 207.15 374.9 324.9 q0a3
+ 5 1 25 166.81 263.49 299.00 118.84 314.5 304.0 q0a3
+ 5 3 20 10.62 123.60 148.00 91.68 255.0 283.5 q0a3
+ 5 5 16 46.63 190.94 220.00 97.19 206.5 262.2 q0a3
+ 5 7 13 388.84 221.20 226.00 80.94 171.3 240.0 q0a2
+ 5 11 7 132.01 109.18 119.00 69.63 94.7 195.6 q0a2
+ 5 19 -2 3096.20 390.38 1851.00 142.71 1509.0 355.0 q3a3
+ 5 27 -8 -0.73 344.36 486.00 188.40 1436.7 1432.9 q3a15
+ 5 29 -9 -514.91 305.40 414.00 165.75 1415.1 1405.6 q3a15
+ 5 31 -10 115.91 229.77 260.00 156.39 1393.1 1377.7 q3a15
+ 5 33 -11 -11.25 221.66 279.00 149.41 1370.7 1349.4 q3a15
+ 5 35 -12 -312.81 272.63 281.00 136.51 1351.0 1320.7 q3a14
+ 5 39 -13 -147.64 238.74 265.00 87.01 1313.3 1286.5 q3a12
+ 5 43 -14 -1.39 104.18 131.00 72.99 1274.1 1222.1 q3a12
+ 6 -2 46 -664.64 249.18 278.00 172.97 325.7 1313.7 q0a15
+ 6 0 37 1094.03 677.48 654.00 245.18 308.2 1424.6 q0a15
+ 6 2 30 -2020.71 726.55 486.00 260.65 371.4 270.0 q0a3
+ 6 4 25 -184.10 222.54 292.00 127.33 310.9 249.5 q0a3
+ 6 6 21 -215.42 148.44 174.00 105.87 261.7 228.1 q0a3
+ 6 8 17 398.60 142.37 148.00 88.60 212.9 206.9 q0a3
+ 6 14 8 201.04 137.21 193.00 136.96 99.7 168.6 q0a0
+ 6 16 6 41.53 131.25 184.00 136.76 70.7 144.8 q0a0
+ 6 26 -3 -716.28 551.40 486.00 227.43 1502.1 1424.5 q3a15
+ 6 38 -9 101.76 269.92 359.00 87.64 1370.2 1280.7 q3a13
+ 6 42 -10 52.94 149.32 294.00 73.06 1335.5 1216.6 q3a12
+ 7 1 46 202.22 251.77 233.00 148.49 268.5 1317.0 q0a15
+ 7 1 47 311.22 233.43 226.00 138.44 267.3 1304.8 q0a15
+ 7 3 38 116.75 303.56 499.00 195.35 251.0 1416.5 q0a15
+ 7 5 31 1023.69 661.16 486.00 242.99 378.9 213.6 q0a3
+ 7 11 19 624.65 159.13 364.00 159.78 229.0 177.5 q0a1
+ 7 17 10 124.36 273.08 401.00 174.93 115.0 110.4 q0a0
+ 7 19 8 -82.16 268.75 315.00 183.04 85.8 86.2 q0a0
+ 7 21 6 -581.60 371.72 458.00 204.93 56.3 61.7 q0a0
+ 7 23 4 -658.18 576.87 708.00 218.53 26.6 37.1 q0a0
+ 7 39 -5 22.16 105.73 144.00 79.04 1416.2 1241.9 q3a13
+ 7 43 -6 -1.30 137.49 166.00 73.70 1379.2 1176.6 q3a13
+ 8 10 28 598.07 463.37 486.00 231.96 335.3 162.4 q0a1
+ 8 12 24 565.60 513.71 639.00 241.74 285.1 141.4 q0a1
+ 8 14 21 995.37 456.72 604.00 219.30 245.8 118.8 q0a1
+ 8 16 18 569.28 509.52 506.00 230.01 206.4 96.2 q0a1
+ 8 18 15 -891.74 565.23 519.00 246.91 170.0 73.6 q0a0
+ 8 28 5 -1003.90 623.01 456.00 168.57 365.0 719.1 q0a7
+ 8 36 1 -675.01 310.78 336.00 101.65 1507.3 1263.5 q3a13
+ 8 38 0 -196.74 180.72 220.00 88.97 1485.2 1233.3 q3a13
+ 8 42 -1 -53.63 98.49 108.00 68.71 1449.8 1167.9 q3a13
+ 9 7 54 278.83 180.00 265.00 92.17 142.5 1250.4 q0a12
+ 9 7 55 -409.15 210.83 217.00 94.62 140.8 1237.3 q0a12
+ 9 7 56 -220.72 175.54 165.00 86.87 139.0 1224.1 q0a12
+ 9 7 57 -413.31 353.91 444.00 95.03 137.2 1210.8 q0a12
+ 9 9 43 636.87 249.92 475.00 149.68 132.5 1364.5 q0a14
+ 9 11 36 -656.93 501.18 442.00 185.26 115.9 1452.1 q0a14
+ 9 13 31 104.90 390.11 472.00 195.43 364.5 100.9 q0a1
+ 9 15 27 -258.12 356.57 410.00 198.12 313.5 79.9 q0a1
+ 9 17 24 -437.57 212.68 252.00 181.34 273.6 57.0 q0a1
+ 9 19 21 57.75 297.21 343.00 182.60 233.7 34.1 q0a1
+ 9 27 12 191.11 407.53 444.00 140.67 351.7 632.9 q0a7
+ 9 29 10 -223.66 197.32 280.00 122.97 325.7 663.1 q0a7
+ 9 31 9 611.85 185.55 289.00 113.19 296.8 683.4 q0a7
+ 9 39 5 307.00 176.22 192.00 72.29 1542.2 1190.7 q3a13
+ 9 41 4 -220.91 156.26 150.00 77.61 1520.1 1159.3 q3a13
+ 10 12 48 580.22 198.00 195.00 102.65 64.4 1306.3 q0a14
+ 10 14 40 -21.44 244.74 249.00 133.03 50.6 1408.9 q0a14
+ 10 14 41 201.15 180.07 229.00 127.18 48.5 1396.9 q0a14
+ 10 18 31 -29.90 225.82 296.00 170.39 353.9 14.4 q0a1
+ 10 24 22 -878.77 460.97 461.00 133.30 361.6 533.6 q0a5
+ 10 30 16 -151.11 132.71 186.00 101.68 282.9 595.5 q0a7
+ 10 34 13 90.72 107.94 139.00 90.72 226.0 646.5 q0a7
+ 10 38 11 276.09 214.75 222.00 76.75 167.3 688.3 q0a6
+ 10 40 10 404.30 136.16 365.00 69.30 135.7 709.8 q0a6
+ 11 19 41 81.54 182.37 187.00 84.46 340.9 753.2 q0a9
+ 11 23 33 -20.04 157.85 219.00 95.78 338.7 399.3 q0a5
+ 11 25 29 -58.57 184.19 217.00 99.30 317.0 452.0 q0a5
+ 11 27 27 -444.38 155.11 149.00 96.15 290.0 481.9 q0a5
+ 11 31 23 -164.39 234.41 332.00 94.76 235.3 542.5 q0a5
+ 11 37 18 -119.45 157.27 143.00 75.21 152.1 597.2 q0a6
+ 11 43 16 -38.73 85.65 102.00 64.40 50.5 649.6 q0a6
+ 12 22 51 -241.03 145.96 135.00 75.27 217.4 840.7 q0a9
+ 12 22 52 -425.77 160.28 164.00 73.08 204.1 843.6 q0a9
+ 12 24 44 81.73 162.00 234.00 75.58 312.2 854.5 q0a9
+ 12 24 45 236.55 125.00 188.00 73.66 299.5 857.4 q0a9
+ 12 26 40 197.00 195.21 202.00 69.14 367.4 876.6 q0a9
+ 12 30 33 -51.20 113.94 148.00 84.94 212.0 416.0 q0a5
+ 12 32 31 277.37 134.50 138.00 66.89 186.7 446.7 q0a4
+ 12 34 29 -17.95 152.53 204.00 70.39 158.1 477.6 q0a4
+ 12 36 27 121.84 112.88 131.00 65.94 129.3 508.9 q0a4
+ 12 38 26 16.34 142.00 158.00 70.01 96.5 528.8 q0a4
+ 13 29 52 -18.20 93.80 99.00 57.13 215.3 951.9 q0a11
+ 13 29 53 69.44 103.85 117.00 54.85 201.6 955.5 q0a11
+ 13 29 55 -25.11 119.02 109.00 52.70 176.7 962.9 q0a10
+ 13 31 47 -78.40 75.82 92.00 55.09 287.1 970.9 q0a11
+ 13 31 48 0.66 77.75 84.00 55.09 273.8 974.6 q0a11
+ 13 33 43 -215.80 205.93 228.00 63.12 344.8 993.3 q0a11
+ 13 33 44 -88.57 170.22 206.00 59.48 331.8 997.1 q0a11
+ 13 35 41 36.65 189.02 233.00 56.72 376.5 1023.2 q0a11
+ 13 39 36 -266.45 130.32 135.00 64.38 31.1 403.6 q0a4
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035146_1bf0f.h5
+Image serial number: 49
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 3
+photon_energy_eV = 9504.934944
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9504.934944
+average_camera_length = 0.152001 m
+num_peaks = 24
+peak_resolution = 3.419668 nm^-1 or 2.924260 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 88.01 45.99 2.19 852.84 q0a0
+ 92.03 98.88 1.92 2863.67 q0a0
+ 716.35 160.79 2.21 3818.33 q1a1
+ 895.47 60.83 2.11 2143.58 q2a0
+ 857.50 86.52 1.94 2605.64 q2a0
+1531.45 173.79 2.32 2337.11 q3a1
+ 148.10 294.50 0.95 569.26 q0a2
+ 202.53 348.33 1.04 5260.76 q0a3
+ 662.90 346.50 1.40 652.74 q1a3
+ 910.16 249.50 1.07 1572.95 q2a2
+ 938.50 254.97 1.14 1813.66 q2a2
+ 867.66 294.43 0.74 5059.65 q2a2
+ 893.02 360.50 0.57 908.78 q2a2
+1027.50 327.23 1.32 1685.91 q2a3
+ 987.28 361.50 1.06 4269.03 q2a3
+1191.50 224.12 1.05 1542.11 q3a2
+1303.95 227.50 1.20 862.07 q3a2
+1231.50 283.14 0.76 802.47 q3a2
+1331.50 284.84 1.04 1408.66 q3a2
+1241.72 285.80 0.76 2917.51 q3a2
+1262.46 291.69 0.78 12277.28 q3a2
+1272.65 294.50 0.80 2164.60 q3a2
+ 319.13 455.50 3.19 664.64 q0a5
+ 169.90 1271.10 3.42 720.59 q0a12
+End of peak list
+--- Begin crystal
+Cell parameters 6.15674 12.21423 16.79908 nm, 90.55616 89.95575 90.54053 deg
+astar = -0.0138364 +0.0419230 -0.1563163 nm^-1
+bstar = -0.0206709 +0.0762596 +0.0214800 nm^-1
+cstar = +0.0572456 +0.0163195 -0.0006482 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00120 nm^-1
+predict_refine/final_residual = 2.251750e-07
+predict_refine/det_shift x = -0.031 y = 0.012 mm
+diffraction_resolution_limit = 2.11 nm^-1 or 4.74 A
+num_reflections = 130
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -1 -39 -6 20.30 137.88 141.00 93.57 1409.1 617.8 q3a7
+ -1 -39 10 140.30 120.07 138.00 85.73 1459.8 464.2 q3a5
+ -1 -37 -11 56.59 133.80 164.00 100.29 1427.1 682.8 q3a7
+ -1 -37 15 187.24 203.54 236.00 91.12 1509.4 417.8 q3a5
+ -1 -35 -14 -274.65 330.15 443.00 108.18 1451.2 724.6 q3a7
+ -1 -25 23 -8.25 388.18 367.00 160.25 1541.6 143.5 q3a1
+ -1 -23 23 2820.53 505.36 1092.00 177.56 1531.9 174.2 q3a1
+ -1 -17 -17 -773.21 315.69 270.00 105.58 1101.1 300.1 q2a3
+ -1 -13 -13 1842.17 182.61 1377.00 71.32 1030.0 328.1 q2a3
+ -1 -13 16 37.80 116.12 128.00 77.11 1411.0 273.9 q3a3
+ -1 -11 -9 4074.69 243.09 3311.00 71.82 989.1 362.8 q2a3
+ -1 -9 -1 957.80 137.89 971.00 61.80 1219.9 280.7 q3a2
+ -1 -9 0 891.05 121.42 727.00 58.08 1230.2 283.7 q3a2
+ -1 -9 1 2725.31 191.58 1365.00 59.44 1240.6 286.6 q3a2
+ -1 -9 2 1214.44 145.82 1213.00 57.03 1251.0 289.6 q3a2
+ -1 -9 3 12407.34 364.25 7724.00 58.56 1261.4 292.5 q3a2
+ -1 -9 4 2210.52 168.56 1887.00 56.68 1271.8 295.4 q3a2
+ 0 -48 -8 -1.18 110.00 108.00 65.51 1238.8 601.0 q3a6
+ 0 -48 12 44.68 113.41 133.00 63.95 1305.6 389.0 q3a4
+ 0 -42 -22 210.00 129.21 322.00 69.00 1127.1 1154.7 q2a13
+ 0 -42 26 -143.84 101.09 136.00 62.49 1469.6 843.2 q3a9
+ 0 -36 -28 -93.84 130.50 146.00 73.51 1035.4 1240.9 q2a13
+ 0 -34 33 -76.01 123.31 147.00 87.65 1190.9 1335.2 q3a14
+ 0 -32 34 -142.32 137.60 149.00 87.68 1227.0 1335.1 q3a14
+ 0 -26 -32 -1630.03 420.02 395.00 135.82 959.7 1368.5 q2a14
+ 0 -24 -32 -296.29 272.58 272.00 130.29 953.3 1400.8 q2a14
+ 0 -22 -32 293.13 553.82 441.00 153.69 947.0 1432.7 q2a14
+ 0 -20 35 -10.38 144.57 207.00 125.15 1416.0 1389.8 q3a15
+ 0 -14 32 449.22 640.44 451.00 198.49 1496.3 1453.6 q3a15
+ 0 -4 -17 1302.33 188.46 864.00 62.42 911.0 250.5 q2a2
+ 0 -4 20 226.83 132.49 178.00 56.17 33.7 195.4 q0a2
+ 0 -2 -12 5220.02 244.07 3918.00 51.69 868.0 295.7 q2a2
+ 0 -2 15 300.68 102.75 101.00 54.29 46.6 256.3 q0a2
+ 1 -53 19 126.86 95.66 210.00 54.41 1480.8 1048.6 q3a11
+ 1 -45 34 -127.18 143.90 110.00 54.29 1348.5 874.5 q3a8
+ 1 -41 38 -47.41 114.43 97.00 53.25 1325.8 789.4 q3a8
+ 1 -35 42 -21.73 95.85 101.00 57.83 1202.3 1241.7 q3a12
+ 1 -29 44 -27.41 169.74 205.00 63.64 1308.6 1255.1 q3a12
+ 1 -17 43 -253.80 189.83 213.00 124.12 1491.3 1309.1 q3a15
+ 1 -15 -39 94.19 214.26 231.00 141.85 1134.0 68.6 q2a1
+ 1 -13 -38 809.03 211.32 413.00 149.69 1099.9 74.0 q2a1
+ 1 -13 41 -187.58 318.15 355.00 137.26 1545.0 1353.5 q3a15
+ 1 -3 -29 -361.45 195.92 212.00 114.93 926.4 142.4 q2a0
+ 1 -3 32 3207.24 234.27 1153.00 126.06 91.2 98.3 q0a0
+ 1 -1 29 494.45 154.83 403.00 114.91 110.2 139.8 q0a0
+ 1 3 -18 113.67 94.87 222.00 57.33 809.1 211.0 q2a2
+ 1 5 14 711.94 170.34 472.00 58.06 148.2 295.4 q0a2
+ 2 -54 31 -313.95 145.92 132.00 49.47 1314.3 1036.3 q3a10
+ 2 -48 40 32.97 73.62 77.00 49.27 1240.7 915.2 q3a8
+ 2 -46 42 -167.09 97.51 89.00 52.10 1229.6 870.6 q3a8
+ 2 -44 44 -60.43 87.83 99.00 49.52 1218.6 826.5 q3a8
+ 2 -36 49 -213.76 118.40 111.00 53.97 1207.7 1137.8 q3a12
+ 2 -30 51 115.50 92.49 97.00 53.50 1316.8 1153.5 q3a12
+ 2 -20 51 -117.26 120.85 139.00 64.86 1475.9 1217.1 q3a13
+ 2 -10 47 355.87 284.83 342.00 95.51 307.1 695.1 q0a7
+ 2 -6 44 85.18 297.71 304.00 109.47 362.8 646.1 q0a7
+ 2 0 -35 2450.41 323.48 893.00 154.77 895.0 60.5 q2a0
+ 2 2 35 173.99 540.94 483.00 172.04 180.1 85.2 q0a0
+ 2 4 -29 86.00 154.65 173.00 113.00 819.6 113.4 q2a0
+ 2 8 -20 781.26 134.05 508.00 64.10 662.8 348.6 q1a3
+ 2 10 -13 -6.70 223.31 286.00 57.97 596.0 300.3 q1a3
+ 3 -55 39 130.24 87.01 75.00 41.36 1187.4 1038.1 q3a10
+ 3 -35 -52 7.10 100.68 96.00 50.94 845.0 765.9 q2a8
+ 3 -25 -54 -14.13 86.96 89.00 58.33 1016.0 816.8 q2a9
+ 3 -23 -54 11.71 85.30 91.00 56.56 1050.8 822.0 q2a9
+ 3 -11 -51 124.09 143.94 189.00 76.90 1093.8 435.9 q2a5
+ 3 -9 -50 372.48 166.40 232.00 80.72 1100.0 470.9 q2a5
+ 3 -9 53 26.55 116.99 118.00 76.81 234.7 652.0 q0a7
+ 3 -1 -44 -689.43 337.74 386.00 112.70 1146.8 584.8 q2a7
+ 3 13 22 -189.72 178.03 183.00 90.89 300.4 243.9 q0a3
+ 3 15 -11 127.30 148.93 185.00 54.85 597.7 215.8 q1a3
+ 3 15 13 -25.42 131.00 159.00 79.66 299.6 347.5 q0a3
+ 4 -14 61 -169.68 94.09 101.00 55.08 99.4 692.7 q0a6
+ 4 -12 -57 28.90 105.72 105.00 65.41 1012.0 400.8 q2a5
+ 4 -6 -54 -10.16 106.88 122.00 69.23 1032.3 508.0 q2a5
+ 4 6 -43 389.93 296.88 296.00 108.21 1126.9 698.5 q2a7
+ 4 10 -37 -350.42 444.44 450.00 161.86 761.3 1398.4 q1a15
+ 4 16 26 1292.88 506.41 435.00 166.94 366.9 212.9 q0a3
+ 5 -21 -64 -20.90 77.61 82.00 45.10 1045.5 953.7 q2a11
+ 5 -15 -63 125.44 119.56 91.00 46.56 1154.9 954.1 q2a11
+ 5 21 -19 3491.25 608.18 1535.00 202.75 716.1 160.9 q1a1
+ 5 21 21 -428.62 555.73 517.00 204.44 307.1 1446.5 q0a15
+ 5 23 8 -358.33 425.12 467.00 153.33 435.3 52.3 q1a0
+ 6 -18 -68 -62.82 76.16 77.00 42.42 1082.6 1029.6 q2a11
+ 6 -8 -65 85.14 83.41 91.00 50.26 874.7 442.8 q2a4
+ 6 -6 -64 -4.16 80.79 99.00 51.96 882.7 479.9 q2a4
+ 6 0 63 145.70 112.29 114.00 52.70 139.6 474.9 q0a4
+ 6 26 -8 -155.24 287.63 317.00 153.52 620.5 45.0 q1a1
+ 7 -31 -72 100.79 76.39 75.00 35.41 814.7 1080.0 q2a10
+ 7 1 -64 188.12 106.03 89.00 49.88 849.1 572.7 q2a6
+ 7 11 57 -218.34 296.58 268.00 59.09 367.6 869.9 q0a9
+ 7 13 -52 442.01 142.27 313.00 57.39 734.9 1206.5 q1a13
+ 7 23 36 -268.22 202.03 215.00 114.35 149.6 1336.2 q0a14
+ 7 25 -28 162.78 174.74 301.00 107.66 488.1 1421.0 q1a14
+ 7 29 9 579.20 409.46 412.00 132.89 739.6 674.9 q1a7
+ 8 4 -66 103.31 95.26 103.00 51.69 798.1 621.1 q2a6
+ 8 10 63 124.23 92.78 194.00 43.61 342.8 932.4 q0a11
+ 8 26 -34 -275.23 174.20 189.00 90.11 477.6 1338.3 q1a14
+ 8 32 1 -61.71 142.43 147.00 100.65 706.0 570.5 q1a7
+ 8 32 2 14.91 148.78 169.00 105.70 702.8 581.6 q1a7
+ 8 32 3 87.00 136.46 158.00 102.00 699.6 592.8 q1a7
+ 8 32 4 -216.52 152.94 191.00 103.97 696.3 603.9 q1a7
+ 9 17 59 -200.69 137.16 177.00 55.69 235.2 878.7 q0a9
+ 10 26 -47 14.34 77.66 78.00 49.46 487.6 1183.2 q1a12
+ 10 32 -32 -22.92 109.80 96.00 56.08 640.2 747.7 q1a9
+ 10 32 34 -44.31 122.29 141.00 69.07 203.9 1183.4 q0a13
+ 10 36 -13 -39.86 137.23 135.00 72.59 656.8 410.9 q1a5
+ 10 36 15 -205.36 198.07 164.00 79.23 566.1 705.0 q1a6
+ 11 19 65 -84.28 103.42 96.00 43.48 141.2 937.6 q0a10
+ 11 25 56 104.51 84.22 85.00 48.89 88.1 813.1 q0a8
+ 11 37 -21 26.99 172.93 214.00 55.65 740.3 875.3 q1a9
+ 11 37 23 -4.88 125.82 126.00 67.63 355.7 1128.4 q0a13
+ 11 39 -3 -57.72 223.70 208.00 71.83 562.3 506.8 q1a4
+ 11 39 -2 -138.85 212.48 226.00 73.18 558.8 518.5 q1a4
+ 11 39 -1 31.05 253.93 247.00 77.16 555.4 530.1 q1a4
+ 11 39 0 -122.85 175.75 256.00 69.51 551.9 541.7 q1a4
+ 12 18 70 -25.12 69.11 73.00 39.12 111.2 1024.2 q0a10
+ 12 24 62 30.81 74.54 88.00 46.19 53.4 906.1 q0a8
+ 12 40 17 149.73 92.11 110.00 62.82 454.7 705.8 q1a6
+ 13 35 -43 33.82 89.05 86.00 45.92 451.8 814.4 q1a8
+ 13 43 -2 125.85 105.05 110.00 60.55 453.1 487.1 q1a4
+ 13 43 -1 17.91 106.49 143.00 61.57 449.5 499.1 q1a4
+ 13 43 0 -179.88 97.56 112.00 62.12 445.9 511.1 q1a4
+ 13 43 1 168.68 121.65 183.00 60.68 442.3 523.2 q1a4
+ 13 43 2 33.05 117.38 123.00 63.16 438.7 535.2 q1a4
+ 13 43 3 -69.99 91.76 109.00 60.35 435.1 547.2 q1a4
+ 14 42 -26 -241.72 108.59 91.00 50.85 623.0 973.3 q1a11
+ 14 44 -14 323.70 164.57 166.00 51.11 764.7 1044.4 q1a11
+ 15 41 -37 -79.32 103.40 92.00 40.82 472.6 945.5 q1a10
+ 17 45 -35 -3.20 64.93 72.00 37.80 446.6 1069.3 q1a10
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035201_1d4de.h5
+Image serial number: 54
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9511.663754
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9511.663754
+average_camera_length = 0.152001 m
+num_peaks = 23
+peak_resolution = 4.107060 nm^-1 or 2.434831 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 635.50 152.20 1.97 826.29 q1a1
+ 916.50 72.85 2.08 3938.45 q2a0
+1107.49 167.85 2.20 2719.08 q2a1
+ 77.71 201.69 1.23 5064.80 q0a2
+ 136.80 231.85 1.19 1191.84 q0a2
+ 183.90 269.50 1.18 815.74 q0a2
+ 155.50 286.73 1.01 1396.00 q0a2
+ 211.82 361.61 1.07 1848.45 q0a3
+ 510.93 302.30 0.80 1132.21 q1a2
+ 425.09 313.50 0.57 1133.71 q1a2
+ 398.50 325.68 0.51 3085.96 q1a2
+ 873.80 266.79 0.89 4602.58 q2a2
+ 925.99 267.50 1.04 716.18 q2a2
+ 905.50 284.89 0.90 1213.19 q2a2
+1127.50 298.14 1.87 474.68 q2a3
+1335.74 293.43 1.03 22365.90 q3a2
+1426.53 316.50 1.40 4806.19 q3a3
+1514.99 320.50 1.84 1344.41 q3a3
+ 324.25 541.64 3.01 532.12 q0a5
+ 324.50 675.83 2.85 659.34 q0a7
+1310.37 798.91 4.11 -160.07 q3a8
+ 256.91 1417.91 2.51 379.28 q0a15
+ 909.12 1417.50 2.80 671.35 q2a14
+End of peak list
+--- Begin crystal
+Cell parameters 6.23574 12.23289 16.76201 nm, 90.06685 88.98563 90.09978 deg
+astar = +0.0209321 +0.0393321 -0.1540785 nm^-1
+bstar = -0.0743825 +0.0338708 -0.0016053 nm^-1
+cstar = +0.0232575 +0.0520704 +0.0175513 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00228 nm^-1
+predict_refine/final_residual = 4.851101e-07
+predict_refine/det_shift x = 0.022 y = -0.043 mm
+diffraction_resolution_limit = 2.21 nm^-1 or 4.53 A
+num_reflections = 256
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -2 -4 -44 361.12 239.48 275.00 162.88 1060.2 1374.5 q2a15
+ -2 -4 -43 -549.26 386.16 474.00 179.60 1065.0 1385.6 q2a15
+ -2 -4 -42 -252.42 328.25 488.00 188.03 1069.8 1396.7 q2a15
+ -2 -4 -41 469.99 380.45 436.00 185.45 1074.6 1407.7 q2a15
+ -2 -4 -35 -396.22 759.54 578.00 266.86 1102.8 1472.6 q2a15
+ -2 -4 -32 -640.01 668.38 521.00 223.39 1151.6 321.2 q2a3
+ -2 -2 -46 822.62 224.52 424.00 159.56 1021.8 1365.0 q2a15
+ -2 -2 -45 70.86 217.68 250.00 154.47 1026.7 1376.2 q2a15
+ -2 -2 -31 819.31 520.64 894.00 170.85 1128.7 298.1 q2a3
+ -2 -2 -30 -175.94 514.34 436.00 151.45 1118.3 302.6 q2a3
+ -2 0 -47 871.40 215.28 483.00 152.26 988.0 1366.6 q2a15
+ -2 0 -46 520.01 220.35 337.00 156.59 993.0 1377.9 q2a15
+ -2 0 -29 154.79 283.12 247.00 119.15 1095.5 279.6 q2a3
+ -2 2 -48 180.83 353.42 371.00 148.49 957.0 1368.3 q2a14
+ -2 2 -47 1304.22 368.89 342.00 144.44 962.2 1379.6 q2a14
+ -2 2 -29 1080.40 215.75 654.00 112.52 1083.0 252.0 q2a3
+ -2 2 -28 -331.52 208.16 228.00 113.09 1072.8 256.7 q2a3
+ -2 4 -47 -179.42 355.76 318.00 149.27 933.3 1392.5 q2a14
+ -2 4 -46 -445.37 349.25 347.00 162.62 938.5 1403.7 q2a14
+ -2 4 -30 14.35 180.90 170.00 112.20 1080.9 219.6 q2a3
+ -2 4 -29 434.74 193.77 414.00 104.98 1070.6 224.4 q2a3
+ -2 6 -46 1027.60 323.59 671.00 154.07 909.7 1416.6 q2a14
+ -2 6 -45 62.16 420.79 360.00 167.06 914.9 1427.7 q2a14
+ -2 8 -43 3.85 470.43 476.00 168.49 896.7 1462.6 q2a14
+ -2 8 -39 452.40 524.70 500.00 214.54 1149.7 146.1 q2a1
+ -2 8 -37 -119.32 618.85 570.00 241.88 1128.4 156.4 q2a1
+ -2 8 -36 1300.32 707.23 789.00 251.12 1117.9 161.5 q2a1
+ -2 8 -35 2236.60 553.30 1725.00 244.31 1107.3 166.6 q2a1
+ -2 8 -34 -252.72 625.37 651.00 257.63 1096.9 171.7 q2a1
+ -2 8 -33 328.39 551.02 591.00 224.87 1086.5 176.8 q2a1
+ -1 -17 -48 385.64 140.20 290.00 113.64 1411.4 687.5 q3a7
+ -1 -17 -47 515.01 160.38 402.00 113.35 1423.2 683.0 q3a7
+ -1 -17 -28 1937.40 642.34 932.00 252.52 1303.5 55.2 q3a0
+ -1 -15 -23 142.72 229.55 265.00 151.11 1296.6 120.6 q3a0
+ -1 -15 -22 140.56 424.09 455.00 162.25 1300.7 131.0 q3a0
+ -1 -13 -57 -387.21 189.03 196.00 89.47 1129.9 1185.4 q2a13
+ -1 -13 -19 -104.67 183.39 269.00 130.42 1285.7 174.4 q3a0
+ -1 -11 -59 -332.30 133.38 151.00 87.62 1089.7 1174.3 q2a13
+ -1 -9 -61 254.42 135.73 127.00 78.05 1049.1 1163.0 q2a13
+ -1 -7 -63 213.77 131.31 156.00 80.03 1008.1 1151.6 q2a13
+ -1 -7 -13 766.98 158.47 718.00 68.31 1229.4 242.9 q3a2
+ -1 -5 -12 84.42 122.77 133.00 70.03 1206.6 265.0 q3a2
+ -1 -3 -65 -3.24 143.76 147.00 78.03 938.7 1153.8 q2a12
+ -1 -3 -11 792.08 172.41 633.00 67.47 1183.8 286.9 q3a2
+ -1 1 -10 1486.20 170.15 1268.00 69.55 899.5 352.9 q2a2
+ -1 3 -10 385.80 113.72 266.00 66.45 887.3 326.0 q2a2
+ -1 5 -65 -192.58 183.34 205.00 76.05 815.2 1209.0 q2a12
+ -1 7 -65 -220.25 161.79 153.00 79.66 784.2 1222.8 q2a12
+ -1 7 -11 4885.86 243.53 2325.00 65.39 872.4 267.5 q2a2
+ -1 9 -12 -26.53 119.53 135.00 68.03 869.8 235.8 q2a2
+ -1 11 -13 -169.31 144.74 121.00 68.31 867.1 204.0 q2a2
+ -1 13 -61 14.82 102.80 137.00 66.86 996.5 771.1 q2a9
+ -1 15 -59 271.59 116.36 114.00 65.21 1034.3 789.8 q2a9
+ -1 15 -17 -380.27 160.19 218.00 129.99 880.5 158.5 q2a0
+ -1 17 -56 124.55 92.18 123.00 69.52 1083.6 802.2 q2a9
+ -1 19 -53 -70.09 184.80 197.00 75.86 1132.1 814.5 q2a9
+ -1 19 -23 2803.76 547.69 1475.00 208.52 914.2 72.3 q2a0
+ -1 21 -47 -23.21 161.52 168.00 90.21 1102.9 389.6 q2a5
+ -1 21 -29 1517.69 358.81 742.00 189.72 962.0 11.8 q2a0
+ -1 21 -28 90.59 359.91 332.00 183.03 951.8 17.3 q2a0
+ 0 -24 -51 -375.21 213.90 207.00 97.62 1324.9 591.1 q3a6
+ 0 -24 -24 -13.12 342.37 470.00 190.76 1422.0 52.6 q3a1
+ 0 -22 -57 -46.32 125.91 172.00 84.82 1263.1 648.6 q3a6
+ 0 -22 -19 -276.58 460.94 483.00 210.85 1413.6 118.7 q3a1
+ 0 -20 -61 -186.36 179.38 216.00 82.76 1225.4 698.3 q3a6
+ 0 -16 -9 611.33 151.09 179.00 85.81 1370.4 230.8 q3a3
+ 0 -12 -5 22453.69 511.09 7587.00 57.82 1334.7 294.9 q3a2
+ 0 10 -74 183.06 103.17 97.00 59.94 804.8 812.7 q2a8
+ 0 12 -73 -212.11 110.70 113.00 63.51 832.4 838.8 q2a8
+ 0 14 -72 -178.62 107.25 127.00 62.62 860.0 864.8 q2a8
+ 0 24 -15 867.72 303.38 498.00 197.11 797.0 40.9 q2a0
+ 0 28 -26 303.17 437.02 422.00 139.61 1115.5 635.5 q2a7
+ 0 28 -25 -437.60 406.68 366.00 134.07 1121.3 645.7 q2a7
+ 1 -31 -46 -295.87 342.06 326.00 92.08 1331.8 482.8 q3a4
+ 1 -31 -45 -18.24 221.00 187.00 79.47 1344.3 478.8 q3a4
+ 1 -31 -30 -125.04 314.74 352.00 117.04 1520.6 421.0 q3a5
+ 1 -31 -29 64.65 275.45 386.00 122.68 1532.1 417.3 q3a5
+ 1 -29 -20 702.91 302.69 480.00 169.59 1517.7 62.9 q3a1
+ 1 -27 -15 -436.68 554.88 493.00 215.91 1508.1 129.6 q3a1
+ 1 -23 -7 -358.32 441.31 419.00 146.29 1482.5 210.7 q3a3
+ 1 -19 -2 724.67 175.67 648.00 90.90 1446.0 285.8 q3a3
+ 1 -17 0 4872.48 259.18 4506.00 91.09 1426.1 317.8 q3a3
+ 1 -5 7 2830.15 190.49 2847.00 67.30 72.7 319.8 q0a2
+ 1 1 8 3475.64 257.03 2653.00 53.27 396.9 327.1 q1a2
+ 1 3 8 1341.73 163.55 708.00 48.52 423.8 314.8 q1a2
+ 1 9 7 -52.13 130.92 127.00 52.31 508.9 287.1 q1a2
+ 1 11 6 102.03 144.24 410.00 54.88 540.5 283.9 q1a2
+ 1 19 -77 11.32 79.49 75.00 44.08 819.6 966.7 q2a10
+ 1 23 -73 -89.09 87.37 81.00 47.29 903.9 1005.1 q2a10
+ 1 25 -71 -109.45 127.46 111.00 44.05 945.4 1024.0 q2a10
+ 1 27 -68 77.00 90.51 79.00 48.00 996.6 1035.3 q2a11
+ 1 27 -8 -345.51 552.09 450.00 231.19 721.5 1440.3 q1a15
+ 1 29 -11 -748.24 464.42 434.00 178.88 737.5 1395.6 q1a15
+ 1 31 -60 38.82 111.10 125.00 45.58 1127.5 1043.1 q2a11
+ 1 33 -54 -37.92 112.21 97.00 57.69 854.2 389.5 q2a4
+ 1 33 -21 -111.15 179.92 211.00 112.82 1064.4 726.1 q2a7
+ 1 35 -44 86.19 100.70 117.00 63.85 891.0 520.3 q2a4
+ 1 35 -43 -145.50 123.91 119.00 64.50 897.6 531.7 q2a4
+ 1 35 -42 -22.21 124.03 126.00 66.21 904.3 543.0 q2a4
+ 1 35 -34 -81.76 158.91 161.00 73.06 957.3 603.9 q2a6
+ 2 -36 -45 49.03 119.61 142.00 75.90 1302.6 390.9 q3a4
+ 2 -36 -44 -45.63 128.89 137.00 76.65 1315.3 387.1 q3a4
+ 2 -36 -43 -13.23 139.18 157.00 77.92 1328.0 383.2 q3a4
+ 2 -34 -55 -171.69 124.65 125.00 74.77 1185.0 462.3 q3a4
+ 2 -34 -20 779.00 251.95 293.00 124.57 1188.7 1442.0 q3a14
+ 2 -32 -14 1006.57 276.40 383.00 140.48 1268.0 1449.5 q3a14
+ 2 -30 -9 418.70 498.61 393.00 174.99 1334.4 1460.3 q3a14
+ 2 -22 3 670.33 538.26 797.00 161.46 1514.9 321.5 q3a3
+ 2 -20 5 -39.75 247.85 348.00 118.40 1494.7 353.6 q3a3
+ 2 -12 11 5273.13 255.27 3063.00 65.32 75.0 203.0 q0a2
+ 2 -10 12 253.10 146.69 313.00 71.43 96.8 226.2 q0a2
+ 2 -4 14 281.30 165.87 240.00 69.16 152.3 299.5 q0a2
+ 2 32 -6 -374.20 227.70 276.00 139.94 659.6 1374.8 q1a15
+ 2 38 -21 -195.96 194.20 235.00 73.96 767.8 1224.5 q1a13
+ 2 40 -41 -200.19 120.24 105.00 62.15 819.8 566.5 q2a6
+ 2 40 -40 188.00 111.13 100.00 57.00 826.9 577.8 q2a6
+ 2 40 -39 -29.76 106.52 96.00 62.06 833.9 589.0 q2a6
+ 2 40 -38 35.00 105.21 109.00 61.00 840.9 600.2 q2a6
+ 2 40 -37 46.13 89.53 223.00 60.47 847.8 611.3 q2a6
+ 2 40 -36 -57.97 106.15 104.00 63.69 854.7 622.4 q2a6
+ 2 40 -35 -13.79 84.76 99.00 62.55 861.6 633.4 q2a6
+ 2 40 -34 341.79 109.26 129.00 65.47 868.4 644.3 q2a6
+ 3 -39 -23 -54.60 103.98 103.00 73.93 1464.3 756.5 q3a9
+ 3 -37 -15 -228.61 167.78 169.00 109.56 1224.1 1367.2 q3a14
+ 3 -31 -1 376.50 336.62 408.00 156.50 1411.5 1405.8 q3a15
+ 3 -29 2 436.79 523.99 558.00 186.13 1455.3 1423.7 q3a15
+ 3 -25 7 1047.00 597.52 548.00 235.57 1531.2 1462.3 q3a15
+ 3 -21 11 -560.25 344.74 421.00 155.25 25.4 99.6 q0a0
+ 3 -1 20 362.74 116.98 153.00 79.78 233.1 310.1 q0a3
+ 3 21 14 893.03 261.34 768.00 168.92 635.8 153.0 q1a1
+ 3 27 9 585.00 614.12 528.00 217.00 745.0 159.3 q1a1
+ 3 35 -2 -94.67 206.35 230.00 136.67 589.7 1347.8 q1a15
+ 3 39 -10 -205.64 132.78 142.00 73.97 640.1 1268.6 q1a13
+ 3 41 -16 -61.03 106.68 100.00 66.08 686.3 1200.7 q1a13
+ 3 43 -24 46.76 119.73 136.00 60.90 754.8 1117.1 q1a13
+ 4 -44 -43 253.75 116.29 118.00 60.74 1441.6 1021.0 q3a11
+ 4 -44 -42 2.09 81.41 86.00 57.90 1438.0 1007.6 q3a11
+ 4 -44 -41 -62.29 94.84 92.00 60.56 1434.4 994.2 q3a11
+ 4 -44 -40 46.88 98.23 86.00 59.37 1430.9 981.0 q3a11
+ 4 -44 -39 -174.03 104.64 106.00 62.18 1427.3 967.8 q3a11
+ 4 -44 -38 149.09 110.37 100.00 57.28 1423.8 954.7 q3a11
+ 4 -44 -37 -63.00 115.90 117.00 60.00 1420.3 941.6 q3a11
+ 4 -44 -33 -106.73 103.41 121.00 72.93 1406.0 917.6 q3a9
+ 4 -44 -32 -28.74 105.19 121.00 67.40 1402.6 904.9 q3a9
+ 4 -38 -6 307.60 145.87 195.00 111.03 1317.8 1307.3 q3a14
+ 4 -36 -2 225.00 166.18 194.00 127.00 1371.4 1323.3 q3a15
+ 4 -32 5 146.62 152.75 235.00 145.38 1471.2 1357.6 q3a15
+ 4 -2 25 307.31 153.68 224.00 93.97 283.9 270.1 q0a3
+ 4 14 23 438.85 298.88 437.00 153.19 498.4 104.1 q1a0
+ 4 22 19 -10.96 495.02 713.00 213.96 625.6 87.7 q1a1
+ 4 26 16 53.37 355.82 418.00 190.89 697.0 88.3 q1a1
+ 4 28 14 943.12 256.18 427.00 165.88 735.7 93.1 q1a1
+ 4 32 10 -372.42 239.33 265.00 138.74 486.5 1453.1 q1a14
+ 4 38 1 293.45 159.52 183.00 107.93 530.5 1314.2 q1a14
+ 5 -47 -46 -24.76 93.88 90.00 55.97 1385.7 1095.2 q3a11
+ 5 -47 -29 -28.23 157.35 136.00 62.92 1330.3 894.0 q3a8
+ 5 -47 -28 10.32 175.59 198.00 61.22 1327.1 881.2 q3a8
+ 5 -41 -4 132.58 223.82 357.00 79.74 1321.1 1267.6 q3a12
+ 5 -29 15 633.29 459.12 434.00 143.71 365.2 712.6 q0a7
+ 5 -15 26 818.51 448.58 528.00 197.54 221.6 106.3 q0a1
+ 5 1 30 -594.38 533.67 399.00 173.99 361.1 284.7 q0a3
+ 5 3 30 -394.03 545.69 598.00 200.08 373.9 312.3 q0a3
+ 5 25 22 403.88 237.46 241.00 161.37 653.6 25.6 q1a1
+ 5 45 -5 -115.61 126.22 145.00 65.24 525.3 1189.2 q1a12
+ 6 -50 -28 128.17 88.85 98.00 59.83 1258.9 909.0 q3a8
+ 6 -44 -3 280.33 118.73 158.00 62.67 1313.3 1201.1 q3a12
+ 6 -38 9 498.92 168.73 287.00 82.92 1483.1 1253.2 q3a13
+ 6 -36 12 -175.95 379.10 323.00 102.39 1528.2 1273.1 q3a13
+ 6 -16 30 174.40 245.30 354.00 176.91 264.0 66.5 q0a1
+ 6 -8 33 -401.53 639.79 512.00 232.42 343.8 167.1 q0a1
+ 6 4 34 727.37 721.83 572.00 254.42 322.9 1449.1 q0a15
+ 6 6 34 370.42 674.99 524.00 256.18 350.9 1436.1 q0a15
+ 6 44 5 90.78 131.01 124.00 60.66 419.1 1259.0 q1a12
+ 6 46 1 -138.09 136.21 127.00 59.96 443.4 1202.1 q1a12
+ 6 48 -4 31.55 104.86 83.00 51.09 478.3 1137.1 q1a12
+ 7 -53 -30 -128.81 100.74 95.00 51.73 1193.9 938.1 q3a10
+ 7 -51 -16 -21.42 77.10 94.00 56.74 1184.7 766.7 q3a8
+ 7 -49 -8 -42.93 112.50 95.00 60.79 1220.0 1118.5 q3a12
+ 7 -41 10 116.73 104.83 129.00 69.74 1478.6 1187.1 q3a13
+ 7 -33 21 -18.57 109.40 145.00 94.46 256.8 662.3 q0a7
+ 7 -27 27 0.45 150.87 177.00 102.34 324.6 562.7 q0a7
+ 7 -23 30 6.45 421.49 381.00 135.19 371.6 535.8 q0a5
+ 7 -11 36 795.84 440.84 472.00 173.23 365.6 103.3 q0a1
+ 7 -1 38 24.96 357.25 444.00 192.84 229.1 1430.1 q0a15
+ 7 1 38 853.86 288.64 638.00 176.51 257.3 1417.0 q0a15
+ 7 3 38 763.22 249.43 486.00 171.93 285.6 1403.8 q0a15
+ 7 5 38 409.35 361.52 441.00 189.85 313.9 1390.7 q0a15
+ 7 25 31 -110.20 415.97 341.00 129.13 715.5 544.2 q1a5
+ 8 -42 14 -277.91 125.81 113.00 73.14 1520.7 1139.9 q3a13
+ 8 -38 20 -505.70 236.76 203.00 77.38 170.6 698.0 q0a6
+ 8 -26 32 181.97 239.36 285.00 97.10 306.6 523.9 q0a5
+ 8 -10 40 382.76 207.62 453.00 133.64 86.7 1455.4 q0a14
+ 8 -6 41 -274.10 310.24 305.00 156.90 140.1 1419.7 q0a14
+ 8 28 33 -566.99 213.00 247.00 99.39 657.6 509.6 q1a5
+ 8 32 30 451.99 139.70 140.00 84.61 657.1 434.2 q1a5
+ 8 40 22 94.76 96.33 117.00 65.76 704.1 849.6 q1a9
+ 8 48 10 -101.88 98.39 119.00 58.12 506.3 793.9 q1a8
+ 8 50 6 -34.23 110.64 98.00 52.39 447.0 769.6 q1a8
+ 9 -27 35 -148.56 133.58 163.00 87.56 265.9 488.4 q0a5
+ 9 -21 39 259.23 142.74 235.00 87.97 341.3 409.7 q0a5
+ 9 -19 40 82.81 202.34 237.00 90.19 367.2 386.9 q0a5
+ 9 -1 45 -9.87 225.36 282.00 143.67 186.4 1332.5 q0a14
+ 9 1 45 501.54 228.15 235.00 139.66 212.4 1319.0 q0a15
+ 9 3 45 108.41 220.51 265.00 141.79 241.4 1305.5 q0a15
+ 9 11 44 372.65 326.66 348.00 119.63 361.7 1287.1 q0a13
+ 9 15 43 224.75 206.59 279.00 111.25 638.0 723.6 q1a7
+ 9 33 33 192.09 126.29 227.00 84.71 601.6 432.6 q1a5
+ 9 45 20 -3.12 104.72 128.00 61.96 606.2 888.7 q1a9
+ 9 47 17 15.56 146.69 123.00 59.15 557.9 875.0 q1a8
+ 9 51 10 75.57 96.80 91.00 51.52 445.6 837.3 q1a8
+ 10 -12 46 208.38 184.10 238.00 112.01 10.8 1379.9 q0a14
+ 10 12 47 98.89 208.59 243.00 95.51 357.1 1232.6 q0a13
+ 10 30 39 -131.96 219.72 206.00 83.16 548.8 508.7 q1a4
+ 10 34 36 -4.29 145.60 183.00 76.09 547.3 431.0 q1a4
+ 10 42 28 174.55 90.27 96.00 56.05 696.4 937.0 q1a11
+ 11 -41 29 254.65 95.97 95.00 57.15 34.1 595.0 q0a6
+ 11 -31 39 10.15 152.26 173.00 64.65 159.3 447.9 q0a4
+ 11 -27 42 -103.44 120.56 119.00 76.44 208.1 390.5 q0a5
+ 11 -9 50 -131.88 136.31 152.00 102.88 27.0 1303.4 q0a14
+ 11 -3 51 30.86 113.16 144.00 85.74 112.2 1280.3 q0a12
+ 11 -1 51 468.02 218.57 222.00 85.78 142.0 1266.2 q0a12
+ 11 5 51 71.44 142.09 143.00 84.56 228.3 1224.1 q0a13
+ 11 19 48 38.06 141.19 265.00 86.94 523.9 695.8 q1a6
+ 11 29 43 -73.40 115.48 168.00 72.60 495.8 544.6 q1a4
+ 11 41 33 67.24 123.21 161.00 60.36 736.6 1000.6 q1a11
+ 11 49 23 58.69 109.16 107.00 53.31 545.0 968.0 q1a10
+ 11 51 20 83.66 77.94 87.00 47.39 490.9 954.8 q1a10
+ 12 -38 36 75.28 112.78 120.00 63.52 37.5 513.6 q0a4
+ 12 -30 43 69.95 99.23 119.00 63.45 142.2 385.3 q0a4
+ 12 -22 48 -17.98 151.48 185.00 71.78 328.8 889.2 q0a9
+ 12 -20 49 53.70 126.45 155.00 70.70 305.2 861.9 q0a9
+ 12 -12 52 119.86 100.82 105.00 66.74 220.8 750.7 q0a9
+ 12 -8 53 -259.04 131.14 155.00 77.84 17.0 1276.1 q0a12
+ 12 0 54 -234.55 135.24 143.00 81.95 133.9 1210.1 q0a12
+ 12 2 54 -433.98 195.14 176.00 87.78 164.1 1195.8 q0a12
+ 12 32 44 58.85 130.00 137.00 73.35 438.9 502.3 q1a4
+ 12 46 31 47.31 80.03 96.00 54.69 635.5 1047.0 q1a11
+ 13 -35 42 228.32 122.34 145.00 60.08 44.6 414.8 q0a4
+ 13 -27 48 36.91 130.83 135.00 54.29 346.2 958.4 q0a11
+ 13 -17 53 -118.55 136.72 136.00 69.95 225.8 846.9 q0a9
+ 13 -11 55 139.81 147.97 141.00 67.19 167.3 761.4 q0a8
+ 13 23 52 146.52 122.48 132.00 75.28 407.4 661.0 q1a6
+ 13 25 51 89.70 120.85 188.00 76.70 401.3 624.4 q1a6
+ 13 27 50 223.08 151.30 151.00 77.20 395.3 587.5 q1a6
+ 13 51 28 143.60 119.88 233.00 49.60 523.7 1087.1 q1a10
+ 13 53 25 29.12 69.92 78.00 43.88 467.5 1074.5 q1a10
+ 14 -28 50 -17.99 94.74 102.00 51.39 314.5 1001.9 q0a11
+ 14 -16 56 -96.14 235.78 237.00 70.74 171.3 859.3 q0a8
+ 14 -2 59 241.86 127.00 117.00 72.74 58.6 1130.9 q0a12
+ 15 -29 52 -133.94 80.67 75.00 50.94 281.7 1047.0 q0a11
+ 15 -17 58 -81.05 201.99 278.00 66.45 136.2 900.7 q0a8
+ 16 -12 62 -280.27 158.55 167.00 66.47 35.4 853.1 q0a8
+ 17 -27 58 -15.72 171.38 189.00 49.52 163.8 1081.3 q0a10
+ 17 -25 59 280.29 125.04 122.00 45.91 138.2 1051.0 q0a10
+ 17 -23 60 30.69 87.18 91.00 46.31 112.8 1020.8 q0a10
+ 17 -21 61 23.22 70.89 74.00 43.98 87.5 990.8 q0a10
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035038_16020.h5
+Image serial number: 55
+hit = 1
+indexed_by = none
+photon_energy_eV = 9515.448320
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9515.448320
+average_camera_length = 0.152001 m
+num_peaks = 12
+peak_resolution = 3.167913 nm^-1 or 3.156652 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 60.39 289.62 0.74 3853.14 q0a2
+ 86.50 345.03 0.52 695.36 q0a2
+ 397.50 223.98 1.07 -939.50 q1a2
+ 500.50 269.12 0.92 892.00 q1a2
+ 858.50 351.12 0.45 1778.85 q2a2
+1185.50 202.82 1.17 897.30 q3a2
+1347.83 239.50 1.29 486.60 q3a2
+1178.50 254.25 0.90 1939.90 q3a2
+1271.89 255.50 0.98 663.49 q3a2
+1284.50 287.85 0.87 750.91 q3a2
+ 695.93 1280.50 3.17 -92.12 q1a13
+ 283.79 1414.79 2.48 672.97 q0a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035142_1b8fd.h5
+Image serial number: 53
+hit = 1
+indexed_by = none
+photon_energy_eV = 9497.632424
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9497.632424
+average_camera_length = 0.152001 m
+num_peaks = 18
+peak_resolution = 3.550696 nm^-1 or 2.816349 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 125.97 33.97 2.28 412.72 q0a0
+ 522.98 16.07 2.35 3058.83 q1a0
+ 836.50 84.49 1.94 2535.05 q2a0
+1308.73 134.50 1.79 1731.65 q3a0
+1479.10 69.10 2.51 526.07 q3a1
+ 509.91 217.50 1.19 1228.64 q1a2
+ 494.50 269.14 0.91 1034.82 q1a2
+ 517.50 287.04 0.89 620.43 q1a2
+ 405.39 292.63 0.69 2054.62 q1a2
+ 696.10 315.50 1.61 327.54 q1a3
+ 990.50 274.02 1.28 1576.10 q2a3
+1026.01 283.50 1.41 4191.62 q2a3
+1292.50 244.95 1.08 1055.16 q3a2
+1279.95 277.50 0.90 2469.89 q3a2
+1344.09 312.71 1.00 6230.74 q3a2
+1146.45 706.12 2.58 2172.36 q2a7
+1332.92 646.50 3.55 642.01 q3a6
+ 339.70 1435.40 2.30 2708.76 q0a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035052_17385.h5
+Image serial number: 56
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9513.656737
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998596
+hdf5/LCLS/photon_energy_eV = 9513.656737
+average_camera_length = 0.152001 m
+num_peaks = 17
+peak_resolution = 4.107842 nm^-1 or 2.434368 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 118.09 25.09 2.32 408.88 q0a0
+ 78.38 65.79 2.08 2201.35 q0a0
+ 62.50 92.08 1.94 327.01 q0a0
+ 46.50 118.70 1.80 1532.21 q0a0
+ 668.17 161.28 2.04 1158.04 q1a1
+1213.50 142.82 1.65 783.45 q3a0
+1437.68 88.77 2.32 1519.30 q3a1
+ 118.50 207.62 1.26 2794.41 q0a2
+ 153.14 277.02 1.04 2035.02 q0a2
+ 108.50 343.31 0.61 1039.80 q0a2
+ 45.01 345.01 0.42 873.74 q0a2
+ 448.50 211.94 1.13 4713.80 q1a2
+ 867.50 359.79 0.45 1748.11 q2a2
+ 991.68 311.50 1.18 5218.30 q2a3
+1326.50 250.97 1.17 843.49 q3a2
+1310.50 799.04 4.11 223.86 q3a8
+1472.30 1455.18 2.24 832.16 q3a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.16027 12.21587 16.86342 nm, 90.19873 90.52249 90.35041 deg
+astar = -0.0741025 +0.1355669 +0.0498480 nm^-1
+bstar = +0.0667564 +0.0437673 -0.0181528 nm^-1
+cstar = -0.0207955 +0.0094080 -0.0547344 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00162 nm^-1
+predict_refine/final_residual = 2.868517e-07
+predict_refine/det_shift x = 0.020 y = -0.027 mm
+diffraction_resolution_limit = 2.04 nm^-1 or 4.90 A
+num_reflections = 184
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -30 12 -2 -15.00 65.18 67.00 46.00 1257.5 1056.8 q3a10
+ -29 3 -1 -29.03 69.91 88.00 53.23 1426.7 1091.7 q3a11
+ -29 13 -3 -99.28 74.73 76.00 48.48 1264.4 1007.3 q3a10
+ -28 8 -3 -139.56 110.42 106.00 54.56 1366.4 1008.7 q3a11
+ -28 14 -4 -4.38 71.97 80.00 47.38 1271.1 959.1 q3a10
+ -27 -7 1 -2.98 102.99 105.00 65.78 1173.7 412.2 q3a4
+ -27 1 -2 -136.32 141.42 188.00 56.92 1498.7 1029.1 q3a11
+ -27 9 -4 133.31 98.00 102.00 53.69 1371.5 961.5 q3a11
+ -26 -4 -1 55.30 127.55 101.00 61.30 1240.4 382.2 q3a4
+ -25 -3 -2 -87.73 101.92 101.00 68.53 1286.4 384.3 q3a4
+ -25 3 -4 -24.62 93.28 115.00 57.62 1505.1 937.3 q3a11
+ -24 -2 -3 61.95 131.86 154.00 71.45 1331.2 386.3 q3a4
+ -24 18 -7 137.36 122.40 124.00 58.24 1294.6 808.8 q3a8
+ -24 24 -7 -12.71 94.95 94.00 55.91 1197.3 761.1 q3a8
+ -23 -19 5 93.06 108.13 113.00 69.94 1210.7 643.1 q3a6
+ -22 24 -8 205.05 103.41 86.00 53.55 1179.4 1167.5 q3a12
+ -21 -19 4 88.89 145.95 144.00 78.51 1283.0 670.8 q3a6
+ -21 7 -7 -219.91 286.14 396.00 75.71 1517.4 797.2 q3a9
+ -21 13 -8 106.61 119.54 109.00 64.99 1428.7 749.8 q3a9
+ -20 -18 3 306.95 201.74 182.00 80.45 1326.8 668.5 q3a6
+ -19 -17 2 88.06 145.57 164.00 95.94 1366.5 666.4 q3a7
+ -19 -5 -4 -65.09 232.46 262.00 107.29 1468.6 513.2 q3a5
+ -19 17 -9 -41.86 119.61 138.00 84.26 1218.6 1307.7 q3a14
+ -19 25 -9 155.35 91.80 121.00 55.85 1281.3 1214.4 q3a12
+ -18 -14 0 -185.62 146.36 172.00 100.62 1425.1 634.0 q3a7
+ -18 -12 -1 -137.38 139.48 169.00 104.38 1442.0 604.0 q3a7
+ -18 14 -9 313.56 130.31 145.00 92.44 1225.2 1369.9 q3a14
+ -18 28 -9 -14.12 172.30 166.00 59.12 1335.6 1187.9 q3a12
+ -16 -36 17 -19.07 104.38 120.00 65.67 880.1 1131.4 q2a12
+ -16 -32 13 188.54 170.45 275.00 70.66 959.2 1175.6 q2a12
+ -16 6 -8 -253.74 262.16 318.00 156.14 1525.7 62.8 q3a1
+ -16 12 -9 234.89 301.67 426.00 119.51 1268.0 1433.5 q3a14
+ -16 30 -9 187.41 91.18 100.00 57.79 1407.8 1197.0 q3a13
+ -15 -37 18 -51.24 120.67 111.00 63.64 847.1 1154.2 q2a12
+ -15 11 -9 79.02 351.78 381.00 140.78 1288.8 1464.4 q3a14
+ -15 31 -9 -53.15 76.96 90.00 59.35 1444.9 1201.5 q3a13
+ -14 2 -7 1930.20 276.49 966.00 176.20 1438.1 89.3 q3a1
+ -14 6 -8 433.86 288.83 366.00 171.74 1493.4 119.5 q3a1
+ -14 36 -8 -27.64 114.42 130.00 58.24 1516.9 1142.8 q3a13
+ -13 -37 18 96.98 97.87 114.00 66.22 822.2 1221.0 q2a12
+ -13 -31 12 -649.79 304.53 280.00 87.59 939.5 1282.6 q2a12
+ -13 -25 7 182.48 202.34 225.00 118.72 1041.4 1310.8 q2a15
+ -13 -1 -6 192.05 328.22 430.00 185.55 1381.1 94.6 q3a1
+ -13 43 -6 -96.11 128.52 153.00 61.51 36.0 698.8 q0a6
+ -12 -42 24 57.12 94.99 99.00 57.88 882.6 788.3 q2a8
+ -12 -6 -4 -1150.11 499.34 428.00 194.51 1299.2 84.5 q3a0
+ -11 -49 34 34.39 74.16 83.00 39.01 824.0 960.1 q2a10
+ -11 -41 23 224.71 125.38 121.00 58.09 927.2 778.9 q2a8
+ -11 -19 3 188.62 497.96 512.00 207.38 1109.9 1420.1 q2a15
+ -11 -3 -5 209.16 323.09 336.00 143.04 1326.1 134.6 q3a0
+ -11 45 -5 -147.05 104.63 119.00 59.45 44.5 621.5 q0a6
+ -10 -28 10 -424.24 359.72 347.00 141.64 951.5 1372.8 q2a14
+ -10 18 -9 -935.33 678.79 566.00 210.93 1476.4 1452.3 q3a15
+ -10 24 -9 186.95 307.28 351.00 146.45 1524.6 1369.6 q3a15
+ -9 -51 38 8.90 53.01 64.00 38.90 864.1 1053.0 q2a10
+ -9 -31 13 152.71 155.40 218.00 117.09 883.5 1375.2 q2a14
+ -9 -21 5 -133.33 465.79 481.00 195.93 1049.3 1460.0 q2a15
+ -9 -11 -1 163.71 186.56 331.00 126.09 1184.1 128.8 q3a0
+ -9 -9 -2 806.68 163.82 708.00 120.92 1212.6 143.9 q3a0
+ -8 -44 28 -172.74 138.47 124.00 59.14 985.2 895.7 q2a9
+ -8 -40 23 116.30 102.72 110.00 61.30 1029.0 801.3 q2a9
+ -8 -14 1 -152.19 308.37 357.00 116.19 1113.8 345.1 q2a3
+ -8 50 -2 -61.20 123.17 130.00 56.80 20.3 506.8 q0a4
+ -7 -37 20 -311.11 130.58 142.00 70.51 1089.4 751.5 q2a9
+ -7 -15 2 -244.74 318.39 270.00 107.14 1094.6 315.4 q2a3
+ -7 9 -7 428.25 140.61 337.00 77.75 1422.4 302.2 q3a3
+ -7 21 -8 543.04 391.71 433.00 176.16 9.2 58.5 q0a0
+ -7 23 -8 698.74 383.73 622.00 181.86 25.4 31.3 q0a0
+ -7 49 -2 -113.05 87.00 115.00 55.45 59.0 490.1 q0a4
+ -6 -48 35 155.36 86.83 78.00 43.24 1001.4 1011.5 q2a11
+ -6 -46 32 39.95 72.24 88.00 45.45 1025.3 954.5 q2a11
+ -6 -22 7 -362.66 618.20 552.00 196.46 1121.6 193.4 q2a3
+ -6 -6 -2 209.11 116.84 184.00 63.49 1209.2 216.6 q3a2
+ -6 12 -7 -120.48 121.93 127.00 80.28 1445.7 351.1 q3a3
+ -6 50 -1 23.51 85.58 92.00 53.89 62.3 449.2 q0a4
+ -5 -41 26 -265.18 182.59 192.00 63.58 1109.3 873.2 q2a9
+ -5 -15 3 308.48 126.36 134.00 75.72 1041.3 284.9 q2a3
+ -5 -7 -1 252.54 143.17 176.00 60.66 1179.7 235.4 q3a2
+ -5 1 -4 678.84 137.48 438.00 60.23 1287.9 294.2 q3a2
+ -5 9 -6 318.38 133.37 154.00 74.62 1390.3 354.0 q3a3
+ -5 19 -7 1699.44 241.44 1395.00 135.56 45.5 118.6 q0a0
+ -5 21 -7 240.33 320.80 583.00 156.07 61.7 92.0 q0a0
+ -5 23 -7 2201.35 311.62 1118.00 165.85 78.1 65.1 q0a0
+ -5 51 0 -96.32 111.21 90.00 53.92 65.6 408.0 q0a4
+ -5 53 1 -58.29 93.23 92.00 53.09 30.0 382.2 q0a4
+ -4 -12 2 5158.14 257.45 4117.00 77.26 992.8 312.6 q2a3
+ -4 -10 1 215.35 118.75 145.00 71.85 978.1 340.9 q2a3
+ -4 28 -6 -427.71 316.09 384.00 169.91 147.4 14.4 q0a0
+ -4 42 -3 171.62 111.09 112.00 67.38 229.5 484.7 q0a5
+ -3 -27 13 766.56 345.65 500.00 175.44 1078.1 89.3 q2a1
+ -3 11 -5 642.61 124.88 421.00 58.99 35.2 227.2 q0a2
+ -3 43 -2 134.09 103.95 113.00 69.71 233.3 445.8 q0a5
+ -2 -38 25 166.29 129.46 109.00 65.91 1050.7 400.8 q2a5
+ -2 -26 13 -261.67 314.67 367.00 187.07 1043.1 89.6 q2a1
+ -2 -2 -1 13140.76 972.40 8535.00 253.03 1200.0 349.6 q3a2
+ -2 20 -5 397.19 144.60 249.00 123.81 132.4 155.4 q0a0
+ -2 22 -5 455.20 244.48 287.00 136.20 149.0 129.1 q0a0
+ -2 24 -5 246.98 374.49 447.00 177.22 165.7 102.5 q0a0
+ -1 -21 10 17.52 171.97 292.00 136.28 979.0 155.5 q2a1
+ -1 -15 6 490.98 189.37 179.00 64.22 939.0 220.0 q2a2
+ -1 -5 1 1764.04 234.44 1188.00 78.16 866.8 361.6 q2a2
+ -1 15 -4 2901.60 196.83 2788.00 64.60 118.4 208.6 q0a2
+ -1 27 -4 -591.42 563.71 531.00 210.82 215.7 79.6 q0a1
+ -1 51 3 113.34 98.61 110.00 50.46 338.8 964.8 q0a11
+ -1 53 4 101.69 84.46 85.00 49.31 311.6 999.2 q0a11
+ 0 14 -3 142.04 215.11 281.00 66.16 136.7 238.4 q0a2
+ 0 28 -3 -100.91 242.36 308.00 182.71 251.9 83.6 q0a1
+ 1 -45 38 164.40 97.63 88.00 50.40 808.9 424.1 q2a4
+ 1 -43 35 -35.44 89.38 79.00 53.44 865.9 443.0 q2a4
+ 1 -21 12 -413.02 327.33 306.00 146.22 928.1 120.2 q2a0
+ 1 -3 2 1959.46 1155.30 1117.00 555.34 800.4 355.2 q2a2
+ 1 7 -1 821.00 135.91 850.00 63.00 108.3 345.4 q0a2
+ 1 13 -2 948.90 153.28 793.00 61.90 155.0 268.2 q0a2
+ 1 47 3 -84.45 161.07 172.00 65.05 330.4 888.1 q0a9
+ 1 53 6 127.99 80.99 74.00 45.61 248.6 959.4 q0a11
+ 2 -44 38 103.56 103.28 98.00 51.44 811.1 463.9 q2a4
+ 2 -42 35 -60.29 78.77 111.00 54.09 867.9 481.9 q2a4
+ 2 -18 11 -39.85 135.43 192.00 119.65 880.0 149.7 q2a0
+ 2 58 10 240.62 105.41 151.00 41.38 141.0 1029.1 q0a10
+ 3 -43 38 -24.11 104.70 122.00 51.51 813.3 503.3 q2a4
+ 4 -24 18 -295.36 236.71 288.00 167.76 867.0 11.8 q2a0
+ 4 4 3 345.94 128.07 407.00 49.06 437.5 280.7 q1a2
+ 4 46 6 285.86 110.73 126.00 60.74 250.2 815.1 q0a9
+ 5 -37 33 150.36 125.36 135.00 59.24 918.3 585.1 q2a6
+ 5 -29 24 -639.76 311.07 293.00 112.36 1090.1 642.7 q2a7
+ 5 -21 17 375.80 417.53 493.00 176.80 818.4 42.5 q2a0
+ 5 5 4 -59.63 121.84 113.00 50.65 442.6 246.0 q1a2
+ 5 17 2 -293.43 148.69 152.00 90.83 292.6 287.0 q0a3
+ 5 19 2 -104.65 210.39 244.00 101.85 310.1 261.7 q0a3
+ 5 23 2 400.50 532.61 449.00 163.50 345.6 210.2 q0a3
+ 5 43 6 231.60 145.32 111.00 63.60 257.7 751.1 q0a9
+ 6 6 5 4433.21 235.65 2557.00 46.59 447.8 211.1 q1a2
+ 8 -20 21 738.44 454.46 514.00 173.56 745.7 1401.3 q1a15
+ 8 -16 18 245.35 530.80 468.00 202.85 719.3 1468.7 q1a15
+ 8 10 7 -33.57 141.29 174.00 115.17 433.2 152.2 q1a0
+ 8 36 8 -99.09 153.86 179.00 108.29 116.6 1311.4 q0a14
+ 8 42 10 146.80 128.91 303.00 71.80 32.3 1264.4 q0a12
+ 9 -27 29 274.18 258.29 224.00 76.42 761.1 1272.5 q1a13
+ 9 -15 19 161.85 473.20 513.00 184.35 683.4 1462.3 q1a15
+ 9 43 12 -89.85 114.28 115.00 68.65 37.4 1216.2 q0a12
+ 10 -28 32 -657.26 243.85 254.00 72.86 736.1 1223.6 q1a13
+ 10 -26 30 658.40 170.29 201.00 72.40 723.6 1265.1 q1a13
+ 10 -18 23 330.89 305.64 389.00 132.51 673.1 1387.8 q1a15
+ 10 0 13 170.38 200.76 294.00 137.62 604.7 169.7 q1a1
+ 10 30 10 -392.89 187.17 241.00 135.49 233.5 1313.4 q0a15
+ 10 46 15 -156.96 127.15 136.00 68.16 13.1 1136.4 q0a12
+ 11 -3 16 1379.86 277.40 699.00 170.74 669.1 161.1 q1a1
+ 11 21 11 276.85 431.48 405.00 178.35 371.0 1372.5 q0a15
+ 11 23 11 -643.42 323.69 378.00 168.82 345.0 1353.4 q0a15
+ 11 39 14 35.11 127.14 142.00 73.49 134.8 1198.5 q0a12
+ 12 32 14 -4.14 110.45 132.00 78.74 247.9 1249.6 q0a13
+ 12 42 17 -202.86 107.91 106.00 67.26 113.2 1119.0 q0a12
+ 13 -27 38 -184.34 110.87 103.00 59.54 629.2 1147.3 q1a13
+ 13 -15 27 354.65 188.34 234.00 109.15 561.6 1359.5 q1a14
+ 13 -9 23 8.67 445.94 397.00 144.93 522.7 1459.7 q1a14
+ 13 -1 19 13.98 192.05 267.00 164.22 686.7 83.8 q1a1
+ 13 5 17 521.14 309.68 465.00 174.26 602.7 38.1 q1a1
+ 13 15 15 -854.61 707.54 453.00 179.01 759.5 656.8 q1a7
+ 14 -16 30 -6.18 149.83 190.00 102.58 534.2 1312.8 q1a14
+ 14 2 20 -139.30 193.06 220.00 145.70 668.5 28.2 q1a1
+ 14 16 17 215.83 289.67 387.00 128.57 715.9 646.8 q1a7
+ 14 26 17 150.09 381.06 308.00 94.71 370.4 1245.8 q0a13
+ 14 32 18 -22.70 105.96 111.00 76.30 291.3 1175.6 q0a13
+ 14 36 19 52.26 86.51 121.00 67.14 237.3 1124.2 q0a13
+ 15 -25 41 290.88 99.08 106.00 52.12 548.5 1120.4 q1a12
+ 15 -23 39 -166.32 109.42 107.00 56.92 537.5 1164.9 q1a12
+ 15 -21 37 -171.46 150.02 190.00 60.66 526.7 1208.3 q1a12
+ 15 17 19 56.34 173.94 200.00 105.46 671.3 636.6 q1a7
+ 15 23 19 -106.35 170.75 195.00 99.15 610.1 715.0 q1a7
+ 15 31 20 170.89 130.52 135.00 76.51 327.6 1148.5 q0a13
+ 17 5 26 240.81 144.98 313.00 93.19 703.0 448.0 q1a5
+ 17 9 25 -425.02 197.21 228.00 92.22 668.5 504.0 q1a5
+ 17 27 24 294.45 105.58 227.00 70.95 488.1 718.4 q1a6
+ 18 4 29 215.79 144.01 143.00 79.41 671.6 403.1 q1a5
+ 19 -11 40 -63.12 131.14 113.00 59.12 556.7 788.6 q1a8
+ 19 -5 36 28.24 104.86 144.00 59.36 662.9 826.6 q1a9
+ 19 1 33 5.07 205.17 248.00 64.33 761.2 870.0 q1a9
+ 19 23 29 66.35 107.52 114.00 68.85 446.4 610.0 q1a6
+ 20 10 33 50.84 139.13 138.00 68.96 536.5 426.0 q1a4
+ 20 16 32 -125.84 132.25 139.00 69.04 477.4 511.0 q1a4
+ 21 -11 47 -184.95 89.53 90.00 53.55 464.7 884.8 q1a8
+ 21 17 35 53.36 129.67 131.00 69.24 417.5 491.2 q1a4
+ 22 8 40 175.46 168.06 197.00 53.34 759.4 1043.3 q1a11
+ 23 7 44 17.90 107.10 122.00 57.41 700.1 1090.8 q1a11
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035134_1ae02.h5
+Image serial number: 58
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9501.596345
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9501.596345
+average_camera_length = 0.152001 m
+num_peaks = 20
+peak_resolution = 3.899549 nm^-1 or 2.564399 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 156.94 9.50 2.44 214.00 q0a0
+ 95.93 59.59 2.13 3341.69 q0a0
+ 371.39 158.67 2.40 2452.39 q0a1
+ 481.80 94.27 1.93 2226.42 q1a0
+ 906.01 26.57 2.29 5194.55 q2a0
+1301.44 59.37 2.15 4433.11 q3a0
+ 173.61 293.85 1.05 4181.69 q0a2
+ 49.58 299.50 0.68 1870.40 q0a2
+ 308.07 261.05 1.75 3175.62 q0a3
+ 493.50 361.86 0.50 1465.52 q1a2
+ 828.08 227.50 1.03 1411.18 q2a2
+ 804.50 271.15 0.78 899.21 q2a2
+ 962.00 360.28 0.91 1746.21 q2a2
+ 990.19 349.78 1.09 1318.61 q2a3
+1246.33 299.82 0.70 18018.66 q3a2
+1305.50 307.89 0.86 3710.98 q3a2
+1391.77 230.04 1.50 2288.54 q3a3
+1391.05 320.71 1.22 20053.64 q3a3
+ 114.98 530.02 3.90 529.30 q0a4
+ 285.48 1469.85 2.22 2305.64 q0a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.13656 12.26157 16.98475 nm, 89.24862 89.31181 90.06503 deg
+astar = -0.0201003 +0.1565873 +0.0404412 nm^-1
+bstar = +0.0782359 +0.0147330 -0.0177358 nm^-1
+cstar = -0.0155938 +0.0116163 -0.0555825 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00361 nm^-1
+predict_refine/final_residual = 9.282676e-07
+predict_refine/det_shift x = 0.004 y = 0.004 mm
+diffraction_resolution_limit = 2.23 nm^-1 or 4.49 A
+num_reflections = 360
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -26 8 0 92.62 162.42 140.00 76.38 1183.1 493.5 q3a4
+ -26 18 -1 9.38 171.48 158.00 59.62 1528.9 1077.8 q3a11
+ -26 22 -1 56.04 86.22 147.00 61.16 1455.1 1074.1 q3a11
+ -26 24 -1 154.20 96.23 109.00 58.20 1417.7 1072.3 q3a11
+ -26 32 0 -3.11 65.56 87.00 49.51 1263.6 1069.4 q3a10
+ -25 1 1 -77.05 154.97 213.00 75.45 1211.0 593.8 q3a6
+ -25 9 -1 371.39 127.59 148.00 71.01 1227.0 481.1 q3a4
+ -25 19 -2 -204.16 170.14 150.00 66.96 1518.2 1033.3 q3a11
+ -25 21 -2 96.84 102.19 112.00 63.96 1482.0 1031.3 q3a11
+ -25 23 -2 132.36 110.98 91.00 58.24 1445.3 1029.2 q3a11
+ -24 -4 2 -81.91 195.71 163.00 80.71 1239.8 683.8 q3a6
+ -24 10 -2 269.36 116.92 237.00 74.24 1269.9 469.0 q3a4
+ -24 30 -2 -58.31 115.66 121.00 59.31 1325.3 982.2 q3a10
+ -24 36 -1 140.95 77.55 75.00 46.45 1205.8 978.9 q3a10
+ -23 -1 0 330.61 137.25 156.00 84.99 1287.6 633.8 q3a6
+ -23 7 -2 525.00 165.66 168.00 76.00 1303.2 525.4 q3a4
+ -23 13 -3 123.14 163.99 188.00 79.26 1314.2 423.2 q3a4
+ -22 -20 9 54.46 150.97 171.00 75.34 946.0 1123.7 q2a12
+ -22 0 -1 270.05 183.81 193.00 90.55 1328.4 619.8 q3a6
+ -22 8 -3 -437.45 231.75 196.00 88.05 1344.1 513.1 q3a4
+ -21 -25 12 -39.98 137.24 133.00 70.78 848.5 1144.5 q2a12
+ -21 -21 9 -156.52 165.33 174.00 80.72 928.1 1159.7 q2a12
+ -21 -13 4 50.48 180.92 254.00 83.72 1073.5 1185.7 q2a13
+ -21 -11 3 303.31 168.45 265.00 88.69 1108.7 1191.2 q2a13
+ -21 -9 2 1304.48 230.17 309.00 79.72 1143.7 1196.7 q2a13
+ -21 11 -4 481.44 159.60 383.00 91.56 1383.9 468.2 q3a5
+ -20 -28 14 -204.05 148.61 164.00 73.45 787.5 1171.3 q2a12
+ -20 -14 4 -0.26 104.17 150.00 83.86 1055.0 1220.2 q2a13
+ -20 -12 3 -81.25 211.23 229.00 93.25 1089.9 1225.5 q2a13
+ -20 -10 2 1.56 296.98 278.00 99.44 1124.7 1230.9 q2a13
+ -20 0 -2 145.73 167.90 183.00 110.47 1399.0 626.4 q3a7
+ -20 8 -4 203.26 154.12 182.00 95.14 1414.7 522.8 q3a5
+ -20 14 -5 220.59 131.86 161.00 84.21 1426.1 423.9 q3a5
+ -20 26 -5 -67.05 103.20 111.00 67.45 1431.8 855.3 q3a9
+ -20 38 -3 228.18 107.92 103.00 56.42 1210.5 840.9 q3a8
+ -19 -41 27 -63.88 77.91 82.00 45.88 831.2 982.6 q2a10
+ -19 -35 20 191.41 91.20 136.00 61.79 865.2 852.6 q2a8
+ -19 -33 18 -20.29 91.30 113.00 64.09 874.9 805.8 q2a8
+ -19 -31 16 65.71 91.52 111.00 62.09 884.3 760.2 q2a8
+ -19 -25 11 59.51 104.32 140.00 74.89 851.0 1221.4 q2a12
+ -19 -21 8 -233.52 258.98 251.00 88.72 929.0 1235.3 q2a12
+ -19 -15 4 -363.06 211.43 199.00 94.06 1036.8 1254.0 q2a13
+ -19 -13 3 -175.59 242.96 287.00 99.79 1071.5 1259.3 q2a13
+ -19 -11 2 -69.00 327.64 421.00 101.00 1106.0 1264.5 q2a13
+ -19 -9 1 375.39 354.52 268.00 111.01 1140.3 1269.6 q2a13
+ -19 11 -5 139.64 131.75 172.00 100.76 1456.1 478.8 q3a5
+ -18 -40 25 -32.51 80.18 92.00 46.11 879.7 947.2 q2a10
+ -18 0 -3 -630.55 396.76 379.00 146.95 1469.8 632.8 q3a7
+ -18 4 -4 215.18 176.52 214.00 120.42 1477.7 568.6 q3a7
+ -18 8 -5 643.96 240.66 266.00 113.84 1485.4 532.2 q3a5
+ -18 16 -6 29.21 251.76 334.00 107.59 1500.4 402.8 q3a5
+ -18 24 -6 22.26 112.61 142.00 72.14 1481.7 785.9 q3a9
+ -18 26 -6 -86.01 113.30 120.00 69.61 1447.4 782.4 q3a9
+ -17 -45 31 395.25 90.71 82.00 41.75 891.2 1086.2 q2a10
+ -17 -41 26 -38.26 124.92 121.00 50.86 913.9 972.2 q2a10
+ -17 -35 19 -234.61 182.06 154.00 65.01 943.6 846.0 q2a8
+ -17 -33 17 -123.91 169.00 155.00 64.71 952.2 800.3 q2a8
+ -17 -1 -3 457.49 448.18 452.00 154.11 1501.7 652.5 q3a7
+ -17 13 -6 -270.34 403.11 348.00 133.54 1529.0 457.2 q3a5
+ -16 -24 9 -54.99 151.96 156.00 104.39 872.5 1305.9 q2a14
+ -16 -20 6 -25.31 255.29 266.00 133.31 947.8 1318.0 q2a14
+ -16 -2 -3 191.56 493.52 421.00 177.44 1533.1 671.8 q3a7
+ -16 36 -5 118.94 139.70 157.00 68.06 1178.8 1213.6 q3a12
+ -15 -27 11 -278.66 177.92 199.00 109.46 814.6 1331.7 q2a14
+ -15 -23 8 -180.27 172.59 212.00 128.47 890.8 1343.5 q2a14
+ -15 21 -7 530.75 261.55 386.00 130.25 1187.5 1452.4 q3a14
+ -15 23 -7 429.23 213.38 271.00 122.97 1191.1 1419.6 q3a14
+ -15 37 -5 -132.95 100.34 117.00 66.55 1215.7 1203.7 q3a12
+ -14 -26 10 152.12 165.03 202.00 117.88 833.6 1369.1 q2a14
+ -14 -22 7 323.62 319.16 391.00 149.38 908.8 1380.2 q2a14
+ -14 -16 3 27.54 302.99 377.00 173.66 1012.6 1395.7 q2a15
+ -14 -14 2 -182.79 346.97 529.00 181.59 1046.0 1400.3 q2a15
+ -14 -12 1 -925.45 495.30 457.00 200.05 1079.3 1404.9 q2a15
+ -14 -10 0 253.77 492.10 547.00 218.03 1112.4 1409.5 q2a15
+ -14 -8 -1 1185.35 575.68 544.00 221.85 1145.3 1414.0 q2a15
+ -14 0 -4 188.33 415.35 530.00 195.07 1257.1 21.5 q3a0
+ -14 8 -6 1503.86 317.41 603.00 190.74 1379.2 37.0 q3a1
+ -14 16 -7 -15.45 266.24 349.00 174.05 1504.7 51.8 q3a1
+ -14 18 -7 11.25 282.72 368.00 162.75 1536.5 55.3 q3a1
+ -14 24 -7 -341.15 206.48 238.00 122.35 1225.9 1409.6 q3a14
+ -14 26 -7 368.80 184.83 315.00 106.13 1229.8 1376.5 q3a14
+ -13 -45 30 -9.00 60.84 74.00 48.00 1047.3 1071.7 q2a11
+ -13 -35 18 10.38 93.02 110.00 68.62 1086.6 841.3 q2a9
+ -13 -33 16 54.25 120.39 136.00 70.75 1093.2 797.1 q2a9
+ -13 -25 9 -95.99 245.68 245.00 134.39 852.2 1405.6 q2a14
+ -13 3 -5 4469.02 657.50 1832.00 251.78 1300.2 59.3 q3a0
+ -13 15 -7 341.69 248.28 279.00 179.31 1483.6 82.0 q3a1
+ -13 25 -7 80.65 157.58 311.00 126.15 1260.6 1399.6 q3a14
+ -13 27 -7 195.66 284.69 408.00 121.54 1264.6 1366.6 q3a14
+ -13 41 -4 86.68 107.59 135.00 63.92 1292.8 1145.2 q3a12
+ -12 -42 26 -128.16 92.94 95.00 52.96 1097.1 986.0 q2a11
+ -12 -36 19 538.18 155.84 152.00 67.42 1118.1 864.5 q2a9
+ -12 -34 17 439.44 149.87 249.00 68.56 1124.4 820.0 q2a9
+ -12 -32 15 39.64 165.94 199.00 79.76 1130.6 776.5 q2a9
+ -12 -16 3 -44.95 554.17 633.00 233.55 1007.3 1460.1 q2a15
+ -12 14 -7 1997.84 432.49 718.00 204.23 1462.9 111.8 q3a1
+ -12 26 -7 230.21 236.50 277.00 133.59 1295.0 1389.7 q3a14
+ -12 34 -6 71.93 209.14 255.00 73.67 1311.7 1281.9 q3a12
+ -12 38 -5 24.24 158.31 166.00 68.36 1320.4 1210.0 q3a12
+ -11 -45 30 140.54 117.28 117.00 46.66 1122.1 1070.1 q2a11
+ -11 -37 20 273.01 197.22 219.00 59.39 1149.6 887.6 q2a9
+ -11 -35 18 116.66 311.45 384.00 73.54 1155.5 842.9 q2a9
+ -11 -25 9 2590.30 268.41 718.00 137.30 848.6 1471.2 q2a14
+ -11 3 -5 1239.76 231.87 455.00 156.03 1292.0 121.7 q3a0
+ -11 15 -7 -17.81 611.76 494.00 234.81 1473.2 145.1 q3a1
+ -11 27 -7 157.39 250.26 364.00 137.01 1329.2 1379.8 q3a14
+ -10 -26 10 -230.94 236.35 323.00 159.94 1154.3 55.5 q2a1
+ -10 -22 7 247.54 459.66 513.00 202.66 1145.5 129.1 q2a1
+ -10 -16 3 -615.74 715.84 517.00 242.14 1133.0 206.6 q2a3
+ -10 -8 -1 103.76 386.23 408.00 131.64 1116.2 336.5 q2a3
+ -10 0 -4 234.16 169.74 203.00 129.77 1241.6 146.6 q3a0
+ -10 14 -7 734.34 323.35 442.00 186.46 1452.7 174.0 q3a1
+ -10 38 -5 -228.32 162.13 172.00 77.92 1383.8 1225.8 q3a13
+ -9 -41 25 147.88 116.92 130.00 61.12 925.5 381.6 q2a4
+ -9 -3 -3 -285.86 178.51 194.00 127.26 1191.8 171.2 q3a0
+ -9 23 -7 488.24 492.87 502.00 188.36 1380.3 1456.7 q3a15
+ -9 25 -7 812.20 288.78 364.00 157.20 1384.8 1424.9 q3a15
+ -9 37 -5 380.11 103.07 159.00 74.49 1414.1 1250.8 q3a13
+ -9 41 -4 92.81 103.09 108.00 66.19 1424.7 1178.5 q3a13
+ -8 -44 29 -25.85 108.34 108.00 55.65 843.8 407.8 q2a4
+ -8 -40 24 101.00 151.34 157.00 62.00 948.7 418.8 q2a4
+ -8 -28 12 -147.56 180.41 254.00 164.56 1094.6 12.2 q2a1
+ -8 10 -6 57.29 157.98 176.00 89.32 1381.9 199.0 q3a3
+ -8 36 -5 175.02 99.18 165.00 78.78 1443.8 1275.4 q3a13
+ -8 40 -4 -88.12 89.16 110.00 73.12 1454.9 1204.2 q3a13
+ -7 -43 28 4.59 81.45 92.00 58.25 868.5 445.4 q2a4
+ -7 -37 21 152.36 135.74 150.00 78.24 1013.6 459.8 q2a5
+ -7 -15 3 46.34 132.96 182.00 93.46 1038.9 212.8 q2a3
+ -7 -13 2 112.88 135.98 135.00 83.12 1035.0 245.0 q2a3
+ -7 -11 1 -227.55 128.33 134.00 88.95 1031.1 277.1 q2a3
+ -7 -9 0 -70.65 176.21 209.00 85.85 1027.2 309.0 q2a3
+ -7 -7 -1 -27.16 132.26 132.00 83.96 1023.3 340.8 q2a3
+ -7 11 -6 2181.50 241.87 986.00 92.50 1392.1 231.1 q3a3
+ -7 29 -6 223.40 214.18 307.00 146.40 1457.0 1372.6 q3a15
+ -7 39 -4 -289.48 154.44 154.00 79.28 1484.6 1229.5 q3a13
+ -7 45 -2 55.05 96.20 109.00 66.47 1503.6 1117.7 q3a13
+ -6 -34 18 -106.24 251.21 285.00 99.64 1078.4 499.0 q2a5
+ -6 -26 11 520.80 364.98 501.00 173.80 1027.7 43.6 q2a1
+ -6 -6 -1 1710.24 211.27 639.00 82.36 991.4 351.6 q2a3
+ -6 14 -6 -144.04 142.30 170.00 88.90 1431.9 267.8 q3a3
+ -6 26 -6 433.27 532.68 478.00 208.53 1480.3 1427.1 q3a15
+ -6 28 -6 25.35 271.52 333.00 167.85 1485.2 1395.2 q3a15
+ -6 38 -4 688.89 251.29 335.00 80.51 1513.8 1254.3 q3a13
+ -5 -43 29 -27.19 93.29 99.00 57.19 859.4 514.4 q2a4
+ -5 -39 24 -262.58 239.59 276.00 73.11 962.3 522.0 q2a4
+ -5 -27 12 77.21 231.99 300.00 174.59 998.3 22.2 q2a1
+ -5 -23 9 680.14 373.85 598.00 203.26 991.6 95.2 q2a1
+ -5 -5 -1 1629.51 239.71 507.00 60.95 962.7 362.3 q2a2
+ -5 19 -6 159.19 383.89 365.00 136.81 1502.3 309.5 q3a3
+ -5 21 -6 -1163.99 627.81 407.00 208.37 1532.9 314.5 q3a3
+ -5 37 -4 -324.32 349.11 347.00 102.78 1542.5 1278.7 q3a13
+ -4 -44 31 -82.95 120.71 116.00 58.47 825.7 547.2 q2a4
+ -4 2 -3 18084.49 440.15 7828.00 65.11 1245.1 301.3 q3a2
+ -4 6 -4 3404.01 277.56 2091.00 71.37 1304.8 309.6 q3a2
+ -4 12 -5 20042.71 472.49 7372.00 86.09 1391.2 323.0 q3a3
+ -4 42 -2 83.62 185.85 227.00 79.38 184.6 718.5 q0a6
+ -3 -37 23 -20.82 123.91 147.00 89.42 995.8 563.9 q2a7
+ -3 -23 10 1525.75 546.00 747.00 203.25 933.2 86.3 q2a0
+ -3 9 -4 659.47 209.51 177.00 54.73 1344.0 346.0 q3a2
+ -3 37 -3 -160.19 234.33 333.00 103.19 277.1 704.3 q0a7
+ -2 -40 27 -222.56 121.51 141.00 69.56 922.2 593.5 q2a6
+ -2 -26 13 4794.99 486.57 1602.00 201.61 906.3 26.0 q2a0
+ -2 -22 10 113.19 365.67 430.00 169.81 900.9 98.4 q2a0
+ -2 2 -2 -1331.97 1018.48 630.00 220.73 1234.8 360.3 q3a2
+ -2 28 -4 346.58 306.46 318.00 176.82 38.3 15.2 q0a0
+ -2 34 -3 -89.93 287.51 356.00 121.33 334.1 682.6 q0a7
+ -1 -33 20 89.95 243.02 301.00 109.45 1074.0 633.3 q2a7
+ -1 -31 18 349.81 416.51 392.00 128.19 1116.1 635.3 q2a7
+ -1 -25 13 304.02 361.91 373.00 193.78 873.8 38.4 q2a0
+ -1 -21 10 129.16 191.61 260.00 140.04 868.9 110.5 q2a0
+ -1 -7 2 495.24 125.50 145.00 64.36 847.7 311.2 q2a2
+ -1 -5 1 -456.55 259.32 210.00 97.95 844.3 342.5 q2a2
+ -1 5 -2 -128.46 239.95 256.00 97.66 10.7 340.0 q0a2
+ -1 9 -3 57.60 142.21 149.00 68.60 19.2 280.3 q0a2
+ -1 43 0 42.11 189.53 173.00 74.30 186.5 616.2 q0a6
+ 0 -44 34 86.73 141.86 135.00 64.47 798.8 660.0 q2a6
+ 0 -36 24 387.62 144.90 315.00 89.38 1000.7 663.4 q2a7
+ 0 -34 22 260.66 159.16 230.00 98.54 1044.4 665.1 q2a7
+ 0 -32 20 613.43 193.67 388.00 113.17 1087.1 666.8 q2a7
+ 0 -30 18 -360.11 529.89 424.00 151.51 1128.9 668.5 q2a7
+ 0 -24 13 16.00 339.36 394.00 181.00 841.5 50.7 q2a0
+ 0 -20 10 264.02 185.19 209.00 130.78 837.0 122.4 q2a0
+ 0 -12 5 1207.79 149.73 501.00 63.41 826.4 227.3 q2a2
+ 0 -10 4 695.34 127.53 311.00 63.54 823.1 259.0 q2a2
+ 0 -8 3 -202.81 137.38 148.00 68.81 819.9 290.6 q2a2
+ 0 8 -2 1815.35 180.68 907.00 70.85 47.0 301.0 q0a2
+ 0 14 -3 36.90 133.34 131.00 65.06 61.1 211.8 q0a2
+ 0 26 -3 2128.12 371.33 584.00 186.88 93.9 58.3 q0a0
+ 0 44 1 392.77 202.39 239.00 71.03 174.6 578.7 q0a6
+ 1 -41 31 131.49 145.22 214.00 65.11 871.9 695.4 q2a6
+ 1 -35 24 -36.07 149.59 173.00 99.67 1014.3 697.4 q2a7
+ 1 -29 18 -177.46 457.08 428.00 149.66 1141.7 701.4 q2a7
+ 1 -23 13 510.36 377.69 505.00 177.24 809.4 63.0 q2a0
+ 1 -19 10 -105.16 156.26 195.00 125.96 805.3 134.3 q2a0
+ 1 7 -1 -56.82 123.23 145.00 67.42 74.8 321.7 q0a2
+ 1 13 -2 155.32 103.74 103.00 64.08 89.1 232.6 q0a2
+ 1 29 -2 -229.83 399.83 427.00 187.43 134.5 16.7 q0a0
+ 1 49 4 33.96 89.72 111.00 64.84 83.7 545.7 q0a4
+ 2 -40 31 414.94 126.37 203.00 67.06 886.5 730.6 q2a6
+ 2 -36 26 126.70 159.38 151.00 90.70 983.8 730.2 q2a7
+ 2 -34 24 302.12 120.18 170.00 94.88 1027.8 731.3 q2a7
+ 2 2 1 2909.64 310.93 2180.00 143.18 402.5 352.0 q1a2
+ 2 6 0 132.59 120.77 135.00 71.21 102.6 342.3 q0a2
+ 3 -19 12 -264.50 348.78 320.00 113.50 739.3 354.9 q1a3
+ 3 5 1 446.67 135.64 174.00 68.33 130.3 363.0 q0a2
+ 3 11 0 84.84 123.18 150.00 68.96 145.0 274.2 q0a2
+ 3 39 2 95.68 164.15 204.00 89.92 279.0 528.8 q0a5
+ 3 45 4 383.65 178.39 199.00 67.15 173.7 498.6 q0a4
+ 4 -30 22 -269.45 238.77 293.00 137.05 737.8 1313.3 q1a15
+ 4 -16 11 266.84 161.63 595.00 91.96 695.0 320.4 q1a3
+ 4 -4 5 35.43 158.71 176.00 57.17 506.2 302.4 q1a2
+ 4 10 1 4363.86 282.34 2358.00 72.74 172.9 295.0 q0a2
+ 4 36 2 32.48 258.51 254.00 103.72 336.7 509.9 q0a5
+ 5 -37 31 45.44 94.22 100.00 63.56 700.7 1170.1 q1a13
+ 5 -23 17 578.79 567.89 486.00 203.41 702.2 1441.8 q1a15
+ 5 31 2 259.52 221.34 228.00 145.05 267.7 7.5 q0a1
+ 5 39 4 -248.79 151.01 178.00 88.59 291.0 461.0 q0a5
+ 5 45 6 284.82 140.33 143.00 62.58 185.6 428.5 q0a4
+ 6 -26 21 -260.90 226.33 258.00 137.10 669.4 1373.7 q1a15
+ 6 -14 12 -87.05 143.19 155.00 89.45 676.8 254.8 q1a3
+ 6 -12 11 205.11 178.16 257.00 82.30 644.4 252.0 q1a3
+ 6 -6 8 -231.68 187.91 123.00 60.08 551.3 243.5 q1a2
+ 6 -4 7 117.66 147.70 147.00 57.09 519.6 240.7 q1a2
+ 6 2 5 149.15 125.48 107.00 53.65 428.4 228.9 q1a2
+ 6 10 3 26.34 120.75 140.00 86.46 232.0 307.6 q0a3
+ 6 30 3 -3.88 234.76 314.00 160.88 297.2 29.4 q0a1
+ 6 42 6 -114.20 115.92 130.00 78.80 243.7 410.3 q0a5
+ 7 -37 34 -196.91 105.34 101.00 62.71 627.3 1143.5 q1a13
+ 7 -31 27 -281.10 162.34 163.00 78.06 634.3 1287.5 q1a13
+ 7 -29 25 -289.91 176.25 178.00 113.71 635.4 1303.0 q1a15
+ 7 -21 18 1602.81 379.33 477.00 180.19 635.2 1460.4 q1a15
+ 7 -15 14 3.15 263.05 294.00 117.65 702.8 223.0 q1a3
+ 7 -3 8 7.84 133.61 129.00 56.96 512.2 206.4 q1a2
+ 7 11 4 -162.57 124.23 147.00 89.17 266.5 299.3 q0a3
+ 7 29 4 -151.99 248.70 330.00 174.39 326.6 51.2 q0a1
+ 7 35 5 365.14 222.34 193.00 96.26 371.5 413.1 q0a5
+ 7 49 10 -216.76 128.86 129.00 53.36 378.7 991.9 q0a11
+ 7 51 11 208.60 171.02 256.00 53.60 364.0 1032.8 q0a11
+ 8 -34 32 306.43 128.68 139.00 63.17 594.3 1204.1 q1a13
+ 8 -24 22 88.36 233.86 304.00 146.24 601.1 1392.5 q1a15
+ 8 8 6 182.65 163.66 262.00 93.15 292.0 351.7 q0a3
+ 8 14 5 3175.62 239.82 876.00 110.38 308.0 261.3 q0a3
+ 8 28 5 303.86 313.93 405.00 165.74 356.1 73.0 q0a1
+ 8 48 11 -220.80 143.04 145.00 59.20 346.3 967.4 q0a11
+ 8 52 13 -47.30 89.15 85.00 53.70 315.6 1049.6 q0a11
+ 8 54 14 -32.80 114.19 174.00 51.20 299.6 1092.5 q0a11
+ 9 -21 21 229.39 470.22 421.00 165.01 569.3 1439.3 q1a14
+ 9 1 9 -292.33 134.30 168.00 117.46 464.8 163.4 q1a0
+ 9 5 8 225.16 159.26 187.00 114.04 404.2 154.4 q1a0
+ 9 9 7 -319.11 270.23 285.00 115.51 327.0 343.5 q0a3
+ 9 17 6 1373.14 626.76 791.00 198.26 350.4 222.6 q0a3
+ 9 19 6 1360.70 666.45 695.00 225.19 357.5 192.3 q0a3
+ 9 23 6 2396.48 499.70 1015.00 206.72 371.2 157.7 q0a1
+ 9 25 6 908.17 332.02 391.00 167.43 378.3 126.4 q0a1
+ 10 -36 38 10.09 92.25 91.00 57.71 515.4 1121.3 q1a12
+ 10 -32 33 225.45 136.68 220.00 65.95 525.0 1223.8 q1a12
+ 10 -30 31 -196.86 219.16 239.00 75.26 527.3 1268.8 q1a12
+ 10 -26 27 15.45 164.27 192.00 114.95 531.6 1328.1 q1a14
+ 10 -24 25 -363.55 282.62 290.00 131.95 533.6 1370.2 q1a14
+ 10 -16 19 1902.01 556.89 636.00 206.39 748.5 149.2 q1a1
+ 10 6 9 184.46 195.84 240.00 134.34 396.0 119.3 q1a0
+ 10 12 8 -160.75 635.62 433.00 196.75 369.4 305.7 q0a3
+ 10 30 8 187.90 233.30 257.00 130.90 48.2 1444.0 q0a14
+ 10 44 12 -24.46 94.50 104.00 68.66 297.0 907.2 q0a9
+ 10 54 17 -1.74 94.43 90.00 49.14 214.7 1084.7 q0a11
+ 11 -31 34 46.19 101.98 122.00 60.81 486.2 1229.5 q1a12
+ 11 -23 26 316.51 213.50 309.00 115.89 496.5 1376.3 q1a14
+ 11 -15 20 -195.61 337.31 405.00 192.01 741.7 113.1 q1a1
+ 11 1 12 2074.73 289.59 998.00 149.47 481.1 95.2 q1a0
+ 11 15 9 1190.38 667.78 986.00 242.62 286.4 1467.5 q0a15
+ 11 17 9 -207.42 556.20 465.00 228.82 256.1 1460.1 q0a15
+ 11 25 9 2658.96 467.36 644.00 152.84 134.6 1429.8 q0a14
+ 11 37 11 69.73 112.62 117.00 71.47 304.7 775.1 q0a9
+ 11 43 13 296.66 113.63 207.00 67.54 265.2 883.1 q0a9
+ 11 53 18 -228.14 152.81 112.00 52.74 183.6 1058.8 q0a10
+ 12 -32 37 2.81 97.12 103.00 57.19 443.8 1188.9 q1a12
+ 12 -22 27 354.79 158.39 191.00 106.41 459.0 1382.5 q1a14
+ 12 -14 21 -107.01 344.01 376.00 176.61 734.8 76.6 q1a1
+ 12 0 14 198.19 421.00 386.00 196.81 505.6 61.5 q1a0
+ 12 12 11 1684.58 736.27 738.00 272.82 340.0 1440.9 q0a15
+ 12 30 11 -120.82 146.52 189.00 116.42 60.4 1370.3 q0a14
+ 12 38 13 -18.96 108.80 121.00 68.16 258.5 787.1 q0a9
+ 12 44 15 -333.46 187.88 233.00 73.66 216.9 897.0 q0a9
+ 12 48 17 -44.93 126.68 106.00 50.33 185.9 948.9 q0a10
+ 12 50 18 -307.43 250.95 274.00 58.83 168.0 990.3 q0a10
+ 12 52 19 277.36 111.63 117.00 45.24 149.5 1032.9 q0a10
+ 13 -31 38 100.31 93.24 175.00 58.69 403.8 1194.5 q1a12
+ 13 -21 28 -147.30 203.21 256.00 111.70 421.2 1388.8 q1a14
+ 13 -17 25 215.74 216.82 319.00 128.86 422.1 1465.1 q1a14
+ 13 -11 21 256.09 317.96 438.00 163.71 694.0 37.7 q1a1
+ 13 -1 16 787.45 445.54 666.00 211.95 530.5 27.4 q1a0
+ 13 5 14 -417.85 258.96 316.00 182.41 435.9 15.9 q1a0
+ 13 17 12 -378.11 267.39 355.00 168.51 270.4 1388.8 q0a15
+ 13 19 12 421.58 251.69 596.00 166.82 239.5 1380.8 q0a15
+ 13 21 12 1370.27 289.39 518.00 160.53 208.2 1372.9 q0a15
+ 13 23 12 218.73 294.30 358.00 147.47 179.6 1364.8 q0a14
+ 13 31 13 63.07 171.90 188.00 107.33 50.0 1325.2 q0a14
+ 13 39 15 40.00 140.85 180.00 73.00 211.1 799.5 q0a9
+ 14 14 14 -542.83 389.56 450.00 185.43 324.9 1361.5 q0a15
+ 14 16 14 -8.65 216.60 242.00 160.85 294.1 1353.4 q0a15
+ 14 26 14 -260.75 183.62 209.00 126.75 138.6 1311.9 q0a14
+ 14 40 17 -68.76 145.62 168.00 68.36 165.3 812.2 q0a8
+ 14 54 24 -29.93 82.90 88.00 43.33 31.0 1072.6 q0a10
+ 15 -27 38 -165.14 121.06 102.00 61.74 550.7 771.5 q1a8
+ 15 -25 36 -95.78 101.48 106.00 63.98 593.4 767.3 q1a9
+ 15 -23 34 -207.81 112.01 102.00 63.81 638.2 763.2 q1a9
+ 15 -17 29 -159.88 256.62 316.00 80.88 760.1 757.4 q1a9
+ 15 -13 26 -293.84 374.21 333.00 122.04 767.8 400.1 q1a5
+ 15 1 19 421.08 440.09 465.00 158.32 753.0 609.5 q1a7
+ 15 13 16 118.35 232.90 344.00 160.85 349.0 1325.9 q0a15
+ 15 33 17 193.98 168.85 228.00 80.22 28.2 1259.4 q0a12
+ 15 37 18 72.39 101.02 118.00 67.01 143.2 752.4 q0a8
+ 15 43 20 -201.81 98.48 104.00 64.81 96.7 863.5 q0a8
+ 15 45 21 79.21 101.61 115.00 62.59 77.5 903.0 q0a8
+ 15 49 23 72.60 73.41 85.00 47.60 38.0 958.2 q0a10
+ 15 51 24 -346.24 148.37 177.00 46.64 17.1 1001.3 q0a10
+ 16 -30 44 52.39 85.81 96.00 55.01 451.8 829.3 q1a8
+ 16 -18 32 637.57 138.17 250.00 64.83 724.2 800.7 q1a9
+ 16 -6 24 -210.12 359.64 345.00 126.12 722.9 510.2 q1a5
+ 16 -4 23 279.04 349.24 303.00 122.16 720.7 544.3 q1a5
+ 16 4 20 -347.26 423.12 413.00 141.86 707.0 647.2 q1a7
+ 16 8 19 698.35 401.73 420.00 141.85 696.7 711.0 q1a7
+ 16 28 18 27.16 139.63 186.00 86.04 119.3 1246.6 q0a12
+ 16 40 21 373.75 108.05 109.00 61.25 74.3 801.8 q0a8
+ 17 -25 41 194.69 123.32 123.00 58.31 553.6 860.9 q1a8
+ 17 -23 39 -64.70 108.05 108.00 62.30 597.1 855.6 q1a9
+ 17 -21 37 89.53 100.74 134.00 60.27 642.6 850.4 q1a9
+ 17 -15 32 -198.74 344.18 294.00 78.14 766.6 842.4 q1a9
+ 17 -9 28 -88.31 144.98 175.00 93.31 682.0 442.7 q1a5
+ 17 13 20 -396.39 280.10 336.00 108.99 367.0 1271.5 q0a13
+ 17 27 20 29.66 137.55 183.00 85.54 143.1 1207.8 q0a12
+ 17 33 21 -28.01 109.20 128.00 74.61 40.5 1170.7 q0a12
+ 18 -26 45 -2.96 86.42 107.00 57.16 502.3 917.0 q1a8
+ 18 -18 37 -89.04 119.31 125.00 65.84 686.1 893.3 q1a9
+ 18 -10 31 -292.43 133.28 137.00 82.83 637.4 408.5 q1a5
+ 18 2 25 -360.86 156.14 175.00 105.26 626.6 591.3 q1a7
+ 18 14 22 77.96 193.61 181.00 94.84 360.6 1224.8 q0a13
+ 18 16 22 -72.32 144.72 198.00 93.92 328.7 1215.6 q0a13
+ 18 26 22 -170.12 166.92 168.00 83.12 167.3 1168.3 q0a12
+ 18 32 23 53.77 121.30 127.00 73.03 64.5 1129.9 q0a12
+ 19 -27 49 267.39 93.27 83.00 42.01 448.8 948.8 q1a10
+ 19 11 25 -31.01 258.35 337.00 88.61 560.4 727.4 q1a6
+ 19 17 24 -42.09 111.82 130.00 85.29 321.6 1167.4 q0a13
+ 19 19 24 -114.25 104.81 124.00 79.25 288.9 1157.8 q0a13
+ 19 21 24 -81.74 136.10 127.00 81.14 255.9 1148.0 q0a13
+ 19 23 24 50.86 107.00 155.00 80.74 222.6 1138.2 q0a13
+ 20 -26 51 -58.49 74.26 81.00 41.89 444.3 1003.1 q1a10
+ 20 -14 39 141.35 96.46 98.00 56.85 729.7 958.9 q1a11
+ 20 -8 35 63.35 179.62 195.00 72.85 543.5 410.4 q1a4
+ 20 2 30 -210.04 134.58 143.00 84.84 535.6 563.8 q1a6
+ 20 8 28 265.81 158.18 300.00 85.19 522.8 666.1 q1a6
+ 21 -23 51 -21.30 82.88 89.00 46.70 491.4 1050.4 q1a10
+ 21 -15 43 -288.84 172.24 227.00 61.04 683.4 1017.9 q1a11
+ 21 -7 37 124.73 119.59 129.00 64.47 493.1 411.4 q1a4
+ 21 -5 36 54.69 102.02 125.00 68.31 491.5 448.4 q1a4
+ 21 11 30 -43.82 130.27 168.00 74.42 462.7 703.4 q1a6
+ 22 -20 51 267.60 159.57 187.00 43.60 538.8 1097.9 q1a10
+ 22 -16 47 -68.69 89.74 95.00 52.69 634.7 1080.1 q1a11
+ 22 -10 42 256.50 149.07 169.00 52.50 767.5 1064.4 q1a11
+ 22 6 34 -84.16 118.91 157.00 75.96 424.1 603.5 q1a6
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035136_1b05d.h5
+Image serial number: 57
+hit = 1
+indexed_by = none
+photon_energy_eV = 9510.646004
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9510.646004
+average_camera_length = 0.152001 m
+num_peaks = 11
+peak_resolution = 4.107791 nm^-1 or 2.434399 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 17.91 29.50 2.25 929.85 q0a0
+ 47.93 134.64 1.71 2151.83 q0a0
+1375.70 49.01 2.34 714.48 q3a1
+ 807.40 230.15 1.00 10298.12 q2a2
+1343.50 296.82 1.05 1237.25 q3a2
+1339.50 328.07 0.94 640.90 q3a2
+1324.74 331.92 0.86 27989.54 q3a2
+1509.83 278.50 1.88 1375.04 q3a3
+1433.81 330.50 1.41 1196.24 q3a3
+ 310.50 705.09 2.91 309.51 q0a7
+1310.03 798.97 4.11 -13.64 q3a8
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035145_1bd7d.h5
+Image serial number: 59
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9524.324769
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9524.324769
+average_camera_length = 0.152001 m
+num_peaks = 24
+peak_resolution = 2.539443 nm^-1 or 3.937872 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 33.02 31.50 2.24 668.28 q0a0
+ 357.05 142.52 2.40 2765.62 q0a1
+ 985.50 158.20 1.83 943.76 q2a1
+1188.78 169.50 1.51 912.90 q3a0
+ 38.26 217.20 1.12 9015.93 q0a2
+ 159.50 237.24 1.23 1029.36 q0a2
+ 106.10 300.40 0.78 13795.60 q0a2
+ 95.83 329.69 0.62 2970.61 q0a2
+ 184.43 337.82 0.96 2878.33 q0a2
+ 222.50 230.09 1.49 1111.57 q0a3
+ 515.09 194.26 1.32 2052.34 q1a2
+ 496.33 198.50 1.26 1573.30 q1a2
+ 518.06 227.50 1.17 1682.65 q1a2
+ 520.74 260.12 1.02 3536.81 q1a2
+ 740.50 314.11 1.84 989.70 q1a3
+ 893.58 269.96 0.93 3570.44 q2a2
+ 827.50 273.30 0.78 1753.84 q2a2
+1017.50 212.09 1.61 530.11 q2a3
+1245.50 199.81 1.22 1904.82 q3a2
+1274.31 278.92 0.88 8231.47 q3a2
+1332.98 332.50 0.90 3192.84 q3a2
+1418.20 260.76 1.51 2415.84 q3a3
+1481.76 347.73 1.63 1205.91 q3a3
+ 290.50 1400.07 2.54 445.38 q0a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.14899 12.21260 16.88770 nm, 89.40746 89.05509 90.07615 deg
+astar = -0.0553328 +0.1471217 -0.0418175 nm^-1
+bstar = +0.0726442 +0.0327959 +0.0187818 nm^-1
+cstar = +0.0181712 -0.0100140 -0.0554729 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00208 nm^-1
+predict_refine/final_residual = 5.239358e-07
+predict_refine/det_shift x = -0.033 y = -0.033 mm
+diffraction_resolution_limit = 1.83 nm^-1 or 5.45 A
+num_reflections = 198
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -23 5 44 -16.46 84.33 102.00 48.66 1417.7 1049.6 q3a11
+ -22 -4 36 -41.04 96.39 81.00 53.84 1239.3 404.1 q3a4
+ -22 4 40 117.74 75.24 134.00 50.86 1474.1 996.6 q3a11
+ -21 -19 30 65.59 150.81 150.00 65.21 1180.0 643.1 q3a6
+ -21 -17 30 3.38 121.60 124.00 63.62 1198.6 613.0 q3a6
+ -21 -11 31 125.25 88.41 108.00 58.75 1244.2 545.9 q3a4
+ -21 -7 32 -78.97 107.14 122.00 62.77 1272.0 482.4 q3a4
+ -20 -8 29 392.36 128.62 130.00 62.24 1313.2 524.0 q3a4
+ -20 -2 31 -74.82 133.94 126.00 64.14 1350.0 427.7 q3a4
+ -19 -15 25 -158.76 126.23 109.00 67.36 1310.1 627.7 q3a6
+ -19 -3 28 -4.59 118.82 146.00 75.79 1386.3 469.5 q3a5
+ -19 7 33 -225.81 221.70 193.00 59.81 1511.9 864.4 q3a9
+ -18 -2 26 50.57 103.80 113.00 75.83 1434.1 476.9 q3a5
+ -18 8 31 40.88 158.55 274.00 64.12 1521.5 816.5 q3a9
+ -17 -23 20 287.15 145.50 151.00 66.65 1133.0 1184.2 q2a13
+ -17 -11 21 -197.45 129.23 141.00 84.05 1420.6 609.1 q3a7
+ -17 -1 24 468.54 190.29 375.00 87.66 1480.7 484.2 q3a5
+ -16 -26 18 -29.14 89.08 120.00 71.74 1070.9 1199.6 q2a13
+ -16 -18 18 -222.61 166.74 199.00 90.01 1409.7 730.9 q3a7
+ -16 -10 19 171.68 245.49 361.00 95.92 1467.0 614.0 q3a7
+ -16 2 23 497.39 318.12 317.00 105.01 1535.9 458.9 q3a5
+ -16 22 37 446.24 118.30 222.00 51.36 1188.9 1231.2 q3a12
+ -16 24 39 45.38 89.62 89.00 52.62 1193.7 1186.2 q3a12
+ -15 -33 17 -174.06 166.47 182.00 66.06 952.1 1173.3 q2a12
+ -15 -25 16 264.84 149.09 174.00 72.96 1069.0 1248.0 q2a13
+ -14 -32 15 -214.59 282.60 323.00 70.79 951.7 1222.9 q2a12
+ -14 -18 14 -337.75 266.96 268.00 134.75 1153.9 1315.0 q2a15
+ -13 -7 14 350.20 297.35 490.00 155.20 1280.4 13.4 q3a0
+ -13 13 23 406.25 284.41 313.00 112.75 1272.4 1453.2 q3a14
+ -13 25 33 22.75 164.34 171.00 59.25 1315.0 1249.4 q3a12
+ -13 27 35 -164.45 163.93 150.00 56.05 1321.0 1205.6 q3a12
+ -12 -44 15 -22.86 105.07 102.00 52.26 857.6 755.0 q2a8
+ -12 -8 12 -447.62 348.72 441.00 159.62 1249.1 41.7 q3a0
+ -12 -4 13 720.50 545.62 597.00 181.50 1306.9 65.1 q3a0
+ -12 22 28 -124.71 178.70 178.00 94.91 1342.1 1309.3 q3a14
+ -11 -27 9 402.96 146.74 212.00 115.90 977.4 1352.1 q2a15
+ -11 -17 9 -965.25 634.50 472.00 204.25 1120.6 1426.6 q2a15
+ -11 3 14 -277.54 340.23 383.00 146.34 1391.6 134.7 q3a1
+ -11 9 17 -299.52 499.73 442.00 180.72 1485.3 163.2 q3a1
+ -11 23 27 -88.65 139.06 150.00 98.85 1377.4 1311.9 q3a15
+ -11 29 33 105.86 103.18 111.00 55.74 1397.3 1212.0 q3a13
+ -10 28 30 -48.64 109.52 144.00 60.24 1429.2 1258.3 q3a13
+ -9 -57 17 58.06 64.22 65.00 37.94 799.6 1011.5 q2a10
+ -9 -33 7 23.73 146.05 191.00 95.47 863.3 1369.2 q2a14
+ -9 -25 6 -449.48 373.75 382.00 145.05 977.5 1434.7 q2a15
+ -8 -42 8 -32.89 94.55 93.00 56.49 1029.3 778.6 q2a9
+ -8 -14 5 270.79 239.88 451.00 96.41 1113.4 323.3 q2a3
+ -8 -8 6 879.51 160.63 644.00 97.95 1188.0 170.0 q3a0
+ -8 12 14 225.81 291.71 404.00 94.19 1481.6 245.0 q3a3
+ -8 18 18 -82.05 417.46 404.00 163.45 1455.2 1462.5 q3a15
+ -8 34 33 -72.68 100.23 119.00 56.08 1518.9 1168.5 q3a13
+ -7 -57 14 -115.04 88.62 104.00 41.84 883.2 1038.6 q2a10
+ -7 -43 7 57.96 78.35 88.00 55.84 1054.2 808.9 q2a9
+ -7 -31 4 -159.45 177.95 218.00 111.05 865.4 1452.6 q2a14
+ -7 -3 6 2047.96 177.92 1283.00 50.90 1244.8 199.4 q3a2
+ -7 7 10 75.36 115.69 117.00 70.24 1388.4 251.2 q3a3
+ -7 9 11 2415.84 183.62 1069.00 68.96 1418.8 261.0 q3a3
+ -7 27 24 -257.15 188.39 221.00 114.35 1524.7 1314.4 q3a15
+ -7 31 28 143.04 287.37 271.00 70.16 1540.7 1258.5 q3a13
+ -6 -46 7 69.86 69.72 89.00 53.74 1056.6 873.3 q2a9
+ -6 -20 2 997.59 201.41 393.00 95.21 1091.0 211.3 q2a3
+ -6 -6 4 1175.75 136.03 1003.00 53.25 1188.4 212.3 q3a2
+ -5 -41 4 -200.36 223.76 230.00 62.76 1141.2 803.8 q2a9
+ -5 -33 2 257.25 187.07 212.00 121.75 1155.0 37.2 q2a1
+ -5 -25 1 1568.35 500.16 507.00 175.85 1094.7 154.5 q2a1
+ -5 -19 1 -10.51 137.75 141.00 84.11 1054.6 212.0 q2a3
+ -5 1 5 8341.86 307.64 4265.00 53.96 1273.8 279.7 q3a2
+ -5 15 12 1157.27 236.73 632.00 84.53 1482.9 349.0 q3a3
+ -5 37 32 24.35 133.28 128.00 51.85 148.4 680.0 q0a6
+ -4 -58 11 -30.81 72.72 78.00 40.81 981.2 1101.8 q2a11
+ -4 -44 4 -42.99 151.73 156.00 53.39 1144.9 867.0 q2a9
+ -4 -26 0 914.73 440.73 473.00 169.47 1071.4 127.0 q2a1
+ -4 -18 0 586.38 117.98 490.00 71.62 1018.5 212.7 q2a3
+ -4 6 6 3326.12 248.13 1572.00 46.88 1332.9 334.2 q3a2
+ -4 10 8 84.12 111.34 158.00 67.88 1390.1 354.0 q3a3
+ -4 34 27 154.94 100.16 148.00 65.06 235.9 661.3 q0a7
+ -3 -55 8 -226.93 121.01 159.00 47.33 1058.2 1053.9 q2a11
+ -3 -53 7 -3.56 68.21 86.00 44.56 1081.8 1014.9 q2a11
+ -3 -49 5 -46.04 76.27 84.00 43.84 1127.2 940.2 q2a11
+ -3 -33 0 58.30 187.21 246.00 127.30 1093.1 10.8 q2a1
+ -3 -25 -1 -779.15 390.18 482.00 161.35 1034.7 128.4 q2a1
+ -3 -17 -1 -154.69 116.15 148.00 72.69 982.8 213.4 q2a3
+ -3 17 11 213.62 130.23 151.00 96.38 30.6 154.3 q0a0
+ -3 35 27 -128.20 105.88 118.00 67.80 230.3 625.4 q0a7
+ -2 -44 2 42.84 106.23 97.00 59.96 1017.1 385.5 q2a5
+ -2 -24 -2 -184.00 337.95 410.00 147.00 998.3 129.8 q2a1
+ -2 -22 -2 943.76 197.06 622.00 119.64 985.3 158.4 q2a1
+ -2 -10 -1 464.56 158.84 375.00 58.44 915.4 297.8 q2a2
+ -2 -2 1 11733.26 927.69 8660.00 222.14 1191.1 349.4 q3a2
+ -2 8 5 453.32 120.18 285.00 50.08 15.4 278.0 q0a2
+ -2 10 6 220.21 85.78 104.00 48.59 25.4 248.0 q0a2
+ -2 12 7 9006.94 319.50 5053.00 51.06 35.5 217.9 q0a2
+ -1 -37 -1 -237.21 273.31 253.00 88.41 1116.7 478.3 q2a5
+ -1 -11 -2 3578.99 210.11 1417.00 55.61 892.9 271.3 q2a2
+ -1 25 15 -491.12 322.04 509.00 158.12 127.0 45.5 q0a0
+ 0 -40 -1 -328.91 165.40 218.00 74.71 1055.3 483.9 q2a5
+ 0 -36 -2 250.62 315.10 385.00 92.38 1118.7 516.4 q2a5
+ 0 -30 -3 -164.21 186.79 227.00 139.41 981.0 16.7 q2a1
+ 0 18 9 621.34 133.47 460.00 96.91 121.6 177.8 q0a0
+ 0 26 15 -70.89 316.70 502.00 153.49 161.2 40.8 q0a0
+ 0 44 35 -92.86 89.33 109.00 47.26 60.9 508.6 q0a4
+ 1 -45 0 -118.01 152.92 168.00 55.61 960.6 470.7 q2a4
+ 1 -39 -2 239.86 118.00 139.00 68.74 1057.6 522.5 q2a5
+ 1 7 2 3128.64 192.43 1889.00 51.76 94.6 331.4 q0a2
+ 1 9 3 13709.02 377.05 7017.00 52.77 104.8 301.6 q0a2
+ 1 11 4 0.19 83.81 135.00 53.81 115.1 271.7 q0a2
+ 1 37 25 37.53 98.05 110.00 62.27 250.6 518.8 q0a5
+ 2 14 5 1212.31 182.71 792.00 58.69 158.4 237.9 q0a2
+ 2 34 21 -561.84 266.52 266.00 85.04 329.0 505.7 q0a5
+ 2 44 33 75.72 70.57 172.00 46.48 95.5 443.8 q0a4
+ 2 46 36 7.44 75.57 72.00 43.56 37.4 430.0 q0a4
+ 3 -13 -5 98.62 120.36 116.00 57.38 792.6 193.8 q2a2
+ 3 25 12 1124.10 318.87 503.00 157.10 240.5 96.6 q0a1
+ 4 -38 -4 188.18 128.71 120.00 74.42 1032.8 592.0 q2a7
+ 4 -24 -6 -483.64 293.67 354.00 142.24 829.1 54.0 q2a0
+ 4 -22 -6 981.79 191.86 654.00 116.41 816.9 83.0 q2a0
+ 4 -20 -6 -125.40 174.48 228.00 109.60 804.9 111.8 q2a0
+ 4 4 -1 298.19 133.88 128.00 39.81 411.1 283.7 q1a2
+ 4 16 5 1111.57 143.28 765.00 67.83 222.2 230.4 q0a3
+ 4 22 9 -145.69 169.41 301.00 132.69 253.6 160.8 q0a1
+ 4 38 24 13.18 102.00 104.00 57.42 268.9 420.2 q0a5
+ 5 -43 -3 78.35 144.27 163.00 57.85 937.9 583.2 q2a6
+ 5 31 16 139.43 154.57 207.00 120.17 332.8 9.8 q0a1
+ 5 35 20 -186.40 132.12 141.00 70.60 347.6 408.7 q0a5
+ 6 -44 -3 72.95 87.15 105.00 53.45 905.5 605.4 q2a6
+ 6 -32 -6 -26.38 396.01 347.00 104.38 1100.4 693.0 q2a7
+ 6 -2 -4 3573.49 218.72 1752.00 43.11 520.2 260.0 q1a2
+ 6 46 33 176.80 142.87 155.00 45.80 347.6 1014.3 q0a11
+ 6 48 36 197.04 94.91 110.00 44.16 330.8 1073.6 q0a11
+ 7 -45 -3 -89.38 76.44 85.00 52.38 872.6 628.0 q2a6
+ 7 -17 -7 1078.65 233.95 558.00 87.15 741.7 315.1 q1a3
+ 7 -1 -4 1685.91 154.43 680.00 41.29 517.4 226.8 q1a2
+ 7 13 2 -62.55 120.35 128.00 75.95 291.2 310.6 q0a3
+ 7 25 10 2086.89 430.67 779.00 161.51 357.7 142.0 q0a1
+ 7 41 26 88.18 129.49 198.00 52.42 353.0 900.5 q0a9
+ 7 47 34 -1.31 94.74 123.00 47.31 305.3 1031.4 q0a11
+ 8 -46 -3 -37.89 85.05 89.00 51.49 839.0 651.0 q2a6
+ 8 -14 -7 289.82 178.53 224.00 80.58 711.0 269.9 q1a3
+ 8 0 -4 1875.81 191.83 739.00 45.19 514.5 193.3 q1a2
+ 8 20 6 533.16 603.25 407.00 165.04 358.9 210.3 q0a3
+ 8 38 22 86.53 126.87 135.00 55.27 343.2 819.1 q0a9
+ 9 27 11 286.04 210.21 272.00 114.16 122.7 1450.1 q0a14
+ 10 -44 -4 -84.78 78.89 79.00 52.98 843.6 727.9 q2a6
+ 10 -2 -5 48.57 145.96 166.00 86.83 565.3 175.6 q1a0
+ 10 22 7 -564.96 364.48 402.00 159.16 216.7 1450.3 q0a15
+ 10 26 10 367.79 289.45 397.00 126.41 150.5 1425.9 q0a14
+ 11 -33 -7 -86.56 124.78 162.00 58.56 702.4 1258.2 q1a13
+ 11 41 25 -13.95 146.75 158.00 56.55 220.5 860.7 q0a9
+ 11 47 33 -200.56 127.35 126.00 48.56 167.9 992.5 q0a10
+ 11 49 36 -202.54 107.06 90.00 41.34 146.7 1053.2 q0a10
+ 12 -38 -6 -102.59 90.34 109.00 52.79 704.1 1159.3 q1a13
+ 12 -22 -8 188.65 202.25 275.00 107.15 607.3 1389.1 q1a15
+ 12 -10 -7 1008.89 407.75 482.00 159.51 701.0 160.6 q1a1
+ 12 4 -3 -506.74 255.28 342.00 130.14 499.0 85.3 q1a0
+ 13 -33 -7 -180.22 111.24 122.00 56.02 641.9 1228.8 q1a13
+ 13 51 39 -72.68 66.52 65.00 39.18 46.7 1102.9 q0a10
+ 14 -32 -7 -91.47 110.96 105.00 53.27 605.2 1230.2 q1a13
+ 14 -6 -6 -267.05 280.36 351.00 141.45 665.6 79.8 q1a1
+ 14 -2 -5 -239.84 441.46 416.00 164.04 606.6 58.3 q1a1
+ 14 16 3 670.26 333.56 334.00 143.14 354.3 1364.2 q0a15
+ 14 22 7 -39.05 197.42 212.00 111.45 254.2 1326.5 q0a15
+ 15 -37 -6 -91.75 79.83 79.00 48.75 604.1 1129.0 q1a13
+ 15 19 5 179.02 178.55 233.00 117.78 314.5 1314.0 q0a15
+ 15 27 11 249.08 157.88 190.00 66.20 176.6 1287.5 q0a12
+ 16 -36 -6 -161.01 128.33 113.00 50.61 569.1 1130.1 q1a12
+ 16 -30 -7 -384.20 143.05 105.00 55.80 533.9 1233.1 q1a12
+ 16 28 12 13.61 145.87 120.00 60.99 166.3 1246.5 q0a12
+ 17 -27 -7 234.11 88.37 205.00 50.49 485.1 1267.5 q1a12
+ 17 31 15 159.86 113.49 123.00 58.74 115.2 1188.1 q0a12
+ 17 33 17 -135.10 98.56 82.00 55.90 73.8 1171.1 q0a12
+ 17 35 19 -34.97 90.51 101.00 56.77 31.4 1153.8 q0a12
+ 18 -22 -7 -1.77 114.58 178.00 72.97 425.8 1306.1 q1a14
+ 18 4 -2 377.57 140.38 154.00 84.83 705.1 565.6 q1a7
+ 18 22 8 -158.52 94.07 95.00 64.72 288.4 1220.8 q0a13
+ 18 26 11 0.28 106.00 132.00 62.52 216.1 1191.7 q0a13
+ 19 -13 -6 401.29 136.73 373.00 56.91 757.3 755.4 q1a9
+ 19 -7 -5 -64.05 177.24 182.00 81.45 735.1 413.6 q1a5
+ 19 -3 -4 337.50 187.98 265.00 87.50 712.4 474.9 q1a5
+ 19 29 14 -87.49 135.35 116.00 58.89 168.7 1131.4 q0a12
+ 20 -18 -6 250.97 114.51 99.00 47.23 664.4 761.3 q1a9
+ 20 26 12 128.46 103.20 95.00 56.34 230.4 1118.4 q0a13
+ 21 -7 -4 -79.44 118.50 117.00 67.44 667.9 388.1 q1a5
+ 21 -3 -3 -80.69 103.24 104.00 68.69 644.9 450.7 q1a5
+ 21 3 -1 87.55 142.26 161.00 71.05 609.2 545.0 q1a5
+ 22 -26 -5 -40.43 72.14 75.00 43.83 502.6 787.0 q1a8
+ 22 -24 -5 -230.93 111.64 93.00 45.33 536.9 798.0 q1a8
+ 22 -18 -5 -141.15 82.29 77.00 50.35 634.5 830.0 q1a9
+ 22 16 6 13.06 75.05 98.00 60.94 491.7 721.0 q1a6
+ 23 15 6 25.97 76.83 95.00 56.23 461.1 694.5 q1a6
+ 24 8 3 -351.01 132.48 108.00 58.61 471.1 566.2 q1a6
+ 24 10 4 76.97 109.13 105.00 57.23 457.4 599.8 q1a6
+ 24 12 5 -146.57 89.26 123.00 60.17 443.7 633.6 q1a6
+ 25 -25 -3 -65.79 78.67 78.00 41.59 466.6 903.8 q1a8
+ 25 -23 -3 -78.74 93.60 103.00 48.14 502.3 914.4 q1a8
+ 26 -16 -2 -130.20 105.26 110.00 46.80 605.0 963.0 q1a11
+ 27 -15 -1 91.04 74.54 91.00 43.16 605.6 1009.0 q1a11
+ 28 -14 0 184.70 77.76 71.00 41.70 606.2 1056.2 q1a11
+ 28 -8 1 -49.85 85.65 90.00 45.65 710.9 1090.0 q1a11
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035102_18096.h5
+Image serial number: 61
+hit = 1
+indexed_by = none
+photon_energy_eV = 9503.728900
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9503.728900
+average_camera_length = 0.152001 m
+num_peaks = 11
+peak_resolution = 4.509722 nm^-1 or 2.217432 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 105.03 15.50 2.35 556.78 q0a0
+ 163.08 155.50 1.75 700.93 q0a0
+1177.50 141.17 1.66 560.35 q3a0
+ 78.20 244.37 1.00 1942.38 q0a2
+ 137.96 323.64 0.80 1210.60 q0a2
+ 221.79 301.50 1.25 632.01 q0a3
+ 918.07 289.96 0.92 2987.38 q2a2
+ 910.59 353.45 0.67 9048.70 q2a2
+ 680.93 711.07 2.97 367.76 q1a7
+1309.94 799.06 4.11 -191.99 q3a8
+ 705.00 1061.00 4.51 491.45 q1a11
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035151_1c6b9.h5
+Image serial number: 60
+hit = 1
+indexed_by = none
+photon_energy_eV = 9501.396086
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9501.396086
+average_camera_length = 0.152001 m
+num_peaks = 14
+peak_resolution = 4.405355 nm^-1 or 2.269965 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 156.98 23.98 2.37 -363.08 q0a0
+ 106.50 156.58 1.65 3056.64 q0a0
+ 259.24 116.03 2.18 3404.61 q0a1
+ 530.91 156.50 1.68 268.61 q1a0
+ 62.50 222.85 1.10 1551.73 q0a2
+ 57.44 255.58 0.92 7837.05 q0a2
+ 76.26 305.07 0.68 5339.39 q0a2
+ 156.02 309.74 0.92 1896.94 q0a2
+ 245.76 211.50 1.65 771.49 q0a3
+ 205.92 275.08 1.26 644.60 q0a3
+ 510.87 242.38 1.08 4807.78 q1a2
+ 926.01 357.16 0.74 1584.01 q2a2
+ 712.12 1032.50 4.41 708.14 q1a11
+ 246.50 1407.22 2.58 975.94 q0a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035027_14fd6.h5
+Image serial number: 62
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9513.134624
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9513.134624
+average_camera_length = 0.152001 m
+num_peaks = 25
+peak_resolution = 3.017205 nm^-1 or 3.314326 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 145.03 29.03 2.33 -15.81 q0a0
+ 629.50 56.08 2.37 1769.50 q1a1
+ 601.91 140.50 1.92 856.88 q1a1
+ 826.50 10.88 2.31 1175.51 q2a0
+1014.50 42.89 2.41 1439.49 q2a1
+1086.16 94.38 2.39 1610.09 q2a1
+1243.88 86.30 1.96 1005.57 q3a0
+1413.82 122.29 2.11 3313.73 q3a1
+ 152.89 285.50 1.01 882.04 q0a2
+ 417.65 193.43 1.22 4368.35 q1a2
+ 535.50 300.20 0.90 304.40 q1a2
+ 540.82 299.69 0.92 967.80 q1a2
+ 711.09 284.43 1.75 2517.91 q1a3
+ 843.50 227.23 1.04 525.01 q2a2
+ 940.71 344.50 0.84 1976.30 q2a2
+1009.11 261.81 1.40 19427.02 q2a3
+1074.87 306.50 1.60 629.49 q2a3
+1296.26 224.00 1.20 -692.68 q3a2
+1291.37 225.94 1.18 4473.24 q3a2
+1300.64 309.84 0.83 9224.46 q3a2
+1302.50 337.35 0.74 2986.15 q3a2
+1387.50 356.79 1.13 643.84 q3a3
+ 298.07 603.50 3.02 385.84 q0a7
+ 289.04 678.50 3.02 858.11 q0a7
+ 344.18 1423.95 2.35 1433.79 q0a15
+End of peak list
+--- Begin crystal
+Cell parameters 6.14007 12.22880 17.10188 nm, 90.07244 89.66396 90.39448 deg
+astar = +0.1215556 -0.0549559 -0.0934403 nm^-1
+bstar = -0.0435780 -0.0666939 -0.0184452 nm^-1
+cstar = -0.0232050 +0.0277761 -0.0459265 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00118 nm^-1
+predict_refine/final_residual = 5.680372e-07
+predict_refine/det_shift x = 0.072 y = 0.009 mm
+diffraction_resolution_limit = 2.36 nm^-1 or 4.23 A
+num_reflections = 110
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -16 -8 70 55.64 85.55 87.00 46.76 446.3 1006.5 q1a10
+ -16 -4 64 83.97 93.16 95.00 58.23 461.8 914.3 q1a8
+ -15 5 49 55.59 111.90 126.00 64.21 445.1 1225.2 q1a12
+ -15 15 45 -100.25 107.27 126.00 68.25 601.7 1154.0 q1a13
+ -14 -16 66 143.64 92.80 137.00 53.76 611.7 1058.3 q1a11
+ -14 -8 54 -276.95 107.25 112.00 68.55 631.2 856.2 q1a9
+ -14 20 39 153.91 93.88 121.00 69.29 717.2 1171.8 q1a13
+ -14 22 39 -184.51 145.03 210.00 68.11 743.7 1150.1 q1a13
+ -13 -17 60 88.01 88.63 96.00 60.21 694.5 999.9 q1a11
+ -13 -9 49 72.57 104.60 125.00 72.83 700.8 817.2 q1a9
+ -13 35 37 -187.06 103.01 100.00 66.06 798.5 588.3 q2a6
+ -12 -18 55 107.40 192.86 197.00 63.40 764.7 955.7 q1a11
+ -12 4 34 747.63 408.90 406.00 144.58 567.9 1382.1 q1a14
+ -12 22 30 -188.89 196.77 223.00 106.49 1019.2 718.3 q2a7
+ -12 24 30 -333.21 182.15 193.00 100.41 998.7 691.9 q2a7
+ -12 30 31 -59.25 138.00 124.00 73.25 929.3 615.9 q2a6
+ -11 -15 45 -168.08 134.01 146.00 87.80 678.7 391.1 q1a5
+ -11 19 26 542.55 225.97 350.00 115.05 1098.4 724.7 q2a7
+ -11 21 26 264.25 309.76 386.00 120.75 1078.7 698.9 q2a7
+ -11 23 26 227.64 139.87 181.00 103.76 1058.8 672.8 q2a7
+ -11 39 30 -212.19 115.46 110.00 65.19 854.4 496.5 q2a4
+ -11 41 31 -58.02 114.33 124.00 65.22 821.2 470.8 q2a4
+ -10 -24 53 -122.56 128.19 111.00 74.56 495.5 443.3 q1a4
+ -9 -17 38 -10.14 421.97 374.00 127.06 725.3 496.0 q1a5
+ -9 -11 32 179.45 247.22 448.00 163.95 675.9 39.6 q1a1
+ -9 -3 26 -463.54 599.11 479.00 239.22 711.5 177.7 q1a1
+ -9 5 22 1165.24 482.82 615.00 170.97 758.4 272.0 q1a3
+ -9 11 20 95.20 559.22 464.00 216.20 764.2 1468.5 q1a15
+ -9 17 19 875.74 389.52 882.00 190.86 824.3 11.3 q2a0
+ -9 25 19 678.66 251.65 405.00 126.54 1127.9 589.0 q2a7
+ -9 35 21 -275.18 163.62 156.00 90.58 1010.8 489.3 q2a5
+ -8 -30 53 -378.35 172.75 191.00 77.15 424.7 546.2 q1a4
+ -8 -18 35 874.68 435.15 399.00 137.78 743.5 543.6 q1a5
+ -8 -12 29 1760.51 354.87 984.00 189.68 629.4 56.9 q1a1
+ -8 4 19 2770.69 288.88 1478.00 102.31 712.1 286.4 q1a3
+ -8 48 24 -49.56 104.35 186.00 54.56 1115.4 1028.6 q2a11
+ -7 15 13 212.04 183.09 223.00 144.16 851.1 105.5 q2a0
+ -6 -22 32 322.83 354.72 371.00 149.17 731.6 609.8 q1a7
+ -6 16 10 261.14 200.75 250.00 139.26 889.0 133.7 q2a0
+ -6 26 10 1439.49 268.71 697.00 177.11 1014.0 42.6 q2a1
+ -5 -35 48 -132.00 128.61 146.00 82.00 424.3 667.7 q1a6
+ -5 45 13 -161.84 110.31 121.00 74.04 1078.4 868.9 q2a9
+ -4 -34 42 -348.41 145.65 141.00 86.21 503.5 713.2 q1a6
+ -4 -26 30 491.34 305.88 389.00 145.46 710.5 699.2 q1a7
+ -4 28 5 1419.34 526.32 1034.00 218.46 1086.6 94.0 q2a1
+ -4 42 9 -61.44 138.47 192.00 75.44 1095.9 786.8 q2a9
+ -4 48 12 -172.82 116.87 125.00 67.42 1011.7 875.0 q2a9
+ -3 61 19 43.76 79.71 106.00 42.64 784.9 1054.0 q2a10
+ -2 -36 38 262.81 174.77 296.00 83.19 348.4 1152.9 q0a13
+ -2 -16 14 591.05 157.87 295.00 120.55 396.8 157.0 q1a0
+ -2 -12 11 4230.11 247.66 3460.00 52.49 416.8 194.1 q1a2
+ -2 20 0 170.75 174.66 363.00 97.25 1027.8 206.0 q2a3
+ -2 46 6 163.69 120.63 147.00 68.31 992.9 767.4 q2a9
+ -1 -35 33 -24.41 123.52 149.00 88.21 311.2 1217.7 q0a13
+ -1 -25 20 1663.69 608.59 915.00 236.31 344.6 1422.2 q0a15
+ -1 3 1 3285.90 1296.27 1999.00 688.06 826.0 362.0 q2a2
+ -1 17 -2 19472.70 454.66 8928.00 87.70 1009.8 262.2 q2a3
+ -1 25 -2 259.95 590.33 488.00 207.45 1113.7 194.0 q2a3
+ 0 10 -3 2279.62 234.04 1471.00 64.38 940.9 345.3 q2a2
+ 1 19 -6 962.82 206.46 683.00 104.58 1076.2 307.2 q2a3
+ 1 23 -6 204.29 464.60 418.00 167.91 1128.6 273.8 q2a3
+ 2 -28 16 1618.25 307.63 536.00 178.75 232.2 1434.4 q0a15
+ 2 -22 10 692.75 401.39 490.00 139.25 331.0 240.3 q0a3
+ 2 -2 -3 928.75 721.16 1831.00 184.25 19.0 348.5 q0a2
+ 3 1 -6 405.99 128.23 441.00 68.61 1276.3 343.7 q3a2
+ 3 29 -9 27.85 308.93 444.00 190.35 1075.7 1407.5 q2a15
+ 4 -30 14 -1206.44 563.19 521.00 194.44 161.3 1437.3 q0a14
+ 4 2 -8 9476.41 332.51 5160.00 67.79 1299.1 311.4 q3a2
+ 5 7 -11 8249.34 306.46 2967.00 70.91 1294.9 224.7 q3a2
+ 6 -16 -2 -214.25 196.66 195.00 121.66 155.0 177.4 q0a0
+ 6 18 -14 986.40 275.74 869.00 167.40 1242.2 87.0 q3a0
+ 8 -26 3 804.15 250.18 350.00 169.65 287.7 60.9 q0a1
+ 8 0 -13 738.26 151.63 568.00 87.14 1424.3 268.5 q3a3
+ 8 12 -16 466.62 357.23 368.00 149.99 1344.8 130.8 q3a0
+ 10 -6 -13 -213.01 538.48 585.00 173.61 1520.4 320.9 q3a3
+ 10 10 -18 3191.33 462.38 1593.00 216.07 1413.5 121.9 q3a1
+ 10 22 -19 -386.71 439.23 355.00 163.91 1536.9 579.1 q3a7
+ 10 32 -18 -50.51 266.34 303.00 120.11 1394.1 665.7 q3a7
+ 11 -17 -8 629.21 293.57 627.00 179.59 86.3 22.2 q0a0
+ 11 5 -18 3017.64 387.19 735.00 202.76 1477.5 173.7 q3a1
+ 11 37 -18 -70.54 160.43 189.00 89.34 1300.7 684.1 q3a6
+ 12 20 -21 -1277.23 579.26 444.00 172.03 1526.3 533.6 q3a5
+ 13 -41 13 -170.18 111.68 133.00 70.58 291.1 909.2 q0a9
+ 14 -46 19 334.64 129.36 186.00 52.76 175.5 953.2 q0a10
+ 14 -44 16 -12.16 91.40 107.00 57.96 228.7 938.4 q0a11
+ 14 -12 -14 451.60 296.64 408.00 156.60 1530.4 1366.2 q3a15
+ 14 -8 -16 1075.55 231.25 502.00 155.05 1469.1 1391.9 q3a15
+ 14 36 -21 -197.14 139.75 124.00 81.74 1249.5 584.5 q3a6
+ 15 -25 -6 -348.34 156.24 132.00 91.54 264.0 578.8 q0a7
+ 15 -3 -19 -149.10 412.09 475.00 158.90 1377.6 1394.1 q3a15
+ 15 3 -21 -670.45 343.67 355.00 158.05 1292.3 1434.5 q3a14
+ 15 7 -22 -240.98 213.41 270.00 136.78 1234.2 1462.2 q3a14
+ 15 29 -23 47.35 217.44 224.00 81.85 1336.3 517.8 q3a4
+ 16 -26 -6 100.26 121.51 173.00 85.14 224.5 575.1 q0a7
+ 16 16 -24 -134.46 127.71 160.00 98.66 1508.3 384.1 q3a5
+ 17 -37 4 149.24 104.71 111.00 58.36 116.3 393.9 q0a4
+ 17 -19 -12 -457.21 150.96 160.00 99.41 238.3 712.4 q0a7
+ 18 -34 0 71.19 117.96 156.00 60.81 102.3 472.2 q0a4
+ 18 -32 -2 101.32 102.18 254.00 64.08 116.9 513.6 q0a4
+ 18 -24 -9 111.16 174.22 152.00 74.04 174.0 639.4 q0a6
+ 18 0 -22 -179.93 174.48 215.00 114.33 1285.7 1321.3 q3a14
+ 18 14 -25 -216.51 167.94 172.00 80.11 1520.0 799.8 q3a9
+ 18 28 -25 -24.61 107.62 174.00 76.01 1287.0 416.9 q3a4
+ 20 0 -23 134.81 108.79 141.00 70.19 1251.1 1284.5 q3a12
+ 20 14 -26 13.57 94.71 132.00 71.83 1456.2 838.9 q3a9
+ 21 11 -26 117.95 104.64 108.00 71.45 1401.3 812.0 q3a9
+ 22 22 -27 177.38 95.38 121.00 60.62 1451.6 980.6 q3a11
+ 22 24 -27 -235.20 187.05 255.00 67.80 1467.4 1013.6 q3a11
+ 23 -3 -23 41.22 112.12 103.00 60.98 1246.1 1161.0 q3a12
+ 23 27 -27 105.32 95.41 107.00 59.08 1457.8 1088.1 q3a11
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035114_191bb.h5
+Image serial number: 63
+hit = 1
+indexed_by = none
+photon_energy_eV = 9501.462945
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9501.462945
+average_camera_length = 0.152001 m
+num_peaks = 12
+peak_resolution = 4.103988 nm^-1 or 2.436654 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 163.05 51.50 2.25 417.09 q0a0
+ 989.05 92.50 2.13 1188.40 q2a1
+ 273.50 199.12 1.80 1190.30 q0a3
+ 411.98 286.50 0.72 1064.93 q1a2
+ 652.80 287.19 1.47 1255.36 q1a3
+ 927.31 312.36 0.87 2408.70 q2a2
+1129.01 587.68 2.74 1337.46 q2a7
+1310.00 799.00 4.10 213.73 q3a8
+ 680.05 1462.50 2.22 688.95 q1a15
+1095.50 1384.06 2.56 474.51 q2a15
+1134.79 1455.09 2.18 979.90 q2a15
+1472.11 1464.89 2.19 671.70 q3a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035216_1e990.h5
+Image serial number: 65
+hit = 1
+indexed_by = xgandalf-nolatt-cell
+n_indexing_tries = 1
+photon_energy_eV = 9507.528744
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9507.528744
+average_camera_length = 0.152001 m
+num_peaks = 24
+peak_resolution = 4.106574 nm^-1 or 2.435120 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 544.35 74.11 2.11 2590.33 q1a0
+ 538.82 163.18 1.66 640.84 q1a0
+ 854.80 81.64 1.96 4164.65 q2a0
+ 879.39 105.07 1.87 3330.84 q2a0
+ 810.50 143.12 1.63 878.68 q2a0
+1249.50 66.80 2.06 554.15 q3a0
+1452.50 20.88 2.64 372.89 q3a1
+1414.22 73.09 2.32 1157.69 q3a1
+1510.77 149.56 2.33 3233.40 q3a1
+ 147.78 318.45 0.86 5647.20 q0a2
+ 212.50 352.23 1.09 532.19 q0a3
+ 247.14 355.50 1.26 950.24 q0a3
+ 509.64 200.50 1.28 1484.24 q1a2
+ 487.50 225.07 1.11 789.89 q1a2
+ 465.53 249.62 0.95 8479.99 q1a2
+ 435.66 266.86 0.83 2092.51 q1a2
+ 407.22 320.78 0.53 7179.03 q1a2
+ 556.74 324.76 0.90 3483.48 q1a2
+ 590.66 303.56 1.14 12123.84 q1a3
+ 907.37 280.90 0.92 6532.10 q2a2
+ 912.98 311.62 0.82 5617.41 q2a2
+1215.50 317.31 0.56 2140.12 q3a2
+1432.34 329.50 1.40 1902.25 q3a3
+1310.01 798.99 4.11 -431.16 q3a8
+End of peak list
+--- Begin crystal
+Cell parameters 6.15393 12.25775 16.83618 nm, 90.18914 89.75144 90.31293 deg
+astar = -0.0921714 +0.1237246 +0.0510240 nm^-1
+bstar = -0.0298522 +0.0094144 -0.0753389 nm^-1
+cstar = -0.0438398 -0.0381095 +0.0123981 nm^-1
+lattice_type = orthorhombic
+centering = C
+unique_axis = ?
+profile_radius = 0.00154 nm^-1
+predict_refine/final_residual = 2.836049e-07
+predict_refine/det_shift x = -0.007 y = 0.020 mm
+diffraction_resolution_limit = 2.11 nm^-1 or 4.74 A
+num_reflections = 148
+num_saturated_reflections = 0
+num_implausible_reflections = 0
+Reflections measured after indexing
+ h k l I sigma(I) peak background fs/px ss/px panel
+ -29 -1 -4 341.64 111.02 212.00 47.42 1315.4 1012.7 q3a10
+ -28 -2 -7 -70.45 107.88 113.00 52.13 1309.3 951.7 q3a10
+ -27 -3 -11 -259.88 129.93 125.00 57.12 1292.4 912.6 q3a8
+ -26 -4 -17 -271.64 119.25 116.00 54.93 1254.8 833.6 q3a8
+ -24 -4 -7 151.75 102.45 110.00 57.25 1404.9 842.7 q3a9
+ -23 -5 -13 -304.35 123.37 132.00 60.82 1368.0 767.6 q3a9
+ -22 4 30 -274.40 135.86 168.00 66.60 1228.2 588.5 q3a6
+ -21 -5 -7 -63.60 100.47 102.00 61.07 1472.8 751.4 q3a9
+ -21 -3 6 -303.64 158.74 155.00 82.09 1453.1 387.1 q3a5
+ -20 -6 -15 -110.85 136.09 131.00 79.18 1209.8 1317.7 q3a14
+ -20 2 26 182.91 142.06 153.00 71.96 1329.3 581.8 q3a6
+ -18 -6 -11 0.70 137.31 149.00 97.58 1236.9 1399.6 q3a14
+ -16 -6 -45 36.97 126.50 117.00 56.27 1531.9 1137.0 q3a13
+ -16 -6 -9 -551.62 364.22 384.00 133.44 1276.4 1459.8 q3a14
+ -16 -4 5 443.45 190.88 482.00 141.07 1452.8 20.0 q3a1
+ -15 -5 -1 188.56 390.93 420.00 177.03 1489.5 88.1 q3a1
+ -15 -3 10 -46.86 230.83 312.00 156.51 1386.3 11.7 q3a1
+ -14 -6 -9 69.14 523.68 449.00 194.77 1543.5 168.6 q3a1
+ -14 -4 5 1049.79 345.22 749.00 179.58 1414.6 72.9 q3a1
+ -13 -5 -53 25.00 102.39 107.00 62.00 113.7 637.6 q0a6
+ -13 -1 18 37.24 300.51 452.00 177.73 1275.3 8.0 q3a0
+ -12 -6 -44 205.03 140.86 155.00 81.82 227.2 685.5 q0a7
+ -12 -6 -10 -1368.98 741.14 500.00 207.94 1513.6 198.3 q3a3
+ -12 -4 4 -165.23 316.49 289.00 165.29 1386.0 130.9 q3a1
+ -12 0 21 612.65 204.50 459.00 165.21 1227.3 12.6 q3a0
+ -12 16 57 -102.11 125.36 127.00 66.51 815.2 1143.0 q2a12
+ -11 -5 -51 -304.96 143.02 140.00 66.22 182.5 604.4 q0a6
+ -11 -1 17 857.70 249.90 755.00 164.27 1248.4 66.9 q3a0
+ -11 5 35 -288.63 244.54 339.00 151.65 1078.3 1343.0 q2a15
+ -11 11 48 -197.01 269.92 287.00 80.61 924.7 1261.0 q2a12
+ -10 -6 -40 -391.42 244.41 291.00 105.25 310.7 667.5 q0a7
+ -10 -6 -14 573.62 492.71 447.00 141.38 1509.6 274.2 q3a3
+ -10 4 32 -244.36 280.45 308.00 171.99 1093.2 1392.9 q2a15
+ -10 6 37 -289.28 205.54 236.00 137.13 1037.8 1354.1 q2a15
+ -10 14 53 -123.41 193.59 243.00 71.21 837.8 1243.1 q2a12
+ -9 -5 -48 -155.92 138.60 131.00 82.45 255.6 580.1 q0a7
+ -9 -5 -6 -0.25 110.23 151.00 76.25 1419.4 244.0 q3a3
+ -9 9 43 -108.95 261.44 261.00 122.55 951.3 1332.2 q2a14
+ -9 23 66 56.79 109.15 139.00 55.41 819.0 880.5 q2a8
+ -8 -6 -28 903.79 262.28 488.00 167.15 32.3 46.5 q0a0
+ -8 -6 -27 771.22 308.52 385.00 175.49 25.2 55.4 q0a0
+ -8 -6 -26 392.22 227.85 265.00 163.49 18.1 64.4 q0a0
+ -8 -4 -53 132.62 179.38 233.00 75.17 228.1 541.3 q0a5
+ -8 -2 -64 -16.69 91.13 114.00 55.69 115.7 440.5 q0a4
+ -8 0 18 181.50 155.97 179.00 119.50 1183.4 135.1 q3a0
+ -7 -5 -42 -298.91 247.52 277.00 116.18 357.0 579.7 q0a7
+ -7 -5 -12 2112.33 177.44 1360.00 71.52 1433.0 332.0 q3a3
+ -7 -1 -67 235.65 93.76 104.00 50.15 106.9 385.5 q0a4
+ -7 29 72 87.12 84.50 84.00 38.88 802.0 1024.9 q2a10
+ -6 -4 -48 196.96 277.87 315.00 92.23 321.8 535.3 q0a5
+ -6 18 57 -123.27 113.87 122.00 64.47 1000.3 788.3 q2a9
+ -6 26 68 -21.55 58.30 69.00 41.95 884.9 958.5 q2a10
+ -5 5 30 -441.18 625.38 424.00 182.35 1122.1 225.1 q2a3
+ -5 25 66 -133.68 153.29 178.00 48.08 937.4 941.7 q2a10
+ -4 -4 -39 279.76 188.82 318.00 156.94 206.4 30.7 q0a1
+ -4 -4 -15 -27.33 112.01 128.00 59.58 36.9 210.9 q0a2
+ -4 -2 -56 -21.25 114.72 112.00 73.25 289.6 416.6 q0a5
+ -4 -2 2 597.33 141.65 506.00 56.67 1255.5 308.8 q3a2
+ -4 16 52 -54.20 127.46 141.00 69.80 1100.0 755.4 q2a9
+ -4 30 71 -31.06 91.10 100.00 42.06 905.3 1076.4 q2a10
+ -3 -3 -9 566.78 119.80 624.00 59.98 19.5 282.1 q0a2
+ -3 3 21 295.41 173.77 232.00 79.15 1011.4 278.1 q2a3
+ -3 5 -81 -46.62 91.99 84.00 38.62 169.0 1070.9 q0a10
+ -3 5 27 39.70 151.71 373.00 94.11 1052.3 217.0 q2a3
+ -3 29 69 21.11 111.30 100.00 36.49 958.8 1057.2 q2a10
+ -2 -2 -5 -416.56 228.57 185.00 79.56 16.0 336.3 q0a2
+ -2 10 38 765.58 361.27 457.00 172.82 1105.0 101.8 q2a1
+ -1 7 -83 132.18 70.85 74.00 39.42 83.4 1045.2 q0a10
+ -1 29 67 -8.34 58.87 65.00 44.54 1034.8 1068.7 q2a11
+ 0 -2 -35 179.48 287.78 371.00 171.17 272.2 149.1 q0a1
+ 0 -2 -19 49.89 130.43 117.00 63.86 158.3 257.2 q0a2
+ 0 2 -64 14.24 96.67 97.00 62.36 283.5 834.1 q0a9
+ 0 2 10 -49.18 107.80 110.00 59.64 870.5 322.3 q2a2
+ 0 16 47 -208.02 271.99 246.00 93.22 1136.0 419.6 q2a5
+ 0 30 67 -152.40 75.32 80.00 46.60 1062.2 1099.0 q2a11
+ 1 -1 -40 -791.03 483.62 431.00 192.82 336.3 126.8 q0a1
+ 1 -1 -14 5662.11 271.27 3566.00 57.08 147.3 319.9 q0a2
+ 1 7 -79 23.19 82.85 77.00 40.81 79.7 945.5 q0a10
+ 2 4 -66 44.64 110.05 153.00 62.76 206.7 807.6 q0a9
+ 3 1 -45 -150.40 334.40 288.00 145.60 121.7 1450.5 q0a14
+ 3 1 -9 602.11 160.25 270.00 43.08 404.6 285.1 q1a2
+ 3 11 31 -1485.45 625.09 446.00 205.13 936.2 72.7 q2a0
+ 3 15 40 -51.09 530.76 407.00 132.57 1156.7 547.0 q2a5
+ 4 2 -46 -669.20 288.60 399.00 146.80 135.1 1415.3 q0a14
+ 4 2 -8 2013.33 181.17 950.00 47.36 434.7 267.6 q1a2
+ 4 6 -67 280.76 143.27 162.00 61.64 140.6 770.4 q0a8
+ 4 8 -74 216.50 104.02 95.00 55.50 53.9 842.7 q0a8
+ 4 10 26 3282.07 242.60 1413.00 131.73 878.6 105.3 q2a0
+ 4 28 59 -168.95 98.40 96.00 54.55 829.9 422.6 q2a4
+ 5 3 -47 -209.80 244.21 258.00 136.63 148.6 1379.8 q0a14
+ 5 3 -7 8528.10 314.49 7054.00 46.10 464.9 250.1 q1a2
+ 5 5 5 948.56 155.32 420.00 44.54 571.3 329.8 q1a2
+ 5 9 -74 48.78 107.58 119.00 56.02 22.0 818.2 q0a8
+ 5 11 26 4433.21 278.67 1869.00 134.53 853.9 81.6 q2a0
+ 5 13 31 -176.58 464.61 529.00 175.18 886.6 24.5 q2a0
+ 5 21 47 513.80 147.63 211.00 73.80 1004.7 546.2 q2a5
+ 5 27 56 9.89 90.46 95.00 53.51 855.1 475.1 q2a4
+ 6 4 -47 -130.76 317.24 315.00 140.34 171.4 1352.1 q0a14
+ 6 4 -7 696.21 140.01 411.00 46.42 487.2 225.3 q1a2
+ 6 6 -59 22.91 100.10 233.00 67.86 64.0 1261.1 q0a12
+ 6 6 5 12306.06 419.73 9038.00 56.12 591.1 305.2 q1a3
+ 6 10 20 -10.20 168.87 221.00 116.29 790.3 121.7 q2a0
+ 7 5 -7 1530.92 159.79 1184.00 50.41 509.8 200.4 q1a2
+ 7 9 -67 -354.41 152.68 160.00 70.21 11.8 1138.2 q0a12
+ 7 9 13 531.27 157.34 391.00 82.24 690.9 332.3 q1a3
+ 7 19 39 137.24 130.81 146.00 93.36 1063.1 626.9 q2a7
+ 7 29 55 -91.38 157.91 141.00 57.38 805.0 536.9 q2a4
+ 8 6 -46 58.66 147.27 181.00 126.03 223.3 1304.7 q0a15
+ 8 8 -58 202.76 144.35 244.00 72.76 120.7 1210.8 q0a12
+ 8 22 42 -5.73 109.94 163.00 79.53 989.3 632.7 q2a7
+ 9 7 -9 693.44 188.18 571.00 113.89 538.8 163.4 q1a0
+ 9 9 -57 -21.46 261.85 343.00 75.66 154.1 1190.0 q0a12
+ 10 8 -11 186.78 235.66 366.00 136.98 545.8 122.6 q1a0
+ 11 9 -14 2266.91 481.92 1583.00 196.59 544.8 73.5 q1a0
+ 11 11 -54 -304.82 125.81 113.00 74.79 227.6 1157.3 q0a13
+ 11 17 22 -51.19 165.63 217.00 134.43 692.6 1374.5 q1a15
+ 11 19 27 186.53 175.40 196.00 122.32 724.1 1314.4 q1a15
+ 12 10 -19 158.14 347.24 350.00 164.45 527.4 7.9 q1a0
+ 12 12 -52 -82.61 127.19 134.00 70.05 270.7 1145.5 q0a13
+ 12 26 38 -162.85 117.15 123.00 59.65 765.1 1155.2 q1a13
+ 13 19 19 -270.55 239.01 311.00 120.34 617.2 1347.1 q1a15
+ 14 14 -46 -61.71 126.98 114.00 71.44 375.1 1140.2 q0a13
+ 14 14 -8 448.78 184.55 589.00 144.13 675.8 28.8 q1a1
+ 14 18 11 -70.96 333.87 395.00 130.96 540.2 1404.8 q1a14
+ 14 24 27 -188.75 120.30 121.00 66.34 636.7 1239.4 q1a13
+ 14 28 35 -212.13 106.07 110.00 59.33 685.8 1123.1 q1a13
+ 15 15 -13 -264.39 482.23 335.00 146.44 766.9 494.0 q1a5
+ 15 21 15 482.89 148.82 186.00 96.74 535.0 1326.7 q1a14
+ 16 16 -30 -38.18 130.13 170.00 90.53 594.3 582.0 q1a7
+ 16 16 -29 26.03 127.76 182.00 93.92 603.1 573.5 q1a7
+ 16 16 -28 -228.88 123.21 142.00 93.63 611.9 565.0 q1a7
+ 16 24 18 -35.82 156.88 193.00 68.94 521.3 1281.1 q1a12
+ 16 26 23 -326.91 150.67 116.00 64.18 552.0 1216.6 q1a12
+ 17 19 -9 -174.32 218.62 265.00 92.99 730.9 393.8 q1a5
+ 18 20 -36 -176.31 125.34 119.00 70.23 463.2 568.3 q1a6
+ 18 20 -18 164.17 112.16 133.00 74.83 624.3 441.4 q1a5
+ 18 22 -3 36.44 106.49 127.00 68.60 735.9 784.7 q1a9
+ 19 23 -9 -112.46 152.21 132.00 65.48 758.0 865.8 q1a9
+ 20 24 -34 43.11 125.33 120.00 65.26 396.8 507.1 q1a4
+ 20 24 -33 -341.36 185.76 214.00 69.99 406.7 498.2 q1a4
+ 20 24 -21 220.22 121.35 129.00 63.93 521.8 394.3 q1a4
+ 20 24 -20 386.51 113.11 112.00 62.91 531.1 385.8 q1a4
+ 21 31 6 63.99 117.93 140.00 60.65 510.2 840.8 q1a8
+ 22 30 -9 -39.54 89.47 94.00 52.28 629.3 966.8 q1a11
+ 22 34 7 229.00 80.29 105.00 52.57 443.6 880.2 q1a8
+ 23 35 1 -65.73 93.65 77.00 42.55 463.5 943.2 q1a10
+ 24 36 -7 98.36 78.91 84.00 44.01 500.8 1056.8 q1a10
+ 24 38 1 71.88 69.92 75.00 40.12 401.2 998.1 q1a10
+End of reflections
+--- End crystal
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035048_16d52.h5
+Image serial number: 64
+hit = 1
+indexed_by = none
+photon_energy_eV = 9503.168986
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9503.168986
+average_camera_length = 0.152001 m
+num_peaks = 13
+peak_resolution = 2.906669 nm^-1 or 3.440364 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 117.50 157.16 1.66 958.00 q0a0
+ 484.50 111.02 1.84 864.26 q1a0
+ 838.76 91.50 1.90 1197.34 q2a0
+ 216.17 230.38 1.46 1818.86 q0a3
+ 445.50 201.82 1.18 3235.76 q1a2
+ 568.03 248.95 1.22 1944.82 q1a2
+ 517.50 266.75 0.98 1312.09 q1a2
+ 555.21 300.97 0.97 2624.89 q1a2
+ 841.50 335.10 0.47 2436.34 q2a2
+1230.50 240.74 0.99 1867.55 q3a2
+1327.93 276.77 1.06 5458.53 q3a2
+1406.17 356.27 1.23 5978.92 q3a3
+1089.06 609.06 2.91 704.90 q2a7
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035159_1d12d.h5
+Image serial number: 66
+hit = 1
+indexed_by = none
+photon_energy_eV = 9516.136495
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9516.136495
+average_camera_length = 0.152001 m
+num_peaks = 13
+peak_resolution = 4.110343 nm^-1 or 2.432887 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 10.50 12.88 2.34 256.72 q0a0
+ 296.50 96.10 2.37 924.11 q0a1
+ 223.31 161.23 1.89 1616.95 q0a1
+1375.78 86.95 2.17 1656.27 q3a1
+ 420.50 210.30 1.13 3397.67 q1a2
+ 512.01 209.84 1.24 1398.26 q1a2
+ 493.50 241.13 1.04 554.36 q1a2
+ 426.00 302.50 0.63 1107.62 q1a2
+ 860.26 207.50 1.17 964.32 q2a2
+1300.15 273.50 0.98 785.26 q3a2
+1391.85 309.78 1.25 1160.44 q3a3
+ 767.18 567.50 2.66 979.36 q1a7
+1310.00 799.00 4.11 102.00 q3a8
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035116_1944f.h5
+Image serial number: 67
+hit = 1
+indexed_by = none
+photon_energy_eV = 9521.719161
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9521.719161
+average_camera_length = 0.152001 m
+num_peaks = 14
+peak_resolution = 4.112535 nm^-1 or 2.431590 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 182.91 20.91 2.43 412.89 q0a0
+ 27.50 62.02 2.09 1093.55 q0a0
+ 109.50 109.84 1.89 672.72 q0a0
+ 40.50 201.68 1.20 1527.49 q0a2
+ 518.99 241.50 1.10 861.40 q1a2
+ 475.81 253.30 0.95 4334.24 q1a2
+ 549.25 279.50 1.03 759.32 q1a2
+ 647.50 323.09 1.36 661.31 q1a3
+ 899.81 334.50 0.68 2282.56 q2a2
+1343.95 358.50 0.89 1795.65 q3a2
+1494.01 208.34 1.99 1404.85 q3a3
+1424.00 355.50 1.32 678.24 q3a3
+1310.04 798.96 4.11 -225.12 q3a8
+ 636.86 1432.50 2.44 765.09 q1a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035157_1ce9c.h5
+Image serial number: 52
+hit = 1
+indexed_by = none
+photon_energy_eV = 9515.302742
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9515.302742
+average_camera_length = 0.152001 m
+num_peaks = 133
+peak_resolution = 2.914234 nm^-1 or 3.431434 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 38.02 75.98 2.02 589.43 q0a0
+ 86.13 171.97 1.54 2121.50 q0a0
+ 229.72 57.72 2.36 1103.69 q0a1
+ 236.57 78.89 2.28 5367.97 q0a1
+ 305.50 78.96 2.47 1234.74 q0a1
+ 255.50 107.93 2.20 572.96 q0a1
+ 236.10 123.50 2.08 750.45 q0a1
+ 316.79 151.08 2.23 3284.76 q0a1
+ 487.88 24.50 2.28 689.30 q1a0
+ 504.98 40.45 2.22 2307.61 q1a0
+ 458.56 41.28 2.18 4483.75 q1a0
+ 488.86 79.14 2.01 1719.24 q1a0
+ 529.37 92.90 1.99 2192.00 q1a0
+ 418.15 125.50 1.74 1422.96 q1a0
+ 488.91 126.72 1.77 1427.24 q1a0
+ 555.06 140.92 1.81 1063.96 q1a0
+ 552.90 146.83 1.77 165.59 q1a0
+ 610.72 50.84 2.35 1678.25 q1a1
+ 691.30 56.06 2.53 1376.89 q1a1
+ 615.50 83.94 2.21 2687.56 q1a1
+ 615.16 87.14 2.20 3429.76 q1a1
+ 642.84 112.44 2.16 1943.35 q1a1
+ 674.80 118.35 2.23 3491.36 q1a1
+ 611.50 127.98 2.01 1117.38 q1a1
+ 623.73 167.16 1.87 3335.31 q1a1
+ 895.38 19.34 2.31 3616.58 q2a0
+ 934.09 51.30 2.21 3189.08 q2a0
+ 908.81 51.69 2.17 1797.85 q2a0
+ 907.50 116.96 1.85 744.76 q2a0
+ 851.56 147.92 1.62 12091.76 q2a0
+ 880.50 162.20 1.58 883.18 q2a0
+1013.37 37.16 2.44 1629.88 q2a1
+1074.06 61.50 2.49 822.75 q2a1
+1007.87 73.76 2.26 5400.83 q2a1
+1147.23 84.50 2.63 1264.10 q2a1
+1005.74 133.27 2.00 990.15 q2a1
+1085.02 160.45 2.15 6556.96 q2a1
+1292.50 40.08 2.24 796.85 q3a0
+1282.12 116.23 1.85 5076.35 q3a0
+1271.50 149.12 1.67 320.99 q3a0
+1536.84 128.73 2.49 865.54 q3a1
+1471.99 159.48 2.15 2689.24 q3a1
+ 66.73 203.50 1.21 2613.27 q0a2
+ 166.77 211.50 1.37 1986.23 q0a2
+ 169.03 221.69 1.33 1916.79 q0a2
+ 42.50 230.81 1.04 1401.68 q0a2
+ 140.06 241.50 1.15 1276.44 q0a2
+ 96.50 245.21 1.03 2570.80 q0a2
+ 10.50 254.77 0.92 1627.43 q0a2
+ 115.22 262.50 0.99 1035.77 q0a2
+ 84.50 267.78 0.89 2941.86 q0a2
+ 169.75 288.89 1.06 1635.66 q0a2
+ 78.50 329.06 0.57 2908.59 q0a2
+ 139.50 343.02 0.74 801.43 q0a2
+ 86.88 352.50 0.49 653.21 q0a2
+ 327.15 199.30 2.01 1477.01 q0a3
+ 304.13 240.50 1.79 946.40 q0a3
+ 366.19 251.36 2.05 1744.49 q0a3
+ 209.80 261.27 1.33 5696.50 q0a3
+ 209.36 347.53 1.08 7613.80 q0a3
+ 465.74 207.50 1.17 -2401.69 q1a2
+ 469.40 212.13 1.15 4973.34 q1a2
+ 419.65 225.80 1.05 2680.25 q1a2
+ 464.93 241.50 0.99 1171.01 q1a2
+ 419.62 254.12 0.89 10312.32 q1a2
+ 508.66 254.96 1.01 4209.71 q1a2
+ 516.26 255.19 1.03 15439.55 q1a2
+ 565.28 265.89 1.15 1703.15 q1a2
+ 449.50 275.18 0.79 622.81 q1a2
+ 519.26 284.50 0.91 770.80 q1a2
+ 443.50 297.08 0.67 1216.74 q1a2
+ 561.90 306.78 0.99 1363.09 q1a2
+ 425.50 325.94 0.50 3603.70 q1a2
+ 523.13 347.30 0.68 11585.24 q1a2
+ 701.82 204.81 1.92 1178.86 q1a3
+ 743.18 217.50 2.06 720.04 q1a3
+ 736.75 268.22 1.91 731.90 q1a3
+ 718.02 297.50 1.76 755.64 q1a3
+ 694.12 341.03 1.57 5589.04 q1a3
+ 719.93 361.50 1.68 466.97 q1a3
+ 869.50 216.30 1.14 2252.05 q2a2
+ 808.50 224.94 1.04 1106.57 q2a2
+ 901.69 238.94 1.10 8717.39 q2a2
+ 872.82 248.47 0.98 30563.62 q2a2
+ 802.89 249.50 0.90 1165.15 q2a2
+ 886.50 250.35 1.00 2845.84 q2a2
+ 915.21 266.79 1.01 1074.61 q2a2
+ 954.38 298.21 1.04 2231.65 q2a2
+ 949.83 319.50 0.95 1235.12 q2a2
+ 882.50 325.27 0.65 3804.16 q2a2
+ 959.83 327.00 0.98 2560.62 q2a2
+ 818.71 332.50 0.45 2147.49 q2a2
+ 904.50 361.17 0.62 1138.34 q2a2
+1011.33 200.81 1.63 5421.76 q2a3
+1134.77 230.97 2.05 1830.71 q2a3
+1146.87 279.50 2.00 2279.24 q2a3
+1107.26 295.50 1.78 873.31 q2a3
+1015.98 299.02 1.33 1149.54 q2a3
+1043.81 319.80 1.42 2530.38 q2a3
+1212.50 195.72 1.21 3457.08 q3a2
+1178.61 216.35 1.10 14373.03 q3a2
+1267.17 241.19 1.04 1626.95 q3a2
+1260.50 250.08 0.98 1293.00 q3a2
+1262.50 261.97 0.93 763.99 q3a2
+1241.50 263.88 0.88 802.35 q3a2
+1248.05 269.95 0.86 1272.70 q3a2
+1268.39 271.20 0.90 3005.67 q3a2
+1233.98 271.72 0.83 1558.65 q3a2
+1334.50 282.02 1.07 740.88 q3a2
+1296.50 294.07 0.88 1036.48 q3a2
+1211.12 295.50 0.67 2578.42 q3a2
+1283.65 295.98 0.83 3075.23 q3a2
+1322.01 300.63 0.95 1942.02 q3a2
+1288.68 320.36 0.74 5219.61 q3a2
+1184.82 325.51 0.50 12680.62 q3a2
+1255.11 340.41 0.54 15402.43 q3a2
+1261.50 341.02 0.56 -4942.90 q3a2
+1409.89 197.11 1.69 1245.76 q3a3
+1401.15 290.50 1.34 3241.36 q3a3
+1406.15 300.17 1.34 2303.01 q3a3
+ 731.13 622.20 2.77 1286.77 q1a7
+1310.03 798.97 4.11 33.76 q3a8
+ 282.50 1313.92 2.94 1714.09 q0a15
+ 291.36 1443.45 2.33 1293.50 q0a15
+ 495.95 1403.95 2.92 1420.25 q1a14
+ 559.07 1423.32 2.67 1353.62 q1a14
+ 628.11 1409.80 2.56 1325.10 q1a15
+ 591.84 1416.45 2.61 1549.80 q1a15
+ 623.21 1445.90 2.41 1221.23 q1a15
+ 993.11 1471.91 2.35 1919.20 q2a15
+1506.50 1311.92 2.88 1080.18 q3a15
+1421.40 1375.26 2.70 2800.98 q3a15
+1439.65 1453.07 2.31 1625.95 q3a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035147_1bffc.h5
+Image serial number: 68
+hit = 1
+indexed_by = none
+photon_energy_eV = 9507.035792
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998810
+hdf5/LCLS/photon_energy_eV = 9507.035792
+average_camera_length = 0.152001 m
+num_peaks = 45
+peak_resolution = 4.105924 nm^-1 or 2.435505 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 183.98 22.98 2.42 201.39 q0a0
+ 269.05 164.50 2.01 655.16 q0a1
+ 166.11 218.50 1.33 725.80 q0a2
+ 21.93 233.50 1.03 2903.96 q0a2
+ 151.72 277.81 1.03 3277.27 q0a2
+ 130.05 284.16 0.93 2315.11 q0a2
+ 119.97 284.50 0.90 871.59 q0a2
+ 128.50 317.96 0.78 1341.31 q0a2
+ 164.24 321.68 0.92 4634.14 q0a2
+ 144.88 324.32 0.83 2561.71 q0a2
+ 50.50 345.05 0.43 60.69 q0a2
+ 483.01 197.04 1.25 3611.67 q1a2
+ 421.50 209.38 1.14 4752.39 q1a2
+ 417.62 210.23 1.13 3899.11 q1a2
+ 489.50 209.87 1.19 1053.38 q1a2
+ 481.86 225.14 1.10 2307.99 q1a2
+ 459.72 230.50 1.04 1559.86 q1a2
+ 549.50 293.04 0.98 961.35 q1a2
+ 506.71 311.89 0.75 15301.15 q1a2
+ 498.90 320.81 0.68 1608.16 q1a2
+ 445.68 323.87 0.53 5749.97 q1a2
+ 507.13 332.50 0.66 990.10 q1a2
+ 721.17 310.24 1.75 1051.77 q1a3
+ 826.24 222.34 1.05 2483.05 q2a2
+ 846.19 250.75 0.92 2879.49 q2a2
+ 946.19 271.50 1.10 1510.55 q2a2
+ 818.65 328.09 0.47 2008.91 q2a2
+ 894.69 335.80 0.65 1899.60 q2a2
+ 866.01 343.50 0.51 1104.20 q2a2
+ 936.85 351.50 0.80 922.12 q2a2
+1002.56 343.21 1.17 661.66 q2a3
+1276.50 232.92 1.10 892.75 q3a2
+1338.15 246.50 1.22 480.54 q3a2
+1190.29 248.79 0.92 1259.65 q3a2
+1324.50 261.87 1.11 1107.45 q3a2
+1243.58 291.33 0.74 2406.75 q3a2
+1278.50 291.97 0.83 698.62 q3a2
+1301.98 295.50 0.89 1385.35 q3a2
+1289.04 340.50 0.67 1865.85 q3a2
+1347.72 350.50 0.92 1204.14 q3a2
+1374.43 336.18 1.10 4318.15 q3a3
+1129.90 812.10 3.52 493.99 q2a9
+1310.20 799.05 4.11 177.14 q3a8
+ 276.50 1355.12 2.76 892.90 q0a15
+1039.24 1461.45 2.29 3185.10 q2a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035157_1ce87.h5
+Image serial number: 69
+hit = 1
+indexed_by = none
+photon_energy_eV = 9503.502239
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9503.502239
+average_camera_length = 0.152001 m
+num_peaks = 43
+peak_resolution = 4.105060 nm^-1 or 2.436018 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 159.08 8.50 2.45 627.61 q0a0
+ 59.04 172.93 1.52 3123.34 q0a0
+ 362.35 110.96 2.53 3463.69 q0a1
+ 398.50 64.28 2.06 766.99 q1a0
+ 644.02 91.17 2.25 2156.29 q1a1
+1007.32 59.94 2.32 585.57 q2a1
+1060.50 87.01 2.34 1822.65 q2a1
+1125.49 156.63 2.30 4059.75 q2a1
+1296.14 151.50 1.69 1180.09 q3a0
+1440.96 152.88 2.07 2637.99 q3a1
+ 120.50 242.13 1.10 1098.55 q0a2
+ 128.67 259.46 1.04 4505.41 q0a2
+ 103.62 286.06 0.84 6251.96 q0a2
+ 170.85 292.10 1.05 3371.30 q0a2
+ 211.76 281.50 1.27 2387.35 q0a3
+ 238.81 302.90 1.33 1606.55 q0a3
+ 213.76 304.50 1.21 1468.50 q0a3
+ 212.50 320.74 1.16 2551.67 q0a3
+ 449.50 252.15 0.92 403.22 q1a2
+ 560.09 256.91 1.16 301.80 q1a2
+ 507.50 260.03 0.98 999.56 q1a2
+ 426.50 284.03 0.73 436.93 q1a2
+ 405.50 315.13 0.56 1603.44 q1a2
+ 661.50 313.92 1.45 685.07 q1a3
+ 661.33 335.50 1.40 2808.74 q1a3
+ 917.50 201.64 1.31 2505.21 q2a2
+ 880.73 238.82 1.04 1552.21 q2a2
+ 864.08 275.50 0.82 2152.60 q2a2
+ 937.15 287.50 1.00 761.22 q2a2
+ 803.30 305.50 0.59 3197.69 q2a2
+ 883.03 333.50 0.61 1142.51 q2a2
+ 938.20 359.50 0.79 778.64 q2a2
+1022.12 347.50 1.26 3267.50 q2a3
+1319.73 216.83 1.29 757.60 q3a2
+1295.50 246.91 1.08 747.72 q3a2
+1311.18 258.08 1.08 5582.11 q3a2
+1262.50 283.00 0.83 1673.77 q3a2
+1264.04 289.50 0.80 200.88 q3a2
+1310.50 295.11 0.93 1392.70 q3a2
+1292.08 329.50 0.72 2612.24 q3a2
+1375.50 300.06 1.20 862.95 q3a3
+1309.97 799.03 4.11 -12.45 q3a8
+ 351.50 1318.15 2.85 197.61 q0a15
+End of peak list
+----- End chunk -----
+----- Begin chunk -----
+Image filename: r0092-ab/data1/LCLS_2013_Mar22_r0092_035224_1f4f1.h5
+Image serial number: 70
+hit = 1
+indexed_by = none
+photon_energy_eV = 9517.888386
+beam_divergence = 0.00e+00 rad
+beam_bandwidth = 1.00e-08 (fraction)
+hdf5/LCLS/detector0-EncoderValue = -429.998993
+hdf5/LCLS/photon_energy_eV = 9517.888386
+average_camera_length = 0.152001 m
+num_peaks = 62
+peak_resolution = 4.064054 nm^-1 or 2.460597 A
+Peaks from peak search
+ fs/px ss/px (1/d)/nm^-1 Intensity Panel
+ 13.85 23.00 2.29 2955.95 q0a0
+ 141.50 43.67 2.26 987.96 q0a0
+ 153.98 147.98 1.77 1817.54 q0a0
+ 216.56 92.46 2.17 13434.07 q0a1
+ 321.07 160.48 2.21 2847.90 q0a1
+ 568.50 141.12 1.83 1983.66 q1a0
+ 654.50 60.26 2.41 682.36 q1a1
+ 595.71 100.29 2.09 770.89 q1a1
+ 681.31 133.28 2.19 1138.23 q1a1
+ 605.73 139.11 1.94 1501.65 q1a1
+ 723.80 164.53 2.23 1957.82 q1a1
+ 641.86 166.14 1.94 1278.35 q1a1
+ 785.10 70.65 2.01 1540.70 q2a0
+ 800.50 142.20 1.63 629.85 q2a0
+1423.35 139.91 2.07 2636.64 q3a1
+ 41.50 247.85 0.95 -1539.30 q0a2
+ 42.65 253.61 0.92 4316.85 q0a2
+ 138.50 274.70 1.00 2691.52 q0a2
+ 70.50 316.14 0.62 757.88 q0a2
+ 173.88 320.50 0.97 1232.25 q0a2
+ 161.18 358.79 0.80 1004.00 q0a2
+ 307.79 303.50 1.66 1590.00 q0a3
+ 552.50 195.85 1.41 222.96 q1a2
+ 572.27 228.50 1.32 925.24 q1a2
+ 482.70 241.58 1.02 5093.22 q1a2
+ 558.36 243.50 1.21 3818.70 q1a2
+ 425.50 257.84 0.87 1248.90 q1a2
+ 557.62 258.03 1.15 2253.59 q1a2
+ 557.20 287.30 1.03 5015.69 q1a2
+ 572.66 291.78 1.08 2952.04 q1a2
+ 526.93 298.50 0.87 719.36 q1a2
+ 402.50 309.21 0.60 853.38 q1a2
+ 497.50 319.87 0.68 1137.54 q1a2
+ 515.50 332.88 0.70 613.32 q1a2
+ 672.35 261.66 1.63 2129.14 q1a3
+ 649.19 299.21 1.42 1158.65 q1a3
+ 647.50 354.95 1.31 875.89 q1a3
+ 888.50 210.09 1.20 1510.43 q2a2
+ 791.91 231.90 1.00 10315.66 q2a2
+ 922.34 278.56 0.98 7836.84 q2a2
+ 938.17 311.50 0.92 1104.65 q2a2
+ 882.92 336.50 0.60 572.96 q2a2
+ 870.50 348.07 0.51 980.38 q2a2
+ 908.50 360.06 0.64 1203.44 q2a2
+1056.12 339.21 1.45 1141.84 q2a3
+1286.13 211.50 1.23 2376.01 q3a2
+1245.50 223.78 1.10 468.41 q3a2
+1257.50 264.08 0.91 1085.56 q3a2
+1349.62 267.75 1.18 7178.49 q3a2
+1315.39 273.69 1.03 5537.95 q3a2
+1196.50 274.63 0.78 5179.05 q3a2
+1288.00 274.50 0.94 917.81 q3a2
+1307.09 277.50 0.99 1628.50 q3a2
+1312.30 293.50 0.94 881.71 q3a2
+1329.40 333.64 0.88 1048.99 q3a2
+1528.50 948.97 4.06 710.32 q3a11
+ 335.91 1442.77 2.27 2100.58 q0a15
+ 623.34 1444.63 2.42 2424.21 q1a15
+ 928.84 1453.11 2.60 2995.17 q2a14
+1032.21 1406.72 2.56 1462.20 q2a15
+1470.22 1436.82 2.34 4664.50 q3a15
+1524.31 1467.07 2.12 4155.80 q3a15
+End of peak list
+----- End chunk -----
diff --git a/tests/transformation_check.c b/tests/transformation_check.c
index bb835f4d..95b3a7b2 100644
--- a/tests/transformation_check.c
+++ b/tests/transformation_check.c
@@ -26,11 +26,6 @@
*
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
diff --git a/tests/wavelength_geom.c b/tests/wavelength_geom.c
new file mode 100644
index 00000000..8bf86a74
--- /dev/null
+++ b/tests/wavelength_geom.c
@@ -0,0 +1,67 @@
+/*
+ * wavelength_geom.c
+ *
+ * Check that wavelength reading works
+ *
+ * Copyright © 2020 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2020 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <image.h>
+
+int main(int argc, char *argv[])
+{
+ DataTemplate *dtempl;
+ struct image *image;
+ const char *geom_filename;
+ const char *image_filename;
+ double expected_wavelength_m;
+
+ image_filename = argv[1];
+ geom_filename = argv[2];
+ expected_wavelength_m = atof(argv[3]);
+
+ dtempl = data_template_new_from_file(geom_filename);
+ if ( dtempl == NULL ) {
+ ERROR("Failed to load data template\n");
+ return 1;
+ }
+
+ image = image_read(dtempl, image_filename, NULL, 0, 0);
+ if ( image == NULL ) return 1;
+
+ printf("wavelength = %e\n", image->lambda);
+ printf("should be %e\n", expected_wavelength_m);
+
+ if ( !within_tolerance(image->lambda,
+ expected_wavelength_m,
+ 0.1) ) return 1;
+
+ data_template_free(dtempl);
+
+ return 0;
+}
diff --git a/tests/wavelength_geom.h5 b/tests/wavelength_geom.h5
new file mode 100644
index 00000000..f3b37e0f
--- /dev/null
+++ b/tests/wavelength_geom.h5
Binary files differ
diff --git a/tests/wavelength_geom1.geom b/tests/wavelength_geom1.geom
new file mode 100644
index 00000000..91b87385
--- /dev/null
+++ b/tests/wavelength_geom1.geom
@@ -0,0 +1,11 @@
+wavelength = /LCLS/wavelength m
+panel/min_fs = 0
+panel/min_ss = 1
+panel/max_fs = 0
+panel/max_ss = 1
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
diff --git a/tests/wavelength_geom10.geom b/tests/wavelength_geom10.geom
new file mode 100644
index 00000000..a315c458
--- /dev/null
+++ b/tests/wavelength_geom10.geom
@@ -0,0 +1,11 @@
+photon_energy = 9e3 eV
+panel/min_fs = 0
+panel/min_ss = 1
+panel/max_fs = 0
+panel/max_ss = 1
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
diff --git a/tests/wavelength_geom11.geom b/tests/wavelength_geom11.geom
new file mode 100644
index 00000000..676dc68a
--- /dev/null
+++ b/tests/wavelength_geom11.geom
@@ -0,0 +1,11 @@
+wavelength = 1.125 A
+panel/min_fs = 0
+panel/min_ss = 1
+panel/max_fs = 0
+panel/max_ss = 1
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
diff --git a/tests/wavelength_geom12.geom b/tests/wavelength_geom12.geom
new file mode 100644
index 00000000..b47eb243
--- /dev/null
+++ b/tests/wavelength_geom12.geom
@@ -0,0 +1,11 @@
+wavelength = 1.125e-10 m
+panel/min_fs = 0
+panel/min_ss = 1
+panel/max_fs = 0
+panel/max_ss = 1
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
diff --git a/tests/wavelength_geom2.geom b/tests/wavelength_geom2.geom
new file mode 100644
index 00000000..73ef91cc
--- /dev/null
+++ b/tests/wavelength_geom2.geom
@@ -0,0 +1,11 @@
+photon_energy = /LCLS/photon_energy
+panel/min_fs = 0
+panel/min_ss = 1
+panel/max_fs = 0
+panel/max_ss = 1
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
diff --git a/tests/wavelength_geom3.geom b/tests/wavelength_geom3.geom
new file mode 100644
index 00000000..bcd890bd
--- /dev/null
+++ b/tests/wavelength_geom3.geom
@@ -0,0 +1,11 @@
+photon_energy = /LCLS/photon_energyK keV
+panel/min_fs = 0
+panel/min_ss = 1
+panel/max_fs = 0
+panel/max_ss = 1
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
diff --git a/tests/wavelength_geom4.geom b/tests/wavelength_geom4.geom
new file mode 100644
index 00000000..fa03b724
--- /dev/null
+++ b/tests/wavelength_geom4.geom
@@ -0,0 +1,11 @@
+electron_voltage = /LCLS/electron_energy2 kV
+panel/min_fs = 0
+panel/min_ss = 1
+panel/max_fs = 0
+panel/max_ss = 1
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
diff --git a/tests/wavelength_geom5.geom b/tests/wavelength_geom5.geom
new file mode 100644
index 00000000..de26de3b
--- /dev/null
+++ b/tests/wavelength_geom5.geom
@@ -0,0 +1,11 @@
+electron_voltage = /LCLS/electron_energy V
+panel/min_fs = 0
+panel/min_ss = 1
+panel/max_fs = 0
+panel/max_ss = 1
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
diff --git a/tests/wavelength_geom6.geom b/tests/wavelength_geom6.geom
new file mode 100644
index 00000000..9ee5dc87
--- /dev/null
+++ b/tests/wavelength_geom6.geom
@@ -0,0 +1,11 @@
+photon_energy = /LCLS/photon_energy eV
+panel/min_fs = 0
+panel/min_ss = 1
+panel/max_fs = 0
+panel/max_ss = 1
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
diff --git a/tests/wavelength_geom7.geom b/tests/wavelength_geom7.geom
new file mode 100644
index 00000000..a1c311cf
--- /dev/null
+++ b/tests/wavelength_geom7.geom
@@ -0,0 +1,11 @@
+photon_energy = 9000
+panel/min_fs = 0
+panel/min_ss = 1
+panel/max_fs = 0
+panel/max_ss = 1
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
diff --git a/tests/wavelength_geom8.geom b/tests/wavelength_geom8.geom
new file mode 100644
index 00000000..00bdb45a
--- /dev/null
+++ b/tests/wavelength_geom8.geom
@@ -0,0 +1,11 @@
+electron_voltage = 300 kV
+panel/min_fs = 0
+panel/min_ss = 1
+panel/max_fs = 0
+panel/max_ss = 1
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array
diff --git a/tests/wavelength_geom9.geom b/tests/wavelength_geom9.geom
new file mode 100644
index 00000000..9012b5d6
--- /dev/null
+++ b/tests/wavelength_geom9.geom
@@ -0,0 +1,11 @@
+photon_energy = 9 keV
+panel/min_fs = 0
+panel/min_ss = 1
+panel/max_fs = 0
+panel/max_ss = 1
+panel/corner_x = -100
+panel/corner_y = -100
+panel/clen = 50 mm
+panel/res = 1000000
+panel/adu_per_photon = 1
+panel/data = /data/data_array