Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions src/logic_network_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1588,6 +1588,7 @@ def create_pathway_logic_network(
decomposed_uid_mapping: pd.DataFrame,
reaction_connections: pd.DataFrame,
best_matches: Any,
diagram_bridge_pairs: Optional[Set[Tuple[str, str]]] = None,
) -> PathwayResult:
"""Create a pathway logic network from decomposed UID mappings and reaction connections.

Expand Down Expand Up @@ -1810,6 +1811,40 @@ def create_pathway_logic_network(
"edge_reaction_id": reaction_stid,
})

# Phase 3b (optional): additive diagram bridges. For each diagram-drawn
# (producer, consumer) reaction pair, connect their shared entity by ADDING
# an edge from the producer's output-copy to the consumer's input-copy
# instead of MERGING the two copies (Phase 2). This preserves every node and
# edge — nothing is unified or dropped — while still giving the
# producer -> entity_out -> entity_in -> consumer path. Pairs already merged
# via precedingEvent (same canonical uuid) are skipped. Layout-filtered pairs
# only (cofactor hubs already excluded by the caller). See #39.
if diagram_bridge_pairs:
n_bridges = 0
for a_rid, b_rid in diagram_bridge_pairs:
for p_vr in reactome_to_vr.get(a_rid, []):
p_outputs = set(vr_entities.get(p_vr, ([], [], {}, {}))[1])
for f_vr in reactome_to_vr.get(b_rid, []):
f_inputs = set(vr_entities.get(f_vr, ([], [], {}, {}))[0])
for eid in p_outputs & f_inputs:
src = entity_uuid_registry.get((eid, p_vr, "output"))
tgt = entity_uuid_registry.get((eid, f_vr, "input"))
# Skip if missing or already the same node (already
# connected via a precedingEvent merge).
if not src or not tgt or src == tgt:
continue
pathway_logic_network_data.append({
"source_id": src,
"target_id": tgt,
"pos_neg": "pos",
"and_or": None,
"edge_type": "diagram_bridge",
"stoichiometry": 1,
"edge_reaction_id": None,
})
n_bridges += 1
logger.info(f"Diagram bridges: +{n_bridges} additive edges (no merge)")

# Log UUID registry statistics
unique_uuids = set(entity_uuid_registry.values())
unique_entities = set(key[0] for key in entity_uuid_registry.keys())
Expand Down
31 changes: 24 additions & 7 deletions src/pathway_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,17 +122,34 @@ def generate_pathway_file(
logger.warning(f"Could not cache decomposition results: {e}")
# Continue without caching

# Augment connectivity with curator-drawn diagram flow (product->substrate
# pairs the diagram links but precedingEvent may omit — esp. old pathways).
# Only the connectivity/merge step sees this; the matching layer above
# stays on pure precedingEvent. See reactome/logic-network-generator#39.
from src.diagram_connectivity import augment_reaction_connections
connectivity = augment_reaction_connections(pathway_id, reaction_connections)
# Add curator-drawn diagram connectivity (product->substrate pairs the
# diagram links but precedingEvent may omit). See reactome/logic-network-generator#39.
#
# DEFAULT = additive-bridge mode (LNG_DIAGRAM_BRIDGE=1): the diagram-drawn
# shared-entity connections are added as NEW bridge edges (producer's
# output-copy -> consumer's input-copy) — nothing is merged or lost. Raw
# precedingEvent connectivity still merges its shared entities (the core
# mechanism), but the diagram json NEVER drives a merge. Benchmark-neutral
# vs the legacy merge (curator 83.2%, experimental 73.6%; TP53 +2) while
# preserving every node and edge. Set LNG_DIAGRAM_BRIDGE=0 to fall back to
# the legacy merge-based augmentation; set both LNG_DIAGRAM_BRIDGE=0 and
# LNG_DIAGRAM_CONNECTIVITY=0 to disable diagram connectivity entirely.
from src.diagram_connectivity import (
augment_reaction_connections,
diagram_shared_product_pairs,
)
diagram_bridge_pairs = None
if os.environ.get("LNG_DIAGRAM_BRIDGE", "1") == "1":
connectivity = reaction_connections
diagram_bridge_pairs = diagram_shared_product_pairs(pathway_id)
else:
connectivity = augment_reaction_connections(pathway_id, reaction_connections)

# Generate logic network
logger.info("Creating pathway logic network...")
result = create_pathway_logic_network(
decomposed_uid_mapping, connectivity, best_matches
decomposed_uid_mapping, connectivity, best_matches,
diagram_bridge_pairs=diagram_bridge_pairs,
)

# Save logic network (main output file users need)
Expand Down
Loading