Skip to content

Serializers

JSON serialization for Tracks and Regions. Uses only the public Track protocol — no private attribute access. NaN and Inf values are sanitized to null for JSON safety.

region_to_dict

region_to_dict(r: Region) -> dict[str, Any]

Convert a Region to a JSON-safe dictionary.

Reads public fields only. Sanitizes NaN/Inf on score.

Parameters:

Name Type Description Default
r Region

A Region instance.

required

Returns:

Type Description
dict[str, Any]

Dictionary with chrom, start, end, strand, score, name, tags.

Examples:

>>> region_to_dict(Region("chr1", 10, 20, score=5.0))
{'chrom': 'chr1', 'start': 10, 'end': 20, 'strand': '.', 'score': 5.0, 'name': '', 'tags': {}}
Source code in src/seqchain/api/serializers.py
def region_to_dict(r: Region) -> dict[str, Any]:
    """Convert a Region to a JSON-safe dictionary.

    Reads public fields only. Sanitizes NaN/Inf on score.

    Args:
        r: A Region instance.

    Returns:
        Dictionary with chrom, start, end, strand, score, name, tags.

    Examples:
        >>> region_to_dict(Region("chr1", 10, 20, score=5.0))
        {'chrom': 'chr1', 'start': 10, 'end': 20, 'strand': '.', 'score': 5.0, 'name': '', 'tags': {}}
    """
    return {
        "chrom": r.chrom,
        "start": r.start,
        "end": r.end,
        "strand": r.strand,
        "score": _sanitize_float(r.score),
        "name": r.name,
        "tags": _sanitize_tags(r.tags),
    }

serialize_interval_track

serialize_interval_track(track: Any, chroms: dict[str, int]) -> list[dict]

Serialize an IntervalTrack to a list of region dicts.

When chroms is populated, queries each chromosome via track.regions(chrom, 0, size). When empty (e.g. tracks loaded from BED upload without a reference), falls back to direct iteration over the track.

Parameters:

Name Type Description Default
track Any

An IntervalTrack instance.

required
chroms dict[str, int]

Chromosome name → size mapping (may be empty).

required

Returns:

Type Description
list[dict]

List of region dictionaries.

Examples:

>>> from seqchain.region import Region
>>> from seqchain.track import IntervalTrack, TrackLabel
>>> t = IntervalTrack(TrackLabel("t"), [Region("chr1", 0, 10, score=1.0)])
>>> serialize_interval_track(t, {"chr1": 100})
[{'chrom': 'chr1', 'start': 0, 'end': 10, 'strand': '.', 'score': 1.0, 'name': '', 'tags': {}}]
Source code in src/seqchain/api/serializers.py
def serialize_interval_track(track: Any, chroms: dict[str, int]) -> list[dict]:
    """Serialize an IntervalTrack to a list of region dicts.

    When ``chroms`` is populated, queries each chromosome via
    ``track.regions(chrom, 0, size)``.  When empty (e.g. tracks
    loaded from BED upload without a reference), falls back to
    direct iteration over the track.

    Args:
        track: An IntervalTrack instance.
        chroms: Chromosome name → size mapping (may be empty).

    Returns:
        List of region dictionaries.

    Examples:
        >>> from seqchain.region import Region
        >>> from seqchain.track import IntervalTrack, TrackLabel
        >>> t = IntervalTrack(TrackLabel("t"), [Region("chr1", 0, 10, score=1.0)])
        >>> serialize_interval_track(t, {"chr1": 100})
        [{'chrom': 'chr1', 'start': 0, 'end': 10, 'strand': '.', 'score': 1.0, 'name': '', 'tags': {}}]
    """
    if chroms:
        chrom_order: list[str] = []
        for chrom in chroms:
            chrom_order.append(chrom)
        chrom_order.sort()
        result = []
        for chrom in chrom_order:
            for region in track.regions(chrom, 0, chroms[chrom]):
                result.append(region_to_dict(region))
        return result
    # Fallback: iterate the track directly (no chrom info available)
    fallback = []
    for r in track:
        fallback.append(region_to_dict(r))
    return fallback

serialize_table_track

serialize_table_track(track: Any) -> dict[str, float | None]

Serialize a TableTrack to a key-value dictionary.

Calls track.keys() and track.get(key) for each key.

Parameters:

Name Type Description Default
track Any

A TableTrack instance.

required

Returns:

Type Description
dict[str, float | None]

Dictionary of key → sanitized float value.

Examples:

>>> from seqchain.track import TableTrack, TrackLabel
>>> serialize_table_track(TableTrack(TrackLabel("t"), {"a": 1.0, "b": 2.0}))
{'a': 1.0, 'b': 2.0}
Source code in src/seqchain/api/serializers.py
def serialize_table_track(track: Any) -> dict[str, float | None]:
    """Serialize a TableTrack to a key-value dictionary.

    Calls ``track.keys()`` and ``track.get(key)`` for each key.

    Args:
        track: A TableTrack instance.

    Returns:
        Dictionary of key → sanitized float value.

    Examples:
        >>> from seqchain.track import TableTrack, TrackLabel
        >>> serialize_table_track(TableTrack(TrackLabel("t"), {"a": 1.0, "b": 2.0}))
        {'a': 1.0, 'b': 2.0}
    """
    result: dict[str, float | None] = {}
    for key in track.keys():
        result[key] = _sanitize_float(track.get(key))
    return result

serialize_signal_summary

serialize_signal_summary(track: Any, chrom: str, start: int, end: int) -> float | None

Get a signal summary value for a region.

Parameters:

Name Type Description Default
track Any

A SignalTrack instance.

required
chrom str

Chromosome name.

required
start int

Start coordinate.

required
end int

End coordinate.

required

Returns:

Type Description
float | None

Mean signal value, or None if NaN.

Examples:

>>> from seqchain.region import Region
>>> from seqchain.track import IntervalTrack, TrackLabel
>>> t = IntervalTrack(TrackLabel("t"), [Region("chr1", 0, 100, score=5.0)])
>>> serialize_signal_summary(t, "chr1", 0, 100)
5.0
Source code in src/seqchain/api/serializers.py
def serialize_signal_summary(track: Any, chrom: str, start: int, end: int) -> float | None:
    """Get a signal summary value for a region.

    Args:
        track: A SignalTrack instance.
        chrom: Chromosome name.
        start: Start coordinate.
        end: End coordinate.

    Returns:
        Mean signal value, or ``None`` if NaN.

    Examples:
        >>> from seqchain.region import Region
        >>> from seqchain.track import IntervalTrack, TrackLabel
        >>> t = IntervalTrack(TrackLabel("t"), [Region("chr1", 0, 100, score=5.0)])
        >>> serialize_signal_summary(t, "chr1", 0, 100)
        5.0
    """
    value = track.signal_at(chrom, start, end)
    return _sanitize_float(value)

genome_to_dict

genome_to_dict(genome: Genome) -> dict[str, Any]

Convert a Genome to a JSON-safe dictionary.

Parameters:

Name Type Description Default
genome Genome

A Genome instance.

required

Returns:

Type Description
dict[str, Any]

Dictionary with name, chroms (name → size), and topologies.

Examples:

>>> from seqchain.io.genome import Genome
>>> genome_to_dict(Genome("test", {}, {"chr1": "ATCG"}, (), {}))
{'name': 'test', 'chroms': {'chr1': 4}, 'topologies': {}}
Source code in src/seqchain/api/serializers.py
def genome_to_dict(genome: Genome) -> dict[str, Any]:
    """Convert a Genome to a JSON-safe dictionary.

    Args:
        genome: A Genome instance.

    Returns:
        Dictionary with name, chroms (name → size), and topologies.

    Examples:
        >>> from seqchain.io.genome import Genome
        >>> genome_to_dict(Genome("test", {}, {"chr1": "ATCG"}, (), {}))
        {'name': 'test', 'chroms': {'chr1': 4}, 'topologies': {}}
    """
    return {
        "name": genome.name,
        "chroms": genome.chrom_lengths,
        "topologies": dict(genome.topologies),
    }