plinder.core.scores.custom#

Annotate and score custom mmCIF structures against PLINDER.

class plinder.core.scores.custom.SearchDatabaseBundle(backend: str, root: Path, search_target: Path, conversion_target: Path, cluster_alignments: Path | None, manifest: Mapping[str, object])[source]#

Bases: object

Portable exact-clustered target database for one search backend.

backend: str#
root: Path#
search_target: Path#
conversion_target: Path#
cluster_alignments: Path | None#
manifest: Mapping[str, object]#
class plinder.core.scores.custom.CustomScoringAssets(annotation_table: ~pathlib.Path, entry_chains: ~pathlib.Path, interface_annotations: ~pathlib.Path, alignment_chain_lookup: ~pathlib.Path, search_databases: ~typing.Mapping[str, ~plinder.core.scores.custom.SearchDatabaseBundle], ligand_archives: ~typing.Mapping[str, ~pathlib.Path], monomer_search_databases: ~typing.Mapping[str, ~plinder.core.scores.custom.SearchDatabaseBundle] = <factory>, overlay_search_databases: ~typing.Mapping[str, ~plinder.core.scores.custom.SearchDatabaseBundle] = <factory>, overlay_monomer_search_databases: ~typing.Mapping[str, ~plinder.core.scores.custom.SearchDatabaseBundle] = <factory>, shadowed_entries: frozenset[str] = frozenset({}))[source]#

Bases: object

Release files required by custom-structure scoring.

annotation_table: Path#
entry_chains: Path#
interface_annotations: Path#
alignment_chain_lookup: Path#
search_databases: Mapping[str, SearchDatabaseBundle]#
ligand_archives: Mapping[str, Path]#
monomer_search_databases: Mapping[str, SearchDatabaseBundle]#
overlay_search_databases: Mapping[str, SearchDatabaseBundle]#
overlay_monomer_search_databases: Mapping[str, SearchDatabaseBundle]#
shadowed_entries: frozenset[str] = frozenset({})#
class plinder.core.scores.custom.CustomQueryInputs(root: Path, chain_cif_dir: Path, sequence_fasta: Path, chain_manifest: Path)[source]#

Bases: object

Written per-chain coordinates, sequences, and stable metadata.

root: Path#
chain_cif_dir: Path#
sequence_fasta: Path#
chain_manifest: Path#
class plinder.core.scores.custom.CustomQueryDatabases(root: Path, inputs: CustomQueryInputs, databases: Mapping[str, Path], identifier_map: Path)[source]#

Bases: object

Foldseek/MMseqs query DBs and their backend identifier mapping.

root: Path#
inputs: CustomQueryInputs#
databases: Mapping[str, Path]#
identifier_map: Path#
class plinder.core.scores.custom.CustomProteinSearchConfig(evalue: float = 0.01, foldseek_evalue: float | None = None, mmseqs_evalue: float | None = None, steam_evalue: float | None = None, sensitivity: float = 11.0, max_seqs: int = 10000, coverage: float = 0.0, min_seq_id: float = 0.0)[source]#

Bases: object

Custom search filters, with optional E-value overrides per backend.

evalue sets all backends to the same threshold (default 0.01). foldseek_evalue, mmseqs_evalue and steam_evalue take precedence for their respective backends when supplied.

evalue: float = 0.01#
foldseek_evalue: float | None = None#
mmseqs_evalue: float | None = None#
steam_evalue: float | None = None#
sensitivity: float = 11.0#
max_seqs: int = 10000#
coverage: float = 0.0#
min_seq_id: float = 0.0#
evalue_for(backend: str) → float#

Use the backend override, or the shared E-value (default 0.01).

class plinder.core.scores.custom.CustomStructureAnnotations(root: Path, ligand_sdf_root: Path, annotation_table: Path, entry_chains: Path, interface_annotations: Path, entries_by_structure: Mapping[str, Any])[source]#

Bases: object

Custom ligand/interface annotations and their generated ligand SDFs.

root: Path#
ligand_sdf_root: Path#
annotation_table: Path#
entry_chains: Path#
interface_annotations: Path#
entries_by_structure: Mapping[str, Any]#
class plinder.core.scores.custom.CustomScoringResult(annotations: CustomStructureAnnotations, query_inputs: CustomQueryInputs, query_databases: CustomQueryDatabases, protein_hits: Mapping[str, Path], chain_similarity_scores: Path, score_alignments: Mapping[str, Path], protein_score_alignments: Mapping[str, Path], protein_scores: Path, aligned_pocket_residues: Path | None, ligand_scores: Path | None, interface_scores: Path | None)[source]#

Bases: object

Files produced by the complete custom-CIF scoring workflow.

query_inputs: CustomQueryInputs#
query_databases: CustomQueryDatabases#
protein_hits: Mapping[str, Path]#
chain_similarity_scores: Path#
score_alignments: Mapping[str, Path]#
protein_score_alignments: Mapping[str, Path]#
protein_scores: Path#
aligned_pocket_residues: Path | None#
ligand_scores: Path | None#
interface_scores: Path | None#
class plinder.core.scores.custom.CustomSequenceScoringResult(query_inputs: CustomQueryInputs, query_databases: CustomQueryDatabases, protein_hits: Mapping[str, Path], chain_similarity_scores: Path, protein_score_alignments: Mapping[str, Path], protein_scores: Path, aligned_pocket_residues: Path | None, sequence_links: Path, best_sequence_links: Path)[source]#

Bases: object

Files produced by protein-sequence scoring against PLINDER pockets.

query_inputs: CustomQueryInputs#
query_databases: CustomQueryDatabases#
protein_hits: Mapping[str, Path]#
chain_similarity_scores: Path#
protein_score_alignments: Mapping[str, Path]#
protein_scores: Path#
aligned_pocket_residues: Path | None#
plinder.core.scores.custom.resolve_search_database(backend: str, *, data_dir: Path | None = None, monomer: bool = False) → SearchDatabaseBundle[source]#

Download or validate one portable PLINDER search database bundle.

plinder.core.scores.custom.resolve_ligand_archives(pdb_or_system_ids: Iterable[str], *, data_dir: Path | None = None) → dict[str, Path][source]#

Download or validate only ligand-coordinate shards needed by targets.

plinder.core.scores.custom.resolve_custom_scoring_assets(*, data_dir: Path | None = None, backends: Iterable[str] = ('foldseek', 'mmseqs'), ligand_pdb_ids: Iterable[str] = (), include_monomers: bool = False) → CustomScoringAssets[source]#

Download or validate the bounded asset set for custom scoring.

Ligand archives are intentionally omitted unless ligand_pdb_ids are supplied. A caller can therefore run protein search first and fetch only the coordinate shards containing target ligands with positive pocket coverage.

plinder.core.scores.custom.write_custom_sequence_query_files(sequence_fasta: Path, *, work_dir: Path, min_chain_length: int = 12) → CustomQueryInputs[source]#

Write stable internal query IDs for a protein FASTA.

Each FASTA record represents one ligand-free protein chain. Original identifiers remain in the manifest and generated result tables; internal IDs keep search-database identifiers unambiguous.

plinder.core.scores.custom.write_custom_query_files(cif_files: Iterable[Path], *, work_dir: Path, structure_mode: str = 'as_is', assembly_ids: Iterable[str] | None = None, min_chain_length: int = 12) → CustomQueryInputs[source]#

Write one Foldseek-ready CIF and one FASTA record per protein chain.

as_is treats each supplied coordinate file as an already assembled structure. pdb applies the selected deposited assembly definitions, but searches only one rigid-transform-equivalent copy per label asym ID. Nucleic-acid entities and protein chains shorter than min_chain_length are excluded from both search backends.

plinder.core.scores.custom.annotate_custom_cif_files(cif_files: Iterable[Path], *, work_dir: Path, structure_mode: Literal['as_is', 'pdb'] = 'as_is', assembly_ids: Iterable[str] | None = None, ligand_smiles_dict: Mapping[str, str] | None = None, ligand_ccd_code_dict: Mapping[str, str] | None = None, include_ligands: bool = True, include_interfaces: bool = True, interface_annotate_prodigy: bool = True, data_dir: Path | None = None) → CustomStructureAnnotations[source]#

Annotate custom structures and write the scorer’s three index tables.

Ligand chemistry overrides are passed directly to Entry.from_custom_cif_file(). The same component mapping is applied to every input file; callers with different meanings for a repeated component name such as LIG should score those files in separate calls. Generated SDFs live under ligand_sdf_root/<entry>/ligand_files and contain the bond orders assigned during custom-CIF ingest.

plinder.core.scores.custom.create_custom_query_databases(inputs: CustomQueryInputs, *, work_dir: Path, backends: Iterable[str] = ('foldseek', 'mmseqs'), threads: int = 1) → CustomQueryDatabases[source]#

Create unindexed, scratch-local query DBs for selected search backends.

plinder.core.scores.custom.map_custom_alignment_hits(*, raw_alignment: Path, backend: str, query_databases: CustomQueryDatabases, alignment_chain_lookup: Path, output_path: Path, exclude_target_entries: Iterable[str] = ()) → Path[source]#

Replace backend identifiers with custom and PLINDER label-asym IDs.

plinder.core.scores.custom.prepare_custom_score_alignments(protein_hits: Mapping[str, Path], *, entries_by_structure: Mapping[str, Any], output_dir: Path) → dict[str, Path][source]#

Write hit tables in the compact alignment format used by PLINDER scores.

plinder.core.scores.custom.prepare_custom_protein_score_alignments(protein_hits: Mapping[str, Path], *, entries_by_structure: Mapping[str, Any], output_dir: Path) → dict[str, Path][source]#

Write reverse compact alignments for PLINDER-to-custom protein scores.

plinder.core.scores.custom.run_custom_protein_searches(*, query_databases: CustomQueryDatabases, assets: CustomScoringAssets, output_dir: Path, scratch_dir: Path, config: CustomProteinSearchConfig | None = None, backends: Iterable[str] = ('foldseek', 'mmseqs'), threads: int = 1) → dict[str, Path][source]#

Search custom protein chains and write backend-independent hit tables.

plinder.core.scores.custom.run_custom_monomer_searches(*, query_databases: CustomQueryDatabases, assets: CustomScoringAssets, output_dir: Path, scratch_dir: Path, config: CustomProteinSearchConfig | None, backends: Iterable[str], threads: int) → dict[str, Path][source]#

Search protein chains absent from pocket/interface targets.

plinder.core.scores.custom.write_custom_chain_similarity_scores(protein_hits: Mapping[str, Path], *, output_path: Path, chain_manifest: Path | None = None, monomer_hits: Mapping[str, Path] | None = None) → Path[source]#

Write direct custom-to-PLINDER protein-chain alignment scores.

Coverage and similarity values use integer percentages, as in the release protein similarity table. Each alignment remains a separate row.

plinder.core.scores.custom.calculate_custom_protein_similarity_scores(protein_score_alignments: Mapping[str, Path], *, assets: CustomScoringAssets, work_dir: Path, plinder_system_ids: Iterable[str] | None = None, custom_chain_ids: Iterable[str] | None = None, output_path: Path | None = None) → DataFrame[source]#

Score PLINDER receptors and ligand pockets against custom protein chains.

plinder.core.scores.custom.write_custom_aligned_pocket_residues(protein_score_alignments: Mapping[str, Path], *, protein_scores: Path, assets: CustomScoringAssets, output_path: Path) → Path[source]#

Write residue pairs supporting custom-chain pocket identity scores.

Attach sequence IDs and ligand chemistry to pocket-identity scores.

plinder.core.scores.custom.add_sequence_ids_to_aligned_pocket_residues(aligned_pocket_residues: Path, *, chain_manifest: Path) → Path[source]#

Add original FASTA identifiers to sequence-query residue mappings.

plinder.core.scores.custom.score_custom_sequence_file(sequence_fasta: Path, *, work_dir: Path, scratch_dir: Path | None = None, data_dir: Path | None = None, search_config: CustomProteinSearchConfig | None = None, backends: Iterable[str] = ('mmseqs',), plinder_entry_ids: Iterable[str] | None = None, threads: int = 1, store_aligned_pocket_residues: bool = False, include_monomers: bool = False) → CustomSequenceScoringResult[source]#

Search protein sequences and score PLINDER ligand-pocket identity.

plinder_entry_ids builds a small MMseqs target from the scoreable receptor and interface chains in the selected release entries instead of fetching the complete search database. This bounded mode currently requires backends=("mmseqs",).

plinder.core.scores.custom.calculate_custom_similarity_scores(score_alignments: Mapping[str, Path], *, annotations: CustomStructureAnnotations, assets: CustomScoringAssets, work_dir: Path, include_shape: bool = True, shape_score_threads: int = 1, target_system_ids: Iterable[str] | None = None, target_ligand_ids: Iterable[str] | None = None, data_dir: Path | None = None, output_path: Path | None = None) → DataFrame[source]#

Calculate directed ligand-pocket scores from custom structures.

plinder.core.scores.custom.calculate_custom_interface_similarity_scores(score_alignments: Mapping[str, Path], *, annotations: CustomStructureAnnotations, assets: CustomScoringAssets, target_interface_ids: Iterable[str] | None = None, output_path: Path | None = None) → DataFrame[source]#

Calculate directed protein-interface coverage from custom structures.

plinder.core.scores.custom.score_custom_cif_files(cif_files: Iterable[Path], *, work_dir: Path, scratch_dir: Path | None = None, data_dir: Path | None = None, structure_mode: Literal['as_is', 'pdb'] = 'as_is', assembly_ids: Iterable[str] | None = None, ligand_smiles_dict: Mapping[str, str] | None = None, ligand_ccd_code_dict: Mapping[str, str] | None = None, include_ligands: bool | None = True, include_interfaces: bool | None = True, include_shape: bool = True, interface_annotate_prodigy: bool = True, search_config: CustomProteinSearchConfig | None = None, backends: Iterable[str] = ('foldseek', 'mmseqs'), plinder_entry_ids: Iterable[str] | None = None, threads: int = 1, shape_score_threads: int = 1, store_aligned_pocket_residues: bool = False, include_monomers: bool = False) → CustomScoringResult[source]#

Run custom-CIF annotation, protein search, and PLINDER scoring.

Unknown component IDs such as LIG can be assigned chemistry with either ligand_smiles_dict or ligand_ccd_code_dict. The resulting bond-aware SDFs are used as the query conformers for shape, color, and SuCOS scores. Target ligand archives are first opened after a positive pocket match, and each required archive shard is read at most once.

The returned object points to the written custom annotation tables, backend hit tables, compact score alignments, and the final protein, ligand, and/or interface score parquet files under work_dir. Protein scores use each PLINDER ligand pocket as the directed query and each custom protein chain as a ligand-free target, so include_ligands=False still yields protein metrics and pocket_fident. Passing None for ligand or interface inclusion annotates that feature and emits its score table only when the custom structures contain a proper ligand or protein interface, respectively. plinder_entry_ids builds a small MMseqs target from scoreable receptor and interface chains in selected release entries rather than fetching the complete search database; this bounded mode currently requires backends=("mmseqs",).