{"id":23541289,"url":"https://github.com/blsqr/paramspace","last_synced_at":"2025-08-17T21:37:01.078Z","repository":{"id":146269872,"uuid":"223982639","full_name":"blsqr/paramspace","owner":"blsqr","description":"Python package for dictionary-based, multi-dimensional parameter space definition and iteration, which can be conveniently defined using YAML — NOTE: This repo is MIRRORED! The development project and issue tracker can be found here:","archived":false,"fork":false,"pushed_at":"2025-01-15T09:44:24.000Z","size":584,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-03T20:05:29.389Z","etag":null,"topics":["dictionary","iteration","modeling","python","python3","scientific-workflows","tools","yaml"],"latest_commit_sha":null,"homepage":"https://gitlab.com/blsqr/paramspace","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blsqr.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-11-25T15:36:10.000Z","updated_at":"2021-10-01T11:47:08.000Z","dependencies_parsed_at":"2024-08-10T09:27:09.073Z","dependency_job_id":"b14f055b-11b0-487b-ad90-9e271a540f33","html_url":"https://github.com/blsqr/paramspace","commit_stats":null,"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"purl":"pkg:github/blsqr/paramspace","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blsqr%2Fparamspace","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blsqr%2Fparamspace/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blsqr%2Fparamspace/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blsqr%2Fparamspace/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blsqr","download_url":"https://codeload.github.com/blsqr/paramspace/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blsqr%2Fparamspace/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265365981,"owners_count":23753430,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dictionary","iteration","modeling","python","python3","scientific-workflows","tools","yaml"],"created_at":"2024-12-26T05:14:57.082Z","updated_at":"2025-07-14T23:10:37.228Z","avatar_url":"https://github.com/blsqr.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![PyPI](https://img.shields.io/pypi/v/paramspace)](https://pypi.org/project/paramspace/)\n[![conda-forge](https://img.shields.io/conda/vn/conda-forge/paramspace)](https://anaconda.org/conda-forge/paramspace)\n[![Python Versions](https://img.shields.io/pypi/pyversions/paramspace)](https://pypi.org/project/paramspace/)\n[![Documentation](https://img.shields.io/readthedocs/paramspace)](https://paramspace.readthedocs.io/en/latest/)\n[![License](https://img.shields.io/pypi/l/paramspace)](https://opensource.org/licenses/BSD-2-Clause)\n[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3826470.svg)](https://doi.org/10.5281/zenodo.3826470)\n\n[![Pipeline Status](https://gitlab.com/blsqr/paramspace/badges/master/pipeline.svg)](https://gitlab.com/blsqr/paramspace/commits/master)\n[![Coverage](https://gitlab.com/blsqr/paramspace/badges/master/coverage.svg)](https://gitlab.com/blsqr/paramspace/-/blob/master/tox.ini)\n[![Code Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n[![Pre-Commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen)](https://github.com/pre-commit/pre-commit)\n\n\n# The `paramspace` package\n\nThe `paramspace` package supplies classes that make it easy to iterate over a multi-dimensional parameter space while maintaining a data structure that is convenient for passing hierarchically structured arguments around: `dict`s.\n\nA parameter space is an `n`-dimensional space, where each dimension corresponds to one of `n` parameters and each point in this space represents a certain combination of parameter values.  \nIn modelling and simulations, it is often useful to be able to iterate over certain values of multiple parameters, creating a multi-dimensional, discrete parameter space.\nFor example, having a model with six parameters that are worth varying, an iteration would go over the cartesian product of all possible parameter values.\n(This is hinted at in the icon of this repository, a 2D representation of a 6-dimensional [hybercube](https://en.wikipedia.org/wiki/Hypercube)).\n\nTo that end, this package supplies the `ParamSpace` class, which is initialised with a Python `dict`; it holds the whole set of parameters that are required by a simulation (i.e., _not_ only those that correspond to a parameter dimension).\nTo add a parameter dimension that can be iterated over, an entry in the dictionary can be replaced by a `ParamDim` object, for which the discrete values to iterate over are defined.\n\nAfter initialisation of such a `ParamSpace` object, this package allows operations like the following:\n\n```python\nfor params in pspace:\n    run_my_simulation(**params)\n```\n\nThe `params` object is then a dictionary that holds the configuration of the simulation at one specific point in parameter space.  \nIn other words: each point in this parameter space refers to a specific state of the given dictionary of simulation parameters.\n\n#### Further features of the `paramspace` package\n* With the `default` argument to `ParamDim`, it is possible to define a default position in parameter space that is used when not iterating over the parameter space\n* The `order` argument allows ordering the `ParamDim` objects, such that it can be decided which dimensions are iterated over most frequently.\n* `ParamDim` values can be created from `range`, `np.linspace`, and `np.logspace`\n* With `ParamDim.mask` and `ParamSpace.set_mask`, a subspace of a parameter space can be selected for iteration.\n* Via `ParamSpace.state_map`, an [`xarray.DataArray`](http://xarray.pydata.org/en/stable/data-structures.html#dataarray) with labelled dimensions and coordinates is returned.\n* `CoupledParamDim` objects allow coupling one parameter in an iteration to another parameter dimension.\n* The `paramspace.yaml` object (based on [`ruamel.yaml.YAML`](https://yaml.readthedocs.io/en/latest/)) supplies the constructors and representers necessary to load or dump `paramspace` objects in YAML format. Defining parameter spaces via this interface is much more convenient than it is directly in Python.\n\n#### Contents of this README and further reading\n* Short [__installation instructions__](#install)\n* A few __usage examples__ are given [below](#usage). Note that a full documentation does not yet exist... but the docstrings are quite informative :)\n* For an overview over the __changes,__ see the [changelog](CHANGELOG.md).\n* A list of [__known issues__](#known-issues) with some classes\n* [Information for Developers](#information-for-developers)\n\n\n## Install\nThe `paramspace` package is tested for Python 3.6 - 3.10 and is available [on the Python Package Index](https://pypi.org/project/paramspace/) or [via `conda-forge`](https://anaconda.org/conda-forge/paramspace).\n\nYou can install it via `pip` or `conda` using the respective command:\n\n```bash\npip install paramspace\nconda install -c conda-forge paramspace\n```\n\n\n### For Developers\nFor installation of versions that are not on the PyPI, `pip` allows specifying a git repository:\n\n```bash\n$ pip3 install git+\u003cclone-URL\u003e@\u003csome-branch-name\u003e\n```\n\nHere, replace `\u003cclone-URL\u003e` with the repositories clone URL and specify the branch you want to install the package from.\nAlternatively, omit the `@` and everything after it.\n\nFor local development and testing, it's best to clone this repository and install it (in editable mode) from the local directory:\n```bash\n$ git clone \u003cclone-URL\u003e\n$ pip3 install -e paramspace/\n```\n\n\n## Usage\n\n### Basics\nThe example below illustrates how `ParamDim` and `ParamSpace` objects can be created and used together.\n\n```python\nfrom paramspace import ParamSpace, ParamDim\n\n# Create the parameter dictionary, values for differently shaped cylinders\ncylinders = dict(pi=3.14159,\n                 r=ParamDim(default=1, values=[1, 2, 3, 5, 10]),\n                 h=ParamDim(default=1, linspace=[0, 10, 11]))\n\n# Define the volume calculation function\ndef calc_cylinder_vol(*, pi, r, h):\n    return pi * (r**2) * h\n\n# Initialise the parameter space\npspace = ParamSpace(cylinders)\n\n# Iterate over it, using the parameters to calculate the cylinder's volume\nfor params in pspace:\n    print(\"Height: {},   Radius: {}\".format(params['h'], params['r']))\n    vol = calc_cylinder_vol(**params)  # Really handy way of passing params :)\n    print(\"  --\u003e Volume: {}\".format(vol))\n```\n\n### Using the power of YAML\nWhile the above way is possible, using the capabilities of the `yaml` module make defining `ParamSpace` objects much more convenient.\n\nSay we have a configuration file that is to be given to our simulation function. With the YAML constructors implemented in this package, we can construct `ParamDim` and `ParamSpace` objects right inside the file where we define all the other parameters: just by adding a `!pspace` and `!pdim` tag to a mapping.\n\n```yaml\n# This is the configuration file for my simulation\n---\nsim_name: my_first_sim\nout_dir: ~/sim_output/{date:}\n\nsim_params: !pspace    # \u003c- will construct a ParamSpace from what is inside\n\n  # Define a number of simulation seeds\n  seed: !pdim          # \u003c- will create a parameter dimension with seeds 0...22\n    default: 0\n    range: [23]\n\n  some_param: 1.23\n  some_params_to_pass_along:\n    num_agents: !pdim  # \u003c- creates values: 10, 32, 100, 316, 1000, 3162, ...\n      default: 100\n      logspace: [1, 5, 9]\n      as_type: int\n\n  more_params:\n    foo: 42\n    deep:\n      down:\n        magic_number: !pdim\n          default: 2\n          values: [2, 8, 20, 28, 50, 82, 126]\n\n    # Can also have parameter dimensions inside a sequence\n    things_to_do:\n      - do_this\n      - do_that\n      - !pdim\n        default: do_some_thing\n        values:\n          - do_foo\n          - do_bar\n          - do_spam\n      - do_final_things\n\n  # ... and so on\n```\n\nWe can now load this file and will already have the `ParamSpace` constructed:\n\n```python\nfrom paramspace import yaml\n\nwith open(\"path/to/cfg.yml\", mode='r') as cfg_file:\n    cfg = yaml.load(cfg_file)\n\n# cfg is now a dict with keys: sim_name, out_dir, sim_params, ...\n\n# Get the ParamSpace object and print some information\npspace = cfg['sim_params']\nprint(\"Received parameter space with volume\", pspace.volume)\nprint(pspace.get_info_str())\n\n# Now perform the iteration and run the simulations\nprint(\"Starting simulation '{}' ...\".format(cfg['sim_name']))\nfor params in pspace:\n    run_my_simulation(**params)\n```\n\n#### Comments\n* The yaml constructors supply full functionality. It is highly recommended to use them. Additional constructors are:\n   * `!pdim-default`: returns the default value _instead_ of the `ParamDim` object; convenient to deactivate a dimension completely.\n   * `!coupled-pdim` and `!coupled-pdim-default` have the analogue behaviour, just with `CoupledParamDim`.\n* The `yaml` object can also be used to `yaml.dump` the configuration into a yaml file again.\n* There is the possibility to iterate and get information about the current state of the parameter space alongside the current value. For that, use the `ParamSpace.iterate` method.\n\n\n## Known issues\n* `CoupledParamDim` objects are implemented a bit inconsistently:\n   * They behave in some cases not equivalent to regular `ParamDim` objects, e.g., they cannot be iterated over on their own (in fact, this will lead to an infinite loop).\n   * Their `mask` behaviour might be unexpected.\n   * Within a `ParamSpace`, they are mostly hidden from the user. The iteration over parameter space works reliably, but they are, e.g., not accessible within the state maps.\n* YAML representation is quite fragile, especially for `CoupledParamDim`. This\n  will require some rewriting sooner or later, quite possibly accompanied by an\n  interface change ...\n* [#47](https://gitlab.com/blsqr/paramspace/-/issues/47): When defining `ParamDim` inside a YAML mapping or sequence that is also an anchor, it may occur multiple times inside `ParamDim`, thus leading to an infinite iteration. (Workaround introduced in [!44](https://gitlab.com/blsqr/paramspace/-/merge_requests/44).)\n\nFor more information, see the [issue tracker](https://gitlab.com/blsqr/paramspace/-/issues).\n\n\n## Information for Developers\n### Dependencies\nWhen developing for `paramspace`, additionally install the test and development dependencies:\n\n```bash\npip install -e .[test,dev]\n```\n\n\n### Tests\nTests are implemented using [`pytest`](https://github.com/pytest-dev/pytest).\n\nInvoke the following command to run tests and see the coverage report:\n\n```bash\npython -m pytest -xv tests/ --cov=paramspace --cov-report=term-missing\n```\n\nAdditionally, [`tox`](https://github.com/tox-dev/tox) is used in the GitLab CI pipeline to test against various Python versions.\n\n\n### Code Formatting\nThis package uses [`black`](https://github.com/psf/black) for formatting.\nTo run it, simply invoke:\n\n```bash\nblack .\n```\n\n(Yes, it's uncompromising.)\n\n_Note:_ Code formatting is part of the [commit hooks](#commit-hooks), so you won't have to invoke this separately.\n\n\n### Commit Hooks\nA number of [`pre-commit`](https://pre-commit.com) hooks are configured to make development more convenient.\nWith the development dependencies installed as described above, the git commit hook can be installed by invoking:\n\n```bash\npre-commit install\n```\n\nUpon invoking `git commit` the first time, the corresponding dependencies will be installed and the hooks will be executed.\nIf they fail, make sure that no unexpected changes were performed.\n\nYou can also run the hooks on all files, prior to committing:\n\n```bash\npre-commit run -a\n```\n\nFor more details about currently configured hooks, see [`.pre-commit-config.yaml`](.pre-commit-config.yaml).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblsqr%2Fparamspace","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblsqr%2Fparamspace","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblsqr%2Fparamspace/lists"}