API reference¶
Everything below is re-exported from the top level, so
from causalphylo import find_adjustment_set and
from causalphylo.backdoor import find_adjustment_set are equivalent.
causalphylo.graph_semantics¶
Which edges may carry a causal claim. See Which edges earn an arrow.
Which edges may carry a causal claim.
A disease graph assembled from public sources mixes two kinds of edge. Some assert a mechanism with a direction: OmniPath's signed regulatory interactions, where a curator has said that A acts on B. Others assert only that two things occur together: a literature co-mention, membership of a shared pathway, an undirected protein interaction whose arrow exists because one protein landed in the first column of an API response.
Do-calculus over the second kind assumes the very thing a causal method is supposed to establish. So this module partitions the edge types and identification runs only on the causal-admissible subgraph. Associational edges keep contributing to evidence scoring; they stop being arrows.
Gene -> disease is admitted only on genetic evidence. A germline variant is randomised at conception, so a genetic association carries a natural-experiment warrant that a co-mention does not -- the Mendelian randomisation argument (Davey Smith & Ebrahim, 2003, Int J Epidemiol 32:1-22). That warrant is what earns the arrow.
AcyclicCore
dataclass
¶
A DAG carved out of a possibly-cyclic graph, and what was removed.
excluded names every node that sat in a feedback loop. Those
nodes are not silently repaired: d-separation is undefined on them,
and identification reports cyclic_component rather than guessing
an acyclic orientation.
Source code in src/causalphylo/graph_semantics.py
is_causal_admissible ¶
Whether an edge with these attributes may carry a causal claim.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
attrs
|
dict
|
Edge attribute mapping, as stored on the NetworkX graph. Reads
|
required |
Source code in src/causalphylo/graph_semantics.py
causal_subgraph ¶
The subgraph of causal-admissible edges, attributes preserved.
Nodes left with no admissible edge are dropped: a node that participates in no causal relation cannot be a treatment, an outcome, or a confounder.
Source code in src/causalphylo/graph_semantics.py
cyclic_components ¶
Strongly connected components with cycles, including self-loops.
Source code in src/causalphylo/graph_semantics.py
acyclic_core ¶
Remove every node in a strongly connected component with cycles.
Biological regulatory networks are full of feedback, and
nx.is_d_separator requires a DAG of the whole graph -- not merely
of the neighbourhood under test. So cyclic nodes come out entirely,
and the caller is told which.
Source code in src/causalphylo/graph_semantics.py
Vocabularies¶
CAUSAL_EDGE_TYPES- Frozenset of
edge_typevalues that assert a directed mechanism. GENETIC_EVIDENCE_CLASSES- Frozenset of
evidence_classvalues that license a gene-to-disease arrow.
causalphylo.backdoor¶
Identification on the admissible subgraph. See Identification.
Pearl's backdoor criterion, and an honest verdict when it cannot be met.
Z satisfies the backdoor criterion relative to (X, Y) when no node in Z is a descendant of X, and Z blocks every path between X and Y that starts with an arrow into X (Pearl, Causality, 2nd ed., Def. 3.3.1). Both halves matter: the descendant condition rules out conditioning on a mediator or a collider downstream of the treatment, and blocking only the backdoor paths -- never the causal path itself -- is what a plain d-separation test does not do for free. To test the second half with a generic d-separation routine, the edges leaving the treatment are removed first: that deletes the causal path (and anything X causes) while leaving every backdoor path, the ones entering X through an arrow, exactly as they were.
This module reports why identification failed, not merely that it did. The reasons are a closed enum so that a run's failures aggregate into a distribution rather than a pile of prose.
A note on trivial identification. When no confounder appears in the
graph, the empty set satisfies the criterion and the effect is
identifiable -- but a knowledge graph is open-world, and a missing edge
is missing knowledge rather than evidence of no confounding. So a
trivial verdict is reported under its own reason and carries
n_near_miss_confounders: how many nodes regulate the treatment and
have some association with the outcome that fell short of admissibility.
A target with many near misses is fragile. This is the same move as an
E-value in observational epidemiology -- not "there is no confounding"
but "here is how much it would take to break this".
Identification
dataclass
¶
The verdict on one (treatment, outcome) pair.
Source code in src/causalphylo/backdoor.py
IdentificationReason ¶
Bases: StrEnum
Why identification succeeded or failed. A closed set.
Source code in src/causalphylo/backdoor.py
find_adjustment_set ¶
Search for a minimal valid backdoor adjustment set.
G is the full disease graph. Restriction to the causal subgraph
and to its acyclic core happens here, so no caller can forget it.
Source code in src/causalphylo/backdoor.py
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | |
satisfies_backdoor ¶
Whether adjustment satisfies the backdoor criterion.
G must be a DAG containing both nodes; callers reach this through
find_adjustment_set, which guarantees that.
Source code in src/causalphylo/backdoor.py
mutilated_graph ¶
G with every edge into treatment removed. G is not modified.
confounding_sensitivity ¶
Count near-miss confounders of treatment and outcome.
A near miss is a node that reaches the treatment in the causal DAG and carries some edge to the outcome in the full graph that was not admissible -- a literature association, a shared pathway. Each one is a confounder the graph hints at but does not license adjusting for.
Source code in src/causalphylo/backdoor.py
Search bounds¶
MAX_ADJUSTMENT_SET_SIZE- Largest adjustment set the search will consider. Default
3. MAX_CANDIDATE_POOL- Largest candidate pool the search will draw from. Default
20.
Reaching either bound sets Identification.search_truncated.