{"id":30893227,"url":"https://github.com/rosettacommons/atomworks","last_synced_at":"2025-09-08T20:06:17.988Z","repository":{"id":310543718,"uuid":"1037693767","full_name":"RosettaCommons/atomworks","owner":"RosettaCommons","description":"A generalized computational framework for biomolecular modeling.","archived":false,"fork":false,"pushed_at":"2025-09-03T20:43:48.000Z","size":150246,"stargazers_count":217,"open_issues_count":1,"forks_count":18,"subscribers_count":4,"default_branch":"production","last_synced_at":"2025-09-03T22:21:50.321Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://baker-laboratory.github.io/atomworks-dev/latest","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RosettaCommons.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-14T01:25:27.000Z","updated_at":"2025-09-03T17:05:45.000Z","dependencies_parsed_at":"2025-09-03T22:23:07.798Z","dependency_job_id":null,"html_url":"https://github.com/RosettaCommons/atomworks","commit_stats":null,"previous_names":["rosettacommons/atomworks"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/RosettaCommons/atomworks","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RosettaCommons%2Fatomworks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RosettaCommons%2Fatomworks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RosettaCommons%2Fatomworks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RosettaCommons%2Fatomworks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RosettaCommons","download_url":"https://codeload.github.com/RosettaCommons/atomworks/tar.gz/refs/heads/production","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RosettaCommons%2Fatomworks/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274231512,"owners_count":25245600,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-08T02:00:09.813Z","response_time":121,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-09-08T20:06:15.382Z","updated_at":"2025-09-08T20:06:17.965Z","avatar_url":"https://github.com/RosettaCommons.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n[![PyPI version](https://img.shields.io/pypi/v/atomworks.svg)](https://pypi.org/project/atomworks/)\n[![Python versions](https://img.shields.io/pypi/pyversions/atomworks.svg)](https://pypi.org/project/atomworks/)\n[![Documentation Status](https://img.shields.io/badge/docs-latest-brightgreen.svg)](https://baker-laboratory.github.io/atomworks-dev/latest/index.html)\n[![License: BSD 3-Clause](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)\n\n\u003cimg src=\"docs/_static/atomworks_logo_color.svg\" width=\"450\" alt=\"atomworks logo\"\u003e\n\n**atomworks** is an open-source platform that maximizes research velocity for biomolecular modeling tasks. Much like how [Torchdata](https://docs.pytorch.org/data/beta/index.html) enables rapid prototyping within the vision and language domains, AtomWorks aims to accelerate development and experimentation within biomolecular modeling.\n\n\u003e **⚠️ Notice:** We are currently finalizing some cleanup work within our repositories. Please expect the APIs (e.g., function and class names, inputs and outputs) to stabilize within the next two weeks. Thank you for your patience!\n\nIf you're looking for the models themselves (e.g., RF3, MPNN) that integrate with AtomWorks rather than the underlying framework, check out [ModelForge](https://github.com/RosettaCommons/modelforge)\n\nAtomWorks is composed of two symbiotic libraries:\n\n- **atomworks.io:** A universal Python toolkit for parsing, cleaning, manipulating, and converting biological data (structures, sequences, small molecules). Built on the [biotite](https://www.biotite-python.org/) API, it seamlessly loads and exports between standard formats like mmCIF, PDB, FASTA, SMILES, MOL, and more.\n- **atomworks.ml:** Advanced dataset featurization and sampling for deep learning workflows that uses `atomworks.io` as its structural backbone. We provide a comprehensive, pre-built and well-tested set of `Transforms` for common tasks that can be easily composed into full deep-learning pipelines; users may also create their own `Transforms` for custom operations.\n\nFor more detail on the motivation for and applications of AtomWorks, please see the [preprint](https://doi.org/10.1101/2025.08.14.670328). \n\nAtomWorks is built atop [biotite](https://www.biotite-python.org/): We are grateful to the Biotite developers for maintaining such a high-quality and flexible toolkit, and hope that our package will prove a helpful addition to the broader `biotite` community.\n\n---\n\n## atomworks.io\n\n\u003e *A general-purpose Python toolkit for cleaning up, standardizing, and working with biomolecular files - based on biotite*\n\n**atomworks.io** lets you:\n\n- Parse, convert, and clean any common biological file (structure or sequence). For example, identifying and removing leaving groups, correcting bond order after nucleophilic addition, fixing charges, parsing covalent geometries, and appropriate treatment of structures with multiple occupancies and ligands at symmetry centers\n- Transform all data to a consistent `AtomArray` representation for further analysis or machine learning applications, regardless of initial source\n- Model missing atoms (those implied by the sequence but not represented in the coordinates) and initialize entity- and instance-level annotations (see the [glossary]() for more detail on our composable naming conventions)\n\nWe have found `atomworks.io` to be useful to a general bioinformatics and protein design audience; in many cases, `atomworks.io` can replace bespoke scripts and manual curation, enabling researchers to spend more time testing hypothesis and less time juggling dozens of tools and dependencies.\n\n---\n\n## atomworks.ml\n\n\u003e *Modular, component-based library for dataset featurization within biomolecular deep learning workflows*\n\n**atomworks.ml** provides:\n\n- A library of pre-built, well-tested `Transforms` that can be slotted into novel pipelines\n- An extensible framework, integrated with `atomworks.io`, to write `Transforms` for arbitrary use cases\n- Scripts to pre-process the PDB or other databases into dataframes appropriate for network training\n- Efficient sampling and batching utilities for training machine learning models\n\nWithin the AtomWorks paradigm, the output of each `Transform` is not an opaque dictionary with model-specific tensors but instead an updated version of our atom-level structural representation (Biotite's `AtomArray`). Operations within – and between – pipelines thus maintain a common vocabulary of inputs and outputs.\n\n---\n\n## Installation\n\n```shell\npip install atomworks # base installation version without torch (for only atomworks.io)\npip install \"atomworks[ml]\" # with torch and ML dependencies (for atomworks.io plus atomworks.ml)\npip install \"atomworks[dev]\" # with development dependencies\npip install \"atomworks[ml,dev]\" # with all dependencies\n```\n\nIf you are using [uv](https://docs.astral.sh/uv/reference/policies/versioning/) for package management, you can install atomworks with:\n\n```shell\nuv pip install \"atomworks[ml,openbabel,dev]\"\n```\n\nFor more advanced setup options (including how to run workflows via apptainers) see the [full documentation](https://baker-laboratory.github.io/atomworks-dev/latest).\n\n---\n\n## Getting started\n\n### 1. When to use `atomworks.io` vs `atomworks.ml`?\n\n- Use `atomworks.io` when you:\n  - Need to parse/clean/convert between biological file formats (mmCIF, PDB, FASTA, etc.)\n  - Want a unified structural representation to plug into any downstream analysis or modeling\n  - Need structural operations like adding missing atoms, filtering ligands/solvents, or assembly generation\n\n- Use `atomworks.ml` when you:\n  - Need to featurize entire datasets for deep learning\n  - Want ready-made sampling and batching utilities for training pipelines\n  - Already use `atomworks.io` and want a seamless bridge to ML-ready feature engineering\n\n### 2. Quick Start\n\nTo parse a pdb file (parse = load, clean, annotate relevant metadata such as entities, molecules, etc) you can use the `parse` function:\n\n```python\n\nfrom atomworks.io.parser import parse\n\nresult = parse(filename=\"3nez.cif.gz\")\n\nasym_unit: AtomArrayStack = result[\"asym_unit\"]\nassemblies: dict[str, AtomArrayStack] = result[\"assemblies\"]\n\nfor chain_id, info in result[\"chain_info\"].items():\n    print(chain_id, info[\"sequence\"])\n\n```\n\nThe output of `parse` includes:\n\n- **chain_info** — Sequences/metadata for each chain\n- **ligand_info** — Ligand annotation \u0026 metrics\n- **asym_unit** — Structure (`AtomArrayStack`)\n- **assemblies** — Built biological assemblies (each are their own `AtomArrayStack`)\n- **metadata** — Experimental and source information\n\nSee [usage examples](https://baker-laboratory.github.io/atomworks-dev/latest/auto_examples/) for more details.\n\nIf you just want to load a file, you can use the `load_any` function:\n\n```python\nfrom atomworks.io.utils.io_utils import load_any\n\natom_array: AtomArray = load_any(\"3nez.cif.gz\", model=1)  # model=1 means that we want to load the model 1 (i.e. the first model) rather than a stack of all models in the file\n```\n\n### 3. Training on the PDB\n\n\u003e ⚠️ **Disclaimer:** Documentation for this section is currently under construction. Please check back soon for updates!\n\n**Step 1 — Mirror the PDB (mmCIFs)**\n  To train on the PDB, you first need to make sure you have access to the samples form the PDB. We use `mmCIF` files as the highly recommended format for training.\n  For convenience, we provide a command to mirror the PDB:\n\n  ```bash\n  # Full mirror (~100 GB)\n  atomworks pdb sync /path/to/pdb_mirror  # This will create a carbon-copy of the PDB, dated today, in the specified directory. It will download the .mmcif files in the same sharding pattern as the original PDB and keep them gzipped for efficiency.\n\n#   # If, for some reason you only want to download specific IDs, the CLI also supports this:\n#   atomworks pdb sync /path/to/pdb_mirror --pdb-id 1A0I --pdb-id 7XYZ  # This will only download the specified PDB IDs.\n#   # or\n#   atomworks pdb sync /path/to/pdb_mirror --pdb-ids-file /path/to/ids.txt  # This will download the PDB IDs listed in the file, one per line. Each line should be a PDB ID (e.g. '6lyz') and separated by a newline.\n  ```\n\n  Once the mirror is created, set the environment variable:\n\n  ```bash\n  export PDB_MIRROR_PATH=/path/to/pdb_mirror\n  ```\n\n  To have this more permanent, you can add it to a `.env` file in your home directory. Here is an [example of a `.env`](.env.sample) file structure that you can copy, rename to `.env` and edit with your own paths.\n\n**Step 2 — Get PDB metadata (PN units and interfaces)**\n    To calculate sampling probabilities and filter examples for splits, we pre-process the PDB with metadata for each PDB entry. \n    To save you the work, we provide pre-computed metadata (dated July 15/2025) for downloading:\n\n  ```bash\n  atomworks setup metadata /path/to/metadata  # This will download the metadata (as .tar.gz) and extract it to the specified directory.\n  ```\n\n  This produces parquet files at:\n\n- `/path/to/metadata/pn_units_df.parquet` — Contains metadata for each *PN unit* in the PDB. The term *pn unit* is shorthand for `polymer XOR non-polymer unit` and behaves for almost all purposes like the `chain` in a PDB file. The only difference is that a ligand composed of multiple covalently bonded ligands is considered a single PN unit (whilst it would be multiple chains in a PDB file). Effectively this `.parquet` is a large table of all individual chains, ligands, etc (to be precise, it has one entry per  pn unit) in the PDB that includes helpful metadata for filtering and sampling.\n- `/path/to/metadata/interfaces_df.parquet` — Contains metadata for each interface in the PDB. This `.parquet` is a large table of all binary interfaces in the PDB. It lists each interface as (pn_unit_1, pn_unit_2) pairs and includes helpful metadata for filtering and sampling.\n\n  Alternatively, you can generate fresher metadata yourself (scripts will be uploaded in the coming weeks).\n\n**Step 3 — Configure an AF3-style dataset (example: train only on D-polypeptides)**\nNext we need to use the metadata to configure a dataset that we would like to sample from. This includes e.g. training cut-off, filters, transforms to apply, etc.\nHere's a simple example that:\n\n- Filters to D-polypeptide and L-polypeptide chains only (`POLYPEPTIDE_D` and `POLYPEPTIDE_L` -- to include additional chain types, replace the lists with the appropriate IDs (see [mapping](./src/atomworks/enums.py#L31-L45) in comments).\n- Excludes ligands in the AF3 list of excluded ligands, available at [`atomworks.io.constants.AF3_EXCLUDED_LIGANDS_REGEX`](./src/atomworks/io/constants.py#L350).\n\n```yaml\n# NOTE: The below is a hydra config and the _target_ fields are the hydra syntax for instantiating a class.\n#  You can use this without hyrda, but will then instead need to provide the corresponding arguments for the\n#  _target_ objects directly.\n\n# Chain type ids used below (from atomworks.enums.ChainType):\n# 0=CyclicPseudoPeptide, 1=OtherPolymer, 2=PeptideNucleicAcid,\n# 3=DNA, 4=DNA_RNA_HYBRID, 5=POLYPEPTIDE_D, 6=POLYPEPTIDE_L, 7=RNA,\n# 8=NON_POLYMER, 9=WATER, 10=BRANCHED, 11=MACROLIDE\n\naf3_pdb_dataset:\n  _target_: atomworks.ml.datasets.datasets.ConcatDatasetWithID\n  datasets:\n    # Single PN units\n    - _target_: atomworks.ml.datasets.datasets.StructuralDatasetWrapper\n      dataset_parser:\n        _target_: atomworks.ml.datasets.parsers.PNUnitsDFParser\n      transform:\n        _target_: atomworks.ml.pipelines.af3.build_af3_transform_pipeline\n        is_inference: false\n        n_recycles: 5  # This means that we will subsample 5 random sets from the MSA for each example.\n        crop_size: 256\n        crop_contiguous_probability: 0.3333333333333333\n        crop_spatial_probability: 0.6666666666666666\n        diffusion_batch_size: 32\n        # Optional templates (if available)\n        template_lookup_path: ${paths.shared}/template_lookup.csv\n        template_base_dir: ${paths.shared}/template\n        # Optional MSAs (see Step 4)\n        # protein_msa_dirs:\n        #   - { dir: /path/to/msa, extension: .a3m.gz, directory_depth: 2 }\n        # rna_msa_dirs:\n        #   - { dir: /path/to/msa, extension: .afa, directory_depth: 0 }\n      dataset:\n        _target_: atomworks.ml.datasets.datasets.PandasDataset\n        name: pn_units\n        id_column: example_id\n        data: /path/to/metadata/pn_units_df.parquet\n        filters:\n          - \"deposition_date \u003c '2022-01-01'\"\n          - \"resolution \u003c 5.0 and ~method.str.contains('NMR')\"\n          - \"num_polymer_pn_units \u003c= 20\"\n          - \"cluster.notnull()\"\n          - \"method in ['X-RAY_DIFFRACTION', 'ELECTRON_MICROSCOPY']\"\n          # Train only on D-polypeptides:\n          - \"q_pn_unit_type in [5, 6]\"  # 5 = POLYPEPTIDE_D, 6 = POLYPEPTIDE_L\n          # Exclude ligands from AF3 excluded set:\n          - \"~(q_pn_unit_non_polymer_res_names.notnull() and q_pn_unit_non_polymer_res_names.str.contains('${af3_excluded_ligands_regex}', regex=True))\"\n        columns_to_load: null\n      save_failed_examples_to_dir: null\n\n    # Binary interfaces\n    - _target_: atomworks.ml.datasets.datasets.StructuralDatasetWrapper\n      dataset_parser:\n        _target_: atomworks.ml.datasets.parsers.InterfacesDFParser\n      transform:\n        _target_: atomworks.ml.pipelines.af3.build_af3_transform_pipeline\n        is_inference: false\n        n_recycles: 5\n        crop_size: 256\n        crop_spatial_probability: 1.0\n        crop_contiguous_probability: 0.0\n        diffusion_batch_size: 32\n        template_lookup_path: ${paths.shared}/template_lookup.csv\n        template_base_dir: ${paths.shared}/template\n        # Optional MSAs (see Step 4)\n        # protein_msa_dirs:\n        #   - { dir: /path/to/msa, extension: .a3m.gz, directory_depth: 2 }\n        # rna_msa_dirs:\n        #   - { dir: /path/to/msa, extension: .afa, directory_depth: 0 }\n      dataset:\n        _target_: atomworks.ml.datasets.datasets.PandasDataset\n        name: interfaces\n        id_column: example_id\n        data: /path/to/metadata/interfaces_df.parquet\n        filters:\n          - \"deposition_date \u003c '2022-01-01'\"\n          - \"resolution \u003c 5.0 and ~method.str.contains('NMR')\"\n          - \"num_polymer_pn_units \u003c= 20\"\n          - \"cluster.notnull()\"\n          - \"method in ['X-RAY_DIFFRACTION', 'ELECTRON_MICROSCOPY']\"\n          # Train only on D-polypeptide interfaces:\n          - \"pn_unit_1_type in [5, 6]\"  # 5 = POLYPEPTIDE_D, 6 = POLYPEPTIDE_L\n          - \"pn_unit_2_type in [5, 6]\"  # 5 = POLYPEPTIDE_D, 6 = POLYPEPTIDE_L\n          - \"~(pn_unit_1_non_polymer_res_names.notnull() and pn_unit_1_non_polymer_res_names.str.contains('${af3_excluded_ligands_regex}', regex=True))\"\n          - \"~(pn_unit_2_non_polymer_res_names.notnull() and pn_unit_2_non_polymer_res_names.str.contains('${af3_excluded_ligands_regex}', regex=True))\"\n        columns_to_load: null\n      cif_parser_args:\n        cache_dir: null\n      save_failed_examples_to_dir: null\n```\n\n**Step 4 — MSAs (optional)**\nWe are working on a way to make MSAs accessible to the public, but due to the large storage requirements (multiple TB) we are still working on this. If your organization has interest \u0026 capacity to host the MSAs, please contact us. In the meantime, if you have MSAs (e.g., from OpenProteinSet) you can configure the pipeline to use them like so:\n\n```yaml\n    protein_msa_dirs:\n      - { dir: /path/to/msa, extension: .a3m.gz, directory_depth: 2 }\n    rna_msa_dirs:\n      - { dir: /path/to/msa, extension: .afa, directory_depth: 0 }\n```\n\nOr alternatively not use MSAs.\n\n**Step 5 — Train a model**\nYou now have a full fledged dataset that you can use to train models on! If you want to just try this out without having to download the whole PDB and the metdatada, you can instead run our tests which have a mini-mockup of the pipeline with real pdb files, metadata, distillation data, templates and MSAs for the example of AF3. You can download all this relevant metadata via the atomworks CLI:\n\n```bash\natomworks setup tests  # This will download the test pack to `tests/data` and unpack it there (~500 MB)\n```\n\nYou will now have a mini PDB at `tests/data/pdb` and a mini custom CCD at `tests/data/ccd`. MSA and template data is in `tests/data/shared` and the distillation and metadata are in `data/ml/af2_distillation`, `data/ml/pdb_pn_units` and `data/ml/pdb_interfaces`. A dataset that uses all of these is [for example here](./tests/ml/conftest.py#L300).\n\nTo run the tests for the various datasets, you can run the following command:\n\n```bash\n# Make sure you have the correct environment activated, and set your paths correctly in the .env file / shell environment variables (see points above)\npytest tests/ml/test_data_loading_pipelines.py\n```\n\n---\n\n## Contribution\n\nWe welcome improvements!  \nPlease see the [full documentation](https://baker-laboratory.github.io/atomworks-dev/latest/index.html) for contribution guidelines.\n\n## Citation\n\nIf you make use of AtomWorks in your research, please cite:\n\n\u003e N. Corley\\*, S. Mathis\\*, R. Krishna\\*, M. S. Bauer, T. R. Thompson, W. Ahern, M. W. Kazman, R. I. Brent, K. Didi, A. Kubaney, L. McHugh, A. Nagle, A. Favor, M. Kshirsagar, P. Sturmfels, Y. Li, J. Butcher, B. Qiang, L. L. Schaaf, R. Mitra, K. Campbell, O. Zhang, R. Weissman, I. R. Humphreys, Q. Cong, J. Funk, S. Sonthalia, P. Lio, D. Baker, F. DiMaio,\n\u003e \"Accelerating Biomolecular Modeling with AtomWorks and RF3,\" bioRxiv, August 2025. doi: [10.1101/2025.08.14.670328](https://doi.org/10.1101/2025.08.14.670328)\n\nIf you use bibtex, here's the GoogleScholar formatted citation:\n\n```bibtex\n@article{corley2025accelerating,\n  title={Accelerating Biomolecular Modeling with AtomWorks and RF3},\n  author={Corley, Nathaniel and Mathis, Simon and Krishna, Rohith and Bauer, Magnus S and Thompson, Tuscan R and Ahern, Woody and Kazman, Maxwell W and Brent, Rafael I and Didi, Kieran and Kubaney, Andrew and others},\n  journal={bioRxiv},\n  pages={2025--08},\n  year={2025},\n  publisher={Cold Spring Harbor Laboratory}\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frosettacommons%2Fatomworks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frosettacommons%2Fatomworks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frosettacommons%2Fatomworks/lists"}