pinder 0.5.0
PINDER: The Protein INteraction Dataset and Evaluation Resource
Requires Python: >=3.10

![pinder](https://github.com/pinder-org/pinder/raw/main/assets/pinder.png)
<div align="center">
    <h1>PINDER: The Protein INteraction Dataset and Evaluation Resource</h1>
</div>

---

[![PyPI](https://img.shields.io/pypi/v/pinder)](https://pypi.org/project/pinder/)
[![license](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/pinder-org/pinder/blob/master/LICENSE)
[![GitHub Repo stars](https://img.shields.io/github/stars/pinder-org/pinder)](https://github.com/pinder-org/pinder/stargazers)
[![test](https://github.com/pinder-org/pinder/actions/workflows/pr.yaml/badge.svg)](https://github.com/pinder-org/pinder/actions/workflows/pr.yaml)
[![codecov](https://codecov.io/gh/pinder-org/pinder/graph/badge.svg?token=NPQAYW75OD)](https://codecov.io/gh/pinder-org/pinder)

# 📚 About

**pinder**, short for **p**rotein **in**teraction **d**ataset and **e**valuation **r**esource, is a dataset and resource for training and evaluation of protein-protein docking algorithms. It is ~500x larger than previous state of the art datasets and is the first dataset to include paired predicted and apo structures to train flexible docking methods.

The dataset is large (~700Gb) and hosted on Google Cloud Storage (available at the `gs://pinder` bucket).

# 👨‍💻 Getting Started

## Prerequisites

### fastpdb support

pinder uses [fastpdb](https://github.com/biotite-dev/fastpdb) to accelerate PDB
I/O operations. fastpdb is a dependency of pinder-core, and pip will attempt to
install it for you during the installation of pinder. Pre-built wheels of
fastpdb are available on PyPI for the following platforms:
1. Linux with `glibc>=2.34` (e.g., Debian 12, Ubuntu 22.04, RHEL 9, etc.)
2. MacOS Sierra (10.12) or newer
3. Windows

If your platform doesn't match these conditions, you will not get a wheel and
pip will attempt to build fastpdb from source. In order to build fastpdb from
source, you will need the rust toolchain, which you can install by running:

```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

before installing pinder.

## Install pinder

### Initialize a virtual environment or conda environment

We recommend installing pinder into a clean virtual environment or conda
environment. This can be done using
[`mamba`](https://github.com/mamba-org/mamba) or `conda` (you can swap `mamba`
for `conda` for the same functionality):


```bash
mamba create --name pinder python=3.11
mamba activate pinder
```


or via `venv` from the Python standard library:

```bash
# clone the repo and cd into it, unless you plan to install from PyPI, then
python3 -m venv venv
source venv/bin/activate
```

## Install optional dependencies

### pytorch-cluster

`pytorch-cluster` is an optional dependency for pinder. If you wish to make use
of its features, you will need to install it separately.

To install from a wheel, run

```bash
pip install torch-cluster -f https://data.pyg.org/whl/torch-${TORCH}+${CUDA}.html
```

where `${TORCH}` should be replaced by the version of PyTorch installed and `${CUDA}` should be replaced by either `cpu`, `cu118`, or `cu121`
depending on your PyTorch installation.

To install from source, first make sure you have pytorch installed in the
current environment (`pip install torch`), then run

```bash
pip install torch-cluster
```

Note that on Apple Silicon MacOS machines, installation from source is the only option.

### PRODIGY-cryst

PRODIGY-cryst is used in the data ingestion pipeline to predict the probability that an interface is a biological interaction. While it is not needed to use `pinder.core`, it is an optional dependency of `pinder.data` and can be installed as a git-based installation. To install, run

```bash
pip install git+https://github.com/yusuf1759/prodigy-cryst.git
```

### Install pinder packages from PyPI

To install with the minimal dependencies needed to use `pinder.core`
```bash
pip install pinder
```

Install optional extras, for instance to use the `pinder.eval` package

```bash
pip install pinder[eval]
```

Or, install all extras

```bash
pip install pinder[all]
```


# ⬇️ Getting the dataset

We strongly recommend to interact via the provided python API in `pinder-core`, as follows, which will automatically download and load the data into either `$PINDER_BASE_DIR` or `$XDG_DATA_HOME` (usually `~/.local/share/pinder` on Mac and Linux) if no explicit download path is provided (recommended)

NOTE: the default location for the dataset is `~/.local/share/pinder/<release version>`

If you want to use a different location, you can do so by setting the `PINDER_BASE_DIR` environment variable.

The base dir refers to a fully qualified path name up until the `<release version>` (not inclusive).

For instance, you could:
```bash
export PINDER_BASE_DIR=~/my-custom-location-for-pinder/pinder
```

You can always check the current location of the dataset like so:
```python
from pinder.core import get_pinder_location
get_pinder_location()
```

The current release version of pinder is `2024-02`.

You can find the list of available dataset releases and the associated changes in the [data changelog](changelog_data.md).

## To download the complete dataset run the following

```
pinder_download --help

usage: Download latest pinder dataset to disk [-h] [--pinder_base_dir PINDER_BASE_DIR] [--pinder_release PINDER_RELEASE] [--skip_inflation]

optional arguments:
  -h, --help            show this help message and exit
  --pinder_base_dir PINDER_BASE_DIR
                        specify a non-default pinder base directory
  --pinder_release PINDER_RELEASE
                        specify a pinder dataset version
  --skip_inflation      if passed, will only download the compressed archives without unpacking
```

The full dataset should look like this:

```bash
get_pinder_location()/
    pdbs/
    test_set_pdbs/
    mappings/
    index.parquet
    metadata.parquet
```

* `pdbs/` contains individual monomer and ground-truth dimer PDB structures
* `mappings/` contains mapping information for holo and apo monomers for PDB<->uniprot, as well as original PDB assembly information used in some utilities
* `index.parquet` contains the master index of every dimer in pinder. See [here](examples/pinder-index.ipynb) for more details.
* `metadata.parquet` contains additional metadata detail for each entry in the index.

It is also possible to download it manually, via

```bash
export PINDER_RELEASE=2024-02
export PINDER_ROOT=pinder/$PINDER_RELEASE
mkdir -p $XDG_DATA_HOME/$PINDER_ROOT/
gsutil -m cp gs://$PINDER_ROOT/pdbs.zip $XDG_DATA_HOME/$PINDER_ROOT/
gsutil -m cp gs://$PINDER_ROOT/test_set_pdbs.zip $XDG_DATA_HOME/$PINDER_ROOT/
gsutil -m cp gs://$PINDER_ROOT/mappings.zip $XDG_DATA_HOME/$PINDER_ROOT/
gsutil -m cp gs://$PINDER_ROOT/index.parquet $XDG_DATA_HOME/$PINDER_ROOT/
gsutil -m cp gs://$PINDER_ROOT/metadata.parquet $XDG_DATA_HOME/$PINDER_ROOT/
cd $XDG_DATA_HOME/$PINDER_ROOT
unzip pdbs.zip && rm pdbs.zip
unzip test_set_pdbs.zip && rm test_set_pdbs.zip
unzip mappings.zip && rm mappings.zip
```

however, this is discouraged and requires installing gsutil.

Note: to download the full dataset, you will need ~700Gb of free disk space.
```
# compressed
144G    pdbs.zip
149M    test_set_pdbs.zip
6.8G    mappings.zip

# unpacked
672G    pdbs
705M    test_set_pdbs
25G     mappings
```

## Updating the dataset
In the event that there are patch (non-breaking) changes to the index or metadata, you can sync your local copy of the index using a similar command-line interface:

```
pinder_update_index --help

usage: Download latest pinder index to disk [-h] [--pinder_base_dir PINDER_BASE_DIR] [--pinder_release PINDER_RELEASE] [--skip_inflation]

optional arguments:
  -h, --help            show this help message and exit
  --pinder_base_dir PINDER_BASE_DIR
                        specify a non-default pinder base directory
  --pinder_release PINDER_RELEASE
                        specify a pinder dataset version
```

If any *structure* files have been changed (will be announced in [data changelog](changelog_data.md)), but a major release (PINDER_RELEASE) has not yet been published, to sync your local dataset:

```
pinder_sync_data --help
usage: Sync missing pinder structural data files to disk [-h] [--pinder_base_dir PINDER_BASE_DIR] [--pinder_release PINDER_RELEASE] [--skip_inflation]

optional arguments:
  -h, --help            show this help message and exit
  --pinder_base_dir PINDER_BASE_DIR
                        specify a non-default pinder base directory
  --pinder_release PINDER_RELEASE
                        specify a pinder dataset version

```


# Pinder datasets & resources

## 1. 🏅 Gold standard benchmark sets
A set of 4 interface structure & sequence-deleaked, gold standard benchmark sets, all of which were redundancy removed and filtered to be of highest quality

| Dataset         |   # of PDB IDs |   # of Clusters |   # Holo pairs |   # Apo pairs |   # AF2 Pairs | Description                                                                                                                                                                                                                                                                                                                                                               |
|:----------------|---------------:|----------------:|---------------:|--------------:|--------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| PINDER-XL       |           1955 |            1955 |           1955 |           342 |          1747 | Full test set, 1,955 cluster representatives, including 342 apo paired structures and 1,747 AFDB structures                                                                                                                                                                                                                                                               |
| PINDER-S        |            250 |             250 |            250 |            93 |           250 | A smaller subset of PINDER-XL, comprised of 250 clusters (188 heterodimer and 62 homodimers) sampled for diverse Uniprot and PFAM annotations, 93 of which have apo paired structures (143 have at least one apo monomer) and all of which have paired AFDB structures, to evaluate methods for which sampling from the full set is too slow                              |
| PINDER-AF2      |            180 |             180 |            180 |            30 |           127 | A smaller subset of PINDER-XL, comprised of 180 clusters, 30 of which have paired apo structures and 131 with paired AFDB structures, which were deleaked against the AF2MM training set with a more rigorous deleaking process to remove any members with interfaces similar to the AF2MM training set as determined by iAlign, to evaluate methods against AF2MM                                                                                                                                                |


All of these contain ready to use, pre-rotated & translated monomer structures


**A validation holdout set:**

| Dataset   |   # of PDB IDs |   # of Clusters |   # Holo pairs |   # Apo pairs |   # AF2 Pairs | Description                                                                                                                                         |
|:----------|---------------:|----------------:|---------------:|--------------:|--------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------|
| Val       |           1958 |            1958 |           1958 |           342 |          1789 | Validation set, consisting of 1,958 cluster representatives, of which 342 have paired apo structures and 1,789 of which have paired AFDB structures |


**A training set which provides an extensive number of possible training examples:**

|                              |                                                                                                                                                             |
|:-----------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Dataset                      | Train                                                                                                                                                           |
| Size<sup>1</sup>             | 2456152                                                                                                                                                         |
| Theoretical Size<sup>2</sup> | 25130994                                                                                                                                                        |
| # of PDB IDs                 | 62706                                                                                                                                                           |
| # of Clusters                | 42220                                                                                                                                                           |
| # Apo Pairs                  | 136498                                                                                                                                                          |
| # AF2 Pairs                  | 566171                                                                                                                                                          |
| # At least one Apo Monomer   | 274194                                                                                                                                                          |
| # At least one AF2 Monomer   | 621276                                                                                                                                                          |
| Description                  | Training set, consisting of 1,560,682 dimers from 42,220 clusters, of which 136,498 have paired apo structures and 566,171 of which have paired AFDB structures |



1. Size refers to the sum of training examples with at least one Apo monomer (274,194), at least one AF2 monomer (621,276), and the holo monomers (1,560,682)
2. Theoretical size refers to the theoretical number of training examples made available by pinder. It includes all of the available Apo monomers for each of receptor and ligand, respectively, and all of the combinations with other monomer types. E.g., holo-receptor + apo-ligand1, AF2-receptor + apo-ligand2, etc.



See [Dataset Generation](#-dataset-generation) for details on how the dataset was generated.

##  2. 📊 Leaderboard
A **leaderboard** of the current state of the art physics-based docking methods as reference

| Type    | Name       | Train Dataset | Leaderboards
|---------|------------|---------| ----|
| Physics | FroDock    | N/A     | `PINDER-XL`, `PINDER-S`, `PINDER-AF2` |
| Physics | PatchDock  | N/A     |`PINDER-XL`, `PINDER-S`, `PINDER-AF2` |
| Physics | HDock      | N/A     |`PINDER-XL`, `PINDER-S`, `PINDER-AF2` |
| ML      | DiffDock-PP| pinder-holo    |`PINDER-XL`, `PINDER-S`, `PINDER-AF2` |
| ML      | AF2-MM    | af2mm    |`PINDER-AF2` |


## 3. ⚖️ Evaluation harness

A complete evaluation harness with a set of highly efficient pure-python or rust implementations of standard metrics for evaluation, such as DockQ is provided.

We use the community-standard CAPRI metrics for assessing docking methods. Further detail can be found [here](https://predictioncenter.org/casp15/doc/presentations/Day2/Assessment_Assembly-CAPRI_MLensink.pdf)

The evaluation harness can be used either through methods in pinder.eval or as a CLI script:

```
pinder_eval --help

usage: pinder_eval [-h] --eval_dir eval_dir [--serial] [--method_name method_name] [--allow_missing] [--custom_index CUSTOM_INDEX] [--max_workers MAX_WORKERS]

options:
  -h, --help            show this help message and exit
  --eval_dir eval_dir, -f eval_dir
                        Path to eval
  --serial, -s          Whether to disable parallel eval over systems
  --method_name method_name, -m method_name, -n method_name
                        Optional name for output csv
  --allow_missing, -a   Whether to allow missing systems for a given pinder-set + monomer
  --custom_index CUSTOM_INDEX, -c CUSTOM_INDEX
                        Optional local filepath or GCS uri to a custom index with non-pinder splits. Note: must still follow the pinder index schema and define test holdout sets, but does not need to share the same
                        split members.
  --max_workers MAX_WORKERS, -w MAX_WORKERS
                        Optional maximum number of processes to spawn in multiprocessing. Default is None (all available cores).
```

The expected format for the contents of `eval_dir` are shown below:
```
eval_dir_example/
└── some_method
    ├── 1an1__A1_P00761--1an1__B1_P80424
    │   ├── apo_decoys
    │   │   ├── model_1.pdb
    │   │   └── model_2.pdb
    │   ├── holo_decoys
    │   │   ├── model_1.pdb
    │   │   └── model_2.pdb
    │   └── predicted_decoys
    │       ├── model_1.pdb
    │       └── model_2.pdb
    └── 1b8m__A1_P23560--1b8m__B1_P34130
        ├── holo_decoys
        │   ├── model_1.pdb
        │   └── model_2.pdb
        └── predicted_decoys
            ├── model_1.pdb
            └── model_2.pdb
```

The eval directory should contain one or more methods to evaluate as sub-directories.

Each method sub-directory should contains sub-directories that are named by pinder system ID.

Inside of each pinder system sub-directory, you should have three subdirectories:
* `holo_decoys` (predictions that were made using holo monomers)
* `apo_decoys` (predictions made using apo monomers)
* `predicted_decoys` (predictions made using predicted, e.g. AF2, monomers)

You can have any number of decoys in each directory; however, the decoys should be named in a way that the prediction rank can be extracted. In the above example, the decoys are named using a `model_<rank>.pdb` convention. Other names for decoy models are accepted, so long as they can match the regex pattern used in `pinder.eval.dockq.MethodMetrics`: `r"\d+(?=\D*$)"`

Each model decoy should have exactly two chains: {R, L} for {Receptor, Ligand}, respectively.


⚠️ **Note: in order to make a fair comparison of methods across complete test sets, if a method is missing predictions for a system, the following metrics are used as a penalty**

```python

{
    "iRMS": 100.0,
    "LRMS": 100.0,
    "Fnat": 0.0,
    "DockQ": 0.0,
    "CAPRI": "Incorrect",
}
```

For more details on the implementations of the eval metrics, see the [eval tutorial](https://pinder-org.github.io/pinder/pinder-eval.html), [API docs](https://pinder-org.github.io/pinder/source/pinder.eval.dockq.html#) and [eval FAQ](https://pinder-org.github.io/pinder/faq.html#how-can-i-use-the-evaluation-harness-outside-of-a-pinder-context).

For more details on leaderboard generation, see the [MethodMetrics](src/pinder-eval/pinder/eval/dockq/method.py) implementation.


## 4. 🧪 Training set

We provide a ready-to-use, large training set, `PINDER-Train` with **2,456,152** pairs, consisting of 1,560,682 bound structures, 274,194 structures with at least one paired apo structure and 621,276 pairs with at least one paired AFDB structures. These can be combined to yield up to 25,130,994 unique training examples.
They are clustered by __interface__ similarity via FoldSeek and deleaked by structure and interface similarity against the `PINDER-XL` (and thus against all others) and validation set, `PINDER-Val`.

`PINDER-Val` is included as a redundancy removed validation set of 1,958 holo structures from 1,958 clusters, prepared in identical fashion and distribution to the test set, including 342 apo paired structures and 1,789 AFDB structures, filtered with the same quality criteria as the test set to allow for representative monitoring of training performance.

See [Dataset Generation](#-dataset-generation) for details on how the dataset was generated.

## 5. 📦 Dataloader

We provide two flavors of dataloaders based on the `Dataset` and `DataLoader` APIs from `torch` and `torch-geometric` as example implementations (and are happy to provide more if there are feature requests) for easy loading of datasets.

All dataloaders are based on iterators over `PinderSystem`, a core abstraction which provides the collection of structural data associated with an entry in the pinder database.

The `PinderSystem` exposes the following structures:
* Ground-truth crystal structure
* Holo receptor and ligand
* Apo receptor and ligand (where available)
* Predicted receptor and ligand (currently from alphafold; where available)

**Note: all monomers follow the chain naming convention of R, L for receptor and ligand, respectively. However, if you are using the PDB files directly without `PinderSystem`, note that the apo and predicted monomers are both stored with chain ID A. This was done to reduce file/disk burden by not duplicating apo/predicted monomers that map to both receptor and/or ligand across multiple systems.**


Each structure is defined by the `Structure` abstraction. See the [example notebook](https://pinder-org.github.io/pinder/pinder-system.html) for more details.


We provide the following features:

| Feature                                                                                                                                                                                                                        | Abstraction                                                          | Example                                             |
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------|:----------------------------------------------------|
| Get collection of monomers associated with a pinder entry using `PinderSystem`                                                                                                                                                 | [PinderSystem](src/pinder-core/pinder/core/index/system.py)          | [pinder-system.ipynb](examples/pinder-system.ipynb) |
| Classify system difficulty based on degree of conformational shift in unbound and bound using `PinderSystem`                                                                                                                   | [PinderSystem](src/pinder-core/pinder/core/index/system.py)          | [pinder-system.ipynb](examples/pinder-system.ipynb) |
| Get various structural features like coordinates, residues, atoms and sequence and structural utilities using the `Structure` abstraction. All of the monomers in the `PinderSystem` object are themselves `Structure` objects | [Structure](src/pinder-core/pinder/core/loader/structure.py)         | [pinder-system.ipynb](examples/pinder-system.ipynb) |
| Filter pinder systems to construct data mixes using `PinderFilterBase`                                                                                                                                                         | [PinderFilterBase](src/pinder-core/pinder/core/loader/filters.py)    | [pinder-loader.ipynb](examples/pinder-loader.ipynb) |
| Filter pinder systems to construct data mixes with specific monomers or monomers that satisfy specific filter criteria using `PinderFilterSubBase`                                                                             | [PinderFilterSubBase](src/pinder-core/pinder/core/loader/filters.py) | [pinder-loader.ipynb](examples/pinder-loader.ipynb) |
| Filter individual `Structure` objects in a system to construct data mixes with specific monomer properties using `StructureFilter`                                                                                             | [StructureFilter](src/pinder-core/pinder/core/loader/filters.py)     | [pinder-loader.ipynb](examples/pinder-loader.ipynb) |
| Construct iterator for getting specific data mixes and applying collection of filters through `PinderLoader`                                                                                                                   | [PinderLoader](src/pinder-core/pinder/core/loader/loader.py)         | [pinder-loader.ipynb](examples/pinder-loader.ipynb) |
| Load systems as a pytorch dataset using `PinderDataset`                                                                                                                                                                        | [PinderDataset](src/pinder-core/pinder/core/loader/dataset.py)       | [pinder-loader.ipynb](examples/pinder-loader.ipynb) |
| Load datasets as pytorch geometric graph datasets using `PPIDataset`                                                                                                                                                           | [PPIDataset](src/pinder-core/pinder/core/loader/dataset.py)          | [pinder-loader.ipynb](examples/pinder-loader.ipynb) |
| Create standard pytorch dataloaders using `get_torch_loader` with `PinderDataset` as input                                                                                                                                     | [get_torch_loader](src/pinder-core/pinder/core/loader/dataset.py)    | [pinder-loader.ipynb](examples/pinder-loader.ipynb) |
| Create standard torch-geometric dataloaders using `get_geo_loader` with `PPIDataset` as input                                                                                                                                  | [get_geo_loader](src/pinder-core/pinder/core/loader/dataset.py)      | [pinder-loader.ipynb](examples/pinder-loader.ipynb) |
| Transform structures in a system before use in downstream tasks using `TransformBase`                                                                                                                                          | [TransformBase](src/pinder-core/pinder/core/loader/transforms.py)    | [examples](examples/README.md#transforms)           |
| Transform individual `Structure` objects before use in downstream tasks using `StructureTransform`                                                                                                                             | [StructureTransform](src/pinder-core/pinder/core/loader/transforms.py)| [examples](examples/README.md#transforms)          |


...

We are open to feature requests to add further functionality.

### Torch dataloader

A standardized pytorch dataloader to load subsets of the dataset for training and validation is provided.

Pinder provides a [torch.utils.data.Dataset](https://pytorch.org/tutorials/beginner/basics/data_tutorial.html#datasets-dataloaders) sub-class, [PinderDataset](src/pinder-core/pinder/core/loader/dataset.py), which is used to create a tensor dataset.

The dataset class provides an interface for processing the `PinderSystem` object into a dictionary object containing the feature/sample complex and the target (ground-truth) complex represented as a dictionary of structural properties encoded as `Tensor` objects.

It can be used as follows:

```python
from pinder.core import get_pinder_location, get_torch_loader, PinderDataset
from pinder.core.loader import filters, transforms


train_dataset = PinderDataset(
    split="train",
    # We can leverage holo, apo, pred, random and random_mixed monomer sampling strategies
    monomer_priority="random_mixed",
    base_filters: list[filters.PinderFilterBase] = [],
    sub_filters: list[filters.PinderFilterSubBase] = [],
    structure_filters: list[filters.StructureFilter] = [],
    structure_transforms_target: list[transforms.StructureTransform] = [],
    structure_transforms_feature: list[transforms.StructureTransform] = [],
)

train_loader = get_torch_loader(train_dataset, batch_size=2, shuffle=True)
# Get a batch from the dataloader
batch = next(iter(train_dataloader))
```

**Note: this is only one example of a featurizer that illustrates how to construct dict batch structure containing dicts of structure properties as tensors from `PinderSystem` objects.**

### Pytorch-geometric dataloader

A standardized pytorch-geometric dataloader to load subsets of the dataset for training and validation is provided.

Pinder provides a [torch_geometric.data.Dataset](https://pytorch-geometric.readthedocs.io/en/latest/generated/torch_geometric.data.Dataset.html#torch_geometric.data.Dataset) sub-class, [PPIDataset](src/pinder-core/pinder/core/loader/dataset.py), which is used to create a graph dataset.

The dataset class provides an interface for processing the `PinderSystem` object into `HeteroData` objects that are written to disk.

It can be used as follows:

```python
from pinder.core import get_pinder_location, get_geo_loader, PPIDataset
from pinder.core.loader import filters
from pinder.core.loader.geodata import NodeRepresentation


nodes = {
  NodeRepresentation("atom"), NodeRepresentation("residue")
}

train_dataset = PPIDataset(
    node_types=nodes,
    split="train",
    monomer1="holo_receptor",
    monomer2="holo_ligand",
    base_filters: list[filters.PinderFilterBase] = [],
    sub_filters: list[filters.PinderFilterSubBase] = [],
    root: Path = get_pinder_location(),
    transform: Callable[[PinderSystem], PinderSystem] | None = None,
    pre_transform: Callable[[PinderSystem], PinderSystem] | None = None,
    pre_filter: Callable[[PinderSystem], PinderSystem | bool] | None = None,
    limit_by: int | None = None,
    force_reload: bool = False,
    filenames_dir: Path | str | None = None,
    repeat: int = 1,
    use_cache: bool = False,
    ids: list[str] | None = None,
    add_edges: bool = True,
    k: int = 10,
)

loader = get_geo_loader(train_dataset)
```

**Note: this is only one example of a featurizer that illustrates how to construct a hetero graph from a `PinderSystem` object.**

We welcome and encourage contributions of additional featurizers. To implement additional featurizers, please see the [PairedPDB](src/pinder-core/pinder/core/loader/geodata.py) implementation. New featurizers should implement a way to convert `Structure` instances belonging to `PinderSystem`'s into the respective pytorch or pytorch-geometric data objects.

For more detailed usage examples, including how to use the underlying loader without torch-geometric, see the [example notebook](examples/pinder-loader.ipynb).


## 6. ℹ️ Filters & Annonations

A core philosophy behind pinder is to provide a large, unfiltered training dataset to derive data mixes for evaluating the impact of different data selection strategies. To that end, we provide extensive tooling for leveraging annotations in filters.

A large set of quality control annotations including interface cluster, resolution, interfacial gaps, planarity, elongation, and more can be accessed via the `PinderSystem` object or directly in data frames.

We also provide the effective MSA Depth ($N_{eff}$) calculated for each of the test members in `PINDER-XL/S/AF2` to allow accurate performance assessment by evolutionary information.

Each `PinderSystem` object has an `.entry` and `.metadata` property, which expose all the primary annotations in the index and detailed metadata, respectively.

For detailed schemas of these properties, see the `IndexEntry` and `MetadataEntry` objects. Their fields are shown below for reference:

**IndexEntry**

| Field             | Type    | Description                                                                                                                                                                                                                                                                                                    |
|:------------------|:--------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| split             | string  | The type of data split (e.g., 'train', 'test').                                                                                                                                                                                                                                                                |
| id                | string  | The unique identifier for the dataset entry.                                                                                                                                                                                                                                                                   |
| pdb_id            | string  | The PDB identifier associated with the entry.                                                                                                                                                                                                                                                                  |
| cluster_id        | string  | The cluster identifier associated with the entry.                                                                                                                                                                                                                                                              |
| cluster_id_R      | string  | The cluster identifier associated with receptor dimer body.                                                                                                                                                                                                                                                    |
| cluster_id_L      | string  | The cluster identifier associated with ligand dimer body.                                                                                                                                                                                                                                                      |
| pinder_s          | boolean | Flag indicating if the entry is part of the Pinder-S dataset.                                                                                                                                                                                                                                                  |
| pinder_xl         | boolean | Flag indicating if the entry is part of the Pinder-XL dataset.                                                                                                                                                                                                                                                 |
| pinder_af2        | boolean | Flag indicating if the entry is part of the Pinder-AF2 dataset.                                                                                                                                                                                                                                                |
| uniprot_R         | string  | The UniProt identifier for the receptor protein.                                                                                                                                                                                                                                                               |
| uniprot_L         | string  | The UniProt identifier for the ligand protein.                                                                                                                                                                                                                                                                 |
| holo_R_pdb        | string  | The PDB identifier for the holo form of the receptor protein.                                                                                                                                                                                                                                                  |
| holo_L_pdb        | string  | The PDB identifier for the holo form of the ligand protein.                                                                                                                                                                                                                                                    |
| predicted_R_pdb   | string  | The PDB identifier for the predicted structure of the receptor protein.                                                                                                                                                                                                                                        |
| predicted_L_pdb   | string  | The PDB identifier for the predicted structure of the ligand protein.                                                                                                                                                                                                                                          |
| apo_R_pdb         | string  | The PDB identifier for the apo form of the receptor protein.                                                                                                                                                                                                                                                   |
| apo_L_pdb         | string  | The PDB identifier for the apo form of the ligand protein.                                                                                                                                                                                                                                                     |
| apo_R_pdbs        | string  | The PDB identifiers for the apo forms of the receptor protein.                                                                                                                                                                                                                                                 |
| apo_L_pdbs        | string  | The PDB identifiers for the apo forms of the ligand protein.                                                                                                                                                                                                                                                   |
| holo_R            | boolean | Flag indicating if the holo form of the receptor protein is available.                                                                                                                                                                                                                                         |
| holo_L            | boolean | Flag indicating if the holo form of the ligand protein is available.                                                                                                                                                                                                                                           |
| predicted_R       | boolean | Flag indicating if the predicted structure of