From 0c4ae2d4d1abc616dd45cd057fde83b5d20391bf Mon Sep 17 00:00:00 2001 From: Sandro Dias Pinto Vitenti Date: Tue, 6 Feb 2024 16:55:36 -0300 Subject: [PATCH] Improved numcosmo connector (#369) - Removed unnecessary models and NumCosmo run scripts - Introduced new NumCosmo app (0.21.1) with required features - Updated example to remove deprecated variable usage - Removed unused variables from example values.ini - Updated NumCosmo connector to utilize new facilities (0.21.0) for serialization - Updated example ini to use proper Cosmosis configuration - Reorganized examples testing in CI - Added power spectra to NumCosmo conversions - Moved conversion functions to NamedParameters, added unit tests - Updated unit tests for new NumCosmo connector - Conducted more testing for next connector helper functions - Inverted conversion order since bool is int - Tested set/get in NumCosmo likelihoods - Tested empty NumCosmo data objects - Employed cleaner parametrization (omega_b, omega_c) instead of (omega_m, omega_c) - Created new NumCosmo cookbook - Resolved tabs issue in codecov.yml, changed tabs to spaces, removed comments, and linked to documentation - Upgraded codecov-action to v4, added flag to fail CI if upload fails We are passsing this review even though Coveralls is complaining because the changed lines have 100% test coverage, as verified by CodeCov. --- .github/workflows/ci.yml | 64 +++-- codecov.yml | 51 +--- docs/environment.yml | 2 +- docs/index.rst | 9 +- docs/numcosmo_bestfit.rst | 81 ++++++ docs/numcosmo_cookbook.rst | 16 ++ docs/numcosmo_fisher.rst | 110 ++++++++ docs/numcosmo_fisher_bias.rst | 57 ++++ environment.yml | 2 +- .../cluster_richness_values.ini | 3 +- examples/cosmicshear/cosmicshear.ini | 2 +- examples/cosmicshear/cosmicshear_values.ini | 3 +- .../des_y1_3x2pt/des_y1_3x2pt_PT_values.ini | 25 +- examples/des_y1_3x2pt/des_y1_3x2pt_values.ini | 4 +- .../des_y1_3x2pt/numcosmo_firecrown_model.yml | 194 ------------- .../numcosmo_firecrown_model_PT.yml | 86 ------ examples/des_y1_3x2pt/numcosmo_run.py | 231 ---------------- examples/des_y1_3x2pt/numcosmo_run_PT.py | 89 ------ .../srd_sn/numcosmo_firecrown_model_snia.yml | 14 - examples/srd_sn/numcosmo_run.py | 118 -------- examples/srd_sn/sn_only.ini | 3 +- examples/srd_sn/sn_srd_values.ini | 3 +- examples/srd_sn/snonly_values.ini | 3 +- firecrown/connector/numcosmo/model.py | 122 --------- firecrown/connector/numcosmo/numcosmo.py | 211 ++++++++++---- firecrown/likelihood/likelihood.py | 60 +++- tests/connector/numcosmo/conftest.py | 63 ++--- .../numcosmo/test_numcosmo_connector.py | 257 ++++++++++++++++-- .../numcosmo/test_numcosmo_mapping.py | 94 ++++--- .../connector/numcosmo/test_numcosmo_model.py | 57 ---- tests/likelihood/test_named_parameters.py | 205 ++++++++++++++ 31 files changed, 1078 insertions(+), 1161 deletions(-) create mode 100644 docs/numcosmo_bestfit.rst create mode 100644 docs/numcosmo_cookbook.rst create mode 100644 docs/numcosmo_fisher.rst create mode 100644 docs/numcosmo_fisher_bias.rst delete mode 100644 examples/des_y1_3x2pt/numcosmo_firecrown_model.yml delete mode 100644 examples/des_y1_3x2pt/numcosmo_firecrown_model_PT.yml delete mode 100755 examples/des_y1_3x2pt/numcosmo_run.py delete mode 100755 examples/des_y1_3x2pt/numcosmo_run_PT.py delete mode 100644 examples/srd_sn/numcosmo_firecrown_model_snia.yml delete mode 100755 examples/srd_sn/numcosmo_run.py delete mode 100644 firecrown/connector/numcosmo/model.py delete mode 100644 tests/connector/numcosmo/test_numcosmo_model.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5998ae733..56e087763 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -86,9 +86,9 @@ jobs: - name: Running mypy shell: bash -l {0} run: | - mypy -p firecrown -vv - mypy -p examples -vv - mypy -p tests -vv + mypy -p firecrown + mypy -p examples + mypy -p tests - name: Running pylint shell: bash -l {0} run: | @@ -98,64 +98,76 @@ jobs: - name: Running pytest shell: bash -l {0} run: python -m pytest -vv --runslow --cov firecrown --cov-report xml - - name: Running example - cosmosis - cosmic-shear + - name: Running example - cosmic-shear - cosmosis shell: bash -l {0} run: | cd examples/cosmicshear python generate_cosmicshear_data.py cosmosis cosmicshear.ini - - name: Running example - cosmosis - des-y1-3x2pt + - name: Running example - cosmic-shear - NumCosmo shell: bash -l {0} run: | - cd examples/des_y1_3x2pt - cosmosis des_y1_3x2pt.ini - - name: Running example - cosmosis - des-y1-3x2pt-PT + cd examples/cosmicshear + numcosmo from-cosmosis cosmicshear.ini --matter-ps eisenstein_hu --nonlin-matter-ps halofit + numcosmo run test cosmicshear.yaml + - name: Running example - des-y1-3x2pt - cosmosis shell: bash -l {0} run: | cd examples/des_y1_3x2pt + cosmosis des_y1_3x2pt.ini cosmosis des_y1_3x2pt_PT.ini - - name: Running example - cobaya - des-y1-3x2pt + - name: Running example - des-y1-3x2pt - cobaya shell: bash -l {0} run: | cd examples/des_y1_3x2pt cobaya-run cobaya_evaluate.yaml - - name: Running example - cobaya - des-y1-3x2pt-PT - shell: bash -l {0} - run: | - cd examples/des_y1_3x2pt cobaya-run cobaya_evaluate_PT.yaml - - name: Running example - NumCosmo - des-y1-3x2pt + - name: Running example - des-y1-3x2pt - NumCosmo shell: bash -l {0} run: | cd examples/des_y1_3x2pt - python numcosmo_run.py - - name: Running example - NumCosmo - des-y1-3x2pt-PT - shell: bash -l {0} - run: | - cd examples/des_y1_3x2pt - python numcosmo_run_PT.py - - name: Running example - cosmosis - srd_sn + numcosmo from-cosmosis des_y1_3x2pt.ini --matter-ps eisenstein_hu --nonlin-matter-ps halofit + numcosmo run test des_y1_3x2pt.yaml + numcosmo from-cosmosis des_y1_3x2pt_PT.ini --matter-ps eisenstein_hu --nonlin-matter-ps halofit + numcosmo run test des_y1_3x2pt_PT.yaml + - name: Running example - srd_sn - cosmosis shell: bash -l {0} run: | cd examples/srd_sn cosmosis sn_srd.ini - - name: Running example - NumCosmo - srd_sn + cosmosis sn_only.ini + - name: Running example - srd_sn - NumCosmo shell: bash -l {0} run: | cd examples/srd_sn - python numcosmo_run.py - - name: Running example - cosmosis - cluster_number_counts + numcosmo from-cosmosis sn_srd.ini + numcosmo run test sn_srd.yaml + numcosmo from-cosmosis sn_only.ini + numcosmo run test sn_only.yaml + - name: Running example - cluster_number_counts - cosmosis shell: bash -l {0} - run: | + run: | cd examples/cluster_number_counts python generate_rich_mean_mass_sacc_data.py cosmosis cluster_counts_redshift_richness.ini cosmosis cluster_mean_mass_redshift_richness.ini cosmosis cluster_counts_mean_mass_redshift_richness.ini + - name: Running example - cluster_number_counts - NumCosmo + shell: bash -l {0} + run: | + cd examples/cluster_number_counts + numcosmo from-cosmosis cluster_counts_redshift_richness.ini --matter-ps eisenstein_hu + numcosmo run test cluster_counts_redshift_richness.yaml + numcosmo from-cosmosis cluster_mean_mass_redshift_richness.ini --matter-ps eisenstein_hu + numcosmo run test cluster_mean_mass_redshift_richness.yaml + numcosmo from-cosmosis cluster_counts_mean_mass_redshift_richness.ini --matter-ps eisenstein_hu + numcosmo run test cluster_counts_mean_mass_redshift_richness.yaml - name: Upload coverage reports to Codecov if: ${{ (matrix.os == 'ubuntu') && (matrix.python-version == '3.11') }} - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 + with: + fail_ci_if_error: true env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/codecov.yml b/codecov.yml index c02ea7cc7..ccd651182 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,67 +1,38 @@ -# comment: false +# See https://docs.codecov.com/docs/codecovyml-reference for config reference +# To validate: `curl -X POST --data-binary @codecov.yml https://codecov.io/validate` + comment: layout: "diff, flags, files" behavior: default - # if true: only post the comment if coverage changes require_changes: false - - # [true :: must have a base report to post] require_base: false - - # [true :: must have a head report to post] require_head: true - - # [true :: only show coverage on the git diff] hide_project_coverage: false coverage: - - # What precision do you want the coverage value to be precision: 1 - # Which direction to you want to round the coverage value round: down - # The value range where you want the value to be green - range: 95..100 + # red below 70, yellow between 70 and 95, green above 95. + range: 70..95 status: - # The codecov/patch status only measures lines adjusted - # in the pull request or single commit, if the commit is - # not in a pull request. This status provides an indication - # on how well the pull request is tested. patch: default: - # basic target: 100% threshold: 0% - - # advanced - branches: - - master - if_ci_failed: error #success, failure, error, ignore + branches: [master] + if_ci_failed: error only_pulls: false - # The codecov/project status measures overall project - # coverage and compares it against the base of the pull - # request or parent commit. project: default: - # auto will use the coverage from the base commit - # (pull request base or parent commit) coverage to - # compare against. target: auto - # Allow the coverage to drop by X%, and posting a success status threshold: 0% - - # advanced settings - branches: - - master - if_ci_failed: error #success, failure, error, ignore + branches: [master] + if_ci_failed: error only_pulls: false - # These behaviors allows users to specify what should happen - # to the project status in case changes causes overall coverage - # to drop, but are part of good development practices. - removed_code_behavior: fully_covered_patch #off, removals_only, adjust_base", + removed_code_behavior: fully_covered_patch github_checks: - annotations: true #,false + annotations: true diff --git a/docs/environment.yml b/docs/environment.yml index 6f9abfbbe..b34789cb1 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -10,7 +10,7 @@ dependencies: - flake8 - jupyter - mypy - - numcosmo>=0.18.2 + - numcosmo>=0.21.1 - numpy>=1.21.0 - plantuml - pip>=20.1 # pip is needed as dependency diff --git a/docs/index.rst b/docs/index.rst index a2c5d7e60..23ffaafaf 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -28,8 +28,6 @@ It can also be used as a library in other contexts, and so the installation of F Installation Quickstart Using Firecrown - - .. toctree:: :maxdepth: 1 :caption: Developing with Firecrown @@ -39,6 +37,13 @@ It can also be used as a library in other contexts, and so the installation of F Developer Notes Contributing +.. toctree:: + :maxdepth: 2 + :caption: Cookbook + :name: cookbook + + NumCosmo + .. toctree:: :maxdepth: 1 :caption: Reference diff --git a/docs/numcosmo_bestfit.rst b/docs/numcosmo_bestfit.rst new file mode 100644 index 000000000..9fc9899f1 --- /dev/null +++ b/docs/numcosmo_bestfit.rst @@ -0,0 +1,81 @@ +======================================= +NumCosmo: Firecrown Likelihood Best Fit +======================================= + +This recipe outlines the process to compute the best fit for Supernova SNIa data using +the Firecrown example with NumCosmo. Ensure that you have already installed +Firecrown, CosmoSIS, and NumCosmo and set the environment variable ``FIRECROWN_DIR`` +to the location of the Firecrown installation. + +.. _convert-configuration-file-sn-srd: + +Convert Configuration File +========================== + +Use the NumCosmo command-line tool to convert the ``sn_srd.ini`` file into a NumCosmo +configuration in a ``yaml`` file. Since this likelihood does not require a +power-spectrum likelihood, you can use the ``from-cosmosis`` command without any extra +flags `--matter-ps eisenstein_hu` nor `--nonlin-matter-ps halofit`. To mute the output +of the consistency cosmosis module, use ``--mute-cosmosis``. + +.. code-block:: bash + + cd $FIRECROWN_DIR/examples/srd_sn + numcosmo from-cosmosis sn_srd.ini --mute-cosmosis + +This command creates a file called ``sn_srd.yaml``, NumCosmo's experiment file. It +contains cosmological and likelihood parameters, modeling choices, and chosen precision. + +.. _compute-bestfit-sn-srd: + +Run NumCosmo App +================ + +Execute the NumCosmo app with the experiment file to compute the best fit. The +following command saves the output in a new ``yaml`` file. Use the ``--help`` flag for +available options. + +.. code-block:: bash + + cd $FIRECROWN_DIR/examples/srd_sn + numcosmo run fit sn_srd.yaml --output sn_srd-bestfit.yaml + +The best fit is saved in ``sn_srd-bestfit.yaml``. Inspect the file to view the +best-fitting values. This file serves as the starting point for subsequent runs. + +Restart Minimization Algorithm (Optional) +========================================= + +If dealing with a high-dimensional parameter space or non-converging algorithms, +consider using the `--restart` flag. This restarts the minimization algorithm from the +best-fit found so far. + +.. code-block:: bash + + cd $FIRECROWN_DIR/examples/srd_sn + numcosmo run fit sn_srd.yaml --output sn_srd-bestfit.yaml --starting-point sn_srd-bestfit.yaml --restart 1.0e-3 0.0 + +The command restarts the minimization algorithm if the absolute change in the +likelihood is less than 1.0e-3 and the relative change is less than 0.0. + +Note: ``sn_srd-bestfit.yaml`` cannot be used as the experiment file for the +``numcosmo`` command-line tool since it lacks data and model information. + +Results Summary +=============== + +* **Starting Point:** + + * m2lnL: 1215 + * Parameters: + + * sn_ddf_sample_M: -19.30 + * Omegac: 0.260 + +* **Best Fit:** + + * m2lnL: 1.70934 + * Parameters: + + * sn_ddf_sample_M: -19.426 + * Omegac: 0.265 diff --git a/docs/numcosmo_cookbook.rst b/docs/numcosmo_cookbook.rst new file mode 100644 index 000000000..fa57c1538 --- /dev/null +++ b/docs/numcosmo_cookbook.rst @@ -0,0 +1,16 @@ +================================================= +Cookbook using NumCosmo +================================================= + +Recipes for using Firecrown through the NumCosmo connector for cosmological analyses. + +.. toctree:: + :maxdepth: 2 + :caption: NumCosmo Cookbook + :name: numcosmo_cookbook + + Computing Best-Fit + Computing Fisher Matrix + Computing Fisher Bias + + \ No newline at end of file diff --git a/docs/numcosmo_fisher.rst b/docs/numcosmo_fisher.rst new file mode 100644 index 000000000..8ee836d19 --- /dev/null +++ b/docs/numcosmo_fisher.rst @@ -0,0 +1,110 @@ +===================================== +NumCosmo: Firecrown Likelihood Fisher +===================================== + +This recipe outlines the process of computing the Fisher matrix for Supernova SNIa data +likelihood using the Firecrown example with NumCosmo. Ensure that you have already +installed Firecrown, CosmoSIS, and NumCosmo and set the environment variable +``FIRECROWN_DIR`` to the location of the Firecrown installation. + +The starting point for this recipe is the NumCosmo experiment configuration file +``sn_srd.yaml``. In section :ref:`convert-configuration-file-sn-srd`, we show how to +convert this file to a Firecrown configuration file. The steps below assume that you +have already converted the configuration file. + +Computing the Fisher Matrix +=========================== + +The next step is to compute the Fisher matrix using NumCosmo's command line tool. There +are two options for the command ``numcosmo run fisher`` that can be used to compute the +Fisher matrix: + +Expected Fisher Matrix +---------------------- + +This option computes the Fisher matrix using the analytic formula for the expected +Fisher matrix. This requires a Gaussian or Poisson likelihood. The command to compute +the Fisher matrix is: + +.. code-block:: bash + + cd $FIRECROWN_DIR/examples/srd_sn + numcosmo run fisher sn_srd.yaml --fisher-type expected + +This command produces the output: + +.. code-block:: text + + # NcmMSet parameters covariance matrix + # ------------------------------- + # sn_ddf_sample_M[00000:00] = -19.3 +/- 0.01389 | 1 | 0.9626 | + # Omegac[04000:01] = 0.26 +/- 0.01315 | 0.9626 | 1 | + # ------------------------------- + +When possible, the expected Fisher matrix is the preferred option as it is faster, more +accurate, and can be computed at any point in the parameter space. + +Observed Fisher Matrix +---------------------- + +This option computes the Fisher matrix using the observed Fisher matrix. This option +computes an estimate of the Fisher matrix using the observed data. It computes the +Hessian of the likelihood and therefore should be computed at the maximum likelihood +point. The command to compute the Fisher matrix is: + +.. code-block:: bash + + cd $FIRECROWN_DIR/examples/srd_sn + numcosmo run fisher sn_srd.yaml --fisher-type observed + +This command produces the output: + +.. code-block:: text + + # ------------------------------- + # sn_ddf_sample_M[00000:00] = -19.3 +/- 0.008047 | 1 | 0.8837 | + # Omegac[04000:01] = 0.26 +/- 0.006992 | 0.8837 | 1 | + # ------------------------------- + +The observed Fisher matrix is less accurate and slower to compute than the expected +Fisher matrix. The output above shows that the observed Fisher matrix does not agree +with the expected Fisher matrix. This is because the observed Fisher matrix is an +estimate that needs to be computed at the maximum likelihood point. + +Running the command again but now using the previously computed maximum likelihood +point as the starting point (:ref:`compute-bestfit-sn-srd`): + +.. code-block:: bash + + numcosmo run fisher sn_srd.yaml --fisher-type observed --starting-point sn_srd-bestfit.yaml + +Resulting in the output: + +.. code-block:: text + + # ------------------------------- + # sn_ddf_sample_M[00000:00] = -19.43 +/- 0.01396 | 1 | 0.9629 | + # Omegac[04000:01] = 0.2654 +/- 0.01332 | 0.9629 | 1 | + # ------------------------------- + +The observed Fisher matrix now agrees with the expected Fisher matrix. Recomputing the +expected Fisher matrix at the maximum likelihood point will produce almost exactly the +same result as the observed Fisher matrix. One notable advantage of the observed Fisher +matrix is its applicability to any likelihood function, providing a versatile option +despite its computational demands. + + +Output +====== + +The Fisher matrix commands support the ``--output`` option, allowing you to save the +computed Fisher matrix to a file. For instance: + +.. code-block:: bash + + numcosmo run fisher sn_srd.yaml --fisher-type expected --starting-point sn_srd-bestfit.yaml --output sn_srd-bestfit.yaml + +Executing this command saves the Fisher matrix as ``sn_srd-bestfit.yaml`` in the same +directory as the input configuration file. This feature proves useful for storing the +Fisher matrix for future use, such as initializing a Markov Chain Monte Carlo (MCMC) +run by sampling from the saved matrix. diff --git a/docs/numcosmo_fisher_bias.rst b/docs/numcosmo_fisher_bias.rst new file mode 100644 index 000000000..2f9f7d775 --- /dev/null +++ b/docs/numcosmo_fisher_bias.rst @@ -0,0 +1,57 @@ +========================================== +NumCosmo: Firecrown Likelihood Fisher Bias +========================================== + +This recipe outlines the process of computing the Fisher bias for Supernova SNIa data +likelihood using the Firecrown example with NumCosmo. Ensure you have already +installed Firecrown, CosmoSIS, and NumCosmo and set the environment variable +``FIRECROWN_DIR`` to the location of the Firecrown installation. + +The starting point for this recipe is the NumCosmo experiment configuration file +``sn_srd.yaml``. In section :ref:`convert-configuration-file-sn-srd`, we explain how to +convert this file to a Firecrown configuration file. The steps below assume you have +already completed this conversion. + +Computing the Theory Vector +=========================== + +The Fisher bias represents the difference between the current parameters and the +parameters most compatible with a given theory vector. To compute the theory vector, we +first need to calculate it at any point in the parameter space. In this example, we +compute the theory vector at the previously determined best-fit point, obtained in +:ref:`compute-bestfit-sn-srd`. + +Run the following command to compute the theory vector: + +.. code-block:: bash + + numcosmo run theory-vector sn_srd.yaml --starting-point sn_srd-bestfit.yaml --output sn_srd-bestfit.yaml + +This command updates the file ``sn_srd-bestfit.yaml`` to include the theory vector. + +Computing the Fisher Bias +========================= + +Now, compute the Fisher bias using the following command: + +.. code-block:: bash + + numcosmo run fisher-bias sn_srd.yaml --theory-vector sn_srd-bestfit.yaml + +This command produces the shift vector: [-0.126, 0.005]. + +The shift vector represents the difference between the current parameters and the +parameters most compatible with the theory vector. The parameters in ``sn_srd.yaml`` +are: + + * sn_ddf_sample_M: -19.3 + * Omegac: 0.26 + +While the best-fit parameters are: + + * sn_ddf_sample_M: -19.426 + * Omegac: 0.265 + +Note that the shift vector precisely reflects the difference between the best-fit +parameters and the parameters in the configuration file. This aligns with expectations, +as we utilized the best-fit point to compute the theory vector. diff --git a/environment.yml b/environment.yml index 5e5ffa05c..43b6af6cd 100644 --- a/environment.yml +++ b/environment.yml @@ -19,7 +19,7 @@ dependencies: - matplotlib-base - more-itertools - mypy - - numcosmo < 0.21.0 + - numcosmo >=0.21.1 - numpy >= 1.21.0 - pip - pip: diff --git a/examples/cluster_number_counts/cluster_richness_values.ini b/examples/cluster_number_counts/cluster_richness_values.ini index c8496c1c3..c2951b1b8 100644 --- a/examples/cluster_number_counts/cluster_richness_values.ini +++ b/examples/cluster_number_counts/cluster_richness_values.ini @@ -4,7 +4,7 @@ [cosmological_parameters] ; These are the only cosmological parameters being varied. -omega_m = 0.2 0.25 0.4 +omega_c = 0.1552 0.2052 0.3552 # We are choosing to use a flat prior in sigma_8. # To choose a float prior in A_s, remove the specification # of a prior for sigma_8 and replace it with the @@ -12,7 +12,6 @@ omega_m = 0.2 0.25 0.4 sigma_8 = 0.7 0.800 0.9 ; The following parameters are set, but not varied. ; -; omega_c is not set, because the consistency module sets it to omega_m - omega_b omega_k = 0.0 omega_b = 0.0448 tau = 0.08 diff --git a/examples/cosmicshear/cosmicshear.ini b/examples/cosmicshear/cosmicshear.ini index 77ae5df36..516354eb4 100644 --- a/examples/cosmicshear/cosmicshear.ini +++ b/examples/cosmicshear/cosmicshear.ini @@ -42,7 +42,7 @@ file = ${FIRECROWN_DIR}/firecrown/connector/cosmosis/likelihood.py ;; 'firecrown_ini' rather than the better 'likelihood_source', to ;; test the backward compatibility. Please don't do this for new ;; code. -firecrown_config = ${FIRECROWN_DIR}/examples/cosmicshear/cosmicshear.py +likelihood_source = ${FIRECROWN_DIR}/examples/cosmicshear/cosmicshear.py require_nonlinear_pk = True sampling_parameters_sections = firecrown_two_point diff --git a/examples/cosmicshear/cosmicshear_values.ini b/examples/cosmicshear/cosmicshear_values.ini index 7537c6ad1..fc75d3bc7 100644 --- a/examples/cosmicshear/cosmicshear_values.ini +++ b/examples/cosmicshear/cosmicshear_values.ini @@ -4,12 +4,11 @@ [cosmological_parameters] ; These are the only parameters being varied. -omega_m = 0.1 0.3 0.5 +omega_c = 0.06 0.26 0.46 omega_b = 0.03 0.04 0.07 ; The following parameters are set, but not varied. ; -; omega_c is not set, because the consistency module sets it to omega_m - omega_b omega_k = 0.0 tau = 0.08 n_s = 0.971 diff --git a/examples/des_y1_3x2pt/des_y1_3x2pt_PT_values.ini b/examples/des_y1_3x2pt/des_y1_3x2pt_PT_values.ini index f36cedbe8..f3d18f3d4 100644 --- a/examples/des_y1_3x2pt/des_y1_3x2pt_PT_values.ini +++ b/examples/des_y1_3x2pt/des_y1_3x2pt_PT_values.ini @@ -4,12 +4,11 @@ [cosmological_parameters] ; These are the only parameters being varied. -omega_m = 0.1 0.3 0.5 +omega_c = 0.06 0.26 0.46 omega_b = 0.03 0.04 0.07 ; The following parameters are set, but not varied. ; -; omega_c is not set, because the consistency module sets it to omega_m - omega_b omega_k = 0.0 tau = 0.08 n_s = 0.971 @@ -29,28 +28,6 @@ lens0_b_2 = 0.8 1.0 1.2 lens0_b_s = 0.8 1.0 1.2 lens0_mag_bias = 0.8 1.0 1.2 -ia_bias = -5.0 0.5 +5.0 -alphaz = -5.0 0.0 +5.0 -z_piv = 0.62 - lens0_bias = 0.8 2.0 3.0 -lens1_bias = 0.8 1.6 3.0 -lens2_bias = 0.8 1.6 3.0 -lens3_bias = 0.8 1.9 3.0 -lens4_bias = 0.8 2.0 3.0 - src0_delta_z = -0.05 -0.001 0.05 -src1_delta_z = -0.05 -0.019 0.05 -src2_delta_z = -0.05 0.009 0.05 -src3_delta_z = -0.05 -0.018 0.05 - lens0_delta_z = -0.05 0.001 0.05 -lens1_delta_z = -0.05 0.002 0.05 -lens2_delta_z = -0.05 0.001 0.05 -lens3_delta_z = -0.05 0.003 0.05 -lens4_delta_z = -0.05 0.000 0.05 - -src0_mult_bias = 0.001 0.012 0.1 -src1_mult_bias = 0.001 0.012 0.1 -src2_mult_bias = 0.001 0.012 0.1 -src3_mult_bias = 0.001 0.012 0.1 diff --git a/examples/des_y1_3x2pt/des_y1_3x2pt_values.ini b/examples/des_y1_3x2pt/des_y1_3x2pt_values.ini index faaf19a13..30904a3fb 100644 --- a/examples/des_y1_3x2pt/des_y1_3x2pt_values.ini +++ b/examples/des_y1_3x2pt/des_y1_3x2pt_values.ini @@ -4,12 +4,10 @@ [cosmological_parameters] ; These are the only parameters being varied. -omega_m = 0.1 0.3 0.5 +omega_c = 0.06 0.26 0.46 omega_b = 0.03 0.04 0.07 ; The following parameters are set, but not varied. -; -; omega_c is not set, because the consistency module sets it to omega_m - omega_b omega_k = 0.0 tau = 0.08 n_s = 0.971 diff --git a/examples/des_y1_3x2pt/numcosmo_firecrown_model.yml b/examples/des_y1_3x2pt/numcosmo_firecrown_model.yml deleted file mode 100644 index 6c064c0d6..000000000 --- a/examples/des_y1_3x2pt/numcosmo_firecrown_model.yml +++ /dev/null @@ -1,194 +0,0 @@ -!NumCosmoModel -name: NcFirecrown -description: Firecrown model interface -scalar_params: -- !ScalarParameter - symbol: ia_\mathrm{bias} - name: ia_bias - lower_bound: -5.0 - upper_bound: 5.0 - scale: 0.1 - absolute_tolerance: 0.0 - default_value: 0.5 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: \alpha_z - name: alphaz - lower_bound: -5.0 - upper_bound: 5.0 - scale: 0.1 - absolute_tolerance: 0.0 - default_value: 0.0 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: z_\mathrm{piv} - name: z_piv - lower_bound: 0.0 - upper_bound: 5.0 - scale: 0.1 - absolute_tolerance: 0.0 - default_value: 0.62 - fit_type: !NcmParamType 'fixed' -- !ScalarParameter - symbol: lens0_bias - name: lens0_bias - lower_bound: 0.8 - upper_bound: 3.0 - scale: 0.1 - absolute_tolerance: 0.0 - default_value: 1.4 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: lens1_bias - name: lens1_bias - lower_bound: 0.8 - upper_bound: 3.0 - scale: 0.1 - absolute_tolerance: 0.0 - default_value: 1.6 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: lens2_bias - name: lens2_bias - lower_bound: 0.8 - upper_bound: 3.0 - scale: 0.1 - absolute_tolerance: 0.0 - default_value: 1.6 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: lens3_bias - name: lens3_bias - lower_bound: 0.8 - upper_bound: 3.0 - scale: 0.1 - absolute_tolerance: 0.0 - default_value: 1.9 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: lens4_bias - name: lens4_bias - lower_bound: 0.8 - upper_bound: 3.0 - scale: 0.1 - absolute_tolerance: 0.0 - default_value: 2.0 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: src0_delta_z - name: src0_delta_z - lower_bound: -0.16 - upper_bound: 0.16 - scale: 0.001 - absolute_tolerance: 0.0 - default_value: -0.001 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: src1_delta_z - name: src1_delta_z - lower_bound: -0.13 - upper_bound: 0.13 - scale: 0.001 - absolute_tolerance: 0.0 - default_value: -0.019 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: src2_delta_z - name: src2_delta_z - lower_bound: -0.11 - upper_bound: 0.11 - scale: 0.001 - absolute_tolerance: 0.0 - default_value: 0.009 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: src3_delta_z - name: src3_delta_z - lower_bound: -0.22 - upper_bound: 0.22 - scale: 0.001 - absolute_tolerance: 0.0 - default_value: -0.018 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: lens0_delta_z - name: lens0_delta_z - lower_bound: -0.1 - upper_bound: 0.1 - scale: 0.001 - absolute_tolerance: 0.0 - default_value: 0.001 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: lens1_delta_z - name: lens1_delta_z - lower_bound: -0.1 - upper_bound: 0.1 - scale: 0.001 - absolute_tolerance: 0.0 - default_value: 0.002 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: lens2_delta_z - name: lens2_delta_z - lower_bound: -0.1 - upper_bound: 0.1 - scale: 0.001 - absolute_tolerance: 0.0 - default_value: 0.001 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: lens3_delta_z - name: lens3_delta_z - lower_bound: -0.1 - upper_bound: 0.1 - scale: 0.001 - absolute_tolerance: 0.0 - default_value: 0.003 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: lens4_delta_z - name: lens4_delta_z - lower_bound: -0.1 - upper_bound: 0.1 - scale: 0.001 - absolute_tolerance: 0.0 - default_value: 0.0 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: src0_mult_bias - name: src0_mult_bias - lower_bound: -0.23 - upper_bound: 0.23 - scale: 0.001 - absolute_tolerance: 0.0 - default_value: 0.0 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: src1_mult_bias - name: src1_mult_bias - lower_bound: -0.23 - upper_bound: 0.23 - scale: 0.001 - absolute_tolerance: 0.0 - default_value: 0.0 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: src2_mult_bias - name: src2_mult_bias - lower_bound: -0.23 - upper_bound: 0.23 - scale: 0.001 - absolute_tolerance: 0.0 - default_value: 0.0 - fit_type: !NcmParamType 'free' -- !ScalarParameter - symbol: src3_mult_bias - name: src3_mult_bias - lower_bound: -0.23 - upper_bound: 0.23 - scale: 0.001 - absolute_tolerance: 0.0 - default_value: 0.0 - fit_type: !NcmParamType 'free' -vector_params: [] diff --git a/examples/des_y1_3x2pt/numcosmo_firecrown_model_PT.yml b/examples/des_y1_3x2pt/numcosmo_firecrown_model_PT.yml deleted file mode 100644 index d828f5884..000000000 --- a/examples/des_y1_3x2pt/numcosmo_firecrown_model_PT.yml +++ /dev/null @@ -1,86 +0,0 @@ -!NumCosmoModel -description: Firecrown model interface with PT -name: NcFirecrownPT -scalar_params: -- !ScalarParameter - absolute_tolerance: 0.0 - default_value: 1.4 - fit_type: !NcmParamType 'free' - lower_bound: 0.8 - name: lens0_bias - scale: 0.1 - symbol: lens0_bias - upper_bound: 3.0 -- !ScalarParameter - absolute_tolerance: 0.0 - default_value: -0.001 - fit_type: !NcmParamType 'free' - lower_bound: -0.16 - name: src0_delta_z - scale: 0.001 - symbol: src0_delta_z - upper_bound: 0.16 -- !ScalarParameter - absolute_tolerance: 0.0 - default_value: 0.001 - fit_type: !NcmParamType 'free' - lower_bound: -0.1 - name: lens0_delta_z - scale: 0.001 - symbol: lens0_delta_z - upper_bound: 0.1 -- !ScalarParameter - absolute_tolerance: 0.0 - default_value: 1.0 - fit_type: !NcmParamType 'free' - lower_bound: 0.9 - name: ia_a_1 - scale: 0.01 - symbol: ia_a_1 - upper_bound: 1.2 -- !ScalarParameter - absolute_tolerance: 0.0 - default_value: 0.5 - fit_type: !NcmParamType 'free' - lower_bound: 0.4 - name: ia_a_2 - scale: 0.01 - symbol: ia_a_2 - upper_bound: 0.6 -- !ScalarParameter - absolute_tolerance: 0.0 - default_value: 0.5 - fit_type: !NcmParamType 'free' - lower_bound: 0.4 - name: ia_a_d - scale: 0.01 - symbol: ia_a_d - upper_bound: 0.6 -- !ScalarParameter - absolute_tolerance: 0.0 - default_value: 1.0 - fit_type: !NcmParamType 'free' - lower_bound: 0.8 - name: lens0_b_2 - scale: 0.01 - symbol: lens0_b_2 - upper_bound: 1.2 -- !ScalarParameter - absolute_tolerance: 0.0 - default_value: 1.0 - fit_type: !NcmParamType 'free' - lower_bound: 0.8 - name: lens0_b_s - scale: 0.01 - symbol: lens0_b_s - upper_bound: 1.2 -- !ScalarParameter - absolute_tolerance: 0.0 - default_value: 1.0 - fit_type: !NcmParamType 'free' - lower_bound: 0.8 - name: lens0_mag_bias - scale: 0.01 - symbol: lens0_mag_bias - upper_bound: 1.2 -vector_params: [] diff --git a/examples/des_y1_3x2pt/numcosmo_run.py b/examples/des_y1_3x2pt/numcosmo_run.py deleted file mode 100755 index ff23520d9..000000000 --- a/examples/des_y1_3x2pt/numcosmo_run.py +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/env python -"""Example of running the DES Y1 3x2pt likelihood using NumCosmo.""" - -import math -import os -from typing import Tuple -import argparse -from pathlib import Path - - -import yaml - -from numcosmo_py import Nc, Ncm -from numcosmo_py.sampling.esmcmc import create_esmcmc - -from firecrown.connector.numcosmo.numcosmo import MappingNumCosmo, NumCosmoFactory -from firecrown.connector.numcosmo.model import define_numcosmo_model -from firecrown.likelihood.likelihood import NamedParameters - -# Any NumCosmo model should be loaded before NumCosmo cfg_init -# is called. Otherwise, the NumCosmo model will not be registered -# in the model set. This is required for the NumCosmo MPI support -# to work properly. - - -module_path = Path(os.path.dirname(__file__)) -with open( - module_path / r"numcosmo_firecrown_model.yml", "r", encoding="utf-8" -) as modelfile: - ncmodel = yaml.load(modelfile, Loader=yaml.Loader) - -NcFirecrown = define_numcosmo_model(ncmodel) - - -def setup_numcosmo_cosmology() -> Tuple[Nc.HICosmo, MappingNumCosmo]: - """Setup NumCosmo cosmology. - - Creates a NumCosmo cosmology object. - """ - - cosmo = Nc.HICosmoDEXcdm(massnu_length=1) - cosmo.omega_x2omega_k() - cosmo.param_set_by_name("H0", 68.2) - cosmo.param_set_by_name("Omegak", 0.0) - cosmo.param_set_by_name("Omegab", 0.022558514 / 0.682**2) - cosmo.param_set_by_name("Omegac", 0.118374058 / 0.682**2) - cosmo.param_set_by_name("massnu_0", 0.06) - cosmo.param_set_by_name("ENnu", 2.0328) - cosmo.param_set_by_name("Yp", 0.2454) - cosmo.param_set_by_name("w", -1.0) - - prim = Nc.HIPrimPowerLaw.new() - prim.param_set_by_name("ln10e10ASA", math.log(1.0e10 * 2.0e-09)) - prim.param_set_by_name("n_SA", 0.971) - - reion = Nc.HIReionCamb.new() - reion.set_z_from_tau(cosmo, 0.0561) - - cosmo.add_submodel(prim) - cosmo.add_submodel(reion) - - p_ml = Nc.PowspecMLTransfer.new(Nc.TransferFuncEH.new()) - p_mnl = Nc.PowspecMNLHaloFit.new(p_ml, 3.0, 1.0e-5) - dist = Nc.Distance.new(6.0) - dist.comoving_distance_spline.set_reltol(1.0e-5) - - map_cosmo = MappingNumCosmo( - require_nonlinear_pk=True, - p_ml=p_ml, - p_mnl=p_mnl, - dist=dist, - ) - - return cosmo, map_cosmo - - -def setup_firecrown(map_cosmo: MappingNumCosmo) -> Tuple[Ncm.Model, NumCosmoFactory]: - """Setup Firecrown object.""" - - nc_factory = NumCosmoFactory( - str(module_path / "des_y1_3x2pt.py"), - NamedParameters(), - map_cosmo, - [ncmodel.name], - ) - - fc = NcFirecrown() - - return fc, nc_factory - - -def setup_likelihood( - cosmo: Nc.HICosmo, - fc: Ncm.Model, - nc_factory: NumCosmoFactory, -) -> Tuple[Ncm.Likelihood, Ncm.MSet]: - """Setup the likelihood and model set objects.""" - - mset = Ncm.MSet() - mset.set(cosmo) - mset.set(fc) - - fc_data = nc_factory.get_data() - - dset = Ncm.Dataset() - dset.append_data(fc_data) - - lh = Ncm.Likelihood(dataset=dset) - - lh.priors_add_gauss_param_name(mset, "NcFirecrown:src0_delta_z", -0.001, 0.016) - lh.priors_add_gauss_param_name(mset, "NcFirecrown:src1_delta_z", -0.019, 0.013) - lh.priors_add_gauss_param_name(mset, "NcFirecrown:src2_delta_z", +0.009, 0.011) - lh.priors_add_gauss_param_name(mset, "NcFirecrown:src3_delta_z", -0.018, 0.022) - - lh.priors_add_gauss_param_name(mset, "NcFirecrown:lens0_delta_z", +0.001, 0.008) - lh.priors_add_gauss_param_name(mset, "NcFirecrown:lens1_delta_z", +0.002, 0.007) - lh.priors_add_gauss_param_name(mset, "NcFirecrown:lens2_delta_z", +0.001, 0.007) - lh.priors_add_gauss_param_name(mset, "NcFirecrown:lens3_delta_z", +0.003, 0.010) - lh.priors_add_gauss_param_name(mset, "NcFirecrown:lens4_delta_z", +0.000, 0.010) - - lh.priors_add_gauss_param_name(mset, "NcFirecrown:src0_mult_bias", +0.012, 0.023) - lh.priors_add_gauss_param_name(mset, "NcFirecrown:src0_mult_bias", +0.012, 0.023) - lh.priors_add_gauss_param_name(mset, "NcFirecrown:src0_mult_bias", +0.012, 0.023) - lh.priors_add_gauss_param_name(mset, "NcFirecrown:src0_mult_bias", +0.012, 0.023) - - return lh, mset - - -def setup_fit(likelihood: Ncm.Likelihood, mset: Ncm.MSet) -> Ncm.Fit: - """Setup the fit object.""" - - fit = Ncm.Fit.factory( - Ncm.FitType.NLOPT, - "ln-neldermead", - likelihood, - mset, - Ncm.FitGradType.NUMDIFF_FORWARD, - ) - - return fit - - -def setup_fit_all() -> Ncm.Fit: - """Setup all objects necessary to instantiate the fit object.""" - - cosmo, map_cosmo = setup_numcosmo_cosmology() - fc, nc_factory = setup_firecrown(map_cosmo) - likelihood, mset = setup_likelihood(cosmo, fc, nc_factory) - fit = setup_fit(likelihood, mset) - - return fit - - -def run_test() -> None: - """Run the fit.""" - - fit = setup_fit_all() - mset = fit.peek_mset() - mset.param_set_all_ftype(Ncm.ParamType.FIXED) - mset.pretty_log() - - fit.run_restart(Ncm.FitRunMsgs.FULL, 1.0e-3, 0.0, None, None) - - -def run_compute_best_fit() -> None: - """Run the fit.""" - - fit = setup_fit_all() - mset = fit.peek_mset() - - # Sets the default ftype for all model parameters - for i in range(mset.nmodels()): - model = mset.peek_array_pos(i) - model.params_set_default_ftype() - mset.prepare_fparam_map() - mset.pretty_log() - - fit.run_restart(Ncm.FitRunMsgs.FULL, 1.0e-3, 0.0, None, None) - - -def run_apes_sampler(ssize: int) -> None: - """Run the fit.""" - - fit = setup_fit_all() - mset = fit.peek_mset() - - # Sets the default ftype for all model parameters - for i in range(mset.nmodels()): - model = mset.peek_array_pos(i) - model.params_set_default_ftype() - mset.prepare_fparam_map() - - nwalkers = mset.fparam_len() * 100 - esmcmc = create_esmcmc( - fit.props.likelihood, mset, "des_y1_3x2pt_apes", nwalkers=nwalkers, nthreads=1 - ) - - esmcmc.start_run() - esmcmc.run(ssize // nwalkers) - esmcmc.end_run() - - -if __name__ == "__main__": - Ncm.cfg_init() - - parser = argparse.ArgumentParser(description="Run DES Y1 3x2pt likelihood.") - - parser.add_argument( - "--run-mode", - choices=["test_likelihood", "compute_best_fit", "run_apes_sampler"], - default="test_likelihood", - help="Run mode.", - ) - - parser.add_argument( - "--apes-sampler-ssize", - type=int, - default=10, - help="Number of samples to draw from the APES sampler.", - ) - - args = parser.parse_args() - - if args.run_mode == "test_likelihood": - run_test() - elif args.run_mode == "compute_best_fit": - run_compute_best_fit() - elif args.run_mode == "run_apes_sampler": - run_apes_sampler(args.apes_sampler_ssize) - else: - raise ValueError(f"Unknown run mode: {args.run_mode}") diff --git a/examples/des_y1_3x2pt/numcosmo_run_PT.py b/examples/des_y1_3x2pt/numcosmo_run_PT.py deleted file mode 100755 index a73821539..000000000 --- a/examples/des_y1_3x2pt/numcosmo_run_PT.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python - -"""Example of running the DES Y1 3x2pt likelihood using NumCosmo.""" - -import math - -import yaml - -from numcosmo_py import Nc, Ncm - -from firecrown.connector.numcosmo.numcosmo import MappingNumCosmo, NumCosmoFactory -from firecrown.connector.numcosmo.model import define_numcosmo_model -from firecrown.likelihood.likelihood import NamedParameters - - -Ncm.cfg_init() - -with open(r"numcosmo_firecrown_model_PT.yml", "r", encoding="utf-8") as modelfile: - ncmodel = yaml.load(modelfile, Loader=yaml.Loader) - -NcFirecrownPT = define_numcosmo_model(ncmodel) - -cosmo = Nc.HICosmoDEXcdm(massnu_length=1) -cosmo.omega_x2omega_k() -cosmo.param_set_by_name("H0", 68.2) -cosmo.param_set_by_name("Omegak", 0.0) -cosmo.param_set_by_name("Omegab", 0.022558514 / 0.682**2) -cosmo.param_set_by_name("Omegac", 0.118374058 / 0.682**2) -cosmo.param_set_by_name("massnu_0", 0.06) -cosmo.param_set_by_name("ENnu", 2.0328) -cosmo.param_set_by_name("Yp", 0.2454) -cosmo.param_set_by_name("w", -1.0) - -prim = Nc.HIPrimPowerLaw.new() -prim.param_set_by_name("ln10e10ASA", math.log(1.0e10 * 2.0e-09)) -prim.param_set_by_name("n_SA", 0.971) - -reion = Nc.HIReionCamb.new() -reion.set_z_from_tau(cosmo, 0.0561) - -cosmo.add_submodel(prim) -cosmo.add_submodel(reion) - -p_ml = Nc.PowspecMLTransfer.new(Nc.TransferFuncEH.new()) -p_mnl = Nc.PowspecMNLHaloFit.new(p_ml, 3.0, 1.0e-5) -dist = Nc.Distance.new(6.0) -dist.comoving_distance_spline.set_reltol(1.0e-5) - -map_cosmo = MappingNumCosmo( - require_nonlinear_pk=True, - p_ml=p_ml, - p_mnl=p_mnl, - dist=dist, -) - -nc_factory = NumCosmoFactory( - "des_y1_3x2pt_PT.py", - NamedParameters(), - map_cosmo, - model_list=["NcFirecrownPT"], -) - -fc = NcFirecrownPT() -# fc.params_set_default_ftype() - -mset = Ncm.MSet() -mset.set(cosmo) -mset.set(fc) - -fc_data = nc_factory.get_data() - -dset = Ncm.Dataset() -dset.append_data(fc_data) - -lh = Ncm.Likelihood(dataset=dset) - -lh.priors_add_gauss_param_name(mset, "NcFirecrownPT:src0_delta_z", -0.001, 0.016) -lh.priors_add_gauss_param_name(mset, "NcFirecrownPT:lens0_delta_z", +0.001, 0.008) - -fit = Ncm.Fit.factory( - Ncm.FitType.NLOPT, - "ln-neldermead", - lh, - mset, - Ncm.FitGradType.NUMDIFF_FORWARD, -) - -mset.pretty_log() -fit.run_restart(Ncm.FitRunMsgs.FULL, 1.0e-3, 0.0, None, None) diff --git a/examples/srd_sn/numcosmo_firecrown_model_snia.yml b/examples/srd_sn/numcosmo_firecrown_model_snia.yml deleted file mode 100644 index ee05dd7c1..000000000 --- a/examples/srd_sn/numcosmo_firecrown_model_snia.yml +++ /dev/null @@ -1,14 +0,0 @@ -!NumCosmoModel -description: Firecrown model interface for SNIA -name: NcFirecrownSNIa -scalar_params: -- !ScalarParameter - absolute_tolerance: 0.0 - default_value: -19.3 - fit_type: !NcmParamType 'free' - lower_bound: -20.0 - name: sn_ddf_sample_M - scale: 0.1 - symbol: \mathcal{M} - upper_bound: -19.0 -vector_params: [] diff --git a/examples/srd_sn/numcosmo_run.py b/examples/srd_sn/numcosmo_run.py deleted file mode 100755 index 2375618bd..000000000 --- a/examples/srd_sn/numcosmo_run.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python -""" -Numcosmo example using the `sn_srd` likelihood. -""" - -import math -import os.path - -import yaml - -import matplotlib.pyplot as plt -from scipy.stats import chi2 -from numcosmo_py import Nc, Ncm - -from firecrown.connector.numcosmo.numcosmo import ( - MappingNumCosmo, - NumCosmoFactory, -) -from firecrown.connector.numcosmo.model import define_numcosmo_model -from firecrown.likelihood.likelihood import NamedParameters - -Ncm.cfg_init() - -with open(r"numcosmo_firecrown_model_snia.yml", "r", encoding="utf-8") as modelfile: - ncmodel = yaml.load(modelfile, Loader=yaml.Loader) - -NcFirecrownSNIa = define_numcosmo_model(ncmodel) - -cosmo = Nc.HICosmoDEXcdm(massnu_length=1) -cosmo.omega_x2omega_k() -cosmo.param_set_by_name("H0", 68.2) -cosmo.param_set_by_name("Omegak", 0.0) -cosmo.param_set_by_name("Omegab", 0.022558514 / 0.682**2) -cosmo.param_set_by_name("Omegac", 0.118374058 / 0.682**2) -cosmo.param_set_by_name("massnu_0", 0.06) -cosmo.param_set_by_name("ENnu", 2.0328) -cosmo.param_set_by_name("Yp", 0.2454) -cosmo.param_set_by_name("w", -1.0) - -_, H0_i = cosmo.param_index_from_name("H0") -cosmo.param_set_ftype(H0_i, Ncm.ParamType.FREE) - -_, Omegac_i = cosmo.param_index_from_name("Omegac") -cosmo.param_set_ftype(Omegac_i, Ncm.ParamType.FREE) - -prim = Nc.HIPrimPowerLaw.new() -prim.param_set_by_name("ln10e10ASA", math.log(1.0e10 * 2.0e-09)) -prim.param_set_by_name("n_SA", 0.971) - -reion = Nc.HIReionCamb.new() -reion.set_z_from_tau(cosmo, 0.0561) - -cosmo.add_submodel(prim) -cosmo.add_submodel(reion) - -dist = Nc.Distance.new(6.0) -dist.comoving_distance_spline.set_reltol(1.0e-5) - -map_cosmo = MappingNumCosmo(require_nonlinear_pk=False, dist=dist) - -sacc_file = os.path.expandvars("${FIRECROWN_DIR}/examples/srd_sn/srd-y1-converted.sacc") - -nc_factory = NumCosmoFactory( - "sn_srd.py", - NamedParameters({"sacc_file": sacc_file}), - map_cosmo, - model_list=["NcFirecrownSNIa"], -) - -fc = NcFirecrownSNIa() -# fc.params_set_default_ftype() - -mset = Ncm.MSet() -mset.set(cosmo) -mset.set(fc) - -fc_data = nc_factory.get_data() - -dset = Ncm.Dataset() -dset.append_data(fc_data) - -lh = Ncm.Likelihood(dataset=dset) - -fit = Ncm.Fit.factory( - Ncm.FitType.NLOPT, - "ln-neldermead", - lh, - mset, - Ncm.FitGradType.NUMDIFF_FORWARD, -) - -mset.pretty_log() -fit.run_restart(Ncm.FitRunMsgs.SIMPLE, 1.0e-3, 0.0, None, None) -fit.fisher() -fit.log_covar() - -p1 = Ncm.MSetPIndex.new(cosmo.id(), H0_i) -p2 = Ncm.MSetPIndex.new(cosmo.id(), Omegac_i) - -lhr2d = Ncm.LHRatio2d.new(fit, p1, p2, 1.0e-3) - -plt.figure(figsize=(8, 4)) -plt.title("Confidence regions") - -for clevel in [chi2.cdf(chi**2, df=1) for chi in [1, 2, 3]]: - fisher_rg = lhr2d.fisher_border(clevel, 300.0, Ncm.FitRunMsgs.SIMPLE) - plt.plot( - fisher_rg.p1.dup_array(), - fisher_rg.p2.dup_array(), - label=f"Fisher Matrix -- {fisher_rg.clevel*100:.2f}%", - ) - -plt.xlabel(f"${cosmo.param_symbol(H0_i)}$") -plt.ylabel(f"${cosmo.param_symbol(Omegac_i)}$") - -plt.legend(loc="best") - -plt.savefig("srd_sn_fisher_example.pdf") diff --git a/examples/srd_sn/sn_only.ini b/examples/srd_sn/sn_only.ini index d7535ca7e..5d5e958ed 100644 --- a/examples/srd_sn/sn_only.ini +++ b/examples/srd_sn/sn_only.ini @@ -15,6 +15,7 @@ verbosity = debug [pipeline] modules = consistency camb firecrown_likelihood values = ${FIRECROWN_DIR}/examples/srd_sn/snonly_values.ini +likelihoods = firecrown quiet = F debug = F timing = T @@ -43,7 +44,7 @@ use_ppf_w = T ;; installed it) ;; this needs to be udpated for SN-specific analysis! file = ${FIRECROWN_DIR}/firecrown/connector/cosmosis/likelihood.py -firecrown_config =${FIRECROWN_DIR}/examples/srd_sn/sn_srd.py +likelihood_source = ${FIRECROWN_DIR}/examples/srd_sn/sn_srd.py require_nonlinear_pk=F sampling_parameters_sections = firecrown_supernova_parameters diff --git a/examples/srd_sn/sn_srd_values.ini b/examples/srd_sn/sn_srd_values.ini index 61c5e6bf1..4bb87eee2 100644 --- a/examples/srd_sn/sn_srd_values.ini +++ b/examples/srd_sn/sn_srd_values.ini @@ -4,13 +4,12 @@ [cosmological_parameters] ; These are the only parameters being varied. -omega_c = 0.1 0.3 0.5 +omega_c = 0.06 0.26 0.46 omega_b = 0.04 h0=0.72 ; The following parameters are set, but not varied. ; -; omega_c is not set, because the consistency module sets it to omega_m - omega_b omega_k = 0.0 tau = 0.08 n_s = 0.971 diff --git a/examples/srd_sn/snonly_values.ini b/examples/srd_sn/snonly_values.ini index 88139f28e..cc93addbf 100644 --- a/examples/srd_sn/snonly_values.ini +++ b/examples/srd_sn/snonly_values.ini @@ -4,12 +4,11 @@ [cosmological_parameters] ; These are the only parameters being varied. -omega_m = 0.05 0.29352189787340449 0.8 +omega_c = 0.06 0.26 0.76 w = -2. -1. 0.0 wa = -1. 0.0 1.0 ; The following parameters are set, but not varied. -; omega_c is not set, because the consistency module sets it to omega_m - omega_b omega_b = 0.04 h0=0.682 omega_k = 0.0 diff --git a/firecrown/connector/numcosmo/model.py b/firecrown/connector/numcosmo/model.py deleted file mode 100644 index df3f8d2af..000000000 --- a/firecrown/connector/numcosmo/model.py +++ /dev/null @@ -1,122 +0,0 @@ -"""Helper function to create NumCosmo models.""" - -from dataclasses import dataclass, field -from typing import List, Type -import sys - -import yaml -from numcosmo_py import Ncm, GObject - - -@dataclass -class ScalarParameter(yaml.YAMLObject): # pylint: disable=too-many-instance-attributes - """Dataclass to hold scalar parameter information.""" - - yaml_loader = yaml.Loader - yaml_dumper = yaml.Dumper - yaml_tag = "!ScalarParameter" - - symbol: str - name: str - lower_bound: float = -sys.float_info.max - upper_bound: float = +sys.float_info.max - scale: float = 1.0 - absolute_tolerance: float = 0.0 - default_value: float = 0.0 - fit_type: Ncm.ParamType = Ncm.ParamType.FREE - - -@dataclass -class VectorParameter(yaml.YAMLObject): # pylint: disable=too-many-instance-attributes - """Dataclass to hold scalar parameter information.""" - - yaml_loader = yaml.Loader - yaml_dumper = yaml.Dumper - yaml_tag = "!VectorParameter" - - default_length: int - symbol: str - name: str - lower_bound: float = -sys.float_info.max - upper_bound: float = +sys.float_info.max - scale: float = 1.0 - absolute_tolerance: float = 0.0 - default_value: float = 0.0 - fit_type: Ncm.ParamType = Ncm.ParamType.FREE - - -@dataclass -class NumCosmoModel(yaml.YAMLObject): - """Dataclass to hold NumCosmo model information.""" - - yaml_loader = yaml.Loader - yaml_dumper = yaml.Dumper - yaml_tag = "!NumCosmoModel" - - name: str - description: str - scalar_params: List[ScalarParameter] = field(default_factory=list) - vector_params: List[VectorParameter] = field(default_factory=list) - - -def param_type_representer(dumper, ftype): - """Representer for NumCosmo parameter types.""" - return dumper.represent_scalar("!NcmParamType", Ncm.ParamType(ftype).value_nick) - - -def param_type_constructor(loader, node): - """Constructor for NumCosmo parameter types.""" - value = loader.construct_scalar(node) - enum_item = Ncm.cfg_get_enum_by_id_name_nick(Ncm.ParamType, value) - return Ncm.ParamType(enum_item.value) - - -yaml.add_constructor("!NcmParamType", param_type_constructor) -yaml.add_representer(Ncm.ParamType, param_type_representer) - - -def define_numcosmo_model(numcosmo_model: NumCosmoModel) -> Type[Ncm.Model]: - """Define a NumCosmo model. - - :param numcosmo_model: NumCosmo model to define. - - :return: NumCosmo model class. - """ - model_name = numcosmo_model.name - model_description = numcosmo_model.description - scalar_params = numcosmo_model.scalar_params - vector_params = numcosmo_model.vector_params - - mb = Ncm.ModelBuilder.new(Ncm.Model, model_name, model_description) - - for sparam in scalar_params: - mb.add_sparam( - sparam.symbol, - sparam.name, - sparam.lower_bound, - sparam.upper_bound, - sparam.scale, - sparam.absolute_tolerance, - sparam.default_value, - sparam.fit_type, - ) - - for vparam in vector_params: - mb.add_vparam( - vparam.default_length, - vparam.symbol, - vparam.name, - vparam.lower_bound, - vparam.upper_bound, - vparam.scale, - vparam.absolute_tolerance, - vparam.default_value, - vparam.fit_type, - ) - - numcosmo_model_class = mb.create() - GObject.new(numcosmo_model_class) - py_numcosmo_model = numcosmo_model_class.pytype - GObject.type_register(py_numcosmo_model) - - return py_numcosmo_model diff --git a/firecrown/connector/numcosmo/numcosmo.py b/firecrown/connector/numcosmo/numcosmo.py index 2abd293ed..3d4c007d7 100644 --- a/firecrown/connector/numcosmo/numcosmo.py +++ b/firecrown/connector/numcosmo/numcosmo.py @@ -6,12 +6,10 @@ """ from typing import Dict, Union, List, Any, Optional -import pickle -import base64 import numpy as np import pyccl as ccl -from numcosmo_py import Nc, Ncm, GObject +from numcosmo_py import Nc, Ncm, GObject, var_dict_to_dict, dict_to_var_dict from firecrown.likelihood.likelihood import load_likelihood from firecrown.likelihood.likelihood import Likelihood @@ -46,6 +44,12 @@ def __init__( self._p_mnl: Optional[Nc.PowspecMNL] self._dist: Nc.Distance + if not hasattr(self, "_p_ml"): + self._p_ml = None + + if not hasattr(self, "_p_mnl"): + self._p_mnl = None + def _get_mapping_name(self) -> str: """Return the mapping name.""" return self._mapping_name @@ -308,7 +312,9 @@ def __init__(self): self.ccl_cosmo: Optional[ccl.Cosmology] = None self._model_list: List[str] self._nc_mapping: MappingNumCosmo - self._likelihood_str: Optional[str] = None + self._likelihood_source: Optional[str] = None + self._likelihood_build_parameters: Optional[NamedParameters] = None + self._starting_deserialization: bool = False self.dof: int = 100 self.len: int = 100 self.set_init(True) @@ -343,27 +349,67 @@ def _set_nc_mapping(self, value: MappingNumCosmo): setter=_set_nc_mapping, ) - def _get_likelihood_str(self) -> Optional[str]: - """Return the likelihood string.""" - return self._likelihood_str + def _set_likelihood_from_factory(self): + """Deserialize the likelihood.""" + assert self._likelihood_source is not None + assert self._likelihood_build_parameters is not None + likelihood, tools = load_likelihood( + self._likelihood_source, self._likelihood_build_parameters + ) + assert isinstance(likelihood, Likelihood) + assert isinstance(tools, ModelingTools) + self.likelihood = likelihood + self.tools = tools + + def _get_likelihood_source(self) -> Optional[str]: + """Return the likelihood string defining the factory function.""" + return self._likelihood_source + + def _set_likelihood_source(self, value: Optional[str]): + """Set the likelihood string defining the factory function.""" + + if value is not None: + self._likelihood_source = value + if self._starting_deserialization: + self._set_likelihood_from_factory() + self._starting_deserialization = False + else: + self._starting_deserialization = True + + likelihood_source = GObject.Property( + type=str, + flags=GObject.ParamFlags.READWRITE, + getter=_get_likelihood_source, + setter=_set_likelihood_source, + ) + + def _get_likelihood_build_parameters(self) -> Optional[Ncm.VarDict]: + """Return the likelihood build parameters.""" + if self._likelihood_build_parameters is None: + return None + return dict_to_var_dict( + self._likelihood_build_parameters.convert_to_basic_dict() + ) - def _set_likelihood_str(self, value: Optional[str]): - """Set the likelihood string.""" - self._likelihood_str = value + def _set_likelihood_build_parameters(self, value: Optional[Ncm.VarDict]): + """Set the likelihood build parameters.""" + self._likelihood_build_parameters = NamedParameters() if value is not None: - likelihood_source, build_parameters = pickle.loads( - base64.b64decode(value.encode("ascii")) + self._likelihood_build_parameters.set_from_basic_dict( + var_dict_to_dict(value) ) - likelihood, tools = load_likelihood(likelihood_source, build_parameters) - assert isinstance(likelihood, Likelihood) - self.likelihood = likelihood - self.tools = tools - likelihood_str = GObject.Property( - type=str, - flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT, - getter=_get_likelihood_str, - setter=_set_likelihood_str, + if self._starting_deserialization: + self._set_likelihood_from_factory() + self._starting_deserialization = False + else: + self._starting_deserialization = True + + likelihood_build_parameters = GObject.Property( + type=Ncm.VarDict, + flags=GObject.ParamFlags.READWRITE, + getter=_get_likelihood_build_parameters, + setter=_set_likelihood_build_parameters, ) @classmethod @@ -373,7 +419,8 @@ def new_from_likelihood( model_list: List[str], tools: ModelingTools, nc_mapping: MappingNumCosmo, - likelihood_str: Optional[str] = None, + likelihood_source: Optional[str] = None, + likelihood_build_parameters: Optional[NamedParameters] = None, ): """Initialize a NumCosmoGaussCov object representing a Gaussian likelihood with a constant covariance.""" @@ -382,13 +429,13 @@ def new_from_likelihood( cls, model_list=model_list, nc_mapping=nc_mapping, - likelihood_str=None, ) nc_data.likelihood = likelihood nc_data.tools = tools # pylint: disable=protected-access - nc_data._likelihood_str = likelihood_str + nc_data._likelihood_source = likelihood_source + nc_data._likelihood_build_parameters = likelihood_build_parameters # pylint: enable=protected-access return nc_data @@ -473,7 +520,9 @@ def __init__(self): self.len: int self._model_list: List[str] self._nc_mapping: MappingNumCosmo - self._likelihood_str: Optional[str] = None + self._likelihood_source: Optional[str] = None + self._likelihood_build_parameters: Optional[NamedParameters] = None + self._starting_deserialization: bool = False def _get_model_list(self) -> List[str]: """Return the list of models.""" @@ -529,28 +578,67 @@ def _configure_object(self): self.set_init(True) - def _get_likelihood_str(self) -> Optional[str]: - """Return the likelihood string.""" - return self._likelihood_str + def _set_likelihood_from_factory(self): + """Deserialize the likelihood.""" + assert self._likelihood_source is not None + assert self._likelihood_build_parameters is not None + likelihood, tools = load_likelihood( + self._likelihood_source, self._likelihood_build_parameters + ) + assert isinstance(likelihood, ConstGaussian) + assert isinstance(tools, ModelingTools) + self.likelihood = likelihood + self.tools = tools + self._configure_object() - def _set_likelihood_str(self, value: Optional[str]): - """Set the likelihood string.""" - self._likelihood_str = value + def _get_likelihood_source(self) -> Optional[str]: + """Return the likelihood string defining the factory function.""" + return self._likelihood_source + + def _set_likelihood_source(self, value: Optional[str]): + """Set the likelihood string defining the factory function.""" + + if value is not None: + self._likelihood_source = value + if self._starting_deserialization: + self._set_likelihood_from_factory() + self._starting_deserialization = False + else: + self._starting_deserialization = True + + likelihood_source = GObject.Property( + type=str, + flags=GObject.ParamFlags.READWRITE, + getter=_get_likelihood_source, + setter=_set_likelihood_source, + ) + + def _get_likelihood_build_parameters(self) -> Optional[Ncm.VarDict]: + """Return the likelihood build parameters.""" + if self._likelihood_build_parameters is None: + return None + return dict_to_var_dict( + self._likelihood_build_parameters.convert_to_basic_dict() + ) + + def _set_likelihood_build_parameters(self, value: Optional[Ncm.VarDict]): + """Set the likelihood build parameters.""" + self._likelihood_build_parameters = NamedParameters() if value is not None: - likelihood_source, build_parameters = pickle.loads( - base64.b64decode(value.encode("ascii")) + self._likelihood_build_parameters.set_from_basic_dict( + var_dict_to_dict(value) ) - likelihood, tools = load_likelihood(likelihood_source, build_parameters) - assert isinstance(likelihood, ConstGaussian) - self.likelihood = likelihood - self.tools = tools - self._configure_object() + if self._starting_deserialization: + self._set_likelihood_from_factory() + self._starting_deserialization = False + else: + self._starting_deserialization = True - likelihood_str = GObject.Property( - type=str, - flags=GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT, - getter=_get_likelihood_str, - setter=_set_likelihood_str, + likelihood_build_parameters = GObject.Property( + type=Ncm.VarDict, + flags=GObject.ParamFlags.READWRITE, + getter=_get_likelihood_build_parameters, + setter=_set_likelihood_build_parameters, ) @classmethod @@ -560,7 +648,8 @@ def new_from_likelihood( model_list: List[str], tools: ModelingTools, nc_mapping: MappingNumCosmo, - likelihood_str: Optional[str] = None, + likelihood_source: Optional[str] = None, + likelihood_build_parameters: Optional[NamedParameters] = None, ): """Initialize a NumCosmoGaussCov object representing a Gaussian likelihood with a constant covariance.""" @@ -573,13 +662,17 @@ def new_from_likelihood( cls, model_list=model_list, nc_mapping=nc_mapping, - likelihood_str=None, + likelihood_source=None, + likelihood_build_parameters=None, ) + assert isinstance(nc_gauss_cov, NumCosmoGaussCov) + nc_gauss_cov.likelihood = likelihood nc_gauss_cov.tools = tools # pylint: disable=protected-access - nc_gauss_cov._likelihood_str = likelihood_str + nc_gauss_cov._likelihood_source = likelihood_source + nc_gauss_cov._likelihood_build_parameters = likelihood_build_parameters nc_gauss_cov._configure_object() # pylint: enable=protected-access @@ -635,7 +728,6 @@ def do_mean_func(self, _, mean_vector): This method should compute the theoretical mean for the gaussian distribution. """ - theory_vector = self.likelihood.compute_theory_vector(self.tools) mean_vector.set_array(theory_vector) @@ -662,18 +754,25 @@ def __init__( ): likelihood, tools = load_likelihood(likelihood_source, build_parameters) - likelihood_str = base64.b64encode( - pickle.dumps((likelihood_source, build_parameters)) - ).decode("ascii") - + self.data: Union[NumCosmoGaussCov, NumCosmoData] self.mapping: MappingNumCosmo = mapping if isinstance(likelihood, ConstGaussian): - self.data: Ncm.Data = NumCosmoGaussCov.new_from_likelihood( - likelihood, model_list, tools, mapping, likelihood_str + self.data = NumCosmoGaussCov.new_from_likelihood( + likelihood, + model_list, + tools, + mapping, + likelihood_source, + build_parameters, ) else: self.data = NumCosmoData.new_from_likelihood( - likelihood, model_list, tools, mapping, likelihood_str + likelihood, + model_list, + tools, + mapping, + likelihood_source, + build_parameters, ) def get_data(self) -> Ncm.Data: @@ -683,3 +782,7 @@ def get_data(self) -> Ncm.Data: def get_mapping(self) -> MappingNumCosmo: """This method return the current MappingNumCosmo.""" return self.mapping + + def get_firecrown_likelihood(self) -> Likelihood: + """This method returns the firecrown Likelihood.""" + return self.data.likelihood diff --git a/firecrown/likelihood/likelihood.py b/firecrown/likelihood/likelihood.py index 5d2c485c0..c2ad8b235 100644 --- a/firecrown/likelihood/likelihood.py +++ b/firecrown/likelihood/likelihood.py @@ -52,7 +52,7 @@ """ from __future__ import annotations -from typing import Mapping, Tuple, Union, Optional, Set +from typing import Mapping, Tuple, Union, Optional, Set, Dict, Sequence from abc import abstractmethod import types import warnings @@ -215,6 +215,64 @@ def to_set( """Return the contained data as a set.""" return set(self.data) + def set_from_basic_dict( + self, + basic_dict: Dict[ + str, + Union[ + str, float, int, bool, Sequence[float], Sequence[int], Sequence[bool] + ], + ], + ) -> None: + """Set the contained data from a dictionary of basic types.""" + + for key, value in basic_dict.items(): + if isinstance(value, (str, float, int, bool)): + self.data = dict(self.data, **{key: value}) + elif isinstance(value, Sequence): + if all(isinstance(v, float) for v in value): + self.data = dict(self.data, **{key: np.array(value)}) + elif all(isinstance(v, bool) for v in value): + self.data = dict( + self.data, **{key: np.array(value, dtype=np.int64)} + ) + elif all(isinstance(v, int) for v in value): + self.data = dict( + self.data, **{key: np.array(value, dtype=np.int64)} + ) + else: + raise ValueError(f"Invalid type for sequence value: {value}") + else: + raise ValueError(f"Invalid type for value: {value}") + + def convert_to_basic_dict( + self, + ) -> Dict[ + str, + Union[str, float, int, bool, Sequence[float], Sequence[int], Sequence[bool]], + ]: + """Convert a NamedParameters object to a dictionary of basic types.""" + basic_dict: Dict[ + str, + Union[ + str, float, int, bool, Sequence[float], Sequence[int], Sequence[bool] + ], + ] = {} + + for key, value in self.data.items(): + if isinstance(value, (str, float, int, bool)): + basic_dict[key] = value + elif isinstance(value, np.ndarray): + if value.dtype == np.int64: + basic_dict[key] = value.tolist() + elif value.dtype == np.float64: + basic_dict[key] = value.tolist() + else: + raise ValueError(f"Invalid type for sequence value: {value}") + else: + raise ValueError(f"Invalid type for value: {value}") + return basic_dict + def load_likelihood_from_module_type( module: types.ModuleType, build_parameters: NamedParameters diff --git a/tests/connector/numcosmo/conftest.py b/tests/connector/numcosmo/conftest.py index 556488bad..56f661f86 100644 --- a/tests/connector/numcosmo/conftest.py +++ b/tests/connector/numcosmo/conftest.py @@ -1,38 +1,10 @@ """Collection of fixtures for the numcosmo connector tests.""" +from typing import cast import math import pytest -from numcosmo_py import Nc - -from firecrown.connector.numcosmo.model import ( - NumCosmoModel, - ScalarParameter, - VectorParameter, - define_numcosmo_model, -) - - -@pytest.fixture(name="sparams") -def fixture_scalar_parameters(): - """Create a list of scalar parameters.""" - sp1 = ScalarParameter("s_1", "sp1", 0.0, 1.0, 0.1) - sp2 = ScalarParameter("s_2", "sp2", -1.0, 2.0, 0.1) - return [sp1, sp2] - - -@pytest.fixture(name="vparams") -def fixture_vector_parameters(): - """Create a list of vector parameters.""" - vp1 = VectorParameter(3, "v_1", "vp1", 0.0, 1.0, 0.1) - vp2 = VectorParameter(4, "v_2", "vp2", 0.0, 1.0, 0.1) - return [vp1, vp2] - - -@pytest.fixture(name="nc_model") -def fixture_nc_model(sparams, vparams): - """Create a NumCosmoModel instance.""" - return NumCosmoModel("model1", "model1 description", sparams, vparams) +from numcosmo_py import Nc, Ncm, GObject @pytest.fixture(name="numcosmo_cosmo_xcdm") @@ -135,11 +107,28 @@ def fixture_numcosmo_cosmo_cpl(): @pytest.fixture(name="nc_model_trivial", scope="session") def fixture_nc_model_trivial(): """Create a NumCosmoModel instance.""" - return define_numcosmo_model( - NumCosmoModel( - "NcFirecrownTrivial", - "Trivial model description", - [ScalarParameter(r"\mu", "mean", -5.0, 5.0, 0.1)], - [], - ) + my_model_trivial_yaml = r""" +NcmModelBuilder: + parent-type-string: 'NcmModel' + name: 'NcFirecrownTrivial' + description: 'Trivial model description' + sparams: + - NcmSParam: + name: 'mean' + symbol: '\mu' + lower-bound: -5.0 + upper-bound: 5.0 + scale: 1.0 + absolute-tolerance: 0.0 + default-value: 0.1 + fit-type: 0 +""" + ser = Ncm.Serialize.new(Ncm.SerializeOpt.NONE) + mb_model: Ncm.ModelBuilder = cast( + Ncm.ModelBuilder, ser.from_yaml(my_model_trivial_yaml) ) + assert isinstance(mb_model, Ncm.ModelBuilder) + model_type = mb_model.create() + GObject.new(model_type) + + return model_type.pytype diff --git a/tests/connector/numcosmo/test_numcosmo_connector.py b/tests/connector/numcosmo/test_numcosmo_connector.py index d3f0d20c8..cc8ca58d1 100644 --- a/tests/connector/numcosmo/test_numcosmo_connector.py +++ b/tests/connector/numcosmo/test_numcosmo_connector.py @@ -1,45 +1,268 @@ """Unit tests for the numcosmo connector.""" +import pytest from numcosmo_py import Ncm, Nc -from firecrown.connector.numcosmo.numcosmo import NumCosmoFactory, MappingNumCosmo +from firecrown.connector.numcosmo.numcosmo import ( + NumCosmoFactory, + MappingNumCosmo, + NumCosmoData, + NumCosmoGaussCov, +) -from firecrown.likelihood.likelihood import NamedParameters +from firecrown.likelihood.likelihood import NamedParameters, Likelihood Ncm.cfg_init() -def test_numcosmo_connector_plain(): - """Test the NumCosmo connector.""" - +@pytest.fixture(name="factory_plain") +def fixture_factory_plain(): + """Create a NumCosmoFactory instance.""" map_cosmo = MappingNumCosmo( require_nonlinear_pk=True, dist=Nc.Distance.new(6.0), ) - nc_factory = NumCosmoFactory( + build_parameters = NamedParameters() + return NumCosmoFactory( "tests/likelihood/lkdir/lkscript.py", - NamedParameters(), + build_parameters, map_cosmo, model_list=["non_existing_model"], ) - assert nc_factory.get_data() is not None - assert nc_factory.get_mapping() is not None - - -def test_numcosmo_connector_const_gauss(): - """Test the NumCosmo connector.""" +@pytest.fixture(name="factory_const_gauss") +def fixture_factory_const_gauss(): + """Create a NumCosmoFactory instance.""" map_cosmo = MappingNumCosmo( require_nonlinear_pk=True, dist=Nc.Distance.new(6.0), ) - nc_factory = NumCosmoFactory( + build_parameters = NamedParameters() + return NumCosmoFactory( "tests/likelihood/gauss_family/lkscript_const_gaussian.py", - NamedParameters(), + build_parameters, map_cosmo, model_list=["non_existing_model"], ) - assert nc_factory.get_data() is not None - assert nc_factory.get_mapping() is not None + +def test_numcosmo_connector_plain(factory_plain): + """Test the NumCosmo connector.""" + + assert factory_plain.get_data() is not None + assert factory_plain.get_mapping() is not None + + +def test_numcosmo_connector_const_gauss(factory_const_gauss): + """Test the NumCosmo connector.""" + + assert factory_const_gauss.get_data() is not None + assert factory_const_gauss.get_mapping() is not None + + +def test_numcosmo_factory_plain_get_firecrown_likelihood(factory_plain): + """Test the NumCosmo connector.""" + + assert factory_plain.get_data() is not None + assert factory_plain.get_mapping() is not None + + fc_likelihood = factory_plain.get_firecrown_likelihood() + assert fc_likelihood is not None + assert isinstance(fc_likelihood, Likelihood) + + +def test_numcosmo_factory_const_gauss_get_firecrown_likelihood(factory_const_gauss): + """Test the NumCosmo connector.""" + + assert factory_const_gauss.get_data() is not None + assert factory_const_gauss.get_mapping() is not None + + fc_likelihood = factory_const_gauss.get_firecrown_likelihood() + assert fc_likelihood is not None + assert isinstance(fc_likelihood, Likelihood) + + +def test_numcosmo_factory_plain_get_properties(factory_plain): + """Test the NumCosmo connector.""" + + nc_data = factory_plain.get_data() + + assert nc_data is not None + assert isinstance(nc_data, Ncm.Data) + assert isinstance(nc_data, NumCosmoData) + + assert nc_data.likelihood_source == "tests/likelihood/lkdir/lkscript.py" + assert isinstance(nc_data.likelihood_build_parameters, Ncm.VarDict) + + +def test_numcosmo_factory_const_gauss_get_properties(factory_const_gauss): + """Test the NumCosmo connector.""" + + nc_data = factory_const_gauss.get_data() + + assert nc_data is not None + assert isinstance(nc_data, Ncm.Data) + assert isinstance(nc_data, NumCosmoGaussCov) + + assert ( + nc_data.likelihood_source + == "tests/likelihood/gauss_family/lkscript_const_gaussian.py" + ) + assert isinstance(nc_data.likelihood_build_parameters, Ncm.VarDict) + + +def test_numcosmo_factory_plain_set_properties_order1(factory_plain): + """Test the NumCosmo connector.""" + + nc_data = factory_plain.get_data() + + assert nc_data is not None + assert isinstance(nc_data, Ncm.Data) + assert isinstance(nc_data, NumCosmoData) + + old_fc_likelihood = nc_data.likelihood + assert old_fc_likelihood is not None + assert isinstance(old_fc_likelihood, Likelihood) + + nc_data.likelihood_source = "tests/likelihood/lkdir/lkscript.py" + nc_data.likelihood_build_parameters = Ncm.VarDict.new() + + fc_likelihood = nc_data.likelihood + assert fc_likelihood is not None + assert isinstance(fc_likelihood, Likelihood) + assert fc_likelihood != old_fc_likelihood + + +def test_numcosmo_factory_plain_set_properties_order2(factory_plain): + """Test the NumCosmo connector.""" + + nc_data = factory_plain.get_data() + + assert nc_data is not None + assert isinstance(nc_data, Ncm.Data) + assert isinstance(nc_data, NumCosmoData) + + old_fc_likelihood = nc_data.likelihood + assert old_fc_likelihood is not None + assert isinstance(old_fc_likelihood, Likelihood) + + nc_data.likelihood_build_parameters = Ncm.VarDict.new() + nc_data.likelihood_source = "tests/likelihood/lkdir/lkscript.py" + + fc_likelihood = nc_data.likelihood + assert fc_likelihood is not None + assert isinstance(fc_likelihood, Likelihood) + assert fc_likelihood != old_fc_likelihood + + +def test_numcosmo_factory_plain_set_properties_empty_build_parameters(factory_plain): + """Test the NumCosmo connector.""" + + nc_data = factory_plain.get_data() + + assert nc_data is not None + assert isinstance(nc_data, Ncm.Data) + assert isinstance(nc_data, NumCosmoData) + + old_fc_likelihood = nc_data.likelihood + assert old_fc_likelihood is not None + assert isinstance(old_fc_likelihood, Likelihood) + + nc_data.likelihood_source = "tests/likelihood/lkdir/lkscript.py" + nc_data.likelihood_build_parameters = None + + fc_likelihood = nc_data.likelihood + assert fc_likelihood is not None + assert isinstance(fc_likelihood, Likelihood) + assert fc_likelihood != old_fc_likelihood + + +def test_numcosmo_factory_const_gauss_set_properties_order1(factory_const_gauss): + """Test the NumCosmo connector.""" + + nc_data = factory_const_gauss.get_data() + + assert nc_data is not None + assert isinstance(nc_data, Ncm.Data) + assert isinstance(nc_data, NumCosmoGaussCov) + + old_fc_likelihood = nc_data.likelihood + assert old_fc_likelihood is not None + assert isinstance(old_fc_likelihood, Likelihood) + + nc_data.likelihood_source = ( + "tests/likelihood/gauss_family/lkscript_const_gaussian.py" + ) + nc_data.likelihood_build_parameters = Ncm.VarDict.new() + + fc_likelihood = nc_data.likelihood + assert fc_likelihood is not None + assert isinstance(fc_likelihood, Likelihood) + assert fc_likelihood != old_fc_likelihood + + +def test_numcosmo_factory_const_gauss_set_properties_order2(factory_const_gauss): + """Test the NumCosmo connector.""" + + nc_data = factory_const_gauss.get_data() + + assert nc_data is not None + assert isinstance(nc_data, Ncm.Data) + assert isinstance(nc_data, NumCosmoGaussCov) + + old_fc_likelihood = nc_data.likelihood + assert old_fc_likelihood is not None + assert isinstance(old_fc_likelihood, Likelihood) + + nc_data.likelihood_build_parameters = Ncm.VarDict.new() + nc_data.likelihood_source = ( + "tests/likelihood/gauss_family/lkscript_const_gaussian.py" + ) + + fc_likelihood = nc_data.likelihood + assert fc_likelihood is not None + assert isinstance(fc_likelihood, Likelihood) + assert fc_likelihood != old_fc_likelihood + + +def test_numcosmo_factory_const_gauss_set_properties_empty_build_parameters( + factory_const_gauss, +): + """Test the NumCosmo connector.""" + + nc_data = factory_const_gauss.get_data() + + assert nc_data is not None + assert isinstance(nc_data, Ncm.Data) + assert isinstance(nc_data, NumCosmoGaussCov) + + old_fc_likelihood = nc_data.likelihood + assert old_fc_likelihood is not None + assert isinstance(old_fc_likelihood, Likelihood) + + nc_data.likelihood_source = ( + "tests/likelihood/gauss_family/lkscript_const_gaussian.py" + ) + nc_data.likelihood_build_parameters = None + + fc_likelihood = nc_data.likelihood + assert fc_likelihood is not None + assert isinstance(fc_likelihood, Likelihood) + assert fc_likelihood != old_fc_likelihood + + +def test_empty_plain_data(): + """Test the NumCosmo connector.""" + + nc_data = NumCosmoData() + assert nc_data.likelihood_source is None + assert nc_data.likelihood_build_parameters is None + + +def test_empty_gauss_cov_data(): + """Test the NumCosmo connector.""" + + nc_data = NumCosmoGaussCov() + assert nc_data.likelihood_source is None + assert nc_data.likelihood_build_parameters is None diff --git a/tests/connector/numcosmo/test_numcosmo_mapping.py b/tests/connector/numcosmo/test_numcosmo_mapping.py index 8d494a219..9b1558415 100644 --- a/tests/connector/numcosmo/test_numcosmo_mapping.py +++ b/tests/connector/numcosmo/test_numcosmo_mapping.py @@ -1,8 +1,9 @@ """Unit tests for the numcosmo Mapping connector.""" +from typing import cast import pytest import pyccl as ccl -from numcosmo_py import Ncm, Nc +from numcosmo_py import Ncm, Nc, GObject from firecrown.likelihood.likelihood import Likelihood, NamedParameters from firecrown.likelihood.gauss_family.gaussian import ConstGaussian @@ -14,12 +15,6 @@ NumCosmoFactory, ) -from firecrown.connector.numcosmo.model import ( - NumCosmoModel, - ScalarParameter, - define_numcosmo_model, -) - Ncm.cfg_init() @@ -58,18 +53,9 @@ def test_numcosmo_mapping_create_params_map_absent_model(): mset = Ncm.MSet() mset.set(cosmo) - my_model_dc = NumCosmoModel( - name="MyModel", description="MyModel desc", scalar_params=[], vector_params=[] - ) - - MyModel = define_numcosmo_model(my_model_dc) - - my_model = MyModel() - del my_model - with pytest.raises( RuntimeError, - match="Model MyModel was not found in the model set.", + match="Model name MyModel was not found in the model set.", ): map_cosmo.create_params_map(["MyModel"], mset) @@ -88,26 +74,66 @@ def test_numcosmo_mapping_create_params_map_two_models_sharing_parameters(): mset = Ncm.MSet() mset.set(cosmo) - my_model1_dc = NumCosmoModel( - name="MyModel1", - description="MyModel1 desc", - scalar_params=[ - ScalarParameter(symbol="symbol1", name="param1", default_value=1.0), - ScalarParameter(symbol="symbol2", name="param2", default_value=1.0), - ], - vector_params=[], + my_model1_dc_yaml = r""" +NcmModelBuilder: + parent-type-string: 'NcmModel' + name: 'MyModel1' + description: 'My Test Model 1' + sparams: + - NcmSParam: + name: 'param1' + symbol: 'symbol1' + lower-bound: -5.0 + upper-bound: 5.0 + scale: 1.0 + absolute-tolerance: 0.0 + default-value: 1.0 + fit-type: 0 + - NcmSParam: + name: 'param2' + symbol: 'symbol2' + lower-bound: -5.0 + upper-bound: 5.0 + scale: 1.0 + absolute-tolerance: 0.0 + default-value: 1.0 + fit-type: 0 +""" + + my_model2_dc_yaml = r""" +NcmModelBuilder: + parent-type-string: 'NcmModel' + name: 'MyModel2' + description: 'My Test Model 2' + sparams: + - NcmSParam: + name: 'param2' + symbol: 'symbol2' + lower-bound: -5.0 + upper-bound: 5.0 + scale: 1.0 + absolute-tolerance: 0.0 + default-value: 1.0 + fit-type: 0 +""" + + ser = Ncm.Serialize.new(Ncm.SerializeOpt.NONE) + mb_model1: Ncm.ModelBuilder = cast( + Ncm.ModelBuilder, ser.from_yaml(my_model1_dc_yaml) ) - my_model2_dc = NumCosmoModel( - name="MyModel2", - description="MyModel2 desc", - scalar_params=[ - ScalarParameter(symbol="symbol2", name="param2", default_value=1.0), - ], - vector_params=[], + assert isinstance(mb_model1, Ncm.ModelBuilder) + model1_type = mb_model1.create() + GObject.new(model1_type) + + mb_model2: Ncm.ModelBuilder = cast( + Ncm.ModelBuilder, ser.from_yaml(my_model2_dc_yaml) ) + assert isinstance(mb_model2, Ncm.ModelBuilder) + model2_type = mb_model2.create() + GObject.new(model2_type) - MyModel1 = define_numcosmo_model(my_model1_dc) - MyModel2 = define_numcosmo_model(my_model2_dc) + MyModel1 = model1_type.pytype + MyModel2 = model2_type.pytype my_model1 = MyModel1() my_model2 = MyModel2() diff --git a/tests/connector/numcosmo/test_numcosmo_model.py b/tests/connector/numcosmo/test_numcosmo_model.py deleted file mode 100644 index fdd8270f0..000000000 --- a/tests/connector/numcosmo/test_numcosmo_model.py +++ /dev/null @@ -1,57 +0,0 @@ -"""Unit tests for the numcosmo model connector.""" - -import yaml -from firecrown.connector.numcosmo.model import ( - define_numcosmo_model, -) - - -def test_parameterless_module_construction(nc_model): - """Test NumCosmoModel construction.""" - - MyModel = define_numcosmo_model(nc_model) - - m = MyModel() - - assert m is not None - - n_scalar_params = len(nc_model.scalar_params) - assert m.sparam_len() == n_scalar_params - - for i, sparam in enumerate(nc_model.scalar_params): - assert m.param_name(i) == sparam.name - assert m.param_symbol(i) == sparam.symbol - assert m.param_get(i) == sparam.default_value - assert m.param_get_scale(i) == sparam.scale - assert m.param_get_lower_bound(i) == sparam.lower_bound - assert m.param_get_upper_bound(i) == sparam.upper_bound - - i = n_scalar_params - for vparam in nc_model.vector_params: - for j in range(vparam.default_length): - assert m.param_name(i) == f"{vparam.name}_{j}" - assert m.param_symbol(i) == f"{{{vparam.symbol}}}_{j}" - assert m.param_get(i) == vparam.default_value - assert m.param_get_scale(i) == vparam.scale - assert m.param_get_lower_bound(i) == vparam.lower_bound - assert m.param_get_upper_bound(i) == vparam.upper_bound - i += 1 - - -def test_model_save_load(tmp_path, nc_model): - """Test saving and loading a NumCosmo model.""" - - with open( - tmp_path / r"numcosmo_firecrown_model.yml", "w", encoding="utf-8" - ) as modelfile: - yaml.dump(nc_model, modelfile, Dumper=yaml.Dumper) - - with open( - tmp_path / r"numcosmo_firecrown_model.yml", "r", encoding="utf-8" - ) as modelfile: - model_copy = yaml.load(modelfile, Loader=yaml.Loader) - - assert model_copy.name == nc_model.name - assert model_copy.description == nc_model.description - assert model_copy.scalar_params == nc_model.scalar_params - assert model_copy.vector_params == nc_model.vector_params diff --git a/tests/likelihood/test_named_parameters.py b/tests/likelihood/test_named_parameters.py index 0b5ee1a68..5d5f72187 100644 --- a/tests/likelihood/test_named_parameters.py +++ b/tests/likelihood/test_named_parameters.py @@ -154,3 +154,208 @@ def test_named_parameters_wrong_type_float_array(): # Float arrays are int arrays in python # with pytest.raises(AssertionError): # params.get_int_array("a") + + +def test_named_parameters_set_from_basic_dict_string(): + params = NamedParameters() + params.set_from_basic_dict({"a": "Im a string"}) + assert params.get_string("a") == "Im a string" + + params.set_from_basic_dict({"b": "Im another string"}) + assert params.get_string("a") == "Im a string" + assert params.get_string("b") == "Im another string" + + +def test_named_parameters_set_from_basic_dict_int(): + params = NamedParameters() + params.set_from_basic_dict({"a": 1}) + assert params.get_int("a") == 1 + + params.set_from_basic_dict({"b": 2}) + assert params.get_int("a") == 1 + assert params.get_int("b") == 2 + + +def test_named_parameters_set_from_basic_dict_float(): + params = NamedParameters() + params.set_from_basic_dict({"a": 1.0}) + assert params.get_float("a") == 1.0 + + params.set_from_basic_dict({"b": 2.0}) + assert params.get_float("a") == 1.0 + assert params.get_float("b") == 2.0 + + +def test_named_parameters_set_from_basic_dict_bool(): + params = NamedParameters() + params.set_from_basic_dict({"a": True}) + assert params.get_bool("a") is True + + params.set_from_basic_dict({"b": False}) + assert params.get_bool("a") is True + assert params.get_bool("b") is False + + +def test_named_parameters_set_from_basic_dict_int_array(): + params = NamedParameters() + params.set_from_basic_dict({"a": [1, 2, 3]}) + assert params.get_int_array("a").tolist() == [1, 2, 3] + + params.set_from_basic_dict({"b": [4, 5, 6]}) + assert params.get_int_array("a").tolist() == [1, 2, 3] + assert params.get_int_array("b").tolist() == [4, 5, 6] + + +def test_named_parameters_set_from_basic_dict_float_array(): + params = NamedParameters() + params.set_from_basic_dict({"a": [1.0, 2.0, 3.0]}) + assert params.get_float_array("a").tolist() == [1.0, 2.0, 3.0] + + params.set_from_basic_dict({"b": [4.0, 5.0, 6.0]}) + assert params.get_float_array("a").tolist() == [1.0, 2.0, 3.0] + assert params.get_float_array("b").tolist() == [4.0, 5.0, 6.0] + + +def test_named_parameters_set_from_basic_dict_bool_array(): + params = NamedParameters() + params.set_from_basic_dict({"a": [True, False, True]}) + assert params.get_int_array("a").tolist() == [True, False, True] + + params.set_from_basic_dict({"b": [False, True, False]}) + assert params.get_int_array("a").tolist() == [True, False, True] + assert params.get_int_array("b").tolist() == [False, True, False] + + +def test_named_parameters_set_from_basic_dict_mixed(): + params = NamedParameters() + params.set_from_basic_dict( + { + "a": [1, 2, 3], + "b": [1.0, 2.0, 3.0], + "c": "Im a string", + "d": 1, + "e": 1.0, + "f": True, + } + ) + assert params.get_int_array("a").tolist() == [1, 2, 3] + assert params.get_float_array("b").tolist() == [1.0, 2.0, 3.0] + assert params.get_string("c") == "Im a string" + assert params.get_int("d") == 1 + assert params.get_float("e") == 1.0 + assert params.get_bool("f") is True + + +def test_named_parameters_convert_to_basic_dict_string(): + params = NamedParameters({"a": "Im a string"}) + assert params.convert_to_basic_dict() == {"a": "Im a string"} + + params = NamedParameters({"a": "Im a string", "b": "Im another string"}) + assert params.convert_to_basic_dict() == { + "a": "Im a string", + "b": "Im another string", + } + + +def test_named_parameters_convert_to_basic_dict_int(): + params = NamedParameters({"a": 1}) + assert params.convert_to_basic_dict() == {"a": 1} + + params = NamedParameters({"a": 1, "b": 2}) + assert params.convert_to_basic_dict() == {"a": 1, "b": 2} + + +def test_named_parameters_convert_to_basic_dict_float(): + params = NamedParameters({"a": 1.0}) + assert params.convert_to_basic_dict() == {"a": 1.0} + + params = NamedParameters({"a": 1.0, "b": 2.0}) + assert params.convert_to_basic_dict() == {"a": 1.0, "b": 2.0} + + +def test_named_parameters_convert_to_basic_dict_bool(): + params = NamedParameters({"a": True}) + assert params.convert_to_basic_dict() == {"a": True} + + params = NamedParameters({"a": True, "b": False}) + assert params.convert_to_basic_dict() == {"a": True, "b": False} + + +def test_named_parameters_convert_to_basic_dict_int_array(): + params = NamedParameters({"a": np.array([1, 2, 3])}) + assert params.convert_to_basic_dict() == {"a": [1, 2, 3]} + + params = NamedParameters({"a": np.array([1, 2, 3]), "b": np.array([4, 5, 6])}) + assert params.convert_to_basic_dict() == { + "a": [1, 2, 3], + "b": [4, 5, 6], + } + + +def test_named_parameters_convert_to_basic_dict_float_array(): + params = NamedParameters({"a": np.array([1.0, 2.0, 3.0])}) + assert params.convert_to_basic_dict() == {"a": [1.0, 2.0, 3.0]} + + params = NamedParameters( + {"a": np.array([1.0, 2.0, 3.0]), "b": np.array([4.0, 5.0, 6.0])} + ) + assert params.convert_to_basic_dict() == { + "a": [1.0, 2.0, 3.0], + "b": [4.0, 5.0, 6.0], + } + + +def test_named_parameters_convert_to_basic_dict_mixed(): + params = NamedParameters( + { + "a": np.array([1, 2, 3]), + "b": np.array([1.0, 2.0, 3.0]), + "c": "Im a string", + "d": 1, + "e": 1.0, + "f": True, + } + ) + assert params.convert_to_basic_dict() == { + "a": [1, 2, 3], + "b": [1.0, 2.0, 3.0], + "c": "Im a string", + "d": 1, + "e": 1.0, + "f": True, + } + + +def test_named_parameters_to_set(): + params = NamedParameters({"a": True}) + assert params.to_set() == {"a"} + + params = NamedParameters({"a": True, "b": False}) + assert params.to_set() == {"a", "b"} + + params = NamedParameters({"a": True, "b": False, "c": True}) + assert params.to_set() == {"a", "b", "c"} + + +def test_invalid_set_from_basic_dict(): + params = NamedParameters() + with pytest.raises(ValueError): + params.set_from_basic_dict({"a": {"b": "c"}}) # type: ignore + + +def test_invalid_set_from_basic_dict_sequence(): + params = NamedParameters() + with pytest.raises(ValueError): + params.set_from_basic_dict({"a": ["a", "b", "c"]}) # type: ignore + + +def test_invalid_convert_to_basic_dict(): + params = NamedParameters({"a": {"b": "c"}}) # type: ignore + with pytest.raises(ValueError): + params.convert_to_basic_dict() + + +def test_invalid_convert_to_basic_dict_sequence(): + params = NamedParameters({"a": np.array(["a", "b", "c"])}) + with pytest.raises(ValueError): + params.convert_to_basic_dict()