internals.timeline
Timelines: the time vectors of a sim and of each of its modules
They exist so that sim.t and module.t give the current step and date, and a module can step at its own rate.
How a time is read is decided once, from the sim’s start: if it is a date or a year (a bare number from 1800 on), the sim has a calendar, and every bare number given as a time (a stop, when=, the times of ss.schedule and ss.timeseries) is a year; otherwise, a bare time is a time in the sim’s unit from 0. With no start, the stop decides, as long as the unit is years (or not given): ss.Sim(unit='day', stop=3650) runs 3,650 days from 0. A duration given as a time (when=ss.days(30)) is that long after the sim’s start in a sim with a calendar (ss.years(5) is five years in), and with none a time on the sim’s own axis, counted from 0 as sim.t.tvec is (which is the same thing when the start is 0). The sim’s own stop= is a time, read as the start is; its length is dur= (the stop is then the start plus it; given both, the start is the stop minus it).
Used with: agents and compartments; declared and coded modules
Classes
| Name | Description |
|---|---|
| Timeline | Handle time vectors and sequencing (“timelines”) for both simulations and modules. |
| schedule | When something is due: on a calendar cadence (e.g. every 3 months), at a list of times, whenever a function of the date is true, or at every step between a start and a stop (with neither, at every step) |
Timeline
internals.timeline.Timeline(
start=None,
stop=None,
dt=None,
dur=None,
name=None,
init=None,
sim=None,
)Handle time vectors and sequencing (“timelines”) for both simulations and modules.
Each module can have its own time instance, in the case where the time vector is defined by absolute dates, these time vectors are by definition aligned. Otherwise they can be specified using dur objects which express relative times (they can be added to a date to get an absolute time)
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| start | str/int/float/ss.date/ss.Duration |
when the simulation/module starts. For the sim: a date (e.g. ‘2000-01-01’) or a year (a bare number from 1800 on, e.g. 2000) gives it a calendar; any other number, or a duration, is a time in its unit from 0 (default: 2000 for a model in years, else 0). For a module: a time on the sim’s timeline (a bare number as for the sim’s stop; a duration is that long after the sim’s start, in a sim with a calendar) | None |
| stop | str/int/float/ss.date/ss.Duration |
when the simulation/module ends, read as the start is: a date, a bare number (a year if the sim has a calendar, else a time in its unit from 0), or a duration (a time from 0, for a sim with no calendar; ss.years(2030) in a sim of calendar years is the year 2030) (default: a run of 100 days in days, else 50 of the sim’s unit) |
None |
| dur | int/float/ss.Duration |
the length of the run, from its start (a bare number is in years in a sim of calendar years, as a bare stop is, else in the sim’s unit): start=2000, dur=10 is the same as start=2000, stop=2010, and so is stop=2010, dur=10 (any two define the third; all three must agree) |
None |
| dt | int/float/ss.Duration |
the step (a bare number is in the sim’s unit) | None |
| name | str |
if provided, name the Timeline object |
None |
| init | bool |
whether or not to immediately initialize the Timeline object (by default, yes if start and stop are provided; otherwise no) |
None |
| sim | Sim | if provided, initialize the Timeline with this as the parent (i.e. populating missing values) |
None |
The Timeline object, after initialization, has the following time vectors, each representing a different way of representing time:
tvec: ground truth simulation time, either as absolutess.dateinstances, or relativess.Durationinstances, e.g.DateArray([<2021-01-01>, <2021-01-03>, <2021-01-05>, <2021-01-07>])tivec: the vector of time indices (np.arange(len(tvec)))timevec: the “human-friendly” representation oftvec: same astvecif usingss.date, else floats if usingss.Durationyearvec: time represented as floating-point yearsdatevec: time represented asss.dateinstancesrelvec: relative time, in the unit of the sim’s step (dt)
The Timeline object also has the following attributes/methods:
ti(int): the current time point, which is also the current step: steptiruns from time pointtito the next, and its results go attinpts(int): the total number of time points in the timeline, which is also the number of steps (see note below)now()(ss.date/float/str): the current time, time pointti, the start of the current step, based on tvec by default or a different vector if specifiedcalendar(str): ‘dates’, ‘years’, or None (seess.timeline.calendar_of()), andunit, the class of the sim’s unit (e.g.ss.days)dur(ss.Duration): the length of the run, from its start to its stop
Note: the time vectors include both the start and stop endpoints, and a step is taken from each of them, so each time point is a period: a stock at it is the state at its start, and a flow at it is the total over the step that starts there. For example, start=0, stop=1, dt=1 produces two time points ([0, 1]) and takes two steps; the state after the last one is not recorded. Giving the length (dur) is the same as giving the stop (start=2000, dur=1 is the same timeline as start=2000, stop=2001). See the time user guide for the rationale behind the inclusive endpoint.
Examples
t1 = ss.Timeline(start=2000, stop=2020, dt=1.0)
t2 = ss.Timeline(start='2021-01-01', stop='2021-04-04', dt=ss.days(2))
t3 = ss.Timeline(start='2021-01-01', dur=ss.days(90), dt=ss.days(1)) # 90 days from the startAttributes
| Name | Description |
|---|---|
| datevec | Time vector as ss.date objects (derived lazily from tvec/yearvec) |
| dt_year | The timestep size in years |
| is_absolute | Check whether the fundamental simulation unit is absolute |
| npts | The number of time points (inclusive of both endpoints, so one more than the number of steps) |
| ready | Check if all parameters are in place to be initialized |
| relvec | Time since the start of the sim, as numbers in the unit of the sim’s step, dt (e.g. weeks for dt=ss.weeks(1), whatever the sim’s unit); derived lazily |
| timevec | Human-friendly (plotting-friendly) representation of tvec (derived lazily) |
| year | The current time in years |
Methods
| Name | Description |
|---|---|
| date_of | The date of a time point (default: now), as a function of the date in when= (or ss.schedule()) reads it: the time point itself |
| dur_time | A duration given as a time (see to_time()): with a calendar, that long after the sim’s start (or a calendar year, |
| init | Initialize all vectors |
| now | Get the current simulation time: time point ti, the start of the current step, which is when the step |
| reconcile_args | Read the start, stop, and step as given: for the sim (or a timeline on its own), the calendar is decided from the start; a module’s are on the sim’s timeline |
| reconcile_module | A module’s timeline: its start and stop as times on the sim’s (a bare number or a duration as for the sim’s), or the sim’s; or its start plus a length (dur) |
| reconcile_own | The sim’s timeline (or one standing alone): decide the calendar from the start (or, with none, the stop), then read the rest on it; the stop is a time, as the start is, or else the start plus the length (dur); given the stop and the length, the start is the stop minus it |
| to_dict | Return a dictionary of all time vectors |
| to_time | A time (a date, a bare number, or a duration) as the same kind of time as the timeline’s: a date (ss.date) if its |
| update | Update the time parameters, reinitializing the timeline if it was initialized and any changed |
date_of
internals.timeline.Timeline.date_of(now=None)The date of a time point (default: now), as a function of the date in when= (or ss.schedule()) reads it: the time point itself if the times are dates, or the date of the year if they are years (e.g. 2000.5 is 2000-07-02); a sim with no calendar has no dates
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| now | ss.date/ss.Duration |
the time point, one of tvec (default: now()) |
None |
dur_time
internals.timeline.Timeline.dur_time(val, name='time', own_stop=False)A duration given as a time (see to_time()): with a calendar, that long after the sim’s start (or a calendar year, e.g. ss.years(2005)); with none, a point on the timeline’s own axis from 0
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| val | ss.Duration |
the duration | required |
| name | str |
what the time is, for the error message (e.g. ‘until=’) | 'time' |
| own_stop | bool |
whether it is the sim’s own stop, which with a calendar is an error (its length is dur=) |
False |
init
internals.timeline.Timeline.init(sim=None, max_steps=None, force=False)Initialize all vectors
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| sim | ss.Sim |
the sim to take missing values from; if None, the timeline stands alone | None |
| max_steps | int |
the number of steps above which to warn; if None, use ss.options.max_steps |
None |
| force | bool |
whether to initialize again | False |
now
internals.timeline.Timeline.now(key=None)Get the current simulation time: time point ti, the start of the current step, which is when the step happens, what it reads its inputs at, and where its results go (see ss.loop.Loop)
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| key | str |
which type of time to get: “tvec” (default), “time”, “year”, “date”, or “str” | None |
Examples
t = ss.Timeline(start='2021-01-01', stop='2022-02-02', dt='week')
t.ti = 25 # The step from time point 25 to 26
t.now() # Returns <2021-06-25>
t.now('date') # Returns <2021-06-25>
t.now('year') # Returns 2021.479
t.now('str') # Returns '2021-06-25'reconcile_args
internals.timeline.Timeline.reconcile_args(sim=None)Read the start, stop, and step as given: for the sim (or a timeline on its own), the calendar is decided from the start; a module’s are on the sim’s timeline
reconcile_module
internals.timeline.Timeline.reconcile_module(start, stop, dur, dt, sim)A module’s timeline: its start and stop as times on the sim’s (a bare number or a duration as for the sim’s), or the sim’s; or its start plus a length (dur)
reconcile_own
internals.timeline.Timeline.reconcile_own(start, stop, dur, dt, sim=None)The sim’s timeline (or one standing alone): decide the calendar from the start (or, with none, the stop), then read the rest on it; the stop is a time, as the start is, or else the start plus the length (dur); given the stop and the length, the start is the stop minus it
to_dict
internals.timeline.Timeline.to_dict()Return a dictionary of all time vectors
to_time
internals.timeline.Timeline.to_time(val, name='time')A time (a date, a bare number, or a duration) as the same kind of time as the timeline’s: a date (ss.date) if its times are dates, else a duration (ss.years with a calendar of years, else the sim’s unit)
A bare number is a calendar year if the timeline has a calendar, else a time in its unit from 0. A duration is that long after the sim’s start if the timeline has a calendar (ss.years(5) in a sim from 2000 is 2005, and ss.months(3) in one from ‘2020-01-15’ is ‘2020-04-15’), unless it is a calendar year (ss.years(2005), from 1800 on, as the tvec of a sim of calendar years holds); with no calendar, it is a time on the timeline’s own axis, counted from 0, as its start and tvec are (so ss.days(10) is day 10, which is 10 days in when the start is 0). Its unit should then be the sim’s or the module’s (else a warning).
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| val | str/float/ss.date/ss.Duration |
the time | required |
| name | str |
what the time is, for the error message (e.g. ‘when=’) | 'time' |
update
internals.timeline.Timeline.update(**kwargs)Update the time parameters, reinitializing the timeline if it was initialized and any changed
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| kwargs | the time parameters to change (start, stop, dt, dur); those not given (or None) are kept, except that a new stop replaces the length (dur), and a new length the stop |
schedule
internals.timeline.schedule(
*args,
at=None,
every=None,
start=None,
stop=None,
**kwargs,
)When something is due: on a calendar cadence (e.g. every 3 months), at a list of times, whenever a function of the date is true, or at every step between a start and a stop (with neither, at every step)
Make one as an attribute (or parameter) of a module, which links it to the module’s timeline when the sim is initialized; then sched.due(), in the module’s step(), is how many of its times fall in this step (from now up to the next step’s now): usually 0 or 1, so if sched.due(): works. A module can have as many as it needs.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| at | date / dur / list / func |
optionally (by position or keyword): the times (a time or a list of them, e.g. ['2021-06-01', '2023-06-01'], or years, or durations, as ss.days(10), which is 10 days after the start of the sim, not every 10 days), or a function of the date of the start of each step (its now), true when it is due (e.g. lambda now: now.month == 1); told apart by type. A single duration by position is an error, since it could be either: give every= or at= |
None |
| every | dur |
how often; whole months and years are calendar offsets, so every month is the same day of the month | None |
| start | date / dur |
the first time, as a date, a year, or a duration after the start of the sim (default: the start of the timeline), for every |
None |
| stop | date / dur |
no times after this, likewise (default: the end of the timeline) | None |
With only start and/or stop, it is due at every step between them (a window): as the when= of an ss.Event, routine delivery between those times. With no arguments, it is due at every step, so code with an optional every=, start=, and stop= can always make one. A duration given as a time is that long after the sim’s start in a sim with a calendar, and with none a time from 0 (the same when the start is 0).
Examples
class Clinic(ss.Module):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.poll = ss.schedule(every=ss.months(3), start='2020-04-01') # Every 3 months from April 2020
self.checkup = ss.schedule(every=ss.years(1), start=ss.months(6)) # Yearly, the first 6 months after the sim's start
self.campaigns = ss.schedule(['2021-06-01', '2023-06-01'])
self.report = ss.schedule(lambda now: now.month == 1 and now.day == 1) # New Year's Day
self.weekly = ss.schedule(every=ss.weeks(1)) # How often is always every=
self.window = ss.schedule(start='2025-01-01', stop='2026-01-01') # Every step in 2025
def step(self):
if self.poll.due():
...Attributes
| Name | Description |
|---|---|
| steps | The steps (their indices, ti) in which it is due |
Methods
| Name | Description |
|---|---|
| due | The number of times due in this step (or step ti), usually 0 or 1 |
| init | Link to a timeline (of a module or sim, or a ss.Timeline itself), and work out the number due in each of its steps |
due
internals.timeline.schedule.due(ti=None)The number of times due in this step (or step ti), usually 0 or 1
init
internals.timeline.schedule.init(obj)Link to a timeline (of a module or sim, or a ss.Timeline itself), and work out the number due in each of its steps
Functions
| Name | Description |
|---|---|
| calendar_of | Whether times are on a calendar, decided from the start (or, with no start, from the stop): ‘dates’ for a date |
| how_bare | How a bare number is read as a time on a timeline, for error messages |
| of_date | A function of the date (in when=, or ss.schedule()), called on the date of a time point of timeline t (default: now; see Timeline.date_of()) |
| same | Whether two time arguments are the same, for update() |
calendar_of
internals.timeline.calendar_of(start, stop=None, unit=None)Whether times are on a calendar, decided from the start (or, with no start, from the stop): ‘dates’ for a date (e.g. ‘2020-01-01’), ‘years’ for a bare year (a number from 1800 on, e.g. 2000), else None (a time from 0 in the sim’s unit)
With no start, a bare stop from 1800 on is a year only if the unit is years (or not given): with another, it is a time in that unit from 0 (unit='day', stop=3650 is 3,650 days), since the unit is explicit and the stop is not.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| start | str/float/ss.date/ss.Duration |
the start, as given | required |
| stop | str/float/ss.date/ss.Duration |
the stop, as given, read only if there is no start | None |
| unit | str |
the unit given to the sim (unit=), if any |
None |
how_bare
internals.timeline.how_bare(t)How a bare number is read as a time on a timeline, for error messages
of_date
internals.timeline.of_date(fn, t, now=None)A function of the date (in when=, or ss.schedule()), called on the date of a time point of timeline t (default: now; see Timeline.date_of())
same
internals.timeline.same(a, b)Whether two time arguments are the same, for update()