starplast.pf_graph
Relation layers for the Plasmodium table: pairs of genes, in their own index space.
The Toxoplasma graph stores edges as index pairs into nodes.parquet. A falciparum gene has no
index there, so the second species needs a second graph rather than more layers in the first -- the
same reason instruction 39 gives one table per species. Nothing is merged and nothing is compared
across the two files; an index means a row of the table it was built from and of no other.
Three layers, built the way the Toxoplasma ones are
orthogroup and domain join genes that share a category. coexpression joins genes whose
abundance moves together across the life stages. The constructions are copied deliberately rather
than re-invented: if the two arms are ever compared, a difference should mean the biology differs
and not that the edges were drawn by different rules.
The self-edge trap, inherited on purpose
InterPro reports one row per domain MATCH, so a protein carrying two copies of a repeat domain shows up twice in a member list. Pairing a list that contains a gene twice emits (g, g) as an edge and duplicates every other pair through it -- which is how 31 self-edges and 106 duplicated pairs once shipped in the Toxoplasma graph. A self-edge draws as a zero-length line and a duplicate draws twice, reading as twice the evidence. Members are collected into a SET here for that reason, and a test asserts no edge joins a gene to itself.
Genes sharing an OrthoMCL group.
Genes sharing an InterPro domain. Members are a SET; see the module docstring.
Genes whose abundance moves together, keeping each gene's strongest neighbours.
Every layer, in the <name>__a / <name>__b / <name>__w shape the graph file uses.
Build the layers AND the 3D layout, and write them together.
The layout was missing until 2026-08-17, and its absence is why the application could not open
this arm at all: app.load reads xyz out of the graph file, and this file had every edge layer
and no coordinates. The arm was 41 filled slots that nothing could draw.
Laid out by the same build_graph.embed the Toxoplasma table uses, so the two maps are made the
same way -- not the same axes, which would be meaningless across species with different features,
but the same construction, which is what makes comparing them honest.
The shipped Plasmodium graph, or None if it has not been built.
Protein pairs joined by a measured crosslink, weighted by how many were found.
Two filters matter here and neither is optional. The experiment crosslinked PARASITE INSIDE ERYTHROCYTE, so a third of the pairs have a human protein at one or both ends -- spectrin, band 3, protein 4.2. Those are real contacts and they are a host bridge, not a parasite-parasite edge, so they are dropped from this layer rather than quietly indexed against a table that has no row for them. And a pair whose two ends resolve to the same gene is a homomeric crosslink: evidence the protein self-associates, not an edge between two genes, and drawing it would put a zero-length line in the graph.
Identifying which end is which must go through the IDENTITY INDEX and not through a pattern. The
first version of this matched PF3D7_\w+ in the mapping field and shipped 73 edges; the source
writes some rows with a UniProt symbol instead -- sp|Q6ZMA7|Pfs16 is Pfs16, which is
PF3D7_0406200 and a parasite gene -- so six real parasite-parasite contacts were dropped as
"host at one end", and one parasite protein was on its way into a host bridge. Resolving through
the accession index recovers all 79. This is the mistake the Toxoplasma identity layer exists to
prevent, made here anyway because a regex on an accession looks like resolution and is not.
Bait-to-partner edges from the co-immunoprecipitations, weighted by spectra in the bait.
Named ip_ms to match the Toxoplasma layer answering the same slot -- and, as everywhere on this
arm, the shared name is why the species guard exists: these indices are positions in
pf_nodes.parquet and mean different genes in the other graph.
A bait's own row is not an edge (a protein does not bind itself into the graph), and the pairs
are undirected here even though the experiment is not: A pulled down B and B pulled down A
are one line between two genes, and the direction is kept in the table the loader returns rather
than in the layer.
Pairs whose AlphaFold models superpose, as a layer of this graph.
Named struct to match the Toxoplasma layer answering the same slot, and built at the same
TM-score so the two mean one thing. It is the layer that needs no orthology, which in this
genome matters more than in the other one: most of what is exported has no detectable homolog.
The crosslinks this layer throws away: parasite protein to HUMAN protein.
The same file the xlms layer reads, and the other half of its filter. A crosslink between a
parasite protein and an erythrocyte one is a measured contact across the host boundary, which is
a bridge rather than an edge -- the pair's two ends live in different tables and a human protein
has no index in this one, exactly as instruction 39 describes.
Which end is which goes through the accession index, for the reason crosslink_edges records:
reading it off a pattern classified Pfs16, a parasite protein, as human.
How many host proteins each parasite gene was crosslinked to.
Three states, and the middle one is the reason this is not a fillna(0). The Toxoplasma arm sets
this to 0 for every gene without a curated host target, which is right there because its source is
a curated table covering the whole literature. This source is ONE experiment: a gene it never
detected has not been shown to lack host partners, it was simply not seen. So genes that appear in
the crosslink data get a count -- zero included, because being crosslinked only to parasite
proteins is a real observation -- and genes absent from it stay missing.