API Reference

pen_assemble.pen_score

PenScore: composite scoring formula for IS110-family bridge recombinase designs.

The PenScore (Programmable Editor Nomination score) is a weighted linear combination of seven mechanistic axes calibrated for the human_therapeutic_aav_insertion use-case.

References

  • PEN-ASSEMBLE v0.5.0 documented methodology

  • IS621 published lockpoint: pen_score = 0.929 (verbatim pre-registered)

  • MHCflurry 2.2.1-calibrated lockpoint: 0.9255 (secondary analysis)

pen_assemble.pen_score.WEIGHTS: dict[str, float] = {'S_Cargo': 0.2, 'S_DSB': 0.25, 'S_Deliv': 0.15, 'S_Immuno': 0.1, 'S_Mature': 0.05, 'S_Prog': 0.15, 'S_Spec': 0.1}

Axis weights for human_therapeutic_aav_insertion use-case.

pen_assemble.pen_score.IS621_LOCKPOINT: float = 0.929

Verbatim pre-registered IS621 lockpoint (primary threshold).

pen_assemble.pen_score.IS621_LOCKPOINT_CALIBRATED: float = 0.9255

MHCflurry 2.2.1-calibrated lockpoint (secondary analysis only).

class pen_assemble.pen_score.PenScoreAxes(S_DSB=0.0, S_Spec=0.0, S_Cargo=0.0, S_Deliv=0.0, S_Immuno=0.0, S_Prog=0.0, S_Mature=0.0)[source]

Bases: object

Container for the seven PenScore axis scores.

All axes are in [0, 1]. Missing values (None) are treated as 0.0 when computing the composite score.

Parameters:
  • S_DSB (float) – Double-strand break induction score.

  • S_Spec (float) – Target-site specificity score.

  • S_Cargo (float) – Payload compatibility score (IS110-family = 1.0 by mechanism).

  • S_Deliv (float) – Delivery suitability score (AAV packaging compatibility).

  • S_Immuno (float) – De-immunization score (1 - normalised predicted immunogenicity).

  • S_Prog (float) – Programmability score (bRNA re-targeting tractability).

  • S_Mature (float) – Maturity / technology-readiness score.

S_DSB: float = 0.0
S_Spec: float = 0.0
S_Cargo: float = 0.0
S_Deliv: float = 0.0
S_Immuno: float = 0.0
S_Prog: float = 0.0
S_Mature: float = 0.0
as_dict()[source]

Return axes as a plain dict.

Return type:

dict[str, float]

contributions()[source]

Return per-axis weighted contributions.

Return type:

dict[str, float]

pen_assemble.pen_score.pen_score(axes)[source]

Compute the composite PenScore for a single design.

Parameters:

axes (PenScoreAxes) – Seven axis scores packaged as a PenScoreAxes instance.

Returns:

Composite PenScore in [0, 1].

Return type:

float

Examples

>>> from pen_assemble.pen_score import pen_score, PenScoreAxes
>>> ax = PenScoreAxes(S_DSB=1.0, S_Spec=1.0, S_Cargo=1.0,
...                   S_Deliv=1.0, S_Immuno=0.8777, S_Prog=1.0, S_Mature=0.5)
>>> round(pen_score(ax), 4)
0.9628
pen_assemble.pen_score.beats_is621(score, calibrated=False)[source]

Return True if score exceeds the IS621 reference lockpoint.

Parameters:
  • score (float) – A PenScore value.

  • calibrated (bool) – If True, compare against the MHCflurry 2.2.1-calibrated lockpoint (0.9255). Default is False (verbatim pre-registered 0.929).

Return type:

bool

Examples

>>> from pen_assemble.pen_score import beats_is621
>>> beats_is621(0.935)
True
>>> beats_is621(0.928)
False
>>> beats_is621(0.928, calibrated=True)
True

pen_assemble.catalog

Catalog loading utilities for PEN-ASSEMBLE release data.

Functions load the release CSV/Parquet files into pandas DataFrames and provide convenience views (P1 beaters, P5 top-5, strategy subsets).

pen_assemble.catalog.load_catalog(release_dir=None, fmt='parquet')[source]

Load the full 1,029-design PEN-ASSEMBLE scorecard.

Parameters:
  • release_dir (str | Path | None) – Path to the release directory. Defaults to catalog/release_v0.5.0/ relative to the repository root.

  • fmt (str) – "parquet" (default) or "csv".

Returns:

Scorecard with all catalog columns plus protein_sequence.

Return type:

DataFrame

Raises:

FileNotFoundError – If the release directory or catalog file does not exist.

Examples

>>> from pen_assemble.catalog import load_catalog
>>> df = load_catalog()
>>> len(df)
1029
>>> "pen_score" in df.columns
True
pen_assemble.catalog.load_p1_beaters(release_dir=None)[source]

Load the 16 designs that beat the IS621 verbatim lockpoint (pen_score > 0.929).

Parameters:

release_dir (str | Path | None) – Path to the release directory.

Returns:

Sorted by pen_score descending.

Return type:

DataFrame

Examples

>>> from pen_assemble.catalog import load_p1_beaters
>>> p1 = load_p1_beaters()
>>> len(p1)
16
>>> (p1["pen_score"] > 0.929).all()
True
pen_assemble.catalog.load_top5(release_dir=None)[source]

Load the five P5-compliant top designs (diversity-enforced top-5).

Note: the top-5 is not purely rank-ordered - rank-5 was diversity-enforced (A_007 replaces natural rank-5 D023). See validation/P5_diversity_result.json.

Parameters:

release_dir (str | Path | None) – Path to the release directory.

Returns:

Five designs sorted by pen_score descending.

Return type:

DataFrame

Examples

>>> from pen_assemble.catalog import load_top5
>>> t5 = load_top5()
>>> len(t5)
5
>>> t5["strategy"].nunique() >= 3
True
pen_assemble.catalog.filter_strategy(df, strategy)[source]

Filter a catalog DataFrame to a single strategy.

Parameters:
Returns:

Filtered view, sorted by pen_score descending.

Return type:

DataFrame

Raises:

ValueError – If strategy is not A/B/C/D or not present in df.

Examples

>>> from pen_assemble.catalog import load_catalog, filter_strategy
>>> df = load_catalog()
>>> filter_strategy(df, "C")["design_id"].tolist()
['IS621_deimmunized_v2_Y255K_D41C_G65K_E187M_D27C_D203C_V285C_V152C_T224C_L318K_E87C_L193I_L275I_P177V', 'C_targeted_001']

pen_assemble.codon

Codon optimisation utilities for human expression.

Implements rule-based codon optimisation using the Kazusa Homo sapiens high-expression preferred-codon table. Provides restriction-site scanning and ORF assembly helpers.

Note

This is a rule-based optimiser (one preferred codon per amino acid). For synthesis orders, verify the codon-adaptation index (CAI) with a commercial tool (IDT CodonOpt, Twist, GeneArt) before submitting.

pen_assemble.codon.codon_optimise(aa_sequence)[source]

Translate an amino acid sequence to human-preferred-codon DNA.

Unknown amino acid symbols are replaced with NNN.

Parameters:

aa_sequence (str) – Single-letter amino acid sequence (case-insensitive). Stop codons (*) are included if present.

Returns:

DNA sequence (uppercase, no spaces).

Return type:

str

Examples

>>> from pen_assemble.codon import codon_optimise
>>> codon_optimise("MA")
'ATGGCC'
>>> codon_optimise("M*")
'ATGTGA'
pen_assemble.codon.gc_content(dna)[source]

Return the GC fraction of a DNA string.

Parameters:

dna (str) – DNA sequence (any case).

Returns:

GC fraction in [0, 1], or 0.0 for empty strings.

Return type:

float

Examples

>>> from pen_assemble.codon import gc_content
>>> round(gc_content("GCGCAT"), 4)
0.6667
pen_assemble.codon.check_restriction_sites(dna)[source]

Return names of restriction enzymes whose sites appear in dna.

Checks both strands (forward only; palindromic sites are self-complementary so forward-strand search is sufficient for all sites in RESTRICTION_SITES).

Parameters:

dna (str) – DNA sequence (any case).

Returns:

Sorted list of enzyme names with sites found in dna. Empty if none.

Return type:

list[str]

Examples

>>> from pen_assemble.codon import check_restriction_sites
>>> check_restriction_sites("AAAGAATTCAAA")
['EcoRI']
>>> check_restriction_sites("ACGTACGT")
[]
pen_assemble.codon.build_expression_orf(aa_sequence, kozak=True, stop=True)[source]

Build a full expression-ready ORF from an amino acid sequence.

Applies codon optimisation then optionally prepends a Kozak consensus (GCCACC) and appends a preferred stop codon (TGA).

Parameters:
  • aa_sequence (str) – Amino acid sequence (case-insensitive). Must begin with M (Met).

  • kozak (bool) – If True (default), prepend Kozak context GCCACC.

  • stop (bool) – If True (default), append stop codon TGA.

Returns:

DNA sequence ready for gene synthesis.

Return type:

str

Raises:

ValueError – If aa_sequence is empty or does not start with Met.

Examples

>>> from pen_assemble.codon import build_expression_orf
>>> build_expression_orf("MA", kozak=False, stop=False)
'ATGGCC'
>>> build_expression_orf("MA", kozak=True, stop=True)
'GCCACCATGGCCTGA'