Edit on GitHub

starplast.expression

Six further expression datasets, each normalized according to what it actually measures.

These add four biological axes the map did not have, plus a real proteome and site-level phospho:

dataset axis added genes
PMID 31726967 in vivo brain, acute vs chronic, plus bradyzoite 28 DPI 8,678
GSE132248 alkaline-stress bradyzoite induction, 24 h vs 48 h 8,923
PXD058095 MORC depletion and BFD1 knockout 8,920
PXD039400 + PXD042658 total proteome, AP2XII-1/AP2XI-2 depleted or not 3,020
PXD017032 phosphosite positions and ratios, oocyst vs tachyzoite 1,918
PXD003765 oocyst iTRAQ 2,095

Two of them close gaps this project has been explicit about. The total proteome is four times the coverage of the immunoprecipitation data previously shipped (3,020 against 748) and is a proteome rather than an enrichment. The phosphosite table replaces a bare count -- n_phosphosites, present for 14.4% of genes with no positions -- with sites, ratios and p-values.

Every file needed something. Not one was a plain table with a header on the first row: two hide their data behind a Legend sheet, one is a legacy .xls that pandas cannot open at all without xlrd and is converted through libreoffice, and the iTRAQ header sits on the second row. That is normal for supplementary data and is why each dataset is declared here rather than guessed at.

Quantifications are not pooled. Each is normalized by its own type through sources.normalize -- counts and intensities are logged and centered, ratios are left alone because centering moves their reference -- and the columns are named for their dataset so nothing downstream can mistake an iTRAQ ratio for a TPM.

ACC = re.compile('TG[A-Z0-9]{2,6}[-._]?\\d{5,6}', re.IGNORECASE)
def invivo_brain( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

PMID 31726967: tachyzoite, whole brain acute and chronic, bradyzoite 28 DPI.

def stress_induction( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

GSE132248: unstressed 24 h against alkaline-stressed 48 h.

def gse22258_stage( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

GSE22258: matched Pru tachyzoite and 72-hour alkaline-induced bradyzoite array.

Unlike the two older ToxoGeneChip files beside it, this series matrix is already keyed by TGME49 accessions, so no external platform annotation or uncertain probe conversion is needed.

def neuronal_differentiation( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

GSE168465: parasite RNA changes over 1--14 days in infected primary brain cells.

Each workbook sheet is one time point against the tachyzoite comparator. Base means and log2 fold changes are measurements; p-values are inferential confidence and stay in the source file.

def gse99395_ribosome_profiling( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

GSE99395: matched ribosome-footprint and RNA counts, intra- and extracellular.

def gse129869_host_context_ribosome_profiling( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

GSE129869: parasite RPF/RNA counts in confluent and subconfluent infected HFFs.

def gse19092_cell_cycle( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

GSE19092: synchronized tachyzoite cell-cycle microarray, two replicates.

def gse51780_merozoite( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

GSE51780: tachyzoite comparator and feline merozoite expression.

def gse168155_rna_processing_perturbation( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

GSE168155: CPSF4 depletion transcriptome; not a direct per-gene m6A measurement.

def gse200962_restriction_checkpoint( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

GSE200962: tachyzoite/bradyzoite checkpoint and cyclin perturbation RNA counts.

def morc_depletion( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

PXD058095: MORC knockdown and BFD1 knockout. Data is on a second sheet behind a Legend.

def total_proteome( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

PXD039400 + PXD042658: total proteome, AP2XII-1/AP2XI-2 depleted or not.

Four times the protein coverage of the IP experiments previously shipped, and an actual proteome.

def phosphosites( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

PXD017032: oocyst against tachyzoite phosphosite ratios, with positions.

Site level collapsed to gene level, keeping what a gene table can hold: how many sites were measured, how many moved in each direction, and the strongest change. The site positions stay in the source file -- a per-gene table is the wrong shape for them.

def oocyst_itraq( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

PXD003765: oocyst iTRAQ ratios. Legacy .xls, converted through libreoffice.

GSE245775_ARMS = {('parental', 'tachyzoite'): 'parent_tachy', ('parental', 'stress'): 'parent_prebrady', ('eIF1-2-KO', 'tachyzoite'): 'eif12ko_tachy', ('eIF1-2-KO', 'stress'): 'eif12ko_prebrady'}
def gse245775_differentiation_ribosome_profiling( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

GSE245775: RPF and RNA counts for tachyzoites and alkaline-induced pre-bradyzoites.

Both in the parental line and in an eIF1.2 knockout -- the initiation factor whose loss blocks differentiation. The pre-bradyzoite RPF columns are the only ribosome profiling in the map taken under conversion, which is what makes this series worth reading despite being a knockout study.

Which archive member is which sample comes from the series matrix. The file names here happen to be descriptive (GSM7848805_parent_tachy_riboseq_rep1_counts.tabular.txt.gz) and that is exactly the trap: trusting them works until a submitter abbreviates one, and the GSM accession is stated outright a few lines away.

BFD2_RIP_FLOOR = 20
def gse223620_bfd2_rip( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

GSE223620: which transcripts the RNA-binding protein BFD2 pulls down.

IP against input, both scaled to a common library size, as a log2 ratio. The deposit publishes read counts and not the ratio, so it is computed here -- the comparison its two-sample design exists to make.

One column and not a set, because there is one RBP. The slot is RNA-binding protein targets and the column name says which protein, so a second RIP would sit beside this one rather than being averaged into it: two RBPs do not have a shared answer.

LOADERS = (<function invivo_brain>, <function stress_induction>, <function gse22258_stage>, <function neuronal_differentiation>, <function gse99395_ribosome_profiling>, <function gse129869_host_context_ribosome_profiling>, <function gse245775_differentiation_ribosome_profiling>, <function gse223620_bfd2_rip>, <function gse19092_cell_cycle>, <function gse51780_merozoite>, <function gse168155_rna_processing_perturbation>, <function gse200962_restriction_checkpoint>, <function morc_depletion>, <function total_proteome>, <function phosphosites>, <function oocyst_itraq>)
def load_all( base: str, resolve=None, log=<built-in function print>) -> pandas.DataFrame:

Every dataset above, joined on gene id.