loop
loop
Parent class for the integration loop.
Classes
Name | Description |
---|---|
Loop | Define the integration loop |
Loop
self, sim) loop.Loop(
Define the integration loop
The Loop handles the order in which each function is called in the sim. The order is defined in Loop.collect_funcs()
, which searches through the sim and collects all methods to call, in order, in the integration loop.
Each type of module is called at a different time. Within each module type, they are called in the order listed. The default loop order is:
1. sim: start_step() # Initialize the sim, including plotting progress
2. all modules: start_step() # Initialize the modules, including the random number distribution
3. sim.modules: step() # Run any custom modules
4. sim.demographics: step() # Update the demographics, including adding new agents
5. sim.diseases: step_state() # Update the disease states, e.g. exposed -> infected
6. sim.connectors: step() # Run the connectors
7. sim.networks: step() # Run the networks, including adding/removing edges
8. sim.interventions: step() # Run the interventions
9. sim.diseases: step() # Run the diseases, including transmission
10. people: step_die() # Figure out who died on this timestep
11. people: update_results() # Update basic state results
12. all modules: update_results() # Update any results
13. sim.analyzers: step() # Run the analyzers
14. all modules: finish_step() # Do any final tidying
15. people: finish_step() # Clean up dead agents
16. sim: finish_step() # Increment the timestep
Methods
Name | Description |
---|---|
collect_abs_tvecs | Collect numerical time arrays for each module |
collect_funcs | Collect all the callable functions (methods) that comprise the step |
init | Parse the sim into the integration plan |
insert | Insert a function into the loop plan at the specified location. |
make_plan | Combine the module ordering and the time vectors into the integration plan |
plot | Plot a diagram of all the events |
plot_cpu | Plot the CPU time spent on each event; visualization of Loop.cpu_df. |
plot_step_order | Plot the order of the module steps across timesteps – useful for debugging |
run | Actually run the integration loop; usually called by sim.run() |
run_one_step | Take a single step, i.e. call a single function; only used for debugging purposes. |
shrink | Shrink the size of the loop for saving to disk |
store_time | Store the current time in as high resolution as possible |
to_df | Return a user-friendly version of the plan, omitting object columns |
collect_abs_tvecs
loop.Loop.collect_abs_tvecs()
Collect numerical time arrays for each module
collect_funcs
loop.Loop.collect_funcs()
Collect all the callable functions (methods) that comprise the step
init
loop.Loop.init()
Parse the sim into the integration plan
insert
loop.Loop.insert(
func,=None,
label=None,
match_fn=False,
before=True,
verbose=True,
die )
Insert a function into the loop plan at the specified location.
The loop plan is a dataframe with columns including time (e.g. date('2025-05-05')
), label (e.g. 'randomnet.step'
), module (’randomnet'
), and function name ('step'
). By default, this method will match the conditions in the plan based on the criteria specified.
This functionality is similar to an analyzer or an intervention, but gives additional flexibility since can be inserted at (almost) any point in a sim.
Note: the loop must be initialized (sim.init()
) before you can call this.
Parameters
Name | Type | Description | Default |
---|---|---|---|
func | func |
the function to insert; must take a single argument, sim |
required |
label | str | the label (module.name) of the function to match; see sim.loop.plan.label.unique() for choices |
None |
match_fn | func |
if supplied, use this function to perform the matching on the plan dataframe, returning a boolean array or list of indices of matching rows (see example below) | None |
before | bool | if true, insert the function before rather than after the match | False |
die | bool | whether to raise an exception if no matches found | True |
Examples:
# Simple label matching with analyzer-like functionality
def check_pop_size(sim):
print(f'Population size is {len(sim.people)}')
sim = ss.Sim(diseases='sir', networks='random', demographics=True)
sim.init()
sim.loop.insert(check_pop_size, label='people.finish_step')
sim.run()
# Function-based matching with intervention-like functionality
def match_fn(plan):
past_2010 = plan.time > ss.date(2010)
is_step = (plan.label == 'sir.step') | (plan.label == 'randomnet.step')
return past_2010 * is_step
def update_betas(sim):
if not sim.metadata.get('updated'):
print(f'Updating beta values on {sim.now}')
sim.diseases.sis.beta = 0.1
sim.networks.randomnet.edges.beta[:] = 0.5
sim.metadata.updated = True
return
sim = ss.Sim(diseases='sis', networks='random')
sim.init()
sim.loop.insert(update_betas, match_fn=match_fn, before=True)
sim.run()
make_plan
loop.Loop.make_plan()
Combine the module ordering and the time vectors into the integration plan
plot
loop.Loop.plot(=False,
simplify=100,
max_len=None,
fig_kw=None,
plot_kw=None,
scatter_kw )
Plot a diagram of all the events
Parameters
Name | Type | Description | Default |
---|---|---|---|
simplify | bool | if True, skip update_results and finish_step events, which are automatically applied | False |
max_len | int | maximum number of entries to plot | 100 |
fig_kw | dict | passed to plt.figure() |
None |
plot_kw | dict | passed to plt.plot() |
None |
scatter_kw | dict | passed to plt.scatter() |
None |
plot_cpu
=True, max_entries=10, fig_kw=None, bar_kw=None) loop.Loop.plot_cpu(bytime
Plot the CPU time spent on each event; visualization of Loop.cpu_df.
Parameters
Name | Type | Description | Default |
---|---|---|---|
bytime | bool | if True, order events by total time rather than actual order | True |
fig_kw | dict | passed to plt.figure() |
None |
bar_kw | dict | passed to plt.bar() |
None |
plot_step_order
loop.Loop.plot_step_order(='default',
which=500,
max_len=None,
plot_kw=None,
scatter_kw=None,
fig_kw=None,
legend_kw )
Plot the order of the module steps across timesteps – useful for debugging when using different time units.
Note: generates a lot of data, best to debug with a small number of timesteps first!
Parameters
Name | Type | Description | Default |
---|---|---|---|
which | dict | columns and values to filter to (default: {‘func_name’:‘step’}; if None, do not filter) | 'default' |
max_len | int | maximum number of entries to plot | 500 |
plot_kw | dict | passed to plt.plot() |
None |
scatter_kw | dict | passed to plt.scatter() |
None |
fig_kw | dict | passed to plt.figure() |
None |
legend_kw | dict | passed to plt.legend() |
None |
Example:
sis = ss.SIS(dt=0.1)
net = ss.RandomNet(dt=0.5)
births = ss.Births(dt=1)
sim = ss.Sim(dt=0.1, dur=5, diseases=sis, networks=net, demographics=births)
sim.init()
sim.loop.plot_step_order()
run
=None, verbose=None) loop.Loop.run(until
Actually run the integration loop; usually called by sim.run()
run_one_step
loop.Loop.run_one_step()
Take a single step, i.e. call a single function; only used for debugging purposes.
Compare sim.run_one_step(), which runs a full timestep (which involves multiple function calls).
shrink
loop.Loop.shrink()
Shrink the size of the loop for saving to disk
store_time
loop.Loop.store_time()
Store the current time in as high resolution as possible
to_df
loop.Loop.to_df()
Return a user-friendly version of the plan, omitting object columns