> ## 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.

# Segments

> Defining sequence regions and managing dual pools during optimization

# Segments

A **Segment** is a region of biological sequence to be designed or optimized. It is analogous to a gene annotation on a genome map: a bounded region with a specific function (a promoter, a coding sequence, a linker domain) that the framework fills with an optimal sequence.

Each Segment maintains **two pools of sequences** that the optimization loop uses: one for exploring proposals, and one for preserving the best results found so far.

***

## Creating Segments

<Tabs>
  <Tab title="From Length (design from scratch)">
    Creates an entirely new sequence for a region from scratch. The framework fills it during optimization.

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

    # Design a new 100bp DNA promoter
    promoter = Segment(
        length=100,
        sequence_type="dna",
        label="promoter"
    )

    # Design a 250-residue protein enzyme
    enzyme = Segment(
        length=250,
        sequence_type="protein",
        label="enzyme"
    )
    ```

    The Segment starts with an empty sequence. The Generator will populate it with proposals at the start of optimization.
  </Tab>

  <Tab title="From Sequence (optimize existing)">
    Starts from an existing sequence to be improved. The provided sequence becomes the starting point for the Generator.

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

    # Optimize an existing promoter
    promoter = Segment(
        sequence="TTGACATAAATACCACTGGCGGTGATACTGAGCAC",
        sequence_type="dna",
        label="lac_promoter"
    )

    # Optimize a known enzyme
    enzyme = Segment(
        sequence="MSKGEELFTGVVPILVELDGDVNGHKFSVSG",
        sequence_type="protein",
        label="gfp_fragment"
    )

    # Length is inferred from the sequence
    promoter.sequence_length  # 35
    enzyme.sequence_length    # 31
    ```
  </Tab>
</Tabs>

<Warning>
  Either `length` or `sequence` must be provided, but **not both**. If a sequence is provided, the length is inferred automatically.
</Warning>

***

## Sequence Types

| Sequence type | Valid characters                | Example                                           |
| ------------- | ------------------------------- | ------------------------------------------------- |
| **DNA**       | `A` `C` `G` `T`                 | `Segment(length=100, sequence_type="dna")`        |
| **RNA**       | `A` `C` `G` `U`                 | `Segment(length=50, sequence_type="rna")`         |
| **Protein**   | 20 standard amino acids         | `Segment(length=300, sequence_type="protein")`    |
| **Ligand**    | SMILES syntax (RDKit-validated) | `Segment(sequence="CCO", sequence_type="ligand")` |

<Note>
  Ligand segments **must** be initialized with a sequence (SMILES string), not just a length. This is because SMILES syntax cannot be randomly generated; the molecule must be chemically valid.
</Note>

***

## The Dual Pool Model

Each Segment maintains two separate lists of [Sequence](/docs/language/concepts/sequences) objects that serve different purposes during optimization:

<div className="block dark:hidden">
  <svg viewBox="0 0 960 420" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Dual-pool model inside a Segment" style={{width:"100%",height:"auto",display:"block"}}><defs><pattern id="gridsegments1L" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="1.2" fill="#344649" fillOpacity="0.10" /></pattern><marker id="arrsegments1L" 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="936" height="396" rx="16" fill="#f9fcfc" stroke="#dee9e8" strokeWidth="1.2" /><rect x="12" y="12" width="936" height="396" rx="16" fill="url(#gridsegments1L)" /><rect x="340" y="58" width="280" height="312" rx="14" fill="#eef5f4" stroke="#ced9d7" strokeWidth="1.3" fillOpacity="0.55" strokeDasharray="5 4" /><text x="358" y="79" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="10.5" fontWeight="500" fill="#768b8e" textAnchor="start" letterSpacing="1.6">SEGMENT</text><path d="M200,206 C 256,204 308,166 364,162" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arrsegments1L)" /><path d="M596,162 C 652,166 704,204 760,206" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arrsegments1L)" /><path d="M760,224 C 704,228 652,264 596,268" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arrsegments1L)" /><path d="M364,268 C 308,264 256,228 200,224" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arrsegments1L)" /><rect x="44" y="182" width="156" height="66" rx="10" fill="#046e7a" /><rect x="54" y="194" width="4" height="42" rx="2" fill="#bfe2e7" /><text x="66" y="220" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14.5" fontWeight="600" fill="#ffffff" textAnchor="start">Generator</text><rect x="760" y="182" width="156" height="66" rx="10" fill="#eef2f4" stroke="#dbe3e6" strokeWidth="1.2" /><rect x="770" y="194" width="4" height="42" rx="2" fill="#768b8e" /><text x="782" y="220" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14.5" fontWeight="600" fill="#344649" textAnchor="start">Constraints</text><rect x="364" y="92" width="232" height="92" rx="10" fill="#f4f9f9" stroke="#dbe6e4" strokeWidth="1.2" /><rect x="374" y="104" width="4" height="68" rx="2" fill="#046e7a" /><text x="386" y="124" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="14" fontWeight="600" fill="#1d2c2f" textAnchor="start">proposal\_sequences</text><text x="386" y="142" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#768b8e" textAnchor="start">Working space</text><text x="386" y="160" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#768b8e" textAnchor="start">Many proposals being explored</text><rect x="364" y="246" width="232" height="92" rx="10" fill="#f4f9f9" stroke="#dbe6e4" strokeWidth="1.2" /><rect x="374" y="258" width="4" height="68" rx="2" fill="#2f8f6b" /><text x="386" y="278" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="14" fontWeight="600" fill="#1d2c2f" textAnchor="start">result\_sequences</text><text x="386" y="296" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#768b8e" textAnchor="start">Results space</text><text x="386" y="314" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#768b8e" textAnchor="start">Best sequences found so far</text><g fill="#ffffff" stroke="#9eb4b2" strokeWidth="1.4"><circle cx="200" cy="206" r="3.2" /><circle cx="364" cy="162" r="3.2" /><circle cx="596" cy="162" r="3.2" /><circle cx="760" cy="206" r="3.2" /><circle cx="760" cy="224" r="3.2" /><circle cx="596" cy="268" r="3.2" /><circle cx="364" cy="268" r="3.2" /><circle cx="200" cy="224" r="3.2" /></g><rect x="221" y="166.5" width="98" height="35" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="270" y="181.25" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">fills with</text><text x="270" y="194.75" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">new proposals</text><rect x="653" y="173.25" width="74" height="21.5" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="690" y="188" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">scored by</text><rect x="629" y="228.5" width="122" height="35" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="690" y="243.25" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">optimizer selects</text><text x="690" y="256.75" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">best proposals</text><rect x="230" y="228.5" width="80" height="35" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="270" y="243.25" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">seeds next</text><text x="270" y="256.75" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">generation</text></svg>
</div>

<div className="hidden dark:block">
  <svg viewBox="0 0 960 420" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Dual-pool model inside a Segment" style={{width:"100%",height:"auto",display:"block"}}><defs><pattern id="gridsegments1D" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="1.2" fill="#9eb4b2" fillOpacity="0.10" /></pattern><marker id="arrsegments1D" 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="936" height="396" rx="16" fill="#0e1718" stroke="#2b3c3e" strokeWidth="1.2" /><rect x="12" y="12" width="936" height="396" rx="16" fill="url(#gridsegments1D)" /><rect x="340" y="58" width="280" height="312" rx="14" fill="#15211f" stroke="#33474a" strokeWidth="1.3" fillOpacity="0.5" strokeDasharray="5 4" /><text x="358" y="79" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="10.5" fontWeight="500" fill="#7e9498" textAnchor="start" letterSpacing="1.6">SEGMENT</text><path d="M200,206 C 256,204 308,166 364,162" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arrsegments1D)" /><path d="M596,162 C 652,166 704,204 760,206" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arrsegments1D)" /><path d="M760,224 C 704,228 652,264 596,268" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arrsegments1D)" /><path d="M364,268 C 308,264 256,228 200,224" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arrsegments1D)" /><rect x="44" y="182" width="156" height="66" rx="10" fill="#0a7e8c" /><rect x="54" y="194" width="4" height="42" rx="2" fill="#c0e6ea" /><text x="66" y="220" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14.5" fontWeight="600" fill="#ffffff" textAnchor="start">Generator</text><rect x="760" y="182" width="156" height="66" rx="10" fill="#1b2829" stroke="#33474a" strokeWidth="1.2" /><rect x="770" y="194" width="4" height="42" rx="2" fill="#7e9498" /><text x="782" y="220" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14.5" fontWeight="600" fill="#d6e1df" textAnchor="start">Constraints</text><rect x="364" y="92" width="232" height="92" rx="10" fill="#1a2a2b" stroke="#33474a" strokeWidth="1.2" /><rect x="374" y="104" width="4" height="68" rx="2" fill="#0a7e8c" /><text x="386" y="124" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="14" fontWeight="600" fill="#eef5f4" textAnchor="start">proposal\_sequences</text><text x="386" y="142" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#9eb4b2" textAnchor="start">Working space</text><text x="386" y="160" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#9eb4b2" textAnchor="start">Many proposals being explored</text><rect x="364" y="246" width="232" height="92" rx="10" fill="#1a2a2b" stroke="#33474a" strokeWidth="1.2" /><rect x="374" y="258" width="4" height="68" rx="2" fill="#37a07c" /><text x="386" y="278" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="14" fontWeight="600" fill="#eef5f4" textAnchor="start">result\_sequences</text><text x="386" y="296" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#9eb4b2" textAnchor="start">Results space</text><text x="386" y="314" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#9eb4b2" textAnchor="start">Best sequences found so far</text><g fill="#13201f" stroke="#566b6e" strokeWidth="1.4"><circle cx="200" cy="206" r="3.2" /><circle cx="364" cy="162" r="3.2" /><circle cx="596" cy="162" r="3.2" /><circle cx="760" cy="206" r="3.2" /><circle cx="760" cy="224" r="3.2" /><circle cx="596" cy="268" r="3.2" /><circle cx="364" cy="268" r="3.2" /><circle cx="200" cy="224" r="3.2" /></g><rect x="221" y="166.5" width="98" height="35" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="270" y="181.25" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">fills with</text><text x="270" y="194.75" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">new proposals</text><rect x="653" y="173.25" width="74" height="21.5" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="690" y="188" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">scored by</text><rect x="629" y="228.5" width="122" height="35" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="690" y="243.25" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">optimizer selects</text><text x="690" y="256.75" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">best proposals</text><rect x="230" y="228.5" width="80" height="35" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="270" y="243.25" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">seeds next</text><text x="270" y="256.75" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">generation</text></svg>
</div>

<Columns>
  <Column>
    ### proposal\_sequences

    The **working space**. Generators fill this pool with new proposals each step. Constraints score every proposal. The Optimizer ranks them and decides which survive.

    * Rebuilt every optimization step
    * Can contain many sequences (e.g., 100 proposals)
    * Internal to the optimization loop
  </Column>

  <Column>
    ### result\_sequences

    The **results space**. The Optimizer promotes the best proposals here. This pool persists across optimization steps, and when using multi-stage [Programs](/docs/language/concepts/programs), carries results from one stage to the next.

    * Persists across steps and stages
    * Contains the top-K best sequences
    * User-facing output after optimization
  </Column>
</Columns>

```python python icon="python" theme={null}
# During optimization
segment.proposal_sequences   # List[Sequence] - current proposals
segment.result_sequences    # List[Sequence] - best found so far

# After optimization, read results from the result pool
for seq in segment.result_sequences:
    print(f"Sequence: {seq.sequence[:30]}...")
    print(f"Scores: {seq.metadata['constraints']}")
```

***

## Properties Reference

<AccordionGroup>
  <Accordion title="Pool properties">
    | Property             | Type             | Description                              |
    | -------------------- | ---------------- | ---------------------------------------- |
    | `proposal_sequences` | `List[Sequence]` | Current proposals (working space)        |
    | `result_sequences`   | `List[Sequence]` | Best sequences found (results space)     |
    | `num_proposals`      | `int`            | Number of sequences in the proposal pool |
    | `num_results`        | `int`            | Number of sequences in the result pool   |
  </Accordion>

  <Accordion title="Sequence properties">
    | Property                | Type                 | Description                                                |
    | ----------------------- | -------------------- | ---------------------------------------------------------- |
    | `sequence_type`         | `SequenceType`       | `"dna"`, `"rna"`, `"protein"`, or `"ligand"` (read-only)   |
    | `valid_chars`           | `Optional[Set[str]]` | Allowed characters for this segment (read-only)            |
    | `sequence_length`       | `int`                | Expected length of sequences in this segment               |
    | `original_sequence`     | `Sequence`           | The original sequence provided at construction (read-only) |
    | `has_original_sequence` | `bool`               | `True` if created with a sequence (vs. just a length)      |
  </Accordion>

  <Accordion title="State properties">
    | Property              | Type            | Description                                                    |
    | --------------------- | --------------- | -------------------------------------------------------------- |
    | `populated_sequences` | `bool`          | Whether segment has sequences from input or prior optimization |
    | `proposals_populated` | `bool`          | Whether proposal pool has non-empty sequences                  |
    | `is_ligand`           | `bool`          | Whether this is a ligand segment (ligands cannot be mutated)   |
    | `label`               | `Optional[str]` | Identifier for this segment (auto-assigned if not provided)    |
    | `construct_label`     | `Optional[str]` | Label of the parent Construct (set by Program)                 |
  </Accordion>
</AccordionGroup>

***

## Labels

Labels identify segments in multi-segment designs and appear in constraint metadata, so per-segment results are attributable to a named region.

```python python icon="python" theme={null}
promoter = Segment(length=100, sequence_type="dna", label="promoter")
cds = Segment(length=900, sequence_type="dna", label="cds")
terminator = Segment(length=50, sequence_type="dna", label="terminator")
```

If a label is not provided, segments are auto-labeled based on their position in the [Construct](/docs/language/concepts/constructs): `segment_0`, `segment_1`, etc.

***

## Custom Valid Characters

Restrict the allowed characters for specialized applications:

```python python icon="python" theme={null}
# AT-rich region (no G or C allowed)
at_rich = Segment(
    length=50,
    sequence_type="dna",
    valid_chars={"A", "T"},
    label="at_rich_spacer"
)

# Reduced amino acid alphabet for combinatorial libraries
combinatorial = Segment(
    length=100,
    sequence_type="protein",
    valid_chars={"A", "G", "S", "T", "N", "D", "E", "K"},
    label="library_region"
)
```

The `valid_chars` constraint is enforced during validation and used by Generators to only propose valid characters.

***

## Iteration and Indexing

Segments support direct iteration and indexing into the **result pool** (results):

```python python icon="python" theme={null}
# Iterate over result sequences
for sequence in segment:
    print(sequence.sequence)

# Index directly
best = segment[0]
print(best.sequence)
print(best.metadata["constraints"])

# Count results
print(f"{segment.num_results} results, {segment.num_proposals} proposals")
```

***

## Creation Patterns

<CodeGroup>
  ```python python icon="python" title="Fixed Flanks + Variable Middle" theme={null}
  # Optimize the middle region while keeping flanks fixed
  flank_5 = Segment(sequence="ATGCATGC", sequence_type="dna", label="5_flank")
  variable = Segment(length=100, sequence_type="dna", label="variable")
  flank_3 = Segment(sequence="GCATGCAT", sequence_type="dna", label="3_flank")
  ```

  ```python python icon="python" title="Signal Peptide + Domain" theme={null}
  # Fixed signal peptide with a variable protein domain
  signal = Segment(
      sequence="MKFLILLFNILCLFPVLAAD",
      sequence_type="protein",
      label="signal_peptide"
  )
  domain = Segment(length=200, sequence_type="protein", label="catalytic_domain")
  ```

  ```python python icon="python" title="CRISPR Guide RNA" theme={null}
  # Design a guide RNA sequence
  spacer = Segment(length=20, sequence_type="rna", label="spacer")
  scaffold = Segment(
      sequence="GUUUUAGAGCUAGAAAUAGCAAGUUAAAAUAAGGCUAGUCCG",
      sequence_type="rna",
      label="scaffold"
  )
  ```
</CodeGroup>

***

## Serialization

Segments serialize to dictionaries, preserving both pools and all metadata:

<CodeGroup>
  ```python python icon="python" title="Serialize" theme={null}
  data = segment.to_dict()
  # {
  #     "original_sequence": { ... },
  #     "sequence_length": 100,
  #     "proposal_sequences": [{ ... }, { ... }],
  #     "result_sequences": [{ ... }],
  #     "sequence_type": "dna",
  #     "valid_chars": ["A", "C", "G", "T"],
  #     "label": "promoter"
  # }
  ```

  ```python python icon="python" title="Deserialize" theme={null}
  restored = Segment.from_dict(data)
  restored.label            # "promoter"
  restored.sequence_length  # 100
  restored.num_results      # preserved from original
  ```
</CodeGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Constructs" icon="layers" href="/docs/language/concepts/constructs">
    Combine Segments into complete biological designs
  </Card>

  <Card title="Generators" icon="cpu" href="/docs/language/concepts/generators">
    How Generators propose new sequences for Segments
  </Card>

  <Card title="Sequences" icon="dna" href="/docs/language/concepts/sequences">
    The data model underlying each pool entry
  </Card>

  <Card title="Overview" icon="book-open" href="/docs/language/concepts/overview">
    See how Segments fit into the full architecture
  </Card>
</CardGroup>
