{"id":16518646,"url":"https://github.com/darothen/experiment","last_synced_at":"2025-10-03T13:03:46.617Z","repository":{"id":73364302,"uuid":"76286975","full_name":"darothen/experiment","owner":"darothen","description":"Organizing numerical model experiment output","archived":false,"fork":false,"pushed_at":"2017-07-29T19:48:28.000Z","size":145,"stargazers_count":7,"open_issues_count":14,"forks_count":3,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-01-29T17:12:41.517Z","etag":null,"topics":["climate","data","model","science"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/darothen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2016-12-12T19:09:40.000Z","updated_at":"2023-01-20T13:38:25.000Z","dependencies_parsed_at":"2023-09-24T15:06:17.927Z","dependency_job_id":null,"html_url":"https://github.com/darothen/experiment","commit_stats":{"total_commits":22,"total_committers":2,"mean_commits":11.0,"dds":0.09090909090909094,"last_synced_commit":"660bc7b8efecdadf1e058231efe60b58bb9507eb"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darothen%2Fexperiment","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darothen%2Fexperiment/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darothen%2Fexperiment/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darothen%2Fexperiment/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/darothen","download_url":"https://codeload.github.com/darothen/experiment/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219860031,"owners_count":16556029,"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":["climate","data","model","science"],"created_at":"2024-10-11T16:37:16.665Z","updated_at":"2025-10-03T13:03:46.519Z","avatar_url":"https://github.com/darothen.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# experiment: Managing modeling experiment output\n\n[![Build Status](https://travis-ci.org/darothen/experiment.svg?branch=master)](https://travis-ci.org/darothen/experiment)\n\n**experiment** is designed to help you manage your modeling/data analysis workflows using [xarray][].\n\n[xarray]: http://xarray.pydata.org/en/stable/\n\n## Example Scenario\n\nSuppose you've performed a set of climate model simulations with one particular model. In those simulations, you've looked at two emissions scenarios (a \"high\" and a \"low\" emissions case) and you've used three different values for some tuned parameter in the model (let's call them \"x\", \"y\", and \"z\"). Each simulation produces the same set of output tapes on disk, which you've conveniently arranged in the following hierarchical folder layout:\n\n```\nhigh_emis/\n         /param_x\n         /param_y\n         /param_z\nlow_emis/\n        /param_x\n        /param_y\n        /param_z\n```\n\nEach output file has a simple naming scheme which reflects the parameter choices, so for instance surface temperature output for one simulation is in a file named `low.x.TS.nc` under **low_emis/param_x/**.\n\nThe idea underpinning **experiment** is that it should be really easy to analyze this data, and you shouldn't have to spend time writing lots of boilerplate code to load and process your simulations. You went through the hassle to organize your data in a logical manner (which you're doing for reproducibility anyway, right?) - why not leverage that organization to help you out?\n\n## Example Usage\n\n**experiment** lets you describe how your data is organized on disk by defining `Case`s and an `Experiment`. In the example above, we have two `Case`s: an emissions scenario, and a set of values for a given parameter. We record this calling *Case* with a short name (alias), long-name, and set of values:\n\n``` python\nfrom experiment import Case\n\nemis = Case(\"emis\", \"Emissions Scenario\", ['low', 'high'])\nparam = Case(\"param\", \"Tuning Parameter\", ['x', 'y', 'z'])\n```\n\nThe values should correspond to how the output files (or folders) are labeled on disk, using any set of alphanumeric strings. For instance, if the parameter values were 1.5, 2.0, and 4.0, you could encode them as string versions of those numbers, or something like \"1p5\", \"2p5\", and \"4p5\" if that's more convenient.\n\nA collection of `Case`s constitutes an `Experiment`. An `Experiment` defines where the data exists on disk, and uses simple Python format strings to define the naming schema for the directory structure and files. In our example, the **case_path** is a tree-structure, \"emis_{emis}/param_{param}\", where the curly-braced parameters correspond to the short names of the `Case`s we previously defined. At each of these directories, we have files which look like \"{emis}.{param}.\\_\\_\\_.nc\". The \"\\_\\_\\_\" is a placeholder for some identifying label (usually a variable name, if you've saved your data in timeseries format, or a timestamp if in timeslice format), and the surrounding bits (*including* the \".\") are an **output_prefix** and **output_suffix**, respectively.\n\nUsing this information, we can create an `Experiment` to access our data:\n\n``` python\nfrom experiment import Experiment\n\nmy_experiment = Experiment(\n    name='my_climate_experiment',\n    cases=[emis, param],\n    data_dir='/path/to/my/data',\n    case_path=\"emis_{emis}/param_{param}\",\n    output_prefix=\"{emis}.{param}.\",\n    output_suffix=\".nc\"\n)\n```\n\n*my_experiment* has useful helper methods which let you quickly construct filenames to individual parts of your dataset, or iterate over different components.\n\nThe real advantage that **experiment** provides is its flexibility in defining the paths to your data. You can use almost any naming/organizational scheme, such as:\n\n- a single folder with all the metadata contained in the filenames\n- hierarchical folders but incomplete (or missing) metadata in filenames\n- data stored in different places on disk or a cluster\n\nIn the latter case, you could point an `Experiment` to an arbitrary **case_path**, and build a symlinked hierarchy to your data.\n\n## Loading data\n\nThe point behind having an `Experiment` object is to be able to quickly load your data. We can do that with the `Experiment.load()` function, which will return a dictionary of `Dataset`s, each one indexed by a tuple of the case values corresponding to it.\n\n``` python\ndata = my_experiment.load(\"TS\")\n```\n\nThis is useful for organizing your data for further analysis. You can pass a function to the **preprocess** kwarg, and it will be applied to each loaded `Dataset` before loaded into memory. Optionally, you can also pass **master=True** to the `load()` function, which will concatenate the data on new dimensions into a \"master\" dataset that contains all of your data. Preprocessing is applied before the dataset is concatenated, to reduce the memory overhead.\n\n## Saving Experiments\n\nAn `Experiment` can also be directly read from disk in **.yml** format. The case here would serialize to\n\n``` yaml\n---\n# Sample Experiment configuration\nname: my_experiment\ncases:\n    emis:\n        longname: Emissions Scenario\n        vals:\n            - high\n            - low\n    param:\n        longname: Tuning Parameter\n        vals: [x, y, z]\ndata_dir: /path/to/my/data\n# Be sure to use single-quotes here so you don't have to escape the\n# braces\ncase_path: 'emis_{emis}/param_{param}'\noutput_prefix: '{emis}.{param}.'\noutput_suffix: '.nc'\n...\n```\n\nwhich can be directly loaded into an `Experiment` via\n\n``` python\nmy_experiment = Experiment.load(\"my_experiment.yml\")\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarothen%2Fexperiment","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdarothen%2Fexperiment","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarothen%2Fexperiment/lists"}