molfoundry.MultiPhaseStochsim#

class molfoundry.MultiPhaseStochsim(*, labelSettings=None, retainHistory=True, onStep=None, seed=42)[source]#

Bases: TSObject

Exact multiphase (multi-compartment) stochastic simulation.

n phases each run the rule-based Gillespie SSA with lazy network expansion; the whole system is evolved as one combined continuous-time Markov chain by a single shared simulator (one clock, one RNG, one global propensity) – the exact Direct-Method realization.

Stage A: phases only, no interphase channels yet. A phase may still exchange with the implicit outside via its own inputRate/outputRate flows, and a single channel-free phase reproduces Stochsim for the same seed. All phases share one LabelSettings so species identity is comparable across phases by canonical key.

Create a multiphase stochastic simulation.

retainHistory and onStep have the same meaning as for Stochsim: with retainHistory=False the engine holds only O(species) state and the full trajectory is streamed to a history file under ./out so print() can still rebuild the playback (while trajectory() / series() / times(), which need the in-memory log, are unavailable). onStep fires once per step with a StepInfo.

Parameters:
setOnStep(onStep)[source]#

Set a per-step callback, or None to clear it.

See Stochsim.setOnStep(). The callback receives a StepInfo once for the start step and then for every step across the whole (shared-clock) system.

Parameters:

onStep (Callable[[StepInfo], Any] | None)

Return type:

None

addPhase(name, *, graphDatabase, expandStrategy, volume=1.0, initialState=None, reactionRate=None, inputRate=None, outputRate=None, labelSettings=None)[source]#

Add a phase (compartment) with its own chemistry, volume, and rates.

graphDatabase, expandStrategy, and the rate arguments have the same meaning as for Stochsim; volume is stored for later partition channels.

labelSettings overrides the constructor’s LabelSettings for this phase only. Species identity stays comparable across phases (they are matched by the graph’s intrinsic canonical key), so, e.g., a wildcard-free phase can use cheap string/isomorphism matching while a phase with _X-style term rules uses term/specialisation.

Parameters:
Return type:

Phase

addChannel(*, source, target, rate, species=None, select=None)[source]#

Add a constant first-order transport channel source -> target.

Selectivity (which species may cross) is one of: species (a single graph), select (a predicate Graph -> bool or an iterable of graphs), or neither (all species). rate is the per-molecule transfer rate constant (the engine applies mass action, rate * count(species in source), on top), either a number or a callback (Graph) -> float | (float, bool) re-evaluated each step for saturable / gated / state-dependent transport. Bidirectional exchange is two channels (see addPartition for the thermodynamically-consistent pair).

Parameters:
Return type:

Channel

addCoupledChannel(*, reactants, products, rate)[source]#

Add a coupled cross-phase reaction (symport / antiport / reactive transport).

reactants and products are lists of (species_graph, phase) pairs (phase a Phase or index). Mass action requires all reactants present, so e.g. a symport fires only when every co-transported species is available. rate is a constant or a no-argument callback () -> float | (float, bool). All named species must be representable in their phases (in the graphDatabase or derivable there).

Parameters:
Return type:

Channel

addPartition(*, source, target, Kd, rate, species=None, select=None)[source]#

Add a thermodynamically-consistent partition (a bidirectional pair).

Kd is the equilibrium distribution coefficient [target]/[source]; rate is the forward (source -> target) per-molecule rate constant. The backward constant is derived to enforce detailed balance across the (possibly unequal) phase volumes: k_f/k_b = Kd * (V_target/V_source), so the pair on its own relaxes to [target]/[source] = Kd. Selectivity is specified as for addChannel(). Returns (forward, backward).

Parameters:
Return type:

tuple[Channel, Channel]

setDrawTime(drawTime)[source]#

Set the global waiting-time strategy; see Stochsim.setDrawTime().

Parameters:

drawTime (Callable[[float, Callable[[], float]], float] | None)

Return type:

None

simulate(time=None, iterations=None, advanceToEndTime=False)[source]#

Advance the whole system up to a time and/or iteration bound.

Both bounds are relative to the current state, so repeated calls continue; with neither bound the system runs until a global deadlock.

With a time bound, advanceToEndTime parks the shared clock at exactly that time when no reaction fires before it (the drawn event overshot, or the whole system is momentarily dead), so a subsequent segment re-evaluates time-dependent rates there (reviving a dead system) or a scheduled transfer() lands at exactly that time. Off by default.

Parameters:
  • time (float | None)

  • iterations (int | None)

  • advanceToEndTime (bool)

Return type:

None

transfer(source, target, *, species=None, fraction=None, amount=None)[source]#

Discrete scheduled transfer between two phases, applied at the current time.

This is an operator step between simulate() segments – serial passage / dilution, pipetting an aliquot, decanting a layer, or a deterministic spike-in – not an intrinsic reaction, so it does not advance the iteration count. It is applied atomically (one injection) and the target phase’s network is expanded around any species new to it, so the transferred molecules react and flow onward on subsequent steps. Provide exactly one of:

  • fraction – move a binomially-sampled aliquot (each molecule crosses independently with probability fraction, drawn on the shared RNG). With species=None every species currently present in source is aliquoted (a whole-compartment dilution); with a species graph, only that one.

  • amount – move exactly that many molecules of a specific species (a deterministic spike-in / decant); raises if fewer are present.

Returns the total number of molecules moved (source and target are a Phase or an index).

Parameters:
Return type:

int

property phases: List[Phase]#
property iteration: int#
property time: float#
state(phase, graph)[source]#

Current molecule count of graph in phase (a Phase or index).

Parameters:
Return type:

int

concentration(phase, graph)[source]#

Current concentration (count / volume) of graph in phase.

Parameters:
Return type:

float

total(graph)[source]#

Current total count of graph summed across all phases.

Parameters:

graph (Graph)

Return type:

int

times()[source]#

The time stamp of each recorded step (shared across all phases).

Return type:

List[float]

totalSeries(graph)[source]#

Per-step total count of graph across all phases, aligned with times.

Parameters:

graph (Graph)

Return type:

List[int]

trajectory()[source]#

Full event-by-event trajectory across all phases.

Return type:

Trajectory

series(phase, graph)[source]#

Per-step count series of graph in phase, aligned with times.

Parameters:
Return type:

List[int]

print(printer=None, *, name=None, dark='dynamic')[source]#

Write an interactive HTML playback of this multiphase run to the summary folder.

Produces one standalone, seekable page (<name>.html next to summary.html) with one box per phase (name at the top-left), the final per-phase derivation graphs as oval-framed molecule depictions with live counts below them, dotted bent arrows for the inter-phase channels, and input/output flows drawn to the outside of each box. Nodes and hyperedges are revealed at the step they were first expanded; play / pause / stop and a speed control step through the whole simulation.

printer is an optional GraphPrinter – exactly as for DG.print() – threaded to every molecule depiction (across all phases) so its drawMode / collapseHydrogens settings control how the molecules are drawn. name sets the filename (default multiphase). Flushed at process exit; returns the target filename.

With retainHistory=False the trajectory is rebuilt from the streamed ./out history file rather than the (absent) in-memory log.

Parameters:
Return type:

str

class Phase(parent, index, ref)[source]#

Bases: object

A single phase (compartment). Obtained from addPhase().

Parameters:
index#

Index of this phase within its owning simulation.

property name: str#
property volume: float#
property dg: DG#

The derivation graph underlying this phase’s network.

addInitial(graph, count)[source]#
Parameters:
Return type:

None

setReactionRate(rate)[source]#

See Stochsim.setReactionRate() (scoped to this phase).

Parameters:

rate (float | int | Tuple[float, bool] | Callable[[...], Any])

Return type:

None

setInputRate(rate)[source]#

See Stochsim.setInputRate() (this phase’s flow to the outside).

Parameters:

rate (float | int | Tuple[float, bool] | Callable[[...], Any])

Return type:

None

setOutputRate(rate)[source]#

See Stochsim.setOutputRate() (this phase’s flow to the outside).

Parameters:

rate (float | int | Tuple[float, bool] | Callable[[...], Any])

Return type:

None

state(graph)[source]#

Current molecule count of graph in this phase.

Parameters:

graph (Graph)

Return type:

int

concentration(graph)[source]#

Current concentration (count / volume) of graph in this phase.

Parameters:

graph (Graph)

Return type:

float

series(graph)[source]#

Per-step count series of graph in this phase.

Parameters:

graph (Graph)

Return type:

List[int]

class Channel(parent, ref)[source]#

Bases: object

A transport channel. Obtained from addChannel().

Parameters:
property index: int#
property rate: float | None#

The constant rate, or None for a dynamic (callback) channel.

class Trajectory(times, columnPhases, columnVertexIds, counts)[source]#

Bases: object

Parameters:
times#

Time stamp of each recorded step.

columnPhases#

Phase index of each column of counts.

columnVertexIds#

DG vertex index (within its phase) of each column of counts.

counts#

counts[step][column] molecule counts.

series(phaseIndex, vertexId)[source]#
Parameters:
  • phaseIndex (int)

  • vertexId (int)

Return type:

List[int]