# <d></d>  SWARM LEARNING

#### Product version: 2.2.0
Swarm Learning is a decentralized, privacy-preserving Machine Learning framework. This framework utilizes the computing power at, or near, the distributed data sources to run the Machine Learning algorithms that train the models. It uses the security of a blockchain platform to share learnings with peers in a safe and secure manner. In Swarm Learning, training of the model occurs at the edge, where data is most recent, and where prompt, data-driven decisions are mostly necessary. In this completely decentralized architecture, only the insights learned are shared with the collaborating ML peers, not the raw data. This tremendously enhances data security and privacy.

Swarm Learning nodes works in collaboration with other Swarm Learning nodes in the network. It regularly shares its learnings with the other nodes and incorporates their insights. This process continues until the Swarm Learning nodes train the model to desired state.   User can monitor the progress of the current training as shown in the below image. It shows all running Swarm nodes, loss, model metric (for example, accuracy) and overall training progress for each User ML node. On hovering over the "progress bar", one can see the number of completed epochs and the total number of epochs.

## Architecture
  Swarm Learning framework is made up of various components known as nodes, such as Swarm Learning (SL) nodes, Swarm Network (SN) nodes, Swarm Learning Command Interface (SWCI) nodes, and Swarm Operator (SWOP) nodes. Each node of Swarm Learning is modularized and runs in a separate container. The **nodes represent different Swarm Learning _functionality_ and not physical server nodes**.

-   SL nodes run the core of Swarm Learning. An SL node works in collaboration with all the other SL nodes in the network. It regularly shares its learnings with the other nodes and incorporates their insights. SL nodes act as an interface between the user model application (ML node) and other Swarm Learning components. SL nodes take care of distributing and merging model weights in a secured way.

-   SN nodes form the blockchain network. The current version of Swarm Learning uses an open-source version of Ethereum as the underlying blockchain platform. The SN nodes interact with each other using this blockchain platform to maintain and track progress. The SN nodes use this state and progress information to co-ordinate the working of the other swarm learning components. Blockchain can be persisted across SN restart to preserve past progress network. User can lookup blockchain and see all history of operations. Users have the flexibility to stop Swarm after training is completed. Once user restarts the SN network, the existing history can be accessed using the `get` or `list` command of SWCI management interface.
    **Sentinel Node** is a special SN node. The Sentinel node is responsible for initializing the blockchain network. This is the first node to start.

    NOTE: Only metadata is written to the blockchain. The model itself is not stored in the blockchain.

-   SWOP node is an agent that can manage Swarm Learning operations. SWOP is responsible to execute tasks that are assigned to it. A SWOP node can execute only one task at a time. SWOP helps in executing tasks such as starting and stopping Swarm runs, building and upgrading ML containers, and sharing models for training. For more information about SWOP, see [Swarm Operator node \(SWOP\)](./docs/User/Swarm_Operator_node_(SWOP).md).

-   SWCI node is the command interface tool to the Swarm Learning framework. It is used to monitor the Swarm Learning framework. SWCI nodes can connect to any of the SN nodes in a given Swarm Learning framework to manage the framework. For more information on SWCI, see [Swarm Learning Command Interface](./docs/User/Swarm_Learning_Command_Interface.md).

-   SLM-UI node is the GUI management tool to the Swarm Learning framework. It has three functionalities. It is used to [install](./docs/Install/Adding_a_Swarm_Host_in_SLM-UI.md) Swarm Learning framework, [deploy](./docs/User/Running_MNIST_example_using_SLM-UI.md) a Swarm training and [monitor](./docs/User/Monitoring_Swarm_Learning_training_using_SLM-UI.md) the progress of the current training and track past training runs to decide the best training.

-   Swarm Learning security and digital identity aspects are handled by X.509 certificates. Communication among Swarm Learning components are secured using X.509 certificates. User can either generate their own certificates or directly use certificates generated by any standard security software such as SPIRE. For more information on SPIRE, see [https://thebottomturtle.io/Solving-the-bottom-turtle-SPIFFE-SPIRE-Book.pdf](https://thebottomturtle.io/Solving-the-bottom-turtle-SPIFFE-SPIRE-Book.pdf) and [https://spiffe.io/](https://spiffe.io/).

    NOTE: Swarm Learning framework does not initialize if certificates are not provided.

-   Swarm Learning components communicate with each other using a set of TCP/IP ports. For more information on port details that must be opened, see [Exposed Ports](/docs/Install/Exposed_port_numbers.md).

NOTE: The participating nodes must be able to access each other's ports.

-   License Server installs and manages the license that is required to run the Swarm Learning framework. The licenses are managed by the AutoPass License Server \(APLS\) container. For more information, see [APLS User Guide](/docs/HPE%20AutoPass%20License%20Server%20User%20Guide.pdf).

## User ML component
User can transform/modify any Keras or PyTorch based ML program that is written using Python3 into a Swarm Learning ML program by [making a few simple changes](./docs/User/How_to_Swarm_enable_an_ML_algorithm.md) to the model training code by including the `SwarmCallback` API. For more information, see any of the [examples](/examples/README.md) included with the Swarm Learning package.

The transformed user Machine Learning \(user ML node\) program can be built as a Docker container or can be run on the host.

NOTE: HPE recommends users to build an ML Docker container for easier and automatic deployment.

The ML node is responsible to train and iteratively update the model. For each ML node, there is a corresponding SL node in the Swarm Learning framework, which performs the Swarm training. Each pair of ML and SL nodes must run on the same host. This process continues until the SL nodes train the model to the desired state.

NOTE: All the ML nodes must use the same ML platform either Keras (based on TensorFlow 2 backend) or PyTorch. Using Keras for some and PyTorch for the other nodes is not supported.

## Quick Start
  1. [Prerequisites](/docs/Install/Prerequisites.md) for Swarm Learning
  2. [Upgrading from earlier versions](/docs/Install/Versioning_and_upgrade.md)
  3. [Download and setup Swarm Learning](/docs/Install/HPE_Swarm_Learning_installation.md) using the SLM-UI installer
  4. Execute a simple predefined example - [MNIST example](/examples/mnist/README.md)
  5. [Running MNIST example using SLM-UI](/docs/User/Running_MNIST_example_using_SLM-UI.md)
  6. [Monitoring & Tracking Swarm Learning training using SLM-UI](/docs/User/Monitoring_Swarm_Learning_training_using_SLM-UI.md)
  7. [Frequently Asked Questions](/docs/User/Frequently_asked_questions.md)
  8. [Troubleshooting](/docs/User/Troubleshooting.md)
  9. [Release Notes](/docs/HPE_Swarm_learning_2.2.0_Release_Notes.pdf)

NOTE: **Accessing Hewlett Packard Enterprise Support** clause and **Concurrent swarm training** feature mentioned in the documentation are applicable for enterprise customers ONLY.

NOTE: The examples and scripts that are bundled with the Swarm UI installer **may not be latest**. If there are any issues running it, please use the copy directly from github.

## Detailed Documentation
  - [How Swarm Learning Components interact](/docs/User/Swarm_Learning_component_interactions.md)
  - [Component interactions when using Reverse Proxy](/docs/User/Swarm_Learning_Component_Interactions_using_Reverse_Proxy.md)
  - [Swarm Learning Concepts](/docs/User/Swarm_Learning_concepts.md)
  - [Working of a Swarm Learning node](/docs/User/Working_of_a_Swarm_Learning_node.md)
  - [Adapting ML programs for Swarm Learning](/docs/User/Adapting_an_ML_program_for_Swarm_Learning.md)
  - [Swarm wheels package](/docs/User/Swarm_client_interface-wheels_package.md)
  - [Configuring Swarm Learning components](/docs/Install/Configuring_Swarm_Learning.md)
  - [Using SWCI](/docs/User/Swarm_Learning_Command_Interface.md)
  - [Using SWOP](/docs/User/Swarm_Operator_node_(SWOP).md)
  - [Running Swarm learning examples using SLM-UI](/docs/Install/Running_Swarm_Learning_examples_using_SLM-UI.md)
  - [Running Swarm Learning using CLI](/docs/Install/Running_Swarm_Learning_using_CLI.md)
  - [Running Swarm Learning with SE Linux](/docs/Install/Running_Swarm_with_SE_Linux.md)
  - [Running Swarm Learning with Podman](/docs/Install/Running_Swarm_Learning_with_Podman.md)
  - [Running Swarm Learning with Spire](/docs/Install/Running_Swarm_Learning_with_Spire.md)
  - [Examples](/examples/README.md)
  - [Swarm Learning diagnostics using CLI](/docs/User/Swarm_Log_Collector.md)
  - [Centralized Swarm diagnostics using SLM-UI](/docs/Install/Centralized_Swarm_diagnostic.md)
  - [Extending Swarm Learning for new ML platforms](/lib/src/README.md)
  - [Merge Methods - Whitepaper](/docs/HPE_Merge_Methods_Whitepaper.pdf)
  - [Uninstalling Swarm Learning using SLM-UI](/docs/Install/Uninstalling_Swarm_Learning_using_SLM-UI.md)

## Related Publications, Talks and External References
  - [Papers](docs/Generic/papers-and-articles.md)
  - [Videos](docs/Generic/videos.md)
  - [URLs](docs/Generic/URL.md)

## Acronyms and Abbreviations
  Refer to [Acronyms and Abbreviations](docs/Generic/acronyms.md) for more information.

## Getting in touch
  Feedback and questions are appreciated. You can use the issue tracker to report bugs on GitHub.  (Or)
  Join the [HPE Developer Slack Workspace](https://slack.hpedev.io/) and start a discussion in our [#hpe-swarm-learning](https://hpedev.slack.com/archives/C04A5DK9TUK) channel.

## Contributing
  Refer to [Contributing](docs/Generic/CONTRIBUTING.md) for more information.

## License
  The distribution of Swarm Learning in this repository is for non-commercial and experimental use under this [license](docs/Generic/LICENSE.md).

  See [ATTRIBUTIONS](docs/Generic/ATTRIBUTIONS.md) and [DATA LICENSE](docs/Generic/DATA_LICENSE.md) for terms and conditions for using the datasets included in this repository.


| **Status** | [![GH Actions Status](https://github.com/openforcefield/openff-toolkit/workflows/CI/badge.svg)](https://github.com/openforcefield/openff-toolkit/actions?query=branch%3Amain+workflow%3ACI)  [![Codecov coverage](https://img.shields.io/codecov/c/github/openforcefield/openff-toolkit.svg?logo=Codecov&logoColor=white)](https://codecov.io/gh/openforcefield/openff-toolkit) |
| :------ |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Latest Release** | [![Last release tag](https://img.shields.io/github/release-pre/openforcefield/openff-toolkit.svg)](https://github.com/openforcefield/openff-toolkit/releases)  [![Commits since release](https://img.shields.io/github/commits-since/openforcefield/openff-toolkit/0.16.0.svg)](https://github.com/openforcefield/openff-toolkit/releases/tag/0.16.0)[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.10967071.svg)](https://doi.org/10.5281/zenodo.10967071)
| **Communication** | [![docs stable](https://img.shields.io/badge/docs-stable-5077AB.svg?logo=read%20the%20docs)](https://open-forcefield-toolkit.readthedocs.io/) [![user & dev discussions](https://img.shields.io/badge/user%20%26%20dev%20discussions-GitHub-red?logo=github)](https://github.com/openforcefield/discussions/discussions) |
| **Foundation** | [![license](https://img.shields.io/github/license/openforcefield/openff-toolkit.svg)](https://opensource.org/licenses/MIT) [![platforms](https://img.shields.io/badge/Platforms-Linux%2C%20MacOS-orange.svg)](https://open-forcefield-toolkit.readthedocs.io/en/stable/installation.html) [![python](https://img.shields.io/badge/python-3.9%2C%203.10%2C%203.11-blue.svg)](https://open-forcefield-toolkit.readthedocs.io/en/stable/installation.html) [![Funding](https://img.shields.io/badge/Funding-Open%20Force%20Field%20Consortium-brightgreen.svg)](http://openforcefield.org)        |
| **Installation** | [![Releases](https://img.shields.io/badge/obtain-latest-green.svg)](https://github.com/openforcefield/openff-toolkit/releases) [![Conda](https://img.shields.io/conda/v/conda-forge/openff-toolkit.svg)](https://anaconda.org/conda-forge/openff-toolkit) [![Last updated](https://anaconda.org/conda-forge/openff-toolkit/badges/latest_release_relative_date.svg)](https://anaconda.org/conda-forge/openff-toolkit) [![Anaconda Cloud downloads](https://anaconda.org/conda-forge/openff-toolkit/badges/downloads.svg)](https://anaconda.org/conda-forge/openff-toolkit)          |

# The Open Force Field toolkit

The Open Force Field Toolkit, built by the [Open Force Field Initiative](http://openforcefield.org), is a Python toolkit for the development and application of modern molecular mechanics force fields based on direct chemical perception and rigorous statistical parameterization methods.

The toolkit currently covers two main areas we have committed to stably maintain throughout their lifetimes:
* Tools for using [SMIRKS Native Open Force Field (SMIRNOFF)](https://openforcefield.github.io/standards/standards/smirnoff/) force fields
* Tools for [direct chemical environment perception](https://dx.doi.org/10.1021/acs.jctc.8b00640) and manipulation

**Note**: Prior to version 0.9.0, this toolkit and its associated repository were named `openforcefield` and used different import paths. For details on this change and migration instructions, see the [release notes](https://open-forcefield-toolkit.readthedocs.io/en/stable/releasehistory.html#namespace-migration) of version 0.9.0.

## Documentation

[Documentation](https://open-forcefield-toolkit.readthedocs.io/en/stable/) for the Open Force Field Toolkit is hosted at [readthedocs](https://open-forcefield-toolkit.readthedocs.io/en/stable). Example notebooks are available in the `examples/` directory and also hosted on the [`Open Force Field`](https://docs.openforcefield.org/en/latest/examples.html) website.

## How to cite

Please cite the OpenFF Toolkit using the [Zenodo record](https://zenodo.org/record/10103216) of the [latest release](https://zenodo.org/record/10103216) or the version that was used. The BibTeX reference of the latest release can be found [here](https://zenodo.org/record/10103216/export/hx#.Y7cYbOzMKrM).

## Installation

The Open Force Field Toolkit (`openff-toolkit`) is a Python toolkit, and supports Python 3.9 through 3.11.

### Installing via Mamba/Conda

Detailed installation instructions can be found [here](https://open-forcefield-toolkit.readthedocs.io/en/stable/installation.html).

## Force Fields

Two major force field development efforts have been undertaken by the Open Force Field Initiative, with results hosted in separate repositories.

* The [Open Force Fields repository](https://github.com/openforcefield/openff-forcefields/), which features the [Parsley](https://openforcefield.org/community/news/general/introducing-openforcefield-1.0/) and [Sage](https://openforcefield.org/community/news/general/sage2.0.0-release/) force field lines. These are the Open Force Field Initiative's efforts toward building _new_ force fields. The initial parameters are taken from smirnoff99Frosst, but software and data produced by the Initiative's efforts have been used to refit parameter values and add new SMIRKS-based parameters.
* The [smirnoff99Frosst repository](https://github.com/openforcefield/smirnoff99Frosst/), which is descended from AMBER's parm99 force field as well as Merck-Frosst's parm@frosst. This line of force fields does not aim to alter parameter values, but is instead a test of accurately converting an atom type-based force field to the SMIRNOFF format.

Force fields from both of these packages are available in their respective GitHub repositories and also as conda packages. Tables detailing the individual file names/versions within these force field lines are in the README of each repository. By default, installing the Open Force Field toolkit using `conda` or the single-file toolkit installers will also install these conda packages. A [plugin architecture](https://github.com/openforcefield/openff-toolkit/blob/main/FAQ.md#how-can-i-distribute-my-own-force-fields-in-smirnoff-format) is provided for other force field developers to produce python/conda packages that can be imported by the Open Force Field Toolkit as well.

# Toolkit features

## The SMIRKS Native Open Force Field (SMIRNOFF) format

This repository provides tools for using the [SMIRKS Native Open Force Field (SMIRNOFF) specification](https://openforcefield.github.io/standards/standards/smirnoff/), which currently supports an XML representation for force field definition files.

By convention, files containing [XML representations](https://en.wikipedia.org/wiki/XML) of SMIRNOFF force fields carry `.offxml` extensions.

Example SMIRNOFF `.offxml` force field definitions can be found in [`openff/toolkit/data/test_forcefields/`](https://github.com/openforcefield/openff-toolkit/tree/main/openff/toolkit/data/test_forcefields). These force fields are for testing only, and we neither record versions of these files, nor do we guarantee their correctness or completeness.

### Working with SMIRNOFF parameter sets

SMIRNOFF force fields can be parsed by the `ForceField` class, which offers methods including `create_openmm_system` for exporting to OpenMM and `create_interchange` for exporting to other formats (GROMACS, Amber, LAMMPS) via [Interchange](https://docs.openforcefield.org/projects/interchange).

```python
# Load a molecule into the OpenFF Molecule object
from openff.toolkit import Molecule
from openff.toolkit.utils import get_data_file_path
sdf_file_path = get_data_file_path('molecules/ethanol.sdf')
molecule = Molecule.from_file(sdf_file_path)

# Create an OpenFF Topology object from the molecule
from openff.toolkit import Topology
topology = Topology.from_molecules(molecule)

# Load the latest OpenFF force field release: version 2.1.0, codename "Sage"
from openff.toolkit import ForceField
forcefield = ForceField('openff-2.1.0.offxml')

# Create an OpenMM system representing the molecule with SMIRNOFF-applied parameters
openmm_system = forcefield.create_openmm_system(topology)

# Create an Interchange object for representations in other formats
interchange = forcefield.create_interchange(topology)
```

Detailed examples of using SMIRNOFF with the toolkit can be found [in the documentation](https://open-forcefield-toolkit.readthedocs.io/en/stable/examples.html).

# Frequently asked questions (FAQ)

See [`FAQ.md`](FAQ.md) for answers to a variety of common problems, such as:
* Why do I need to provide molecules corresponding to the components of my system, or a `Topology` with bond orders?
* Can I use an Amber, CHARMM, or GROMACS topology/coordinate file as a starting point for applying a SMIRNOFF force field?
* What if I am starting from a PDB file?

# Contributors

For a partial list of contributors, see the [GitHub Contributors page](https://github.com/openforcefield/openff-toolkit/graphs/contributors). Others whose work constitutes significant contributions but did not make it into the `git` history include Shuzhe Wang.


TorchGeo is a [PyTorch](https://pytorch.org/) domain library, similar to [torchvision](https://pytorch.org/vision), providing datasets, samplers, transforms, and pre-trained models specific to geospatial data.

The goal of this library is to make it simple:

1. for machine learning experts to work with geospatial data, and
2. for remote sensing experts to explore machine learning solutions.

Community:
[![slack](https://img.shields.io/badge/Slack-join-4A154B?logo=slack)](https://join.slack.com/t/torchgeo/shared_invite/zt-22rse667m-eqtCeNW0yI000Tl4B~2PIw)
[![osgeo](https://img.shields.io/badge/OSGeo-join-4CB05B?logo=osgeo)](https://www.osgeo.org/community/getting-started-osgeo/)
[![huggingface](https://img.shields.io/badge/Hugging_Face-join-FFD21E?logo=huggingface)](https://huggingface.co/torchgeo)
[![pytorch](https://img.shields.io/badge/PyTorch-join-DE3412?logo=pytorch)](https://pytorch.org/ecosystem/join)

Packaging:
[![pypi](https://badge.fury.io/py/torchgeo.svg)](https://pypi.org/project/torchgeo/)
[![conda](https://anaconda.org/conda-forge/torchgeo/badges/version.svg)](https://anaconda.org/conda-forge/torchgeo)
[![spack](https://img.shields.io/spack/v/py-torchgeo)](https://packages.spack.io/package.html?name=py-torchgeo)

Testing:
[![docs](https://readthedocs.org/projects/torchgeo/badge/?version=latest)](https://torchgeo.readthedocs.io/en/stable/)
[![style](https://github.com/microsoft/torchgeo/actions/workflows/style.yaml/badge.svg)](https://github.com/microsoft/torchgeo/actions/workflows/style.yaml)
[![tests](https://github.com/microsoft/torchgeo/actions/workflows/tests.yaml/badge.svg)](https://github.com/microsoft/torchgeo/actions/workflows/tests.yaml)
[![codecov](https://codecov.io/gh/microsoft/torchgeo/branch/main/graph/badge.svg?token=oa3Z3PMVOg)](https://codecov.io/gh/microsoft/torchgeo)

## Installation

The recommended way to install TorchGeo is with [pip](https://pip.pypa.io/):

```console
$ pip install torchgeo
```

For [conda](https://docs.conda.io/) and [spack](https://spack.io/) installation instructions, see the [documentation](https://torchgeo.readthedocs.io/en/stable/user/installation.html).

## Documentation

You can find the documentation for TorchGeo on [ReadTheDocs](https://torchgeo.readthedocs.io). This includes API documentation, contributing instructions, and several [tutorials](https://torchgeo.readthedocs.io/en/stable/tutorials/getting_started.html). For more details, check out our [paper](https://arxiv.org/abs/2111.08872), [podcast episode](https://www.youtube.com/watch?v=ET8Hb_HqNJQ), [tutorial](https://www.youtube.com/watch?v=R_FhY8aq708), and [blog post](https://pytorch.org/blog/geospatial-deep-learning-with-torchgeo/).

## Example Usage

The following sections give basic examples of what you can do with TorchGeo.

First we'll import various classes and functions used in the following sections:

```python
from lightning.pytorch import Trainer
from torch.utils.data import DataLoader

from torchgeo.datamodules import InriaAerialImageLabelingDataModule
from torchgeo.datasets import CDL, Landsat7, Landsat8, VHR10, stack_samples
from torchgeo.samplers import RandomGeoSampler
from torchgeo.trainers import SemanticSegmentationTask
```

### Geospatial datasets and samplers

Many remote sensing applications involve working with [_geospatial datasets_](https://torchgeo.readthedocs.io/en/stable/api/datasets.html#geospatial-datasets)—datasets with geographic metadata. These datasets can be challenging to work with due to the sheer variety of data. Geospatial imagery is often multispectral with a different number of spectral bands and spatial resolution for every satellite. In addition, each file may be in a different coordinate reference system (CRS), requiring the data to be reprojected into a matching CRS.

In this example, we show how easy it is to work with geospatial data and to sample small image patches from a combination of [Landsat](https://www.usgs.gov/landsat-missions) and [Cropland Data Layer (CDL)](https://data.nal.usda.gov/dataset/cropscape-cropland-data-layer) data using TorchGeo. First, we assume that the user has Landsat 7 and 8 imagery downloaded. Since Landsat 8 has more spectral bands than Landsat 7, we'll only use the bands that both satellites have in common. We'll create a single dataset including all images from both Landsat 7 and 8 data by taking the union between these two datasets.

```python
landsat7 = Landsat7(root="...", bands=["B1", ..., "B7"])
landsat8 = Landsat8(root="...", bands=["B2", ..., "B8"])
landsat = landsat7 | landsat8
```

Next, we take the intersection between this dataset and the CDL dataset. We want to take the intersection instead of the union to ensure that we only sample from regions that have both Landsat and CDL data. Note that we can automatically download and checksum CDL data. Also note that each of these datasets may contain files in different coordinate reference systems (CRS) or resolutions, but TorchGeo automatically ensures that a matching CRS and resolution is used.

```python
cdl = CDL(root="...", download=True, checksum=True)
dataset = landsat & cdl
```

This dataset can now be used with a PyTorch data loader. Unlike benchmark datasets, geospatial datasets often include very large images. For example, the CDL dataset consists of a single image covering the entire continental United States. In order to sample from these datasets using geospatial coordinates, TorchGeo defines a number of [_samplers_](https://torchgeo.readthedocs.io/en/stable/api/samplers.html). In this example, we'll use a random sampler that returns 256 x 256 pixel images and 10,000 samples per epoch. We also use a custom collation function to combine each sample dictionary into a mini-batch of samples.

```python
sampler = RandomGeoSampler(dataset, size=256, length=10000)
dataloader = DataLoader(dataset, batch_size=128, sampler=sampler, collate_fn=stack_samples)
```

This data loader can now be used in your normal training/evaluation pipeline.

```python
for batch in dataloader:
    image = batch["image"]
    mask = batch["mask"]

    # train a model, or make predictions using a pre-trained model
```

Many applications involve intelligently composing datasets based on geospatial metadata like this. For example, users may want to:

- Combine datasets for multiple image sources and treat them as equivalent (e.g., Landsat 7 and 8)
- Combine datasets for disparate geospatial locations (e.g., Chesapeake NY and PA)

These combinations require that all queries are present in at least one dataset, and can be created using a `UnionDataset`. Similarly, users may want to:

- Combine image and target labels and sample from both simultaneously (e.g., Landsat and CDL)
- Combine datasets for multiple image sources for multimodal learning or data fusion (e.g., Landsat and Sentinel)

These combinations require that all queries are present in both datasets, and can be created using an `IntersectionDataset`. TorchGeo automatically composes these datasets for you when you use the intersection (`&`) and union (`|`) operators.

### Benchmark datasets

TorchGeo includes a number of [_benchmark datasets_](https://torchgeo.readthedocs.io/en/stable/api/datasets.html#non-geospatial-datasets)—datasets that include both input images and target labels. This includes datasets for tasks like image classification, regression, semantic segmentation, object detection, instance segmentation, change detection, and more.

If you've used [torchvision](https://pytorch.org/vision) before, these datasets should seem very familiar. In this example, we'll create a dataset for the Northwestern Polytechnical University (NWPU) very-high-resolution ten-class ([VHR-10](https://github.com/chaozhong2010/VHR-10_dataset_coco)) geospatial object detection dataset. This dataset can be automatically downloaded, checksummed, and extracted, just like with torchvision.

```python
from torch.utils.data import DataLoader

from torchgeo.datamodules.utils import collate_fn_detection
from torchgeo.datasets import VHR10

# Initialize the dataset
dataset = VHR10(root="...", download=True, checksum=True)

# Initialize the dataloader with the custom collate function
dataloader = DataLoader(
    dataset,
    batch_size=128,
    shuffle=True,
    num_workers=4,
    collate_fn=collate_fn_detection,
)

# Training loop
for batch in dataloader:
    images = batch["image"]  # list of images
    boxes = batch["boxes"]  # list of boxes
    labels = batch["labels"]  # list of labels
    masks = batch["masks"]  # list of masks

    # train a model, or make predictions using a pre-trained model
```

All TorchGeo datasets are compatible with PyTorch data loaders, making them easy to integrate into existing training workflows. The only difference between a benchmark dataset in TorchGeo and a similar dataset in torchvision is that each dataset returns a dictionary with keys for each PyTorch `Tensor`.

### Pre-trained Weights

Pre-trained weights have proven to be tremendously beneficial for transfer learning tasks in computer vision. Practitioners usually utilize models pre-trained on the ImageNet dataset, containing RGB images. However, remote sensing data often goes beyond RGB with additional multispectral channels that can vary across sensors. TorchGeo is the first library to support models pre-trained on different multispectral sensors, and adopts torchvision's [multi-weight API](https://pytorch.org/blog/introducing-torchvision-new-multi-weight-support-api/). A summary of currently available weights can be seen in the [docs](https://torchgeo.readthedocs.io/en/stable/api/models.html#pretrained-weights). To create a [timm](https://github.com/huggingface/pytorch-image-models) Resnet-18 model with weights that have been pretrained on Sentinel-2 imagery, you can do the following:

```python
import timm
from torchgeo.models import ResNet18_Weights

weights = ResNet18_Weights.SENTINEL2_ALL_MOCO
model = timm.create_model("resnet18", in_chans=weights.meta["in_chans"], num_classes=10)
model.load_state_dict(weights.get_state_dict(progress=True), strict=False)
```

These weights can also directly be used in TorchGeo Lightning modules that are shown in the following section via the `weights` argument. For a notebook example, see this [tutorial](https://torchgeo.readthedocs.io/en/stable/tutorials/pretrained_weights.html).

### Reproducibility with Lightning

In order to facilitate direct comparisons between results published in the literature and further reduce the boilerplate code needed to run experiments with datasets in TorchGeo, we have created Lightning [_datamodules_](https://torchgeo.readthedocs.io/en/stable/api/datamodules.html) with well-defined train-val-test splits and [_trainers_](https://torchgeo.readthedocs.io/en/stable/api/trainers.html) for various tasks like classification, regression, and semantic segmentation. These datamodules show how to incorporate augmentations from the kornia library, include preprocessing transforms (with pre-calculated channel statistics), and let users easily experiment with hyperparameters related to the data itself (as opposed to the modeling process). Training a semantic segmentation model on the [Inria Aerial Image Labeling](https://project.inria.fr/aerialimagelabeling/) dataset is as easy as a few imports and four lines of code.

```python
datamodule = InriaAerialImageLabelingDataModule(root="...", batch_size=64, num_workers=6)
task = SemanticSegmentationTask(
    model="unet",
    backbone="resnet50",
    weights=True,
    in_channels=3,
    num_classes=2,
    loss="ce",
    ignore_index=None,
    lr=0.1,
    patience=6,
)
trainer = Trainer(default_root_dir="...")

trainer.fit(model=task, datamodule=datamodule)
```

TorchGeo also supports command-line interface training using [LightningCLI](https://lightning.ai/docs/pytorch/stable/cli/lightning_cli.html). It can be invoked in two ways:

```console
# If torchgeo has been installed
torchgeo
# If torchgeo has been installed, or if it has been cloned to the current directory
python3 -m torchgeo
```

It supports command-line configuration or YAML/JSON config files. Valid options can be found from the help messages:

```console
# See valid stages
torchgeo --help
# See valid trainer options
torchgeo fit --help
# See valid model options
torchgeo fit --model.help ClassificationTask
# See valid data options
torchgeo fit --data.help EuroSAT100DataModule
```

Using the following config file:

```yaml
trainer:
  max_epochs: 20
model:
  class_path: ClassificationTask
  init_args:
    model: "resnet18"
    in_channels: 13
    num_classes: 10
data:
  class_path: EuroSAT100DataModule
  init_args:
    batch_size: 8
  dict_kwargs:
    download: true
```

we can see the script in action:

```console
# Train and validate a model
torchgeo fit --config config.yaml
# Validate-only
torchgeo validate --config config.yaml
# Calculate and report test accuracy
torchgeo test --config config.yaml ckpt_path=...
```

It can also be imported and used in a Python script if you need to extend it to add new features:

```python
from torchgeo.main import main

main(["fit", "--config", "config.yaml"])
```

See the [Lightning documentation](https://lightning.ai/docs/pytorch/stable/cli/lightning_cli.html) for more details.

## Citation

If you use this software in your work, please cite our [paper](https://dl.acm.org/doi/10.1145/3557915.3560953):

```bibtex
@inproceedings{Stewart_TorchGeo_Deep_Learning_2022,
    address = {Seattle, Washington},
    author = {Stewart, Adam J. and Robinson, Caleb and Corley, Isaac A. and Ortiz, Anthony and Lavista Ferres, Juan M. and Banerjee, Arindam},
    booktitle = {Proceedings of the 30th International Conference on Advances in Geographic Information Systems},
    doi = {10.1145/3557915.3560953},
    month = nov,
    pages = {1--12},
    publisher = {Association for Computing Machinery},
    series = {SIGSPATIAL '22},
    title = {{TorchGeo}: Deep Learning With Geospatial Data},
    url = {https://dl.acm.org/doi/10.1145/3557915.3560953},
    year = {2022}
}
```

## Contributing

This project welcomes contributions and suggestions. If you would like to submit a pull request, see our [Contribution Guide](https://torchgeo.readthedocs.io/en/stable/user/contributing.html) for more information.

This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.


    Bioregistry

   A community-driven integrative meta-registry of life science databases, ontologies, and other resources.

More information here.

The Bioregistry can be accessed, searched, and queried through its associated website at
https://bioregistry.io.

### 📥 Download

The underlying data of the Bioregistry can be downloaded (or edited) directly
from [here](https://github.com/biopragmatics/bioregistry/blob/main/src/bioregistry/data/).
Several exports to YAML, TSV, and RDF, including consensus views over the
registry, are built on a weekly basis and can be downloaded via the
[`exports/`](https://github.com/biopragmatics/bioregistry/tree/main/exports) directory.

The manually curated portions of these data are available under the
[CC0 1.0 Universal License](https://creativecommons.org/publicdomain/zero/1.0/).
Aggregated data are redistributed under their original licenses.

## 🙏 Contributing

Contributions are both welcomed and encouraged. Contribution guidelines for new
prefix requests, record edits, record removals, and code updates are available
in [CONTRIBUTING.md](docs/CONTRIBUTING.md).

The most simple contribution is to submit an issue:

- Submit a new prefix using the [issue template](https://github.com/biopragmatics/bioregistry/issues/new?assignees=cthoyt&labels=New%2CPrefix&template=new-prefix.yml&title=Add+prefix+%5BX%5D). A new pull request will be generated automatically for you.
- Update an existing record using one of the [existing issue templates](https://github.com/biopragmatics/bioregistry/issues/new/choose) (e.g., for updating a record's regular expression, merging two prefixes).
- For any updates that don't have a corresponding template, feel free to start with a [blank issue](https://github.com/biopragmatics/bioregistry/issues/new).

If you want to make a direct contribution, feel free to make edits directly to
the [bioregistry.json](https://github.com/biopragmatics/bioregistry/blob/main/src/bioregistry/data/bioregistry.json)
file either through the GitHub interface or locally by [forking the repository](https://github.com/biopragmatics/bioregistry/blob/main/docs/CONTRIBUTING.md#code-contribution).

If you want to make a contribution but don't know where to start, you can check
[this list](https://biopragmatics.github.io/bioregistry/curation/) of curation
To-Do's that's automatically generated weekly, including more detailed
information on how to contribute.

## ⚖ Governance

The Bioregistry is maintained by a Review Team and Core Development team
whose memberships and duties are described in the
[Project Governance](docs/GOVERNANCE.md).

## 🧹 Maintenance

### 🫀 Health Report

The Bioregistry runs some automated tests weekly to check that various metadata haven't gone stale. For example,
it checks that the homepages are still available and that each provider URL is still able to resolve.

It has a dedicated [dashboard](https://biopragmatics.github.io/bioregistry/health) that is not part of the main
Bioregistry site.

### ♻ Update

The database is automatically updated daily thanks to scheduled workflows in GitHub Actions. The workflow's
configuration can be found [here](https://github.com/biopragmatics/bioregistry/blob/main/.github/workflows/update.yml)
and the last run can be seen [here](https://github.com/biopragmatics/bioregistry/actions?query=workflow%3A%22Update+Data%22).
Further, a [changelog](https://github.com/biopragmatics/bioregistry/commits?author=actions-user) can be recapitulated from the
commits of the GitHub Actions bot.

If you want to manually update the database, run the following:

```shell
$ tox -e update
```

Make sure that you have valid environment variables or `pystow` configurations
for `BIOPORTAL_API_KEY`, `ECOPORTAL_API_KEY`, `AGROPORTAL_API_KEY`,
`FAIRSHARING_LOGIN`, and `FAIRSHARING_PASSWORD`.

## 🚀 Installation

The Bioregistry can be installed from [PyPI](https://pypi.org/project/bioregistry/) with:

```shell
$ pip install bioregistry
```

It can be installed in development mode for local curation with:

```shell
$ git clone https://github.com/biopragmatics/bioregistry.git
$ cd bioregistry
$ pip install --editable .
```

Build the docs locally with `tox -e docs` then view by opening
`docs/build/html/index.html`.

## 💪 Usage

### Normalizing Prefixes

The Bioregistry can be used to normalize prefixes across MIRIAM and all the (very plentiful) variants that pop up in
ontologies in OBO Foundry and the OLS with the `normalize_prefix()` function.

```python
from bioregistry import normalize_prefix

# Doesn't affect canonical prefixes
assert 'ncbitaxon' == normalize_prefix('ncbitaxon')

# This works for uppercased prefixes, like:
assert 'chebi' == normalize_prefix("CHEBI")

# This works for mixed case prefixes like
assert 'fbbt' == normalize_prefix("FBbt")

# This works for synonym prefixes, like:
assert 'ncbitaxon' == normalize_prefix('taxonomy')

# This works for common mistaken prefixes, like:
assert 'pubchem.compound' == normalize_prefix('pubchem')

# This works for prefixes that are often written many ways, like:
assert 'eccode' == normalize_prefix('ec-code')
assert 'eccode' == normalize_prefix('EC_CODE')

# If a prefix is not registered, it gives back `None`
assert normalize_prefix('not a real key') is None
```

### Parsing CURIEs

The Bioregistry supports parsing a CURIE into a pair of normalized prefix
and identifier using the `parse_curie()` function:

```python
from bioregistry import parse_curie

# Obvious for canonical CURIEs
assert ('chebi', '1234') == parse_curie('chebi:1234')

# Normalize mixed case prefixes
assert ('fbbt', '00007294') == parse_curie('FBbt:00007294')

# Normalize common mistaken prefixes
assert ('pubchem.compound', '1234') == parse_curie('pubchem:1234')

# Remove the redundant prefix and normalize
assert ('go', '1234') == parse_curie('GO:GO:1234')
```

This will also apply the same normalization rules for prefixes from the previous
section on normalizing prefixes for the remaining examples.

### Normalizing CURIEs

The Bioregistry supports converting a CURIE to a canonical CURIE by normalizing
the prefix and removing redundant namespaces embedded in LUIs with the
`normalize_curie()` function.

```python
from bioregistry import normalize_curie

# Idempotent to canonical CURIEs
assert 'chebi:1234' == normalize_curie('chebi:1234')

# Normalize common mistaken prefixes
assert 'pubchem.compound:1234' == normalize_curie('pubchem:1234')

# Normalize mixed case prefixes
assert 'fbbt:1234' == normalize_curie('FBbt:1234')

# Remove the redundant prefix and normalize
assert 'go:1234' == normalize_curie('GO:GO:1234')
```

### Parsing IRIs

The Bioregistry can be used to parse CURIEs from IRIs due to its vast registry of provider URL
strings and additional programmatic logic implemented with Python. It can parse OBO Library PURLs,
IRIs from the OLS and identifiers.org, IRIs from the Bioregistry website, and any other IRIs
from well-formed providers registered in the Bioregistry. The `parse_iri()` function
gets a pre-parsed CURIE, while the `curie_from_iri()` function makes a canonical CURIE
from the pre-parsed CURIE.

```python
from bioregistry import curie_from_iri, parse_iri

# First-party IRI
assert ('chebi', '24867') == parse_iri('https://www.ebi.ac.uk/chebi/searchId.do?chebiId=CHEBI:24867')
assert 'chebi:24867' == curie_from_iri('https://www.ebi.ac.uk/chebi/searchId.do?chebiId=CHEBI:24867')

# OBO Library PURL
assert ('chebi', '24867') == parse_iri('http://purl.obolibrary.org/obo/CHEBI_24867')
assert 'chebi:24867' == curie_from_iri('http://purl.obolibrary.org/obo/CHEBI_24867')

# OLS IRI
assert ('chebi', '24867') == parse_iri('https://www.ebi.ac.uk/ols/ontologies/chebi/terms?iri=http://purl.obolibrary.org/obo/CHEBI_24867')
assert 'chebi:24867' == curie_from_iri('https://www.ebi.ac.uk/ols/ontologies/chebi/terms?iri=http://purl.obolibrary.org/obo/CHEBI_24867')

# Identifiers.org IRIs (with varying usage of HTTP(s) and colon/slash separator
assert ('chebi', '24867') == parse_iri('https://identifiers.org/CHEBI:24867')
assert ('chebi', '24867') == parse_iri('http://identifiers.org/CHEBI:24867')
assert ('chebi', '24867') == parse_iri('https://identifiers.org/CHEBI/24867')
assert ('chebi', '24867') == parse_iri('http://identifiers.org/CHEBI/24867')

# Bioregistry IRI
assert ('chebi', '24867') == parse_iri('https://bioregistry.io/chebi:24867')
```

In general, the Bioregistry knows how to parse both the http and https variants
of any given URI:

```python
from bioregistry import parse_iri

assert ('neuronames', '268') == parse_iri("http://braininfo.rprc.washington.edu/centraldirectory.aspx?ID=268")
assert ('neuronames', '268') == parse_iri("https://braininfo.rprc.washington.edu/centraldirectory.aspx?ID=268")
```

### Generating IRIs

You can generate an IRI from either a CURIE or a pre-parsed CURIE
(i.e., a 2-tuple of a prefix and identifier) with the `get_iri()` function.
By default, it uses the following priorities:

1. Custom prefix map (`custom`)
2. First-party IRI (`default`)
3. Identifiers.org / MIRIAM (`miriam`)
4. Ontology Lookup Service (`ols`)
5. OBO PURL (`obofoundry`)
6. Name-to-Thing (`n2t`)
7. BioPortal (`bioportal`)

```python
from bioregistry import get_iri

assert get_iri("chebi", "24867") == 'https://www.ebi.ac.uk/chebi/searchId.do?chebiId=CHEBI:24867'
assert get_iri("chebi:24867") == 'https://www.ebi.ac.uk/chebi/searchId.do?chebiId=CHEBI:24867'
```

It's possible to change the default priority list by passing an alternate
sequence of metaprefixes to the `priority` keyword (see above). For example, if
you're working with OBO ontologies, you might want to make OBO PURLs the highest
priority and when OBO PURLs can't be generated, default to something else:

```python
from bioregistry import get_iri

priority = ["obofoundry", "default", "miriam", "ols", "n2t", "bioportal"]
assert get_iri("chebi:24867", priority=priority) == 'http://purl.obolibrary.org/obo/CHEBI_24867'
assert get_iri("hgnc:1234", priority=priority) == 'https://bioregistry.io/hgnc:1234'
```

Even deeper, you can add (or override) any of the Bioregistry's default prefix
map with the `prefix_map` keyword:

```python
from bioregistry import get_iri

prefix_map = {
   "myprefix": "https://example.org/myprefix/",
   "chebi": "https://example.org/chebi/",
}
assert get_iri("chebi:24867", prefix_map=prefix_map) == 'https://example.org/chebi/24867'
assert get_iri("myprefix:1234", prefix_map=prefix_map) == 'https://example.org/myprefix/1234'
```

A custom prefix map can be supplied in combination with a priority list, using
the `"custom"` key for changing the priority of the custom prefix map.

```python
from bioregistry import get_iri

prefix_map = {"lipidmaps": "https://example.org/lipidmaps/"}
priority = ["obofoundry", "custom", "default", "bioregistry"]
assert get_iri("chebi:24867", prefix_map=prefix_map, priority=priority) == \
    'http://purl.obolibrary.org/obo/CHEBI_24867'
assert get_iri("lipidmaps:1234", prefix_map=prefix_map, priority=priority) == \
    'https://example.org/lipidmaps/1234'
```

Alternatively, there are direct functions for generating IRIs for different
registries:

```python
import bioregistry as br

# Bioregistry IRI
assert br.get_bioregistry_iri('chebi', '24867') == 'https://bioregistry.io/chebi:24867'

# Default Provider
assert br.get_default_iri('chebi', '24867') == 'https://www.ebi.ac.uk/chebi/searchId.do?chebiId=CHEBI:24867'

# OBO Library
assert br.get_obofoundry_iri('chebi', '24867') == 'http://purl.obolibrary.org/obo/CHEBI_24867'

# OLS IRI
assert br.get_ols_iri('chebi', '24867') ==
       'https://www.ebi.ac.uk/ols/ontologies/chebi/terms?iri=http://purl.obolibrary.org/obo/CHEBI_24867'

# Bioportal IRI
assert br.get_bioportal_iri('chebi', '24867') == \
    'https://bioportal.bioontology.org/ontologies/CHEBI/?p=classes&conceptid=http://purl.obolibrary.org/obo/CHEBI_24867'

# Identifiers.org IRI
assert br.get_identifiers_org_iri('chebi', '24867') == 'https://identifiers.org/CHEBI:24867'

# Name-to-Thing IRI
assert br.get_n2t_iri('chebi', '24867') == 'https://n2t.net/chebi:24867'
```

Each of these functions could also return `None` if there isn't a provider available or if the prefix
can't be mapped to the various resources.

### Prefix Map

The Bioregistry can be used to generate prefix maps with various flavors
depending on your context. Prioritization works the same way as when generating
IRIs.

```python
from bioregistry import get_prefix_map

# Standard
prefix_map = get_prefix_map()

# Prioritize OBO prefixes over bioregistry
priority = ["obofoundry", "default", "miriam", "ols", "n2t", "bioportal"]
prefix_map = get_prefix_map(uri_prefix_priority=priority)

# Provide custom remapping that doesn't have prioritization logic
remapping = {"chebi": "CHEBI"}
prefix_map = get_prefix_map(remapping=remapping)
```

### Getting Metadata

The pattern for an entry in the Bioregistry can be looked up quickly with `get_pattern()` if
it exists. It prefers the custom curated, then MIRIAM, then Wikidata pattern.

```python
import bioregistry

assert '^GO:\\d{7}$' == bioregistry.get_pattern('go')
```

Entries in the Bioregistry can be checked for deprecation with the `is_deprecated()` function. MIRIAM and OBO Foundry
don't often agree - OBO Foundry takes precedence since it seems to be updated more often.

```python
import bioregistry

assert bioregistry.is_deprecated('nmr')
assert not bioregistry.is_deprecated('efo')
```

Entries in the Bioregistry can be looked up with the `get_resource()` function.

```python
import bioregistry

entry = bioregistry.get_resource('taxonomy')
# there are lots of mysteries to discover in this dictionary!
```

The full Bioregistry can be read in a Python project using:

```python
import bioregistry

registry = bioregistry.read_registry()
```

### 🕸 Resolver App

After installation with the `[web]` extras, the Bioregistry web application
can be run with the following code:

```shell
$ python -m pip install bioregistry[web]
$ bioregistry web
```

to run a web app that functions like Identifiers.org, but backed by the Bioregistry.
A public instance of this app is hosted by the [Gyori Lab for Computational Biomedicine](https://gyorilab.github.io) at
https://bioregistry.io.

## 👋 Attribution

### ⚖ License

The code in this repository is licensed under the
[MIT License](https://github.com/biopragmatics/bioregistry/blob/main/LICENSE).

### 📛 Badge

If you use the Bioregistry in your code, support us by including our
badge in your project's README.md:

```markdown
[![Powered by the Bioregistry](https://img.shields.io/static/v1?label=Powered%20by&message=Bioregistry&color=BA274A&style=flat&logo=image/png;base64,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)](https://github.com/biopragmatics/bioregistry)
```

If your README uses reStructuredText (.rst), use this instead:

```
.. image:: https://img.shields.io/static/v1?label=Powered%20by&message=Bioregistry&color=BA274A&style=flat&logo=image/png;base64,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
    :target: https://github.com/biopragmatics/bioregistry
    :alt: Powered by the Bioregistry
```

It looks like this: [![Powered by the Bioregistry](https://img.shields.io/static/v1?label=Powered%20by&message=Bioregistry&color=BA274A&style=flat&logo=image/png;base64,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)](https://github.com/biopragmatics/bioregistry)

### 📖 Citation

> [Unifying the identification of biomedical entities with the Bioregistry](https://bioregistry.io/doi:10.1038/s41597-022-01807-3)
>
Hoyt, C. T., Balk, M., Callahan, T. J., Domingo-Fernandez, D., Haendel, M. A., Hegde, H. B., Himmelstein, D. S., Karis, K., Kunze, J., Lubiana, T., Matentzoglu, N., McMurry, J., Moxon, S., Mungall, C. J., Rutz, A., Unni, D. R., Willighagen, E., Winston, D., and Gyori, B. M. (2022)
>
*Nature Scientific Data*, s41597-022-01807-3

```bibtex
@article{Hoyt2022Bioregistry,
    author = {Hoyt, Charles Tapley and Balk, Meghan and Callahan, Tiffany J and Domingo-Fern{\'{a}}ndez, Daniel and Haendel, Melissa A and Hegde, Harshad B and Himmelstein, Daniel S and Karis, Klas and Kunze, John and Lubiana, Tiago and Matentzoglu, Nicolas and McMurry, Julie and Moxon, Sierra and Mungall, Christopher J and Rutz, Adriano and Unni, Deepak R and Willighagen, Egon and Winston, Donald and Gyori, Benjamin M},
    doi = {10.1038/s41597-022-01807-3},
    issn = {2052-4463},
    journal = {Sci. Data},
    number = {1},
    pages = {714},
    title = {{Unifying the identification of biomedical entities with the Bioregistry}},
    url = {https://doi.org/10.1038/s41597-022-01807-3},
    volume = {9},
    year = {2022}
}
```

Talks on the Bioregistry:

- [Future Curation in the Bioregistry](https://bit.ly/wpci2022-bioregistry-maintenance) (WPCI, December 2022)
- [The Bioregistry - Governance and Review Team](https://bit.ly/wpci2022-bioregistry-governance) (WPCI, December 2022)
- [Development, Maintenance, and Expansion of the Bioregistry](https://bit.ly/sorger-lab-bioregistry-2022)
  (Sorger Lab Meeting, October 2022)
- [The Bioregistry, CURIEs, and OBO Community Health](https://bit.ly/icbo2022-cth) (ICBO 2022 (September))
- [Introduction to the Bioregistry](https://bit.ly/bioregistry-short-talk) (Sorger Lab Meeting, July 2021)

### 🎁 Support

The Bioregistry was primarily developed by the [Gyori Lab for Computational Biomedicine](https://gyorilab.github.io)
at Northeastern University, which was previously a part of the
[Laboratory of Systems Pharmacology](https://hits.harvard.edu/the-program/laboratory-of-systems-pharmacology/about/)
in the [Harvard Program in Therapeutic Science (HiTS)](https://hits.harvard.edu)
at [Harvard Medical School](https://hms.harvard.edu/).

### 💰 Funding

1. Chan Zuckerberg Initiative (CZI) 2023-329850
2. DARPA Automating Scientific Knowledge Extraction and Modeling (ASKEM) HR00112220036
3. DARPA Young Faculty Award W911NF2010255 (PI: Benjamin M. Gyori).


# Home Assistant Octopus Energy

![installation_badge](https://img.shields.io/badge/dynamic/json?color=41BDF5&logo=home-assistant&label=integration%20usage&suffix=%20installs&cacheSeconds=15600&url=https://analytics.home-assistant.io/custom_integrations.json&query=$.octopus_energy.total) [![](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/bottlecapdave)
- [Home Assistant Octopus Energy](#home-assistant-octopus-energy)
  - [Features](#features)
  - [How to install](#how-to-install)
    - [HACS](#hacs)
    - [Manual](#manual)
  - [How to setup](#how-to-setup)
  - [Docs](#docs)
  - [FAQ](#faq)
  - [Sponsorship](#sponsorship)

Custom component built from the ground up to bring your Octopus Energy details into Home Assistant to help you towards a more energy efficient (and or cheaper) home. This integration is built against the API provided by Octopus Energy UK and has not been tested for any other countries.

This integration is in no way affiliated with Octopus Energy.

If you find this useful and are planning on moving to Octopus Energy, why not use my [referral link](https://share.octopus.energy/gray-jade-372)?

## Features

Below are the main features of the integration

* [Electricity](https://bottlecapdave.github.io/HomeAssistant-OctopusEnergy/entities/electricity/) and [gas](https://bottlecapdave.github.io/HomeAssistant-OctopusEnergy/entities/gas/) meter support including consumption data and rate information
* [Custom sensor support to target cheapest rates](https://bottlecapdave.github.io/HomeAssistant-OctopusEnergy/setup/target_rate/)
* [Custom sensor support for tracking costs of other entities](https://bottlecapdave.github.io/HomeAssistant-OctopusEnergy/setup/cost_tracker)
* [Custom sensor support for comparing to other tariffs](https://bottlecapdave.github.io/HomeAssistant-OctopusEnergy/setup/tariff_comparison)
* [Octopus Home mini support](https://bottlecapdave.github.io/HomeAssistant-OctopusEnergy/setup/account/#home-mini)
* [Intelligent tariff settings support](https://bottlecapdave.github.io/HomeAssistant-OctopusEnergy/entities/intelligent/)
* [Saving sessions support](https://bottlecapdave.github.io/HomeAssistant-OctopusEnergy/entities/octoplus/#saving-sessions)
* [Wheel of fortune support](https://bottlecapdave.github.io/HomeAssistant-OctopusEnergy/entities/wheel_of_fortune/)
* [Greener days support](https://bottlecapdave.github.io/HomeAssistant-OctopusEnergy/entities/greenness_forecast)

## How to install

There are multiple ways of installing the integration. Once you've installed the integration, you'll need to [setup your account](#how-to-setup) before you can use the integration.

### HACS

[![hacs_badge](https://img.shields.io/badge/HACS-Default-41BDF5.svg?style=for-the-badge)](https://github.com/hacs/integration)

This integration can be installed directly via HACS. To install:

* [Add the repository](https://my.home-assistant.io/redirect/hacs_repository/?owner=BottlecapDave&repository=homeassistant-octopusenergy&category=integration) to your HACS installation
* Click `Download`

### Manual

You should take the latest [published release](https://github.com/BottlecapDave/HomeAssistant-OctopusEnergy/releases). The current state of `develop` will be in flux and therefore possibly subject to change.

To install, place the contents of `custom_components` into the `<config directory>/custom_components` folder of your Home Assistant installation. Once installed, don't forget to restart your home assistant instance for the integration to be picked up.

## How to setup

Please follow the [setup guide](https://bottlecapdave.github.io/HomeAssistant-OctopusEnergy/setup/account) to setup your initial account. This guide details the configuration, along with the sensors that will be available to you.

## Docs

To get full use of the integration, please visit the [docs](https://bottlecapdave.github.io/HomeAssistant-OctopusEnergy/).

## FAQ

Before raising anything, please read through the [faq](https://bottlecapdave.github.io/HomeAssistant-OctopusEnergy/faq). If you have questions, then you can raise a [discussion](https://github.com/BottlecapDave/HomeAssistant-OctopusEnergy/discussions). If you have found a bug or have a feature request please [raise it](https://github.com/BottlecapDave/HomeAssistant-OctopusEnergy/issues) using the appropriate report template.

## Sponsorship

If you are enjoying the integration, why not use my [referral link](https://share.octopus.energy/gray-jade-372) if you're not already a part of Octopus Energy, or if possible, make a one off or monthly [GitHub sponsorship](https://github.com/sponsors/bottlecapdave).


# Schematic
[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2FSage-Bionetworks%2Fschematic%2Fbadge%3Fref%3Ddevelop&style=flat)](https://actions-badge.atrox.dev/Sage-Bionetworks/schematic/goto?ref=develop) [![Documentation Status](https://readthedocs.org/projects/sage-schematic/badge/?version=develop)](https://sage-schematic.readthedocs.io/en/develop/?badge=develop) [![PyPI version](https://badge.fury.io/py/schematicpy.svg)](https://badge.fury.io/py/schematicpy)

# Table of contents
- [Introduction](#introduction)
- [Installation](#installation)
  - [Installation Requirements](#installation-requirements)
  - [Installation guide for data curator app](#installation-guide-for-data-curator-app)
  - [Installation guide for developers/contributors](#installation-guide-for-developerscontributors)
- [Other Contribution Guidelines](#other-contribution-guidelines)
    - [Update readthedocs documentation](#update-readthedocs-documentation)
- [Command Line Usage](#command-line-usage)
- [Testing](#testing)
  - [Updating Synapse test resources](#updating-synapse-test-resources)
- [Code Style](#code-style)
- [Contributors](#contributors)

# Introduction
SCHEMATIC is an acronym for _Schema Engine for Manifest Ingress and Curation_. The Python based infrastructure provides a _novel_ schema-based, metadata ingress ecosystem, that is meant to streamline the process of biomedical dataset annotation, metadata validation and submission to a data repository for various data contributors.

# Installation
## Installation Requirements
* Python version 3.9.0≤x<3.11.0
* You need to be a registered and certified user on [`synapse.org`](https://www.synapse.org/)

Note: Our credential policy for Google credentials in order to create Google sheet files from Schematic, see tutorial ['HERE'](https://scribehow.com/shared/Get_Credentials_for_Google_Drive_and_Google_Sheets_APIs_to_use_with_schematicpy__yqfcJz_rQVeyTcg0KQCINA). If you plan to use `config.yml`, please ensure that the path of `schematic_service_account_creds.json` is indicated there (see `google_sheets > service_account_creds` section)

## Installation guide for data curator app

Create and activate a virtual environment within which you can install the package:

```
python3 -m venv .venv
source .venv/bin/activate
```

Note: Python 3 has a built-in support for virtual environment [venv](https://docs.python.org/3/library/venv.html#module-venv) so you no longer need to install virtualenv.

Install and update the package using [pip](https://pip.pypa.io/en/stable/quickstart/):

```
python3 -m pip install schematicpy
```

If you run into error: Failed building wheel for numpy, the error might be able to resolve by upgrading pip. Please try to upgrade pip by:

```
pip3 install --upgrade pip
```

## Installation guide for developers/contributors

When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change.

Please note we have a [code of conduct](CODE_OF_CONDUCT.md), please follow it in all your interactions with the project.

### Development environment setup
1. Clone the `schematic` package repository.
```
git clone https://github.com/Sage-Bionetworks/schematic.git
```
2. Install `poetry` (version 1.3.0 or later) using either the [official installer](https://python-poetry.org/docs/#installing-with-the-official-installer) or [pipx](https://python-poetry.org/docs/#installing-with-pipx). If you have an older installation of Poetry, we recommend uninstalling it first.

3. Start the virtual environment by doing:
```
poetry shell
```
4. Install the dependencies by doing:
```
poetry install
```
This command will install the dependencies based on what we specify in poetry.lock. If this step is taking a long time, try to go back to step 2 and check your version of poetry. Alternatively, you could also try deleting the lock file and regenerate it by doing `poetry install` (Please note this method should be used as a last resort because this would force other developers to change their development environment)

If you want to install the API you will need to install those dependencies as well:

```
poetry install --extras "api"
```

If you want to install the uwsgi:

```
poetry install --extras "api"
```

5. Fill in credential files:
*Note*: If you won't interact with Synapse, please ignore this section.

There are two main configuration files that need to be edited:
config.yml
and [synapseConfig](https://raw.githubusercontent.com/Sage-Bionetworks/synapsePythonClient/v2.3.0-rc/synapseclient/.synapseConfig)

Configure .synapseConfig File

Download a copy of the ``.synapseConfig`` file, open the file in the
editor of your choice and edit the `username` and `authtoken` attribute under the `authentication` section

*Note*: You could also visit [configparser](https://docs.python.org/3/library/configparser.html#module-configparser>) doc to see the format that `.synapseConfig` must have. For instance:
>[authentication]
 username = ABC
 authtoken = abc

Configure config.yml File

There are some defaults in schematic that can be configured. These fields are in ``config_example.yml``:

```text

# This is an example config for Schematic.
# All listed values are those that are the default if a config is not used.
# Save this as config.yml, this will be gitignored.
# Remove any fields in the config you don't want to change
# Change the values of any fields you do want to change

# This describes where assets such as manifests are stored
asset_store:
  # This is when assets are stored in a synapse project
  synapse:
    # Synapse ID of the file view listing all project data assets.
    master_fileview_id: "syn23643253"
    # Path to the synapse config file, either absolute or relative to this file
    config: ".synapseConfig"
    # Base name that manifest files will be saved as
    manifest_basename: "synapse_storage_manifest"

# This describes information about manifests as it relates to generation and validation
manifest:
  # Location where manifests will saved to
  manifest_folder: "manifests"
  # Title or title prefix given to generated manifest(s)
  title: "example"
  # Data types of manifests to be generated or data type (singular) to validate manifest against
  data_type:
    - "Biospecimen"
    - "Patient"

# Describes the location of your schema
model:
  # Location of your schema jsonld, it must be a path relative to this file or absolute
  location: "tests/data/example.model.jsonld"

# This section is for using google sheets with Schematic
google_sheets:
  # Path to the synapse config file, either absolute or relative to this file
  service_acct_creds: "schematic_service_account_creds.json"
  # When doing google sheet validation (regex match) with the validation rules.
  #   true is alerting the user and not allowing entry of bad values.
  #   false is warning but allowing the entry on to the sheet.
  strict_validation: true
```

If you want to change any of these copy ``config_example.yml`` to ``config.yml``, change any fields you want to, and remove any fields you don't.

For example if you wanted to change the folder where manifests are downloaded your config should look like:

```text

manifest:
  manifest_folder: "my_manifest_folder_path"
```

_Note_: `config.yml` is ignored by git.

_Note_: Paths can be specified relative to the `config.yml` file or as absolute paths.

6. Login to Synapse by using the command line
On the CLI in your virtual environment, run the following command:
```
synapse login -u <synapse username> -p <synapse password> --rememberMe
```

7. Obtain Google credential Files
Running `schematic init` is no longer supported due to security concerns. To obtain  `schematic_service_account_creds.json`, please follow the instructions [here](https://scribehow.com/shared/Enable_Google_Drive_and_Google_Sheets_APIs_for_project__yqfcJz_rQVeyTcg0KQCINA).

> As v22.12.1 version of schematic, using `token` mode of authentication (in other words, using `token.pickle` and `credentials.json`) is no longer supported due to Google's decision to move away from using OAuth out-of-band (OOB) flow. Click [here](https://developers.google.com/identity/protocols/oauth2/resources/oob-migration) to learn more.

*Notes*: Use the ``schematic_service_account_creds.json`` file for the service
account mode of authentication (*for Google services/APIs*). Service accounts
are special Google accounts that can be used by applications to access Google APIs
programmatically via OAuth2.0, with the advantage being that they do not require
human authorization.

*Background*: schematic uses Google’s API to generate google sheet templates that users fill in to provide (meta)data.
Most Google sheet functionality could be authenticated with service account. However, more complex Google sheet functionality
requires token-based authentication. As browser support that requires the token-based authentication diminishes, we are hoping to deprecate
token-based authentication and keep only service account authentication in the future.

8. Set up pre-commit hooks

This repository is configured to utilize pre-commit hooks as part of the development process. To enable these hooks, please run the following command and look for the following success message:
```
$ pre-commit install
pre-commit installed at .git/hooks/pre-commit
```

### Development process instruction

For new features, bugs, enhancements

1. Pull the latest code from [develop branch in the upstream repo](https://github.com/Sage-Bionetworks/schematic)
2. Checkout a new branch develop-<feature/fix-name> from the develop branch
3. Do development on branch develop-<feature/fix-name>
   a. may need to ensure that schematic poetry toml and lock files are compatible with your local environment
4. Add changed files for tracking and commit changes using [best practices](https://www.perforce.com/blog/vcs/git-best-practices-git-commit)
5. Have granular commits: not “too many” file changes, and not hundreds of code lines of changes
6. Commits with work in progress are encouraged:
   a. add WIP to the beginning of the commit message for “Work In Progress” commits
7. Keep commit messages descriptive but less than a page long, see best practices
8. Push code to develop-<feature/fix-name> in upstream repo
9. Branch out off develop-<feature/fix-name> if needed to work on multiple features associated with the same code base
10. After feature work is complete and before creating a PR to the develop branch in upstream
    a. ensure that code runs locally
    b. test for logical correctness locally
    c. wait for git workflow to complete (e.g. tests are run) on github
11. Create a PR from develop-<feature/fix-name> into the develop branch of the upstream repo
12. Request a code review on the PR
13. Once code is approved merge in the develop branch
14. Delete the develop-<feature/fix-name> branch

*Note*: Make sure you have the latest version of the `develop` branch on your local machine.

## Installation Guide - Docker

1. Install docker from https://www.docker.com/ .

2.  Identify docker image of interest from [Schematic DockerHub](https://hub.docker.com/r/sagebionetworks/schematic/tags)

    Ex `docker pull sagebionetworks/schematic:latest` from the CLI or, run `docker compose up` after cloning the schematic github repo

    in this case, `sagebionetworks/schematic:latest` is the name of the image chosen
3. Run Schematic Command with `docker run <flags> <schematic command and args>`.

<t> - For more information on flags for `docker run` and what they do, visit the [Docker Documentation](https://docs.docker.com/engine/reference/commandline/run/)

<t> - These example commands assume that you have navigated to the directory you want to run schematic from. To specify your working directory, use `$(pwd)` on MacOS/Linux or `%cd%` on Windows.

<t> - If not using the latest image, then the full name should be specified: ie `sagebionetworks/schematic:commit-e611e4a`

<t> - If using local image created by `docker compose up`, then the docker image name should be changed: i.e. `schematic_schematic`

<t> - Using the `--name` flag sets the name of the container running locally on your machine

### Example For REST API

#### Use file path of `config.yml` to run API endpoints:
```
docker run --rm -p 3001:3001 \
  -v $(pwd):/schematic -w /schematic --name schematic \
  -e SCHEMATIC_CONFIG=/schematic/config.yml \
  -e GE_HOME=/usr/src/app/great_expectations/ \
  sagebionetworks/schematic \
  python /usr/src/app/run_api.py
```

#### Use content of `config.yml` and `schematic_service_account_creds.json`as an environment variable to run API endpoints:
1. save content of `config.yml` as to environment variable `SCHEMATIC_CONFIG_CONTENT` by doing: `export SCHEMATIC_CONFIG_CONTENT=$(cat /path/to/config.yml)`

2. Similarly, save the content of `schematic_service_account_creds.json` as `SERVICE_ACCOUNT_CREDS` by doing: `export SERVICE_ACCOUNT_CREDS=$(cat /path/to/schematic_service_account_creds.json)`

3. Pass `SCHEMATIC_CONFIG_CONTENT` and `schematic_service_account_creds` as environment variables by using `docker run`

```
docker run --rm -p 3001:3001 \
  -v $(pwd):/schematic -w /schematic --name schematic \
  -e GE_HOME=/usr/src/app/great_expectations/ \
  -e SCHEMATIC_CONFIG_CONTENT=$SCHEMATIC_CONFIG_CONTENT \
  -e SERVICE_ACCOUNT_CREDS=$SERVICE_ACCOUNT_CREDS \
  sagebionetworks/schematic \
  python /usr/src/app/run_api.py
```

### Example For Schematic on mac/linux

To run example below, first clone schematic into your home directory  `git clone https://github.com/sage-bionetworks/schematic ~/schematic`

Then update .synapseConfig with your credentials
```
docker run \
  -v ~/schematic:/schematic \
  -w /schematic \
  -e SCHEMATIC_CONFIG=/schematic/config.yml \
  -e GE_HOME=/usr/src/app/great_expectations/ \
  sagebionetworks/schematic schematic model \
  -c /schematic/config.yml validate \
  -mp /schematic/tests/data/mock_manifests/Valid_Test_Manifest.csv \
  -dt MockComponent \
  -js /schematic/tests/data/example.model.jsonld
```

### Example For Schematic on Windows

```
docker run -v %cd%:/schematic \
  -w /schematic \
  -e GE_HOME=/usr/src/app/great_expectations/ \
  sagebionetworks/schematic \
  schematic model \
  -c config.yml validate -mp tests/data/mock_manifests/inValid_Test_Manifest.csv -dt MockComponent -js /schematic/data/example.model.jsonld
```

# Other Contribution Guidelines
## Updating readthedocs documentation
1. `cd docs`
2. After making relevant changes, you could run the `make html` command to re-generate the `build` folder.
3. Please contact the dev team to publish your updates

*Other helpful resources*:

1. [Getting started with Sphinx](https://haha.readthedocs.io/en/latest/intro/getting-started-with-sphinx.html)
2. [Installing Sphinx](https://haha.readthedocs.io/en/latest/intro/getting-started-with-sphinx.html)

## Update toml file and lock file
If you install external libraries by using `poetry add <name of library>`, please make sure that you include `pyproject.toml` and `poetry.lock` file in your commit.

## Reporting bugs or feature requests
You can **create bug and feature requests** through [Sage Bionetwork's FAIR Data service desk](https://sagebionetworks.jira.com/servicedesk/customer/portal/5/group/8). Providing enough details to the developers to verify and troubleshoot your issue is paramount:
- **Provide a clear and descriptive title as well as a concise summary** of the issue to identify the problem.
- **Describe the exact steps which reproduce the problem** in as many details as possible.
- **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
- **Explain which behavior you expected to see** instead and why.
- **Provide screenshots of the expected or actual behaviour** where applicable.

# Command Line Usage
Please visit more documentation [here](https://sage-schematic.readthedocs.io/en/develop/cli_reference.html)

# Testing

All code added to the client must have tests. The Python client uses pytest to run tests. The test code is located in the [tests](https://github.com/Sage-Bionetworks/schematic/tree/develop-docs-update/tests) subdirectory.

You can run the test suite in the following way:

```
pytest -vs tests/
```

## Updating Synapse test resources

1. Duplicate the entity being updated (or folder if applicable).
2. Edit the duplicates (_e.g._ annotations, contents, name).
3. Update the test suite in your branch to use these duplicates, including the expected values in the test assertions.
4. Open a PR as per the usual process (see above).
5. Once the PR is merged, leave the original copies on Synapse to maintain support for feature branches that were forked from `develop` before your update.
   - If the old copies are problematic and need to be removed immediately (_e.g._ contain sensitive data), proceed with the deletion and alert the other contributors that they need to merge the latest `develop` branch into their feature branches for their tests to work.

# Code style

* Please consult the [Google Python style guide](http://google.github.io/styleguide/pyguide.html) prior to contributing code to this project.
* Be consistent and follow existing code conventions and spirit.

# Contributors

Main contributors and developers:

- [Milen Nikolov](https://github.com/milen-sage)
- [Mialy DeFelice](https://github.com/mialy-defelice)
- [Sujay Patil](https://github.com/sujaypatil96)
- [Bruno Grande](https://github.com/BrunoGrandePhD)
- [Robert Allaway](https://github.com/allaway)
- [Gianna Jordan](https://github.com/giajordan)
- [Lingling Peng](https://github.com/linglp)


[![Documentation Status](https://readthedocs.org/projects/varfish-server/badge/?version=latest)](https://varfish-server.readthedocs.io/en/latest/?badge=latest)
[![Code Coverage](https://codecov.io/gh/bihealth/varfish-server/branch/main/graph/badge.svg?token=5ZACSH5MZZ)](https://codecov.io/gh/bihealth/varfish-server)
[![image](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)

# VarFish

**Comprehensive DNA variant analysis for diagnostics and research.**

This is the repository for the web server component.

Holtgrewe, M.; Stolpe, O.; Nieminen, M.; Mundlos, S.; Knaus, A.; Kornak, U.; Seelow, D.; Segebrecht, L.; Spielmann, M.; Fischer-Zirnsak, B.; Boschann, F.; Scholl, U.; Ehmke, N.; Beule, D. *VarFish: Comprehensive DNA Variant Analysis for Diagnostics and Research*. Nucleic Acids Research 2020, gkaa241. <https://doi.org/10.1093/nar/gkaa241>.

## Getting Started

- [VarFish Homepage](https://www.cubi.bihealth.org/software/varfish/)
- [Manual](https://varfish-server.readthedocs.io/en/latest/)
  - [Installation Instructions](https://varfish-server.readthedocs.io/en/latest/admin_install.html).
- [Docker Compose Installer](https://github.com/bihealth/varfish-docker-compose#run-varfish-server-using-docker-compose).

## VarFish Repositories

- [varfish-server](https://github.com/bihealth/varfish-server) The VarFish Server is the web frontend used by the end users / data analysts.
- [varfish-annotator](https://github.com/bihealth/varfish-annotator) The VarFish Annotator is a command line utility used for annotating VCF files and converting them to files that can be imported into VarFish Server.
- [varfish-cli](https://github.com/bihealth/varfish-cli) The VarFish Command Line Interface allows to import data through the VarFish REST API.
- [varfish-db-downloader](https://github.com/bihealth/varfish-db-downloader) The VarFish DB Downloader is a command line tool for downloading the background database.
- [varfish-docker-compose](https://github.com/bihealth/varfish-docker-compose) Quickly get started running a VarFish server by using Docker Compose. We provide a prebuilt data set with some already imported data.

## At a Glance

- License: MIT
- Dependencies / Tech Stack
  - Python \>=3.8
  - Django 3
  - PostgreSQL \>=12

GitHub is used for public issue tracking. Currently, development happens
on internal infrastructure.

## VarFish Component Compatibility Table

The following combinations have been validated / are supported to work.

| VarFish Server | VarFish CLI | VarFish Annotator |
| -------------- | ----------- | ----------------- |
| v1.2.2         | v0.3.0      | v0.21             |
| v1.2.1         | v0.3.0      | v0.21             |
| v1.2.0         | v0.3.0      | v0.21             |

## VarFish Data Release Compatibility Table

The following combinations have been validated / are supported to work.

| VarFish Server | Data Release | VarFish DB Downloader |
| -------------- | ------------ | --------------------- |
| v1.2.2         | 20210728c    | v0.3.\*               |
| v1.2.1         | 20210728     | v0.3.\*               |
| v1.2.1         | 20210728b    | v0.3.\*               |
| v1.2.0         | 20210728     | v0.3.\*               |
| v1.2.0         | 20210728b    | v0.3.\*               |


# MadMiner: ML based inference for particle physics

**By Johann Brehmer, Felix Kling, Irina Espejo, Sinclert Pérez, and Kyle Cranmer**

[![PyPI version][pypi-version-badge]][pypi-version-link]
[![conda-forge version][conda-forge-version-badge]][conda-forge-version-link]
[![CI/CD Status][ci-status-badge]][ci-status-link]
[![Docs Status][docs-status-badge]][docs-status-link]
[![Gitter chat][chat-gitter-badge]][chat-gitter-link]
[![Code style][code-style-badge]][code-style-link]
[![MIT license][mit-license-badge]][mit-license-link]
[![DOI reference][ref-zenodo-badge]][ref-zenodo-link]
[![ArXiv reference][ref-arxiv-badge]][ref-arxiv-link]

## Introduction

![Schematics of the simulation and inference workflow][image-rascal-diagram]

Particle physics processes are usually modeled with complex Monte-Carlo simulations of the hard process, parton shower,
and detector interactions. These simulators typically do not admit a tractable likelihood function: given a (potentially
high-dimensional) set of observables, it is usually not possible to calculate the probability of these observables
for some model parameters. Particle physicists usually tackle this problem of "likelihood-free inference" by
hand-picking a few "good" observables or summary statistics and filling histograms of them. But this conventional
approach discards the information in all other observables and often does not scale well to high-dimensional problems.

In the three publications ["Constraining Effective Field Theories with Machine Learning"][ref-arxiv-madminer-1],
["A Guide to Constraining Effective Field Theories with Machine Learning"][ref-arxiv-madminer-2], and
["Mining gold from implicit models to improve likelihood-free inference"][ref-arxiv-madminer-3],
a new approach has been developed. In a nutshell, additional information is extracted from the simulations that is
closely related to the matrix elements that determine the hard process. This "augmented data" can be used to train
neural networks to efficiently approximate arbitrary likelihood ratios. We playfully call this process "mining gold"
from the simulator, since this information may be hard to get, but turns out to be very valuable for inference.

But the gold does not have to be hard to mine: MadMiner automates these modern multivariate inference strategies. It
wraps around the simulators MadGraph and Pythia, with different options for the detector simulation. It streamlines all
steps in the analysis chain from the simulation to the extraction of the augmented data, their processing, the training
and evaluation of the neural networks, and the statistical analysis are implemented.

## Resources

### Paper
Our main publication [MadMiner: Machine-learning-based inference for particle physics][ref-arxiv-link]
provides an overview over this package. We recommend reading it first before jumping into the code.

### Installation instructions
Please have a look at our [installation instructions][docs-installation-guide].

### Tutorials
In the [examples][examples-folder-path] folder in this repository, we provide two tutorials. The first is called
[_Toy simulator_][examples-simulator-path], and it is based on a toy problem rather than a full particle-physics simulation.
It demonstrates inference with MadMiner without spending much time on the more technical steps of running the simulation.
The second, called [_Particle physics_][examples-physics-path], shows all steps of a particle-physics analysis with MadMiner.

These examples are the basis of [the online tutorial][jupyter-tutorial-link] built on Jupyter Books. It also walks
through how to run MadMiner using Docker so that you do not have to install Fortran, MadGraph, Pythia, Delphes, etc.
You can even run it with no install using Binder.

### Documentation
The madminer API is documented on [Read the Docs][docs-index].

### Support
If you have any questions, please chat to us in our [Gitter community][chat-gitter-link].

## Citations

If you use MadMiner, please cite our main publication,
```
@article{Brehmer:2019xox,
      author         = "Brehmer, Johann and Kling, Felix and Espejo, Irina and Cranmer, Kyle",
      title          = "{MadMiner: Machine learning-based inference for particle physics}",
      journal        = "Comput. Softw. Big Sci.",
      volume         = "4",
      year           = "2020",
      number         = "1",
      pages          = "3",
      doi            = "10.1007/s41781-020-0035-2",
      eprint         = "1907.10621",
      archivePrefix  = "arXiv",
      primaryClass   = "hep-ph",
      SLACcitation   = "%%CITATION = ARXIV:1907.10621;%%"
}
```

The code itself can be cited as
```
@misc{MadMiner_code,
      author         = "Brehmer, Johann and Kling, Felix and Espejo, Irina and Perez, Sinclert and Cranmer, Kyle",
      title          = "{MadMiner}",
      doi            = "10.5281/zenodo.1489147",
      url            = {https://github.com/madminer-tool/madminer}
}
```

The main references for the implemented inference techniques are the following:

- CARL: [1506.02169][ref-arxiv-carl].
- MAF: [1705.07057][ref-arxiv-maf].
- CASCAL, RASCAL, ROLR, SALLY, SALLINO, SCANDAL:
  - [1805.00013][ref-arxiv-madminer-1].
  - [1805.00020][ref-arxiv-madminer-2].
  - [1805.12244][ref-arxiv-madminer-3].
- ALICE, ALICES: [1808.00973][ref-arxiv-alice].

## Acknowledgements

We are immensely grateful to all [contributors][repo-madminer-contrib] and bug reporters! In particular, we would like
to thank Zubair Bhatti, Philipp Englert, Lukas Heinrich, Alexander Held, Samuel Homiller and Duccio Pappadopulo.

The SCANDAL inference method is based on [Masked Autoregressive Flows][ref-arxiv-scandal], where our implementation is
a PyTorch port of the original code by George Papamakarios, available at [this repository][repo-maf-main-page].

![IRIS-HEP logo][image-iris-logo]

We are grateful for the support of [IRIS-HEP][web-iris-hep] and [DIANA-HEP][web-diana-hep].

[chat-gitter-badge]: https://badges.gitter.im/madminer/community.svg
[chat-gitter-link]: https://gitter.im/madminer/community
[ci-status-badge]: https://github.com/madminer-tool/madminer/actions/workflows/ci.yml/badge.svg?branch=main
[ci-status-link]: https://github.com/madminer-tool/madminer/actions/workflows/ci.yml?query=branch%3Amain
[code-style-badge]: https://img.shields.io/badge/code%20style-black-000000.svg
[code-style-link]: https://github.com/psf/black
[docs-status-badge]: https://readthedocs.org/projects/madminer/badge/?version=latest
[docs-status-link]: https://madminer.readthedocs.io/en/latest/?badge=latest
[mit-license-badge]: https://img.shields.io/badge/License-MIT-blue.svg
[mit-license-link]: https://github.com/madminer-tool/madminer/blob/main/LICENSE.md
[pypi-version-badge]: https://badge.fury.io/py/madminer.svg
[pypi-version-link]: https://badge.fury.io/py/madminer
[conda-forge-version-badge]: https://img.shields.io/conda/vn/conda-forge/madminer.svg
[conda-forge-version-link]: https://prefix.dev/channels/conda-forge/packages/madminer

[ref-arxiv-badge]: http://img.shields.io/badge/arXiv-1907.10621-B31B1B.svg
[ref-arxiv-link]: https://arxiv.org/abs/1907.10621
[ref-zenodo-badge]: https://zenodo.org/badge/DOI/10.5281/zenodo.1489147.svg
[ref-zenodo-link]: https://doi.org/10.5281/zenodo.1489147

[docs-index]: https://madminer.readthedocs.io/en/latest/
[docs-installation-guide ]: https://madminer.readthedocs.io/en/latest/installation.html
[examples-folder-path]: https://github.com/madminer-tool/madminer/tree/main/examples
[examples-physics-path]: https://github.com/madminer-tool/madminer/tree/main/examples/tutorial_particle_physics
[examples-simulator-path]: https://github.com/madminer-tool/madminer/tree/main/examples/tutorial_toy_simulator
[image-iris-logo]: https://iris-hep.org/assets/logos/Iris-hep-4-no-long-name.png
[image-rascal-diagram]: https://raw.githubusercontent.com/madminer-tool/madminer/main/docs/img/rascal-explainer.png
[jupyter-tutorial-link]: https://madminer-tool.github.io/madminer-tutorial
[ref-arxiv-alice]: https://arxiv.org/abs/1808.00973
[ref-arxiv-carl]: https://arxiv.org/abs/1506.02169
[ref-arxiv-maf]: https://arxiv.org/abs/1705.07057
[ref-arxiv-madminer-1]: https://arxiv.org/abs/1805.00013
[ref-arxiv-madminer-2]: https://arxiv.org/abs/1805.00020
[ref-arxiv-madminer-3]: https://arxiv.org/abs/1805.12244
[ref-arxiv-scandal]: https://arxiv.org/abs/1705.07057
[repo-madminer-contrib]: https://github.com/madminer-tool/madminer/graphs/contributors
[repo-maf-main-page]: https://github.com/gpapamak/maf
[web-diana-hep]: https://diana-hep.org
[web-iris-hep]: https://iris-hep.org