;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2018 Konrad Hinsen ;;; Copyright © 2018 Kei Kebreau ;;; Copyright © 2018 Efraim Flashner ;;; Copyright © 2018 Tobias Geerinckx-Rice ;;; Copyright © 2020 Björn Höfling ;;; Copyright © 2020 Vincent Legoll ;;; ;;; This file is part of GNU Guix. ;;; ;;; GNU Guix 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. ;;; ;;; GNU Guix 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 GNU Guix. If not, see . (define-module (gnu packages chemistry) #:use-module (guix packages) #:use-module (guix utils) #:use-module ((guix licenses) #:prefix license:) #:use-module (guix download) #:use-module (guix git-download) #:use-module (gnu packages) #:use-module (gnu packages algebra) #:use-module (gnu packages boost) #:use-module (gnu packages check) #:use-module (gnu packages compression) #:use-module (gnu packages documentation) #:use-module (gnu packages gl) #:use-module (gnu packages graphviz) #:use-module (gnu packages gv) #:use-module (gnu packages maths) #:use-module (gnu packages mpi) #:use-module (gnu packages perl) #:use-module (gnu packages pkg-config) #:use-module (gnu packages python) #:use-module (gnu packages python-xyz) #:use-module (gnu packages qt) #:use-module (gnu
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2015 David Thompson <davet@gnu.org>
;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com>
;;; Copyright © 2021 Sarah Morgensen <iskarian@mgsn.dev>
;;; Copyright © 2022 Taiju HIGASHI <higashi@taiju.info>
;;; Copyright © 2023 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix 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.
;;;
;;; GNU Guix 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 GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define-module (test-gem)
  #:use-module (guix import gem)
  #:use-module (guix upstream)
  #:use-module ((guix download) #:select (url-fetch))
  #:use-module ((guix build-system ruby) #:select (rubygems-uri))
  #:use-module (guix base32)
  #:use-module (gcrypt hash)
  #:use-module (guix tests)
  #:use-module ((guix build utils) #:select (delete-file-recursively))
  #:use-module (srfi srfi-64)
  #:use-module (ice-9 match))

(define test-foo-json
  "{
  \"name\": \"foo\",
  \"version\": \"1.0.0\",
  \"sha\": \"f3676eafca9987cb5fe263df1edf2538bf6dafc712b30e17be3543a9680547a8\",
  \"info\": \"A cool gem\",
  \"homepage_uri\": \"https://example.com\",
  \"dependencies\": {
    \"runtime\": [
      { \"name\": \"bundler\" },
      { \"name\": \"bar\" }
    ]
  },
  \"licenses\": [\"MIT\", \"Apache 2.0\"]
}")

(define test-foo-v2-json
  "{
  \"name\": \"foo\",
  \"version\": \"2.0.0\",
  \"sha\": \"f3676eafca9987cb5fe263df1edf2538bf6dafc712b30e17be3543a9680547a8\",
  \"info\": \"A cool gem\",
  \"homepage_uri\": \"https://example.com\",
  \"dependencies\": {
    \"runtime\": [
      { \"name\": \"bundler\" },
      { \"name\": \"bar\" }
    ]
  },
  \"licenses\": [\"MIT\", \"Apache 2.0\"]
}")

(define test-bar-json
  "{
  \"name\": \"bar\",
  \"version\": \"1.0.0\",
  \"sha\": \"f3676eafca9987cb5fe263df1edf2538bf6dafc712b30e17be3543a9680547a8\",
  \"info\": \"Another cool gem\",
  \"homepage_uri\": \"https://example.com\",
  \"dependencies\": {
    \"runtime\": [
      { \"name\": \"bundler\" }
    ]
  },
  \"licenses\": null
}")

(define test-bundler-json
  "{
  \"name\": \"bundler\",
  \"version\": \"1.14.2\",
  \"sha\": \"3bb53e03db0a8008161eb4c816ccd317120d3c415ba6fee6f90bbc7f7eec8690\",
  \"info\": \"Ruby gem bundler\",
  \"homepage_uri\": \"https://bundler.io/\",
  \"dependencies\": {
    \"runtime\": []
  },
  \"licenses\": [\"MIT\"]
}")

(test-begin "gem")

(test-assert "gem->guix-package"
  ;; Replace network resources with sample data.
  (mock ((guix http-client) http-fetch
         (lambda (url . rest)
           (match url
             ("https://rubygems.org/api/v1/gems/foo.json"
              (values (open-input-string test-foo-json)
                      (string-length test-foo-json)))
             (_ (error "Unexpected URL: " url)))))
    (match (gem->guix-package "foo")
      (`(package
          (name "ruby-foo")
          (version "1.0.0")
          (source (origin
                    (method url-fetch)
                    (uri (rubygems-uri "foo" version))
                    (sha256
                     (base32
                      "1a270mlajhrmpqbhxcqjqypnvgrq4pgixpv3w9gwp1wrrapnwrzk"))))
          (build-system ruby-build-system)
          (propagated-inputs (list bundler ruby-bar))
          (synopsis "A cool gem")
          (description "This package provides a cool gem.")
          (home-page "https://example.com")
          (license (list license:expat license:asl2.0)))
       #t)
      (x
       (pk 'fail x #f)))))

(test-assert "gem->guix-package with a specific version"
  ;; Replace network resources with sample data.
  (mock ((guix http-client) http-fetch
         (lambda (url . rest)
           (match url
             ("https://rubygems.org/api/v2/rubygems/foo/versions/2.0.0.json"
              (values (open-input-string test-foo-v2-json)
                      (string-length test-foo-v2-json)))
             (_ (error "Unexpected URL: " url)))))
    (match (gem->guix-package "foo" #:version "2.0.0")
      (`(package
          (name "ruby-foo")
          (version "2.0.0")
          (source (origin
                    (method url-fetch)
                    (uri (rubygems-uri "foo" version))
                    (sha256
                     (base32
                      "1a270mlajhrmpqbhxcqjqypnvgrq4pgixpv3w9gwp1wrrapnwrzk"))))
          (build-system ruby-build-system)
          (propagated-inputs (list bundler ruby-bar))
          (synopsis "A cool gem")
          (description "This package provides a cool gem.")
          (home-page "https://example.com")
          (license (list license:expat license:asl2.0)))
       #t)
      (x
       (pk 'fail x #f)))))

(test-assert "gem-recursive-import"
  ;; Replace network resources with sample data.
  (mock ((guix http-client) http-fetch
         (lambda (url . rest)
           (match url
             ("https://rubygems.org/api/v1/gems/foo.json"
              (values (open-input-string test-foo-json)
                      (string-length test-foo-json)))
             ("https://rubygems.org/api/v1/gems/bar.json"
              (values (open-input-string test-bar-json)
                      (string-length test-bar-json)))
             ("https://rubygems.org/api/v1/gems/bundler.json"
              (values (open-input-string test-bundler-json)
                      (string-length test-bundler-json)))
             (_ (error "Unexpected URL: " url)))))
        (match (gem-recursive-import "foo")
          (`((package
               (name "ruby-bar")
               (version "1.0.0")
               (source
                (origin
                  (method url-fetch)
                  (uri (rubygems-uri "bar" version))
                  (sha256
                   (base32
                    "1a270mlajhrmpqbhxcqjqypnvgrq4pgixpv3w9gwp1wrrapnwrzk"))))
               (build-system ruby-build-system)
               (propagated-inputs (list bundler))
               (synopsis "Another cool gem")
               (description "Another cool gem.")
               (home-page "https://example.com")
               (license #f))                      ;no licensing info
             (package
               (name "ruby-foo")
               (version "1.0.0")
               (source
                (origin
                  (method url-fetch)
                  (uri (rubygems-uri "foo" version))
                  (sha256
                   (base32
                    "1a270mlajhrmpqbhxcqjqypnvgrq4pgixpv3w9gwp1wrrapnwrzk"))))
               (build-system ruby-build-system)
               (propagated-inputs (list bundler ruby-bar))
               (synopsis "A cool gem")
               (description "This package provides a cool gem.")
               (home-page "https://example.com")
               (license (list license:expat license:asl2.0))))
           #t)
          (x
           (pk 'fail x #f)))))

(test-assert "gem-recursive-import with a specific version"
  ;; Replace network resources with sample data.
  (mock ((guix http-client) http-fetch
         (lambda (url . rest)
           (match url
             ("https://rubygems.org/api/v2/rubygems/foo/versions/2.0.0.json"
              (values (open-input-string test-foo-v2-json)
                      (string-length test-foo-v2-json)))
             ("https://rubygems.org/api/v1/gems/bar.json"
              (values (open-input-string test-bar-json)
                      (string-length test-bar-json)))
             ("https://rubygems.org/api/v1/gems/bundler.json"
              (values (open-input-string test-bundler-json)
                      (string-length test-bundler-json)))
             (_ (error "Unexpected URL: " url)))))
        (match (gem-recursive-import "foo" "2.0.0")
          (`((package
               (name "ruby-bar")
               (version "1.0.0")
               (source
                (origin
                  (method url-fetch)
                  (uri (rubygems-uri "bar" version))
                  (sha256
                   (base32
                    "1a270mlajhrmpqbhxcqjqypnvgrq4pgixpv3w9gwp1wrrapnwrzk"))))
               (build-system ruby-build-system)
               (propagated-inputs (list bundler))
               (synopsis "Another cool gem")
               (description "Another cool gem.")
               (home-page "https://example.com")
               (license #f))                      ;no licensing info
             (package
               (name "ruby-foo")
               (version "2.0.0")
               (source
                (origin
                  (method url-fetch)
                  (uri (rubygems-uri "foo" version))
                  (sha256
                   (base32
                    "1a270mlajhrmpqbhxcqjqypnvgrq4pgixpv3w9gwp1wrrapnwrzk"))))
               (build-system ruby-build-system)
               (propagated-inputs (list bundler ruby-bar))
               (synopsis "A cool gem")
               (description "This package provides a cool gem.")
               (home-page "https://example.com")
               (license (list license:expat license:asl2.0))))
           #t)
          (x
           (pk 'fail x #f)))))

(test-equal "package-latest-release"
  (list '("https://rubygems.org/downloads/foo-1.0.0.gem")
        (list (upstream-input
               (name "bundler")
               (downstream-name name)
               (type 'propagated))
              (upstream-input
               (name "bar")
               (downstream-name "ruby-bar")
               (type 'propagated))))
  (mock ((guix http-client) http-fetch
         (lambda (url . rest)
           (match url
             ("https://rubygems.org/api/v1/gems/foo.json"
              (values (open-input-string test-foo-json)
                      (string-length test-foo-json)))
             (_ (error "Unexpected URL: " url)))))
        (let ((source (package-latest-release
                       (dummy-package "ruby-foo"
                                      (version "0.1.2")
                                      (source (dummy-origin
                                               (method url-fetch)
                                               (uri (rubygems-uri "foo"
                                                                  version))))))))
          (list (upstream-source-urls source)
                (upstream-source-inputs source)))))

(test-end "gem")
rce (origin
              (method url-fetch)
              (uri (string-append "http://ftp.gromacs.org/pub/gromacs/gromacs-"
                                  version ".tar.gz"))
              (sha256
               (base32
                "1wyjgcdl30wy4hy6jvi9lkq53bqs9fgfq6fri52dhnb3c76y8rbl"))
              ;; Our version of tinyxml2 is far newer than the bundled one and
              ;; require fixing `testutils' code. See patch header for more info
              (patches (search-patches "gromacs-tinyxml2.patch"))))
    (build-system cmake-build-system)
    (arguments
     `(#:configure-flags
       (list "-DGMX_DEVELOPER_BUILD=on" ; Needed to run tests
             ;; Unbundling
             "-DGMX_USE_LMFIT=EXTERNAL"
             "-DGMX_BUILD_OWN_FFTW=off"
             "-DGMX_EXTERNAL_BLAS=on"
             "-DGMX_EXTERNAL_LAPACK=on"
             "-DGMX_EXTERNAL_TNG=on"
             "-DGMX_EXTERNAL_ZLIB=on"
             "-DGMX_EXTERNAL_TINYXML2=on"
             (string-append "-DTinyXML2_DIR="
                            (assoc-ref %build-inputs "tinyxml2"))
             ;; Workaround for cmake/FindSphinx.cmake version parsing that does
             ;; not understand the guix-wrapped `sphinx-build --version' answer
             (string-append "-DSPHINX_EXECUTABLE_VERSION="
                            ,(package-version python-sphinx)))
       #:phases
       (modify-phases %standard-phases
         (add-after 'unpack 'fixes
           (lambda* (#:key inputs #:allow-other-keys)
             ;; Still bundled: part of gromacs, source behind registration
             ;; but free software anyways
             ;;(delete-file-recursively "src/external/vmd_molfile")
             ;; Still bundled: threads-based OpenMPI-compatible fallback
             ;; designed to be bundled like that
             ;;(delete-file-recursively "src/external/thread_mpi")
             ;; Unbundling
             (delete-file-recursively "src/external/lmfit")
             (delete-file-recursively "src/external/clFFT")
             (delete-file-recursively "src/external/fftpack")
             (delete-file-recursively "src/external/build-fftw")
             (delete-file-recursively "src/external/tng_io")
             (delete-file-recursively "src/external/tinyxml2")
             (delete-file-recursively "src/external/googletest")
             (copy-recursively (assoc-ref inputs "googletest-source")
                               "src/external/googletest")
             ;; This test warns about the build host hardware, disable
             (substitute* "src/gromacs/hardware/tests/hardwaretopology.cpp"
               (("TEST\\(HardwareTopologyTest, HwlocExecute\\)")
                "void __guix_disabled()"))
             #t)))))
    (native-inputs
     `(("doxygen" ,doxygen)
       ("googletest-source" ,(package-source googletest))
       ("graphviz" ,graphviz)
       ("pkg-config" ,pkg-config)
       ("python" ,python)
       ("python-pygments" ,python-pygments)
       ("python-sphinx" ,python-sphinx)))
    (inputs
     `(("fftwf" ,fftwf)
       ("hwloc" ,hwloc-2 "lib")
       ("lmfit" ,lmfit)
       ("openblas" ,openblas)
       ("perl" ,perl)
       ("tinyxml2" ,tinyxml2)
       ("tng" ,tng)))
    (home-page "http://www.gromacs.org/")
    (synopsis "Molecular dynamics software package")
    (description "GROMACS is a versatile package to perform molecular dynamics,
i.e. simulate the Newtonian equations of motion for systems with hundreds to
millions of particles.  It is primarily designed for biochemical molecules like
proteins, lipids and nucleic acids that have a lot of complicated bonded
interactions, but since GROMACS is extremely fast at calculating the nonbonded
interactions (that usually dominate simulations) many groups are also using it
for research on non-biological systems, e.g. polymers.  GROMACS supports all the
usual algorithms you expect from a modern molecular dynamics implementation.")
    (license license:lgpl2.1+)))

(define-public openbabel
  (package
    (name "openbabel")
    (version "2.4.1")
    (source (origin
              (method url-fetch)
              (uri (string-append "mirror://sourceforge/" name "/" name "/"
                                  version "/" name "-" version ".tar.gz"))
              (sha256
               (base32
                "1z3d6xm70dpfikhwdnbzc66j2l49vq105ch041wivrfz5ic3ch90"))
              (patches
               (search-patches "openbabel-fix-crash-on-nwchem-output.patch"))))
    (build-system cmake-build-system)
    (arguments
     `(#:configure-flags
       (list "-DOPENBABEL_USE_SYSTEM_INCHI=ON"
             (string-append "-DINCHI_LIBRARY="
                            (assoc-ref %build-inputs "inchi")
                            "/lib/inchi/libinchi.so.1")
             (string-append "-DINCHI_INCLUDE_DIR="
                            (assoc-ref %build-inputs "inchi") "/include/inchi"))
       #:test-target "test"))
    (native-inputs
     `(("pkg-config" ,pkg-config)))
    (inputs
     `(("eigen" ,eigen)
       ("inchi" ,inchi)
       ("libxml2" ,libxml2)
       ("zlib" ,zlib)))
    (home-page "http://openbabel.org/wiki/Main_Page")
    (synopsis "Chemistry data manipulation toolbox")
    (description
     "Open Babel is a chemical toolbox designed to speak the many languages of
chemical data.  It's a collaborative project allowing anyone to search, convert,
analyze, or store data from molecular modeling, chemistry, solid-state
materials, biochemistry, or related areas.")
    (license license:gpl2)))