CoVariations
Sometimes parameters must vary together — for example, a rule's base value and its max response[1]. The CoVariation type handles this. It wraps a vector of ElementaryVariations that must all be the same type, giving two forms: CoVariation{DiscreteVariation} and CoVariation{DistributedVariation}.
CoVariation{DiscreteVariation}
Each DiscreteVariation must have the same number of values — the CoVariation constructor rejects mismatched lengths outright, whichever sampling method you use later. Values sharing an index are used together; how you link them is otherwise unrestricted.
base_xml_path = configPath("default", "custom:sample")
ev1 = DiscreteVariation(base_xml_path, [1, 2, 3]) # vary the `sample` custom data for cell type default
max_xml_path = rulePath("default", "custom:sample", "increasing_signals", "max_response") # the max response of the rule increasing sample (must be bigger than the base response above)
ev2 = DiscreteVariation(max_xml_path, [2, 3, 4])
covariation = CoVariation(ev1, ev2) # CoVariation([ev1, ev2]) also worksYou need not build the ElementaryVariations separately; pass (xml_path, values) tuples directly:
# have the phase durations vary and compensate for each other
phase_0_xml_path = configPath("default", "cycle", "duration", 0)
phase_1_xml_path = configPath("default", "cycle", "duration", 1)
phase_0_durations = [300.0, 400.0]
phase_1_durations = [200.0, 100.0] # the (mean) duration through these two phases is 500 min
# input any number of tuples (xml_path, values)
covariation = CoVariation((phase_0_xml_path, phase_0_durations), (phase_1_xml_path, phase_1_durations))You can also name the co-variation itself:
covariation = CoVariation((phase_0_xml_path, phase_0_durations),
(phase_1_xml_path, phase_1_durations);
name="Conserved cycle time")If no name is provided, a default is generated by joining the names of the member variations with " AND ".
CoVariation{DistributedVariation}
A shared CDF value $x \in [0, 1]$ is converted independently for each distribution — in the joint probability space, this restricts sampling to the line connecting $\mathbf{0}$ to $\mathbf{1}$. To let parameters vary inversely, DistributedVariation accepts flip::Bool: with dv.flip=true, a request for CDF $x$ returns the value at CDF $1 - x$.
using PhysiCellModelManager
timing_1_path = configPath("user_parameters", "event_1_time")
timing_2_path = configPath("user_parameters", "event_2_time")
dv1 = UniformDistributedVariation(timing_1_path, 100.0, 200.0)
dv2 = UniformDistributedVariation(timing_2_path, 100.0, 200.0; flip=true)
covariation = CoVariation(dv1, dv2)
cdf = 0.1
PhysiCellModelManager.ModelManager.variationValues.(covariation.variations, cdf) # ModelManager.jl internal for getting values for an ElementaryVariation
# output
2-element Vector{Vector{Float64}}:
[110.0]
[190.0]As with the discrete case, you can pass (xml_path, distribution) tuples directly instead of building ElementaryVariations — though this syntax cannot flip a DistributedVariation.
apop_xml_path = configPath("default", "apoptosis", "death_rate")
apop_dist = Uniform(0, 0.001)
cycle_entry_path = configPath("default", "cycle", "rate", 0)
cycle_dist = Uniform(0.00001, 0.0001)
covariation = CoVariation((apop_xml_path, apop_dist), (cycle_entry_path, cycle_dist))As with the discrete case, this constructor also accepts an optional name keyword argument.
- 1PhysiCell enforces an ordering between base and max response: for increasing signals, base ≤ max; for decreasing signals, base ≥ max.