> ## Documentation Index
> Fetch the complete documentation index at: https://proto.evodesign.org/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Sequences

> The fundamental data unit for biological sequence representation

# Sequences

A **Sequence** is the most fundamental object in Proto. It wraps a biological string (DNA, RNA, protein, or ligand) with type validation, character enforcement, and a metadata system that tracks constraint scores and optimization history.

Sequences are rarely created directly; they are created and managed by [Segments](/docs/language/concepts/segments) during optimization. Understanding the Sequence data model is still essential for interpreting results and working with the metadata system.

***

## What is a Sequence?

A Sequence bundles three things together:

<div className="block dark:hidden">
  <svg viewBox="0 0 520 428" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="A Sequence bundles a string, a type, and metadata" style={{width:"100%",height:"auto",display:"block"}}><defs><pattern id="gridsequences1L" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="1.2" fill="#344649" fillOpacity="0.10" /></pattern><marker id="arrsequences1L" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 L3,5 z" fill="#768b8e" /></marker></defs><rect x="12" y="12" width="496" height="404" rx="16" fill="#f9fcfc" stroke="#dee9e8" strokeWidth="1.2" /><rect x="12" y="12" width="496" height="404" rx="16" fill="url(#gridsequences1L)" /><rect x="40" y="52" width="440" height="336" rx="14" fill="#eef5f4" stroke="#ced9d7" strokeWidth="1.3" fillOpacity="0.55" strokeDasharray="5 4" /><text x="58" y="73" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="10.5" fontWeight="500" fill="#768b8e" textAnchor="start" letterSpacing="1.6">Sequence</text><rect x="80" y="92" width="360" height="76" rx="10" fill="#046e7a" /><rect x="90" y="104" width="4" height="52" rx="2" fill="#bfe2e7" /><text x="102" y="123" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14.5" fontWeight="600" fill="#ffffff" textAnchor="start">String</text><text x="102" y="141" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="10.5" fontWeight="400" fill="#bfe2e7" textAnchor="start">ATGCGATCG...</text><rect x="80" y="192" width="360" height="76" rx="10" fill="#eef2f4" stroke="#dbe3e6" strokeWidth="1.2" /><rect x="90" y="204" width="4" height="52" rx="2" fill="#768b8e" /><text x="102" y="223" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14.5" fontWeight="600" fill="#344649" textAnchor="start">Type</text><text x="102" y="241" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="10.5" fontWeight="400" fill="#768b8e" textAnchor="start">dna | rna | protein | ligand</text><rect x="80" y="292" width="360" height="76" rx="10" fill="#f4f9f9" stroke="#dbe6e4" strokeWidth="1.2" /><rect x="90" y="304" width="4" height="52" rx="2" fill="#768b8e" /><text x="102" y="322" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14.5" fontWeight="600" fill="#1d2c2f" textAnchor="start">Metadata</text><text x="102" y="341" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="12" fontWeight="400" fill="#768b8e" textAnchor="start">scores, length, constraints</text></svg>
</div>

<div className="hidden dark:block">
  <svg viewBox="0 0 520 428" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="A Sequence bundles a string, a type, and metadata" style={{width:"100%",height:"auto",display:"block"}}><defs><pattern id="gridsequences1D" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="1.2" fill="#9eb4b2" fillOpacity="0.10" /></pattern><marker id="arrsequences1D" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 L3,5 z" fill="#7e9498" /></marker></defs><rect x="12" y="12" width="496" height="404" rx="16" fill="#0e1718" stroke="#2b3c3e" strokeWidth="1.2" /><rect x="12" y="12" width="496" height="404" rx="16" fill="url(#gridsequences1D)" /><rect x="40" y="52" width="440" height="336" rx="14" fill="#15211f" stroke="#33474a" strokeWidth="1.3" fillOpacity="0.5" strokeDasharray="5 4" /><text x="58" y="73" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="10.5" fontWeight="500" fill="#7e9498" textAnchor="start" letterSpacing="1.6">Sequence</text><rect x="80" y="92" width="360" height="76" rx="10" fill="#0a7e8c" /><rect x="90" y="104" width="4" height="52" rx="2" fill="#c0e6ea" /><text x="102" y="123" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14.5" fontWeight="600" fill="#ffffff" textAnchor="start">String</text><text x="102" y="141" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="10.5" fontWeight="400" fill="#c0e6ea" textAnchor="start">ATGCGATCG...</text><rect x="80" y="192" width="360" height="76" rx="10" fill="#1b2829" stroke="#33474a" strokeWidth="1.2" /><rect x="90" y="204" width="4" height="52" rx="2" fill="#7e9498" /><text x="102" y="223" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14.5" fontWeight="600" fill="#d6e1df" textAnchor="start">Type</text><text x="102" y="241" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="10.5" fontWeight="400" fill="#8aa0a2" textAnchor="start">dna | rna | protein | ligand</text><rect x="80" y="292" width="360" height="76" rx="10" fill="#1a2a2b" stroke="#33474a" strokeWidth="1.2" /><rect x="90" y="304" width="4" height="52" rx="2" fill="#7e9498" /><text x="102" y="322" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14.5" fontWeight="600" fill="#eef5f4" textAnchor="start">Metadata</text><text x="102" y="341" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="12" fontWeight="400" fill="#9eb4b2" textAnchor="start">scores, length, constraints</text></svg>
</div>

<Columns>
  <Column>
    **The string** is the raw biological sequence: nucleotides, amino acids, or a SMILES representation of a small molecule.
  </Column>

  <Column>
    **The type** determines which characters are valid and how the sequence is validated. **Metadata** tracks constraint scores, system properties, and any custom data attached.
  </Column>
</Columns>

***

## Creating Sequences

<Tabs>
  <Tab title="Direct Creation">
    ```python python icon="python" theme={null}
    from proto_language.core import Sequence

    # DNA sequence
    dna = Sequence(
        sequence="ATGCGATCGATCGATCG",
        sequence_type="dna"
    )

    # Protein sequence
    protein = Sequence(
        sequence="MKFLILLFNILCLFPVLAAD",
        sequence_type="protein"
    )

    # With custom metadata
    annotated = Sequence(
        sequence="AGGAGGTTTTTATG",
        sequence_type="dna",
        metadata={"source": "E. coli K-12", "region": "rbs"}
    )
    ```
  </Tab>

  <Tab title="Through Segments (typical)">
    Most Sequences are created implicitly when a [Segment](/docs/language/concepts/segments) is built. The Segment manages dual pools of Sequences during optimization.

    ```python python icon="python" theme={null}
    from proto_language.core import Segment

    # Segment creates internal Sequence objects
    seg = Segment(sequence="ATGCGATCG", sequence_type="dna")

    # Access the Sequence objects
    seg.result_sequences[0].sequence      # "ATGCGATCG"
    seg.result_sequences[0].sequence_type  # "dna"
    seg.result_sequences[0].metadata       # {...}
    ```
  </Tab>
</Tabs>

***

## Sequence Types

| Type        | Valid characters                                                        | Typical uses                                                              |
| ----------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| **DNA**     | `A` `C` `G` `T`                                                         | Promoters, coding sequences, regulatory elements, synthetic gene circuits |
| **RNA**     | `A` `C` `G` `U`                                                         | mRNA, guide RNAs, ribozymes, aptamers, tRNA scaffolds                     |
| **Protein** | The 20 standard amino acids (`A C D E F G H I K L M N P Q R S T V W Y`) | Enzymes, antibodies, structural proteins, peptide therapeutics            |
| **Ligand**  | SMILES syntax (validated by RDKit)                                      | Small molecules, drug proposals, metabolites                              |

<Info>
  Character validation is **enforced on creation and mutation**. Invalid characters produce a warning but do not terminate the program, allowing flexible handling of edge cases like ambiguity codes.
</Info>

### Custom Valid Characters

The character set can be restricted for specialized applications:

```python python icon="python" theme={null}
# Only allow purines
purine_only = Sequence(
    sequence="AAGGAAGG",
    sequence_type="dna",
    valid_chars={"A", "G"}
)

# Reduced amino acid alphabet (e.g., for directed evolution libraries)
reduced = Sequence(
    sequence="AGSTNDE",
    sequence_type="protein",
    valid_chars={"A", "G", "S", "T", "N", "D", "E"}
)
```

***

## The Metadata System

Every Sequence carries a metadata dictionary that tracks system properties, constraint scores, and custom user data. This is how optimization results are communicated.

### Metadata Structure

```python python icon="python" theme={null}
seq.metadata
# {
#     "sequence": "ATGCGATCG...",           # System: current sequence string
#     "sequence_length": 100,                # System: length of the sequence
#     "constraints": {                       # System: constraint results
#         "GC Content": {
#             "score": 0.02,                 # Raw constraint score (0.0 = perfect)
#             "weight": 1.0,                 # Constraint weight
#             "weighted_score": 0.02,        # score * weight
#             "data": {                      # Constraint-specific data
#                 "gc_content": 52.0
#             }
#         },
#         "Structure pLDDT": {
#             "score": 0.15,
#             "weight": 2.0,
#             "weighted_score": 0.30,
#             "data": {
#                 "plddt": 85.2
#             }
#         }
#     },
#     "generators": {},                      # System: per-generator metadata (always present)
#     "source": "E. coli K-12",              # User: custom metadata
# }
```

<AccordionGroup>
  <Accordion title="System-managed keys (protected)">
    These keys are automatically maintained by the framework. If they are set manually, they are overridden by the computed values, and the framework logs a warning at construction.

    | Key               | Type   | Description                                                              |
    | ----------------- | ------ | ------------------------------------------------------------------------ |
    | `sequence`        | `str`  | The current sequence string (kept in sync with the `.sequence` property) |
    | `sequence_length` | `int`  | Length of the current sequence                                           |
    | `constraints`     | `dict` | Nested dictionary of constraint results, keyed by constraint label       |
    | `generators`      | `dict` | Nested dictionary of per-generator metadata, keyed by generator label    |
  </Accordion>

  <Accordion title="Constraint metadata">
    After optimization, each constraint writes its results into `metadata["constraints"][label]`:

    | Field            | Type    | Description                                                                |
    | ---------------- | ------- | -------------------------------------------------------------------------- |
    | `score`          | `float` | Raw constraint score: 0.0 (perfect) to 1.0 (worst violation)               |
    | `weight`         | `float` | Weight assigned to this constraint                                         |
    | `weighted_score` | `float` | `score * weight`; used for energy calculation                              |
    | `data`           | `Any`   | Constraint-specific data (e.g., actual GC content, pLDDT value, structure) |

    ```python python icon="python" theme={null}
    # Access constraint results after optimization
    for seq in segment.result_sequences:
        gc_score = seq.metadata["constraints"]["GC Content"]["score"]
        gc_actual = seq.metadata["constraints"]["GC Content"]["data"]["gc_content"]
        print(f"GC score: {gc_score:.3f}, actual GC: {gc_actual:.1f}%")
    ```
  </Accordion>

  <Accordion title="User-defined metadata">
    Any custom metadata can be attached when creating a Sequence. This metadata persists through optimization.

    ```python python icon="python" theme={null}
    seq = Sequence(
        sequence="ATGCGATCG",
        sequence_type="dna",
        metadata={
            "source": "E. coli K-12",
            "experiment_id": "EXP-2024-001",
            "notes": "Wild-type promoter region"
        }
    )

    seq.metadata["source"]  # "E. coli K-12"
    ```

    <Warning>
      Do not use the reserved keys `sequence`, `sequence_length`, `constraints`, `generators`, `logits`, or `structure` for custom metadata. They are system-managed (the first four are recomputed and override provided values; `logits` and `structure` are first-class `Sequence` fields), and the framework logs a warning at construction if any of the first four are set.
    </Warning>
  </Accordion>
</AccordionGroup>

***

## Working with Sequences

### String-Like Operations

Sequences support common string operations:

```python python icon="python" theme={null}
seq = Sequence(sequence="ATGCGATCGATCG", sequence_type="dna")

# Length
len(seq)           # 13

# String representation
str(seq)           # "ATGCGATCGATCG"

# Indexing and slicing
seq[0]             # "A"
seq[3:6]           # "CGA"
seq[-3:]           # "TCG"
```

### Mutating Sequences

The `.sequence` property is settable. When it is updated, the metadata is automatically kept in sync:

```python python icon="python" theme={null}
seq = Sequence(sequence="ATGCGA", sequence_type="dna")

seq.sequence = "TTGCGA"  # Validated and metadata updated
seq.metadata["sequence"]         # "TTGCGA"
seq.metadata["sequence_length"]  # 6
```

<Note>
  In practice, Sequences are rarely mutated directly. Generators handle mutation during optimization.
</Note>

***

## Serialization

Sequences serialize to dictionaries for storage or transfer:

<CodeGroup>
  ```python python icon="python" title="Serialize" theme={null}
  data = seq.to_dict()
  # {
  #     "sequence": "ATGCGATCG",
  #     "sequence_type": "dna",
  #     "valid_chars": ["A", "C", "G", "T"],
  #     "metadata": { ... },      # user-provided metadata only
  #     "constraints": { ... },   # per-constraint results (top-level sibling)
  #     "generators": { ... },    # per-generator metadata (top-level sibling)
  # }
  # Pass include_logits=True or include_structure=True to add those keys.
  ```

  ```python python icon="python" title="Deserialize" theme={null}
  restored = Sequence.from_dict(data)
  restored.sequence       # "ATGCGATCG"
  restored.sequence_type  # "dna"
  ```
</CodeGroup>

***

## Automatic Type Detection

The framework can infer sequence type from the characters present. This is useful when working with sequences of unknown origin:

```python python icon="python" theme={null}
from proto_language.core.sequence import detect_sequence_type

detect_sequence_type("ATGCGATCG")        # "dna"
detect_sequence_type("AUGCGAUCG")        # "rna"
detect_sequence_type("MKFLILLFNILC")     # "protein"
detect_sequence_type("CCO")              # "ligand" (ethanol SMILES)
```

<Note>
  Detection priority is DNA > RNA > Protein > Ligand. Ambiguous sequences (e.g., "ACGT" could be DNA or protein) default to the more specific type.
</Note>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Segments" icon="rectangle-horizontal" href="/docs/language/concepts/segments">
    How Segments manage pools of Sequences during optimization
  </Card>

  <Card title="Constructs" icon="layers" href="/docs/language/concepts/constructs">
    Combining Segments into complete biological designs
  </Card>

  <Card title="Constraints" icon="square-function" href="/docs/language/concepts/constraints">
    How constraints write scores into Sequence metadata
  </Card>

  <Card title="Overview" icon="book-open" href="/docs/language/concepts/overview">
    See the full architecture and design patterns
  </Card>
</CardGroup>
