diff --git a/pkgs/applications/science/physics/crystfel/0002-fix-ftbfs-with-gcc-10.patch b/pkgs/applications/science/physics/crystfel/0002-fix-ftbfs-with-gcc-10.patch new file mode 100644 index 00000000000..ddd91aec9a6 --- /dev/null +++ b/pkgs/applications/science/physics/crystfel/0002-fix-ftbfs-with-gcc-10.patch @@ -0,0 +1,43 @@ +Description: Fixing argument mismatches in Fortran code, addressing #957430. +Author: Andrius Merkys +Forwarded: ccp4-dev@dl.ac.uk +--- a/fortran/pack_f.f ++++ b/fortran/pack_f.f +@@ -106,7 +106,7 @@ + endif + 10 continue + filnarray(len(filn) + 1) = 0 +- call pack_wordimage_f(data, x, y, filnarray) ++ call pack_longimage_f(data, x, y, filnarray) + return + end + +@@ -138,7 +138,7 @@ + endif + 10 continue + filnarray(len(filn) + 1) = 0 +- call v2pack_wordimage_f(data, x, y, filnarray) ++ call v2pack_longimage_f(data, x, y, filnarray) + return + end + +--- a/fortran/lgglib.f ++++ b/fortran/lgglib.f +@@ -1236,7 +1236,7 @@ + B3(2) = XYZ(2) * CELL(2) + B3(3) = XYZ(3) * CELL(3) + C +- CALL matmult(3,3,3,1,ORTH,B3,XYZ,B1) ++ CALL matmult(3,3,3,1,ORTH,B3,XYZ) + END + c + c +@@ -1274,7 +1274,7 @@ + B3(1) = XYZ(1) + B3(2) = XYZ(2) + B3(3) = XYZ(3) +- CALL matmult(3,3,3,1,ORTH,B3,XYZ,B1) ++ CALL matmult(3,3,3,1,ORTH,B3,XYZ) + END + character*80 function getnam(filnam) + character*(*) filnam diff --git a/pkgs/applications/science/physics/crystfel/default.nix b/pkgs/applications/science/physics/crystfel/default.nix new file mode 100644 index 00000000000..85b18eb82fd --- /dev/null +++ b/pkgs/applications/science/physics/crystfel/default.nix @@ -0,0 +1,226 @@ +{ lib +, stdenv +, fetchurl +, fetchFromGitHub +, cmake +, lz4 +, bzip2 +, gfortran +, m4 +, hdf5 +, gsl +, slurm +, unzip +, makeWrapper +, meson +, git +, ninja +, eigen +, pkg-config +, wrapGAppsHook +, flex +, bison +, doxygen +, opencl-headers +, ncurses +, msgpack +, fftw +, zeromq +, ocl-icd +, gtk3 +, gdk-pixbuf +, argp-standalone +, memorymappingHook +, withGui ? true +, withBitshuffle ? true +}: + +let + libccp4 = stdenv.mkDerivation rec { + pname = "libccp4"; + version = "6.5.1"; + src = fetchurl { + # Original mirror, now times out + # url = "ftp://ftp.ccp4.ac.uk/opensource/${pname}-${version}.tar.gz"; + url = "https://deb.debian.org/debian/pool/main/libc/${pname}/${pname}_${version}.orig.tar.gz"; + sha256 = "1rfvjliny29vy5bdi6rrjaw9hhhhh72pw536xwvqipqcjlylf2r8"; + }; + nativeBuildInputs = [ gfortran m4 ]; + buildInputs = [ hdf5 gsl ]; + + configureFlags = [ "FFLAGS=-fallow-argument-mismatch" ]; + + # libccp4 tries to read syminfo.lib by looking at an environment variable, which hinders reproducibility. + # We hard-code this by providing a little patch and then passing the absolute path to syminfo.lib as a + # preprocessor flag. + preBuild = '' + makeFlagsArray+=(CFLAGS='-DNIX_PROVIDED_SYMOP_FILE=\"$out/share/syminfo.lib\"') + export NIX_LDFLAGS="-L${gfortran.cc}/lib64 -L${gfortran.cc}/lib $NIX_LDFLAGS"; + ''; + makeFlags = [ "CFLAGS='-DNIX_PROVIDED_SYMOP_FILE=\"${placeholder "out"}/share/syminfo.lib\"" ]; + + patches = [ + ./libccp4-use-hardcoded-syminfo-lib.patch + ./0002-fix-ftbfs-with-gcc-10.patch + ]; + }; + # This is the statically-linked, pre-built binary of mosflm. Compiling it ourselves turns out to be very difficult + # since the build process is very hard-coded for a specific machine, architecture, and libraries. + mosflm = + let + version = "7.4.0"; + src = + if stdenv.isDarwin then + fetchurl + { + url = "https://www.mrc-lmb.cam.ac.uk/mosflm/mosflm/ver${builtins.replaceStrings [ "." ] [ "" ] version}/pre-built/mosflm-osx-64-noX11.zip"; + sha256 = "1da5wimv3kl8bccp49j69vh8gi28cn7axg59lrmb38s68c618h7j"; + } + else + fetchurl { + url = "https://www.mrc-lmb.cam.ac.uk/mosflm/mosflm/ver${builtins.replaceStrings [ "." ] [ "" ] version}/pre-built/mosflm-linux-64-noX11.zip"; + sha256 = "1rqh3nprxfmnyihllw31nb8i3wfhybmsic6y7z6wn4rafyv3w4fk"; + }; + mosflmBinary = if stdenv.isDarwin then "bin/mosflm" else "mosflm-linux-64-noX11"; + in + stdenv.mkDerivation rec { + pname = "mosflm"; + + inherit version src; + + dontBuild = true; + + nativeBuildInputs = [ unzip makeWrapper ]; + + sourceRoot = "."; + + # mosflm statically links against its own libccp4, which as the syminfo.lib environment variable problem. + # Here, we circumvent it by creating a little wrapper script that calls mosflm after setting the SYMINFO variable. + installPhase = '' + mkdir -p $out/bin + cp ${mosflmBinary} $out/bin/mosflm-raw + makeWrapper $out/bin/mosflm-raw $out/bin/mosflm --set SYMINFO ${libccp4}/share/syminfo.lib --add-flags -n + ''; + }; + + xgandalf = stdenv.mkDerivation rec { + pname = "xgandalf"; + version = "c15afa2381d5f87d4aefcc8181a15b4a6fd3a955"; + src = fetchurl { + url = "https://gitlab.desy.de/thomas.white/${pname}/-/archive/${version}/${pname}-${version}.tar.gz"; + sha256 = "11i1w57a3rpnb4x5y4n8d3iffn5m9w1zydl69syzljdk3aqg2pv8"; + }; + + nativeBuildInputs = [ meson pkg-config ninja ]; + buildInputs = [ eigen ]; + }; + + pinkIndexer = stdenv.mkDerivation rec { + pname = "pinkindexer"; + version = "8a828788f8272a89d484b00afbd2500c2c1ff974"; + src = fetchurl { + url = "https://gitlab.desy.de/thomas.white/${pname}/-/archive/${version}/${pname}-${version}.tar.gz"; + sha256 = "1mkgf1xd91ay0z0632kzxm0z3wcxf0cayjvs6a3znds72dkhfsyh"; + }; + + nativeBuildInputs = [ meson pkg-config ninja ]; + buildInputs = [ eigen ]; + }; + + fdip = stdenv.mkDerivation rec { + pname = "fdip"; + version = "29da626f17f66d5c0780fc59b1eafb7c85b81dd6"; + src = fetchurl { + url = "https://gitlab.desy.de/philipp.middendorf/fdip/-/archive/${version}/fdip-${version}.tar.gz"; + sha256 = "184l76r4fgznq54rnhgjk7dg41kqdl0d1da02vr5y4cs2fyqppky"; + }; + + nativeBuildInputs = [ meson ninja pkg-config ]; + buildInputs = [ eigen ]; + }; + + hdf5-external-filter-plugins = stdenv.mkDerivation rec { + pname = "HDF5-External-Filter-Plugins"; + version = "0.1.0"; + src = fetchFromGitHub { + owner = "nexusformat"; + repo = pname; + rev = "d469f175e5273c1d488e71a6134f84088f57d39c"; + sha256 = "1jrzzh75i68ad1yrim7s1nx9wy0s49ghkziahs71mm5azprm6gh9"; + }; + + nativeBuildInputs = [ cmake ]; + buildInputs = [ hdf5 lz4 bzip2 ]; + + cmakeFlags = [ + "-DENABLE_BITSHUFFLE_PLUGIN=yes" + "-DENABLE_LZ4_PLUGIN=yes" + "-DENABLE_BZIP2_PLUGIN=yes" + ]; + }; +in +stdenv.mkDerivation rec { + pname = "crystfel"; + version = "0.10.1"; + src = fetchurl { + url = "https://www.desy.de/~twhite/${pname}/${pname}-${version}.tar.gz"; + sha256 = "0i9d5ggalic7alj97dxjdys7010kxhm2cb4lwakvigl023j8ms79"; + }; + nativeBuildInputs = [ meson pkg-config ninja flex bison doxygen opencl-headers ] + ++ lib.optionals withGui [ wrapGAppsHook ]; + buildInputs = [ + hdf5 + gsl + ncurses + msgpack + fftw + fdip + zeromq + ocl-icd + libccp4 + mosflm + pinkIndexer + xgandalf + ] ++ lib.optionals withGui [ gtk3 gdk-pixbuf ] + ++ lib.optionals stdenv.isDarwin [ + argp-standalone + memorymappingHook + ] + # slurm is not available for Darwin; when it is, remove the condition + ++ lib.optionals (!stdenv.isDarwin) [ slurm ] + # hdf5-external-filter-plugins doesn't link on Darwin + ++ lib.optionals (withBitshuffle && !stdenv.isDarwin) [ hdf5-external-filter-plugins ]; + + patches = [ ./link-to-argp-standalone-if-needed.patch ]; + + # CrystFEL calls mosflm by searching PATH for it. We could've create a wrapper script that sets the PATH, but + # we'd have to do that for every CrystFEL executable (indexamajig, crystfel, partialator). Better to just + # hard-code mosflm's path once. + postPatch = '' + sed -i -e 's#execlp("mosflm"#execl("${mosflm}/bin/mosflm"#' libcrystfel/src/indexers/mosflm.c; + ''; + + postInstall = lib.optionalString (withBitshuffle && !stdenv.isDarwin) '' + for file in $out/bin/*; do + wrapProgram $file --set HDF5_PLUGIN_PATH ${hdf5-external-filter-plugins}/lib/plugins + done + ''; + + meta = with lib; { + description = "Data processing for serial crystallography"; + longDescription = '' + 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.''; + homepage = "https://www.desy.de/~twhite/crystfel/"; + changelog = "https://www.desy.de/~twhite/crystfel/changes.html"; + downloadPage = "https://www.desy.de/~twhite/crystfel/download.html"; + license = licenses.gpl3Plus; + maintainers = with maintainers; [ pmiddend ]; + platforms = [ "x86_64-linux" "x86_64-darwin" ]; + }; + +} diff --git a/pkgs/applications/science/physics/crystfel/libccp4-use-hardcoded-syminfo-lib.patch b/pkgs/applications/science/physics/crystfel/libccp4-use-hardcoded-syminfo-lib.patch new file mode 100644 index 00000000000..9c5e1365492 --- /dev/null +++ b/pkgs/applications/science/physics/crystfel/libccp4-use-hardcoded-syminfo-lib.patch @@ -0,0 +1,30 @@ +diff --git a/ccp4/csymlib.c b/ccp4/csymlib.c +index 76bc70b..7a0c5dc 100644 +--- a/ccp4/csymlib.c ++++ b/ccp4/csymlib.c +@@ -137,24 +137,7 @@ CCP4SPG *ccp4spg_load_spacegroup(const int numspg, const int ccp4numspg, + } + + /* Open the symop file: */ +- if (!(symopfile = getenv("SYMINFO"))) { +- if (debug) +- printf("Environment variable SYMINFO not set ... guessing location of symmetry file. \n"); +- if (!(ccp4dir = getenv("CLIBD"))) { +- printf("Environment variable CLIBD not set ... big trouble! \n"); +- return NULL; +- } +- +- symopfile = ccp4_utils_malloc((strlen(ccp4dir)+22)*sizeof(char)); +- strcpy(symopfile,ccp4_utils_joinfilenames(ccp4dir,"syminfo.lib")); +- symopfile[strlen(ccp4dir)+21] = '\0'; +- ccp4printf(1," SYMINFO file set to %s \n",symopfile); +- } else { +- if (debug) { +- ccp4printf(1,"\n Spacegroup information obtained from library file: \n"); +- ccp4printf(1," Logical Name: SYMINFO Filename: %s\n\n",symopfile); +- } +- } ++ symopfile = NIX_PROVIDED_SYMOP_FILE; + + filein = fopen(symopfile,"r"); + if (!filein) { diff --git a/pkgs/applications/science/physics/crystfel/link-to-argp-standalone-if-needed.patch b/pkgs/applications/science/physics/crystfel/link-to-argp-standalone-if-needed.patch new file mode 100644 index 00000000000..707ecafde8b --- /dev/null +++ b/pkgs/applications/science/physics/crystfel/link-to-argp-standalone-if-needed.patch @@ -0,0 +1,26 @@ +diff --git a/meson.build b/meson.build +index efc9002b..070f37e4 100644 +--- a/meson.build ++++ b/meson.build +@@ -34,6 +34,12 @@ if slurmdep.found() + conf_data.set10('HAVE_SLURM', 1) + endif + ++if build_machine.system() == 'darwin' or build_machine.system() == 'freebsd' or not cc.links('#include \nstatic error_t parse_opt (int key, char *arg, struct argp_state *state) { argp_usage(state); return 0; }; void main() {}') ++ argpdep = cc.find_library('argp') ++else ++ argpdep = dependency('', required : false) ++endif ++ + # Find HDF5 using inbuilt Meson methods. Requires Meson >= 0.50.0 + hdf5dep = dependency('hdf5', language: 'c', required: true) + +@@ -180,7 +186,7 @@ if zmqdep.found() + endif + + executable('indexamajig', indexamajig_sources, +- dependencies: [mdep, libcrystfeldep, gsldep, pthreaddep, zmqdep], ++ dependencies: [mdep, libcrystfeldep, gsldep, pthreaddep, zmqdep, argpdep], + install: true, + install_rpath: '$ORIGIN/../lib64/:$ORIGIN/../lib') + diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 80bc32f334b..e8692211c7b 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -1910,6 +1910,10 @@ with pkgs; checkip = callPackage ../tools/networking/checkip { }; + crystfel = callPackage ../applications/science/physics/crystfel { }; + + crystfel-headless = callPackage ../applications/science/physics/crystfel { withGui = false; }; + ec2-api-tools = callPackage ../tools/virtualization/ec2-api-tools { }; ec2-ami-tools = callPackage ../tools/virtualization/ec2-ami-tools { };