From 4e36e862e490d4e2eabb9c7361b6b391b04eb9d6 Mon Sep 17 00:00:00 2001 From: Mark Gee Date: Thu, 7 May 2026 11:10:21 -0700 Subject: [PATCH 1/6] add ablang and protenix docs --- source/python-api/api-reference/embedding.rst | 5 + .../foundation-models/Using_AbLang2.ipynb | 574 +++++++++ source/python-api/foundation-models/index.rst | 6 +- .../structure-prediction/Using_Protenix.ipynb | 1138 +++++++++++++++++ .../python-api/structure-prediction/index.rst | 10 +- 5 files changed, 1728 insertions(+), 5 deletions(-) create mode 100644 source/python-api/foundation-models/Using_AbLang2.ipynb create mode 100644 source/python-api/structure-prediction/Using_Protenix.ipynb diff --git a/source/python-api/api-reference/embedding.rst b/source/python-api/api-reference/embedding.rst index 80cf2980..7d7cc4e0 100644 --- a/source/python-api/api-reference/embedding.rst +++ b/source/python-api/api-reference/embedding.rst @@ -17,22 +17,27 @@ Models .. autoclass:: openprotein.embeddings.PoET2Model :members: :inherited-members: + :exclude-members: create, get_model .. autoclass:: openprotein.embeddings.PoETModel :members: :inherited-members: + :exclude-members: create, get_model .. autoclass:: openprotein.embeddings.AbLang2Model :members: :inherited-members: + :exclude-members: create, get_model .. autoclass:: openprotein.embeddings.OpenProteinModel :members: :inherited-members: + :exclude-members: create, get_model .. autoclass:: openprotein.embeddings.ESMModel :members: :inherited-members: + :exclude-members: create, get_model These embedding models inherit from a base :py:class:`~openprotein.embeddings.EmbeddingModel`, due to their shared functionality in providing the :py:meth:`~openprotein.embeddings.EmbeddingModel.embed` method. These can also be used to fit the :ref:`transform-models`. diff --git a/source/python-api/foundation-models/Using_AbLang2.ipynb b/source/python-api/foundation-models/Using_AbLang2.ipynb new file mode 100644 index 00000000..8954d683 --- /dev/null +++ b/source/python-api/foundation-models/Using_AbLang2.ipynb @@ -0,0 +1,574 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2ed96b3f-86b6-4492-ba3b-346d0a94e1d4", + "metadata": {}, + "source": [ + "[![Open In Colab](/_static/colab-badge.svg)](https://colab.research.google.com/github/OpenProteinAI/openprotein-docs/blob/main/source/python-api/foundation-models/Using_AbLang2.ipynb)\n", + "[![Get Notebook](/_static/get-notebook-badge.svg)](https://raw.githubusercontent.com/OpenProteinAI/openprotein-docs/refs/heads/main/source/python-api/foundation-models/Using_AbLang2.ipynb)\n", + "[![View In GitHub](/_static/view-in-github-badge.svg)](https://github.com/OpenProteinAI/openprotein-docs/blob/main/source/python-api/foundation-models/Using_AbLang2.ipynb)\n", + "\n", + "# Using AbLang2\n", + "\n", + "This tutorial shows you how to use the community AbLang2 model\n", + "(`` :py:class:`~openprotein.embeddings.AbLang2Model` ``{=rst}) to embed\n", + "antibody sequences and recover residue-level likelihoods. AbLang2 is an\n", + "antibody-specific protein language model trained on paired heavy and\n", + "light variable domains, so it produces representations that are tuned to\n", + "antibody biology rather than generic protein space.\n", + "\n", + "AbLang2 is most useful when you are:\n", + "\n", + "- working with paired antibody variable regions (VH + VL) and want a\n", + " representation that respects chain context,\n", + "- restoring or scoring missing or uncertain residues (e.g. residues that\n", + " came in as ambiguous from sequencing),\n", + "- ranking candidate mutations for antibody design where germline bias in\n", + " generic PLMs would otherwise dominate.\n", + "\n", + "Upstream reference: [oxpig/AbLang2](https://github.com/oxpig/AbLang2).\n", + "Olsen, Moal, and Deane, *Addressing the antibody germline bias and its\n", + "effect on language models for improved antibody design*, bioRxiv 2024\n", + "([10.1101/2024.02.02.578678](https://doi.org/10.1101/2024.02.02.578678)).\n", + "\n", + "## Input format: `:`\n", + "\n", + "AbLang2 always expects a **paired-chain** input. Heavy and light chains\n", + "are concatenated with a single colon (`:`) delimiter:\n", + "\n", + "``` example\n", + ":\n", + "```\n", + "\n", + "The colon is a real token in the AbLang2 vocabulary \u2014 it is not a\n", + "residue and it is not stripped by the backend. Two consequences fall out\n", + "of this:\n", + "\n", + "1. **Single-chain inputs still need the colon.** If you only have a\n", + " heavy chain, send `:` (trailing colon, empty light side). If you\n", + " only have a light chain, send `:` (leading colon, empty heavy\n", + " side). Submitting a bare sequence without a colon will be rejected\n", + " as malformed antibody input.\n", + "2. **Order matters.** The heavy chain always goes on the left of the\n", + " colon, the light chain on the right. Swapping them will silently\n", + " produce embeddings that are biologically meaningless because the\n", + " chain-position priors AbLang2 learned during training no longer line\n", + " up.\n", + "\n", + "## What you need before getting started\n", + "\n", + "You need one or more antibody sequences expressed in the `:`\n", + "format described above. The example below uses trastuzumab (Herceptin)\n", + "variable regions:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "87042978-c05b-4a3a-b45c-d543e9bbe5c7", + "metadata": { + "execution": { + "iopub.execute_input": "2026-05-07T17:28:58.443935Z", + "iopub.status.busy": "2026-05-07T17:28:58.443777Z", + "iopub.status.idle": "2026-05-07T17:28:59.309040Z", + "shell.execute_reply": "2026-05-07T17:28:59.308566Z" + } + }, + "outputs": [], + "source": [ + "import openprotein\n", + "\n", + "# Login to your session\n", + "session = openprotein.connect()\n", + "\n", + "# Trastuzumab VH and VL.\n", + "vh = \"EVQLVESGGGLVQPGGSLRLSCAASGFNIKDTYIHWVRQAPGKGLEWVARIYPTNGYTRYADSVKGRFTISADTSKNTAYLQMNSLRAEDTAVYYCSRWGGDGFYAMDYWGQGTLVTVSS\"\n", + "vl = \"DIQMTQSPSSLSASVGDRVTITCRASQDVNTAVAWYQQKPGKAPKLLIYSASFLYSGVPSRFSGSRSGTDFTLTISSLQPEDFATYYCQQHYTTPPTFGQGTKVEIK\"\n", + "\n", + "paired = f\"{vh}:{vl}\"\n", + "heavy_only = f\"{vh}:\" # trailing colon \u2014 heavy chain alone\n", + "light_only = f\":{vl}\" # leading colon \u2014 light chain alone" + ] + }, + { + "cell_type": "markdown", + "id": "fcc5b762-7c07-4723-b6cd-701544de0a20", + "metadata": {}, + "source": [ + "## Getting the model\n", + "\n", + "Create the `` :py:class:`~openprotein.embeddings.AbLang2Model` ``{=rst}\n", + "object from your session:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "1f979d9b-6802-4c55-9e11-db08ddd064a7", + "metadata": { + "execution": { + "iopub.execute_input": "2026-05-07T17:28:59.310426Z", + "iopub.status.busy": "2026-05-07T17:28:59.310313Z", + "iopub.status.idle": "2026-05-07T17:28:59.423265Z", + "shell.execute_reply": "2026-05-07T17:28:59.422837Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on AbLang2Model in module openprotein.embeddings.ablang:\n", + "\n", + "ablang2\n", + " AbLang2 foundational model for antibodies.\n", + " max_sequence_length = 4096\n", + " supported outputs = ['embed', 'logits']\n", + " supported tokens = ['M', 'R', 'H', 'K', 'D', 'E', 'S', 'T', 'N', 'Q', 'C', 'G', 'P', 'A', 'V', 'I', 'F', 'Y', 'W', 'L', '-', 'X', ':']\n", + "\n" + ] + } + ], + "source": [ + "ablang2 = session.embedding.ablang2\n", + "help(ablang2)" + ] + }, + { + "cell_type": "markdown", + "id": "0bfa508a-7955-4dc7-9982-941d8c2f3c53", + "metadata": {}, + "source": [ + "The model object exposes its metadata: maximum sequence length, the\n", + "supported output types\n", + "(`` :py:meth:`~openprotein.embeddings.AbLang2Model.embed` ``{=rst},\n", + "`` :py:meth:`~openprotein.embeddings.AbLang2Model.logits` ``{=rst},\n", + "etc.), and the full vocabulary \u2014 note the `:` token in\n", + "`supported tokens`, which is what makes paired-chain input work.\n", + "\n", + "## Embedding a paired antibody\n", + "\n", + "Submit your `:` sequence to\n", + "`` :py:meth:`~openprotein.embeddings.AbLang2Model.embed` ``{=rst}. As\n", + "with other embedding models you can pass a list of sequences to batch\n", + "the request, and an optional `reduction` (defaulting to `MEAN` over\n", + "residues):" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "8aeb6688-798c-4fb1-b348-af470c89c8f5", + "metadata": { + "execution": { + "iopub.execute_input": "2026-05-07T17:28:59.424455Z", + "iopub.status.busy": "2026-05-07T17:28:59.424385Z", + "iopub.status.idle": "2026-05-07T17:28:59.676108Z", + "shell.execute_reply": "2026-05-07T17:28:59.675624Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "EmbeddingsJob(num_records=1, job_id='f95c3911-7329-4db4-b34b-e0c150f3e424', job_type=, status=, created_date=datetime.datetime(2026, 5, 7, 17, 28, 59, 495307, tzinfo=TzInfo(0)), start_date=None, end_date=None, prerequisite_job_id=None, progress_message=None, progress_counter=0, sequence_length=None, failure_message=None)" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "future = ablang2.embed(sequences=[paired.encode()])\n", + "future" + ] + }, + { + "cell_type": "markdown", + "id": "abe0ab2e-2512-4921-ba9e-b765bb0f2fa5", + "metadata": {}, + "source": [ + "Wait for the job to complete:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "7d0a9e7c-64a0-4123-8d7a-a4e4cdec503f", + "metadata": { + "execution": { + "iopub.execute_input": "2026-05-07T17:28:59.677853Z", + "iopub.status.busy": "2026-05-07T17:28:59.677754Z", + "iopub.status.idle": "2026-05-07T17:28:59.810405Z", + "shell.execute_reply": "2026-05-07T17:28:59.809833Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + "Waiting: 0%| | 0/100 [00:00`__, `Reference `__ +- **AbLang2**: Community-based antibody language model trained on paired heavy/light variable regions. AbLang2 expects inputs in the form ``:``; single-chain inputs keep a leading or trailing ``:`` to mark the missing chain. Use it for antibody-specific embeddings, residue restoration, and design ranking. See `Using AbLang2 <./Using_AbLang2.ipynb>`__. `GitHub link `__, `Reference `__ + Get started using foundation models ----------------------------------- @@ -28,9 +30,10 @@ Get started using foundation models * `SVD embeddings <./SVD-embeddings.rst>`_ * `Model metadata <./model-metadata.rst>`_ -* `Logits <./logits.rst>`_ +* `Logits <./logits.rst>`_ * `Basic inference endpoints <./basic-inference-endpoints.rst>`_ * `Attention maps <./attention-maps.rst>`_ +* `Using AbLang2 <./Using_AbLang2.ipynb>`_ `API Reference <../api-reference/embedding.rst>`_ @@ -44,3 +47,4 @@ Get started using foundation models SVD and embeddings Logits Attention maps + Using AbLang2 diff --git a/source/python-api/structure-prediction/Using_Protenix.ipynb b/source/python-api/structure-prediction/Using_Protenix.ipynb new file mode 100644 index 00000000..83a4d9f2 --- /dev/null +++ b/source/python-api/structure-prediction/Using_Protenix.ipynb @@ -0,0 +1,1138 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "8af7aa99-c1e3-4c21-ae6d-3ec231036166", + "metadata": {}, + "source": [ + "[![Open In Colab](/_static/colab-badge.svg)](https://colab.research.google.com/github/OpenProteinAI/openprotein-docs/blob/main/source/python-api/structure-prediction/Using_Protenix.ipynb)\n", + "[![Get Notebook](/_static/get-notebook-badge.svg)](https://raw.githubusercontent.com/OpenProteinAI/openprotein-docs/refs/heads/main/source/python-api/structure-prediction/Using_Protenix.ipynb)\n", + "[![View In GitHub](/_static/view-in-github-badge.svg)](https://github.com/OpenProteinAI/openprotein-docs/blob/main/source/python-api/structure-prediction/Using_Protenix.ipynb)\n", + "\n", + "# Using Protenix\n", + "\n", + "This tutorial demonstrates how to use the Protenix model on the\n", + "OpenProtein platform to predict the structure of a molecular complex\n", + "that includes proteins, ligands, DNA, and RNA. Protenix is an\n", + "AlphaFold3-style model and, like AlphaFold3, performs best when each\n", + "protein chain is paired with a multiple sequence alignment (MSA). We\n", + "will walk through assembling a complex, building the MSA, submitting the\n", + "fold, and retrieving the predicted structure together with Protenix's\n", + "confidence metrics.\n", + "\n", + "The full API for the model is documented at\n", + "`` :py:class:`~openprotein.fold.ProtenixModel` ``{=rst}.\n", + "\n", + "## What you need before getting started\n", + "\n", + "First, ensure you have an active `OpenProtein` session. Then, import the\n", + "classes used to define the components of your complex." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "67cd830d-0b5d-484b-bd25-14f5e1699f4a", + "metadata": { + "execution": { + "iopub.execute_input": "2026-05-07T18:04:27.269009Z", + "iopub.status.busy": "2026-05-07T18:04:27.268943Z", + "iopub.status.idle": "2026-05-07T18:04:28.593804Z", + "shell.execute_reply": "2026-05-07T18:04:28.593546Z" + } + }, + "outputs": [], + "source": [ + "import openprotein\n", + "from openprotein.molecules import Complex, Protein, Ligand\n", + "\n", + "# Login to your session\n", + "session = openprotein.connect()\n" + ] + }, + { + "cell_type": "markdown", + "id": "2b215fa7-f97c-495d-a622-69101980f124", + "metadata": {}, + "source": [ + "## Defining the Molecules\n", + "\n", + "Protenix can model proteins, ligands, DNA, and RNA. For this example we\n", + "will predict the structure of a homodimer in complex with a small\n", + "molecule ligand by assembling a\n", + "`` :py:class:`~openprotein.molecules.Complex` ``{=rst} from\n", + "`` :py:class:`~openprotein.molecules.Protein` ``{=rst} and\n", + "`` :py:class:`~openprotein.molecules.Ligand` ``{=rst} chains keyed by\n", + "chain id." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "38f32842-a18a-4934-86e2-4ad3c2b2d29b", + "metadata": { + "execution": { + "iopub.execute_input": "2026-05-07T18:04:28.595252Z", + "iopub.status.busy": "2026-05-07T18:04:28.595149Z", + "iopub.status.idle": "2026-05-07T18:04:28.597232Z", + "shell.execute_reply": "2026-05-07T18:04:28.597008Z" + } + }, + "outputs": [], + "source": [ + "# Define the molecular complex to predict.\n", + "# Start with the protein in a homodimer.\n", + "protein = Protein(sequence=\"MVTPEGNVSLVDESLLVGVTDEDRAVRSAHQFYERLIGLWAPAVMEAAHELGVFAALAEAPADSGELARRLDCDARAMRVLLDALYAYDVIDRIHDTNGFRYLLSAEARECLLPGTLFSLVGKFMHDINVAWPAWRNLAEVVRHGARDTSGAESPNGIAQEDYESLVGGINFWAPPIVTTLSRKLRASGRSGDATASVLDVGCGTGLYSQLLLREFPRWTATGLDVERIATLANAQALRLGVEERFATRAGDFWRGGWGTGYDLVLFANIFHLQTPASAVRLMRHAAACLAPDGLVAVVDQIVDADREPKTPQDRFALLFAASMTNTGGGDAYTFQEYEEWFTAAGLQRIETLDTPMHRILLARRATEPSAVPEGQASENLYFQ\")\n", + "\n", + "# You can also specify the protein to be cyclic by setting the property\n", + "# protein.cyclic = True\n", + "\n", + "# Define the ligand in our complex.\n", + "ligand = Ligand(ccd=\"SAH\")\n", + "\n", + "# Assemble the complex. Group chain ids that share the same entity into a\n", + "# tuple — this serializes the homodimer as a single protein entity with\n", + "# ids [\"A\", \"B\"] and only requires one MSA on the entity.\n", + "complex = Complex({\n", + " (\"A\", \"B\"): protein,\n", + " \"C\": ligand,\n", + "})\n" + ] + }, + { + "cell_type": "markdown", + "id": "57181891-729c-4fb6-a683-ed511033dc43", + "metadata": {}, + "source": [ + "## Create an MSA for the Protein using Homology Search\n", + "\n", + "Protenix is an AlphaFold3-style model and expects each protein chain to\n", + "carry a multiple sequence alignment (MSA). You must either set\n", + "`protein.msa` to an MSA built on the platform, or explicitly opt out by\n", + "setting `protein.msa = Protein.single_sequence_mode` to run in\n", + "single-sequence mode. Submitting a Protenix request without an MSA on\n", + "one of the proteins will raise an error.\n", + "\n", + "Here we build the MSA using the platform's homology search via\n", + "`` :py:meth:`session.align.create_msa ` ``{=rst}.\n", + "Note the syntax: when seeding an MSA for a complex we follow ColabFold's\n", + "convention of joining the chain sequences with `:`, which lets the MSA\n", + "service jointly search the multimer." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "86edb761-ff14-45f7-9989-f660149004ee", + "metadata": { + "execution": { + "iopub.execute_input": "2026-05-07T18:04:28.598320Z", + "iopub.status.busy": "2026-05-07T18:04:28.598266Z", + "iopub.status.idle": "2026-05-07T18:04:29.222048Z", + "shell.execute_reply": "2026-05-07T18:04:29.221802Z" + } + }, + "outputs": [], + "source": [ + "msa_query = []\n", + "for p in complex.get_proteins().values():\n", + " msa_query.append(p.sequence)\n", + "msa = session.align.create_msa(seed=b\":\".join(msa_query))\n", + "\n", + "for p in complex.get_proteins().values():\n", + " p.msa = msa\n", + " # If desired, use single sequence mode to specify no msa\n", + " # p.msa = Protein.single_sequence_mode\n" + ] + }, + { + "cell_type": "markdown", + "id": "869d2cf6-7fa0-4b86-abf6-197c5ace0aa8", + "metadata": {}, + "source": [ + "## Predicting the Complex Structure\n", + "\n", + "Now we can call the\n", + "`` :py:meth:`~openprotein.fold.ProtenixModel.fold` ``{=rst} method on\n", + "the Protenix model.\n", + "\n", + "The key steps are:\n", + "\n", + "1. Access the model via `session.fold.protenix`.\n", + "2. Pass the defined complex.\n", + "3. Optionally tune the diffusion sampler with `diffusion_samples`,\n", + " `num_recycles`, and `num_steps`." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "71d9c396-ea73-4024-988e-f49e653618d0", + "metadata": { + "execution": { + "iopub.execute_input": "2026-05-07T18:04:29.223304Z", + "iopub.status.busy": "2026-05-07T18:04:29.223245Z", + "iopub.status.idle": "2026-05-07T18:04:31.898248Z", + "shell.execute_reply": "2026-05-07T18:04:31.893193Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "FoldJob(num_records=1, job_id='6e51ea51-1b35-4a65-85e0-b60956900007', job_type=, status=, created_date=datetime.datetime(2026, 5, 7, 18, 4, 30, 769318, tzinfo=TzInfo(0)), start_date=None, end_date=None, prerequisite_job_id=None, progress_message=None, progress_counter=0, sequence_length=None, failure_message=None)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Request the fold.\n", + "fold_job = session.fold.protenix.fold(\n", + " sequences=[complex], # list for batch requests\n", + " diffusion_samples=1, # number of diffusion samples per input\n", + " num_recycles=10, # number of recycling steps\n", + " num_steps=200, # number of sampling steps\n", + ")\n", + "fold_job\n" + ] + }, + { + "cell_type": "markdown", + "id": "64ff8972-3b5a-45a5-82f1-51ef24a0dbc2", + "metadata": {}, + "source": [ + "The call returns a\n", + "`` :py:class:`~openprotein.fold.FoldResultFuture` ``{=rst} object\n", + "immediately. This is a reference to your job running on the OpenProtein\n", + "platform: you can monitor its status, or block until completion with\n", + "`` :py:meth:`~openprotein.jobs.Future.wait_until_done` ``{=rst}." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "2d17811c-493d-4796-a333-ed68f5266acd", + "metadata": { + "execution": { + "iopub.execute_input": "2026-05-07T18:04:31.902629Z", + "iopub.status.busy": "2026-05-07T18:04:31.902380Z", + "iopub.status.idle": "2026-05-07T18:09:03.986026Z", + "shell.execute_reply": "2026-05-07T18:09:03.985340Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r", + "Waiting: 0%| | 0/100 [00:00]\n", + "Predicted molecular complex: \n", + "Predicted protein A:\n", + " 0 SEQUENCE MVTPEGNVSLVDESLLVGVTDEDRAVRSAHQFYERLIGLWAPAVMEAAHELGVFAALAEA\n", + "\n", + "60 SEQUENCE PADSGELARRLDCDARAMRVLLDALYAYDVIDRIHDTNGFRYLLSAEARECLLPGTLFSL\n", + "\n", + "120 SEQUENCE VGKFMHDINVAWPAWRNLAEVVRHGARDTSGAESPNGIAQEDYESLVGGINFWAPPIVTT\n", + "\n", + "180 SEQUENCE LSRKLRASGRSGDATASVLDVGCGTGLYSQLLLREFPRWTATGLDVERIATLANAQALRL\n", + "\n", + "240 SEQUENCE GVEERFATRAGDFWRGGWGTGYDLVLFANIFHLQTPASAVRLMRHAAACLAPDGLVAVVD\n", + "\n", + "300 SEQUENCE QIVDADREPKTPQDRFALLFAASMTNTGGGDAYTFQEYEEWFTAAGLQRIETLDTPMHRI\n", + "\n", + "360 SEQUENCE LLARRATEPSAVPEGQASENLYFQ\n", + "Predicted protein B:\n", + " 0 SEQUENCE MVTPEGNVSLVDESLLVGVTDEDRAVRSAHQFYERLIGLWAPAVMEAAHELGVFAALAEA\n", + "\n", + "60 SEQUENCE PADSGELARRLDCDARAMRVLLDALYAYDVIDRIHDTNGFRYLLSAEARECLLPGTLFSL\n", + "\n", + "120 SEQUENCE VGKFMHDINVAWPAWRNLAEVVRHGARDTSGAESPNGIAQEDYESLVGGINFWAPPIVTT\n", + "\n", + "180 SEQUENCE LSRKLRASGRSGDATASVLDVGCGTGLYSQLLLREFPRWTATGLDVERIATLANAQALRL\n", + "\n", + "240 SEQUENCE GVEERFATRAGDFWRGGWGTGYDLVLFANIFHLQTPASAVRLMRHAAACLAPDGLVAVVD\n", + "\n", + "300 SEQUENCE QIVDADREPKTPQDRFALLFAASMTNTGGGDAYTFQEYEEWFTAAGLQRIETLDTPMHRI\n", + "\n", + "360 SEQUENCE LLARRATEPSAVPEGQASENLYFQ\n", + "Predicted ligand C:\n", + " Ligand(ccd='SAH', smiles=None, _structure_block=)\n" + ] + } + ], + "source": [ + "result = fold_job.get()\n", + "structure = result[0]\n", + "predicted_complex = structure[0]\n", + "print(\"Predicted structures:\", result)\n", + "print(\"Predicted molecular complex:\", result[0][0])\n", + "print(\"Predicted protein A:\\n\", predicted_complex.get_protein(\"A\"))\n", + "print(\"Predicted protein B:\\n\", predicted_complex.get_protein(\"B\"))\n", + "print(\"Predicted ligand C:\\n\", predicted_complex.get_ligand(\"C\"))\n" + ] + }, + { + "cell_type": "markdown", + "id": "a5b01fa9-a898-490f-93e0-995d5e81ffc0", + "metadata": {}, + "source": [ + "Visualize the structure using\n", + "[molviewspec](https://github.com/molstar/mol-view-spec)." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "ed9ab7bb-977a-483a-8de2-323a4c20d3ab", + "metadata": { + "execution": { + "iopub.execute_input": "2026-05-07T18:09:04.660170Z", + "iopub.status.busy": "2026-05-07T18:09:04.660094Z", + "iopub.status.idle": "2026-05-07T18:09:05.618800Z", + "shell.execute_reply": "2026-05-07T18:09:05.618560Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: molviewspec in /Users/jmage/Projects/openprotein/openprotein-python-private/.venv/lib/python3.12/site-packages (1.8.1)\r\n", + "Requirement already satisfied: pydantic<3,>=1 in /Users/jmage/Projects/openprotein/openprotein-python-private/.venv/lib/python3.12/site-packages (from molviewspec) (2.12.5)\r\n", + "Requirement already satisfied: annotated-types>=0.6.0 in /Users/jmage/Projects/openprotein/openprotein-python-private/.venv/lib/python3.12/site-packages (from pydantic<3,>=1->molviewspec) (0.7.0)\r\n", + "Requirement already satisfied: pydantic-core==2.41.5 in /Users/jmage/Projects/openprotein/openprotein-python-private/.venv/lib/python3.12/site-packages (from pydantic<3,>=1->molviewspec) (2.41.5)\r\n", + "Requirement already satisfied: typing-extensions>=4.14.1 in /Users/jmage/Projects/openprotein/openprotein-python-private/.venv/lib/python3.12/site-packages (from pydantic<3,>=1->molviewspec) (4.15.0)\r\n", + "Requirement already satisfied: typing-inspection>=0.4.2 in /Users/jmage/Projects/openprotein/openprotein-python-private/.venv/lib/python3.12/site-packages (from pydantic<3,>=1->molviewspec) (0.4.2)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Note: you may need to restart the kernel to use updated packages.\n" + ] + }, + { + "data": { + "text/html": [ + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/javascript": [ + "\n", + " setTimeout(function(){\n", + " var wrapper = document.getElementById(\"molstar_0c25f13c-15c2-4f74-bc0d-4fef36418636\")\n", + " if (wrapper === null) {\n", + " throw new Error(\"Wrapper element #molstar_0c25f13c-15c2-4f74-bc0d-4fef36418636 not found anymore\")\n", + " }\n", + " var blob = new Blob([\"\\n\\n \\n