Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
111ec1e
Sbachmei/mic 6379/attribute pipelines (#646)
stevebachmeier Sep 16, 2025
e0d18a7
Sbachmei/mic 6380/convert pipelines to attribute pipelines (#647)
stevebachmeier Sep 18, 2025
33f9735
leverage get_attribute instead of get_value in results manager (#651)
stevebachmeier Sep 18, 2025
1390b25
Sbachmei/mic 6411/split interfaces into own modules (#652)
stevebachmeier Sep 19, 2025
4e0f97a
support passing column names as an AttributePipeline source (#653)
stevebachmeier Sep 22, 2025
5e61d51
auto-register attribute pipelines from columns_created (#655)
stevebachmeier Sep 22, 2025
d902a77
Sbachmei/mic 6384/convert state table columns to attribute pipelines …
stevebachmeier Sep 23, 2025
b4d375e
implement AttributePipeline.is_simple property (#658)
stevebachmeier Sep 23, 2025
a45e388
break reliance of individual clocks on population views (#662)
stevebachmeier Oct 15, 2025
d964f01
utilize attribute pipelines in get_population (#664)
stevebachmeier Oct 20, 2025
874df25
Sbachmei/mic 6386/handle column ordering and name collisions (#665)
stevebachmeier Oct 23, 2025
0b3e7c1
Sbachmei/mic 6387/implement attribute pipeline metadata (#670)
stevebachmeier Oct 29, 2025
fe13ca9
require attributes be requested from PopulationView.get() (#671)
stevebachmeier Oct 30, 2025
d5f7a75
remove PopulationView subviews (#672)
stevebachmeier Oct 30, 2025
d4f2026
remove untracked feature (#673)
stevebachmeier Nov 4, 2025
1d67322
Sbachmei/mic 6562/remove columns required property throughout (#674)
stevebachmeier Nov 4, 2025
82b9bba
Restrict writing to private columns (#675)
stevebachmeier Nov 13, 2025
1e62c16
implement PopulationView.get_private_columns() (#678)
stevebachmeier Nov 13, 2025
306e60f
allow a string to be passed to get_private_columns (#680)
stevebachmeier Nov 14, 2025
825b38f
Sbachmei/mic 6612/allow get population specific cols (#682)
stevebachmeier Nov 18, 2025
cf6de86
only get draws if non-zero and non-one probability (#683)
stevebachmeier Nov 18, 2025
39d324f
Sbachmei/mic 6609/add pop view get index and improve query tests (#684)
stevebachmeier Nov 20, 2025
3085c31
better handle column arg types (#685)
stevebachmeier Nov 20, 2025
b79c28c
Sbachmei/mic 6636/implement attribute squeezing (#688)
stevebachmeier Nov 25, 2025
9e05063
Refactor organization of pop manager tests (#690)
patricktnast Nov 26, 2025
1aa2829
parse query strings for required columns (#691)
stevebachmeier Dec 1, 2025
9c70b35
handle untracking queries (#689)
stevebachmeier Dec 2, 2025
d3b8002
handle multiindex columns when querying (#692)
stevebachmeier Dec 2, 2025
011dfc5
replace requires_{columns,values} with requires_attributes (#693)
stevebachmeier Dec 4, 2025
115a868
ensure union_post_processor always returns a Series or DataFrame (#696)
rmudambi Dec 8, 2025
641d1c3
fix mypy error in setup.py (#697)
rmudambi Dec 8, 2025
d2180c9
Sbachmei/mic 6391/update results system exclude untracked (#695)
stevebachmeier Dec 8, 2025
ac4cc39
Sbachmei/bugfix handle tracking query columns (#698)
stevebachmeier Dec 10, 2025
e9d0713
separate get_attribute calls that return a Series vs a DataFrame (#699)
rmudambi Dec 12, 2025
c1805a0
update resources (#700)
stevebachmeier Dec 15, 2025
7bc53e6
reduce number of pop view query tests (#703)
stevebachmeier Dec 16, 2025
01ba114
stop returning AttributePipelines when registering them (#704)
stevebachmeier Dec 17, 2025
a0168c4
create logger property on Component for better type-checking (#705)
rmudambi Dec 18, 2025
b5de247
coerce to dataframe in get_attribute_frame (#707)
stevebachmeier Dec 18, 2025
3ed47fe
get_attributes with skip_post_processor (#706)
stevebachmeier Dec 18, 2025
7bc0111
Sbachmei/mic 6631/support attributes as source and modifier (#708)
stevebachmeier Dec 19, 2025
20241fa
TypeSafe LookupTable PR#1 (#709)
rmudambi Dec 26, 2025
c51f0aa
TypeSafe LookupTable PR#2 (#710)
rmudambi Dec 26, 2025
80929d5
drop support for deprecated manner of specifying resources (#711)
rmudambi Dec 26, 2025
5cd5656
require component to be passed in when creating resources (#712)
rmudambi Dec 26, 2025
a80db49
register LookupTables as Resources (#713)
rmudambi Dec 26, 2025
92ae94a
fix mypy errors in disease model (#714)
rmudambi Dec 29, 2025
0108701
properly set pipeline source dependencies (#715)
rmudambi Dec 29, 2025
5a3cc25
Rmudambi/mic 6706/warn unused lookup tables (#716)
rmudambi Dec 30, 2025
284ca3f
Sbachmei/mic 6577/clean up interface (#717)
stevebachmeier Dec 31, 2025
3ed2775
implement implicit component inference in Resources (#718)
rmudambi Jan 3, 2026
def3969
clean up ComponentManager (#719)
rmudambi Jan 3, 2026
0d8b115
type hint get_component_by_type using TypeVar (#721)
rmudambi Jan 6, 2026
2af6d92
remove check following appropriate VPH state machine initialization u…
rmudambi Jan 7, 2026
7dfc56c
Sbachmei/mic 6606/multiple initializers (#724)
stevebachmeier Jan 8, 2026
500fd50
streamline how to get all population columns from interactive ctx (#726)
stevebachmeier Jan 9, 2026
e21e0cc
constrain attribute producer and modifier registration to setup (#725)
stevebachmeier Jan 9, 2026
feef5c5
conflict resolution formatting
stevebachmeier Jan 12, 2026
7610017
fix issues after merge conflict resolution (#727)
stevebachmeier Jan 12, 2026
2161879
change 'alive' string column to 'is_alive' boolean column (#728)
stevebachmeier Jan 13, 2026
e84748a
change default behavior of allow_self_transitions to True (#730)
rmudambi Jan 21, 2026
7e00e2b
Sbachmei/mic 6397/documentation names (#732)
stevebachmeier Jan 21, 2026
ad5e008
Sbachmei/mic 6765/documentation api (#733)
stevebachmeier Jan 23, 2026
6c8fa95
Sbachmei/mic 6769/documentation concept (#734)
stevebachmeier Jan 27, 2026
f161a78
Sbachmei/split remaining managers and interfaces (#736)
stevebachmeier Jan 27, 2026
6317668
Changelog (#739)
stevebachmeier Feb 6, 2026
7b9d19e
Re-order PopulationManager methods (#743)
stevebachmeier Feb 12, 2026
9cbc876
Disallow tracked filtering on initialization or pop creation (#744)
stevebachmeier Feb 13, 2026
f76183b
Remove support for population view default queries (#746)
stevebachmeier Feb 17, 2026
c88f46a
squash lookup table types (#745)
rmudambi Feb 19, 2026
1921ff3
Remove InitializerComponentSet (#747)
stevebachmeier Feb 19, 2026
76e2585
Albrja/mic 6187/update python versions (#740)
albrja Feb 19, 2026
6917e73
Sbachmei/raise if registering duplicate initializer (#748)
stevebachmeier Feb 19, 2026
70aa87c
Sbachmei/change initializer names throughout (#749)
stevebachmeier Feb 19, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.11"
python-version: "3.13"
- name: Install dependencies
run: |
python --version
Expand Down
2 changes: 1 addition & 1 deletion .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ sphinx:
build:
os: ubuntu-22.04
tools:
python: "3.11"
python: "3.13"
python:
install:
# This runs pip install .[docs] from the project root.
Expand Down
82 changes: 82 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,85 @@
**4.0.0 - TBD TBD TBD**
-----------------------

This release introduces a major refactor of the population management system as well
as various other miscellaneous changes.

Breaking changes
----------------

Population management system refactor
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- Interactive context: 'get_population()' will now error if requesting an attribute that doesn't exist.
- Population views: Replace subviews and 'get()' method with 'get_attributes()',
'get_attribute_frame()', and 'get_private_columns()'.

- You must now explicitly request which attributes you want to retrieve.
- Write access (via the 'update()' method) is now restricted to private columns
created by the component the view is attached to.

- Population views: Remove support for population view default queries.
- Population interface: Replace the 'tracked' column and corresponding auto-filter
logic with a new 'register_tracked_query()' method and 'include_untracked' argument
when getting attributes or private columns from a population view.
- Population interface: Require explicit initializer method registration instead
of inferring from methods named 'on_initialize_simulants()'. Supports multiple
initializer methods per component.

- Remove columns_created, columns_required, and initialization_requirements properties throughout.
- Changed the names of all initializer methods (no longer 'on_initialize_simulants').

- Population manager: 'get_population()' now requires an explicit attribute request ("all" is allowed).
- Stop returning AttributePipelines (previously Pipelines) when registering them.

Miscellaneous
~~~~~~~~~~~~~

- Split managers and their corresponding interfaces into separate modules.
- Replace 'requires_columns' and 'requires_values' arguments with 'requires_attributes' throughout.
- Replace 'dependencies' arguments with 'required_resources' throughout.
- Change default behavior of state machine 'allow_self_transition' to True.

Major changes
-------------

- Replace all Pipelines with AttributePipelines throughout.
- Support attribute names as source and/or modifiers to AttributePipelines.
- Add support for python 3.12 and 3.13

Other changes
-------------

Population management system refactor
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- InteractiveContext: Allow specific column request to 'get_population()'.
- InteractiveContext: Implement new 'get_columns()' method to get all attribute names.
- Population views: Implement new 'get_filtered_index()' method.
- Stop using population views inappropriately when using individualized clocks.
- Implement 'skip_post_processor' argument to population view 'get_attributes()'
and population manager 'get_population()' methods.
- Ensure Pipeline 'union_post_processor' always returns a Series or DataFrame.
- Change 'alive' string column to 'is_alive' boolean column in disease model example and various tests.
- Make Mortality a sub-component of BasePopulation component in disease model example.
- Update documentation.

Miscellaneous
~~~~~~~~~~~~~

- LookupTables: Improve type hinting.
- LookupTables: Register tables as resources.
- LookupTables: Warn if unused tables are registered.
- Properly set Pipeline source dependencies.
- Infer component when creating a Resource.
- Clean up Resource registration.
- Clean up ComponentManager.
- Only get random draws for non-0 and non-1 probabilities when calling 'filter_for_probability()'.
- Fix mypy error in setup.py.
- Fix mypy errors in disease model example.
- Create a Component.logger property for better type-checking.
- Removed unnecessary InitializerComponentSet class.

**3.6.6 - 01/06/26**

- Fail deployment if changelog date is not current date
Expand Down
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Vivarium
Vivarium is a simulation framework written using standard scientific Python
tools.

**Vivarium requires Python 3.8-3.11 to run**
**Vivarium requires Python 3.10-3.13 to run**

You can install ``vivarium`` from PyPI with pip:

Expand All @@ -31,7 +31,7 @@ or build it from source with

``> cd vivarium``

``> conda create -n ENVIRONMENT_NAME python=3.11``
``> conda create -n ENVIRONMENT_NAME python=3.12``

``> pip install -e .[dev]``

Expand Down
9 changes: 8 additions & 1 deletion docs/nitpick-exceptions
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,13 @@ py:exc ResultsConfigurationError
py:exc vivarium.framework.results.exceptions.ResultsConfigurationError
py:class vivarium.framework.plugins.M
py:class vivarium.framework.plugins.I
py:class vivarium.framework.utilities.T
py:class vivarium.framework.utilities.TimeValue
py:class T
py:class vivarium.framework.components.manager.T
py:class vivarium.framework.components.manager.C

# layered_config_tree
py:class LayeredConfigTree
py:class layered_config_tree.main.LayeredConfigTree
py:exc layered_config_tree.exceptions.ConfigurationError

Expand All @@ -69,5 +73,8 @@ py:class Logger
py:class Path
py:class LookupTableData

# pathlib internals
py:class pathlib._local.Path

# typing
py:data typing.Union
1 change: 0 additions & 1 deletion docs/source/api_reference/framework/event.rst

This file was deleted.

11 changes: 11 additions & 0 deletions docs/source/api_reference/framework/event/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
================
Event Management
================

.. automodule:: vivarium.framework.event

.. toctree::
:maxdepth: 1
:glob:

*
1 change: 1 addition & 0 deletions docs/source/api_reference/framework/event/interface.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. automodule:: vivarium.framework.event.interface
1 change: 1 addition & 0 deletions docs/source/api_reference/framework/event/manager.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. automodule:: vivarium.framework.event.manager
4 changes: 4 additions & 0 deletions docs/source/api_reference/framework/logging/index.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
==================
Logging Management
==================

.. automodule:: vivarium.framework.logging

.. toctree::
Expand Down
4 changes: 4 additions & 0 deletions docs/source/api_reference/framework/lookup/index.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
=======================
Lookup Table Management
=======================

.. automodule:: vivarium.framework.lookup

.. toctree::
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. automodule:: vivarium.framework.population.interface
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. automodule:: vivarium.framework.population.utilities
1 change: 0 additions & 1 deletion docs/source/api_reference/framework/time.rst

This file was deleted.

11 changes: 11 additions & 0 deletions docs/source/api_reference/framework/time/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
===============
Time Management
===============

.. automodule:: vivarium.framework.time

.. toctree::
:maxdepth: 1
:glob:

*
1 change: 1 addition & 0 deletions docs/source/api_reference/framework/time/interface.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. automodule:: vivarium.framework.time.interface
1 change: 1 addition & 0 deletions docs/source/api_reference/framework/time/manager.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. automodule:: vivarium.framework.time.manager
1 change: 1 addition & 0 deletions docs/source/api_reference/framework/values/interface.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. automodule:: vivarium.framework.values.interface
8 changes: 4 additions & 4 deletions docs/source/concepts/builder.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ they register for services and provide information about their structure. For ex
a component needing to leverage the simulation clock and step size
to determine a numerical effect to apply on each time step, will get the
simulation clock and step size though the Builder and will register
method(s) to apply the effect (e.g., via :meth:`vivarium.framework.values.manager.ValuesInterface.register_value_modifier`).
Another component, needing to initialize state for simulants at before the
simulation begin, might call :meth:`vivarium.framework.population.manager.PopulationInterface.initializes_simulants` in its setup
method to register method(s) that setup the additional state.
method(s) to apply the effect (e.g., via :meth:`vivarium.framework.values.interface.ValuesInterface.register_value_modifier`).
Another component, needing to initialize state for simulants before the
simulation begins, might call :meth:`vivarium.framework.population.interface.PopulationInterface.register_initializer`
in its setup method to register method(s) that set up the additional state.


Outline
Expand Down
21 changes: 11 additions & 10 deletions docs/source/concepts/crn.rst
Original file line number Diff line number Diff line change
Expand Up @@ -188,30 +188,31 @@ for this decision point of whether to move left or not. Here's how we'd do it:

import pandas as pd

class MoveLeft:
from vivarium import Component

class MoveLeft(Component):

@property
def name(self):
return 'move_left'

def setup(self, builder):
self.randomness = builder.randomness.get_stream('move_left')

builder.population.initializes_simulants(self.on_initialize_simulants,
creates_columns=['location'])

self.population_view = builder.population.get_view(['location'])
self.randomness = builder.randomness.get_stream(self.name)

builder.event.register_listener('time_step', self.on_time_step)
builder.population.register_initializer(
initializer=self.initialize_location,
columns='location',
required_resources=[self.randomness],
)

def on_initialize_simulants(self, pop_data):
def initialize_location(self, pop_data):
# all simulants start at position 10
self.population_view.update(pd.Series(10, index=pop_data.index, name='location'))

def on_time_step(self, event):
# with probability 0.5 simulants move to the left 1 position
to_move_index = self.randomness.filter_for_probability(event.index, pd.Series(0.5, index=event.index))
moved_locations = self.population_view.get(to_move_index).location - 1
moved_locations = self.population_view.get_attributes(to_move_index, "location") - 1
self.population_view.update(moved_locations)


Expand Down
27 changes: 17 additions & 10 deletions docs/source/concepts/event.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ a means of coordinating across various components in a simulation.
What is an Event?
-----------------

An :class:`Event <vivarium.framework.event.Event>` is a simple container for a
group of attributes that provide all the necessary information to respond to
the event. Events have the following attributes:
An :class:`~ <vivarium.framework.event.manager.Event>` is a simple container for a
group of class attributes that provide all the necessary information to respond to
the event. Each Event contains the following:

.. list-table:: **Event Attributes**
:header-rows: 1
Expand All @@ -28,7 +28,7 @@ the event. Events have the following attributes:
* - Name
- Description
* - | index
- | An index into the population table that contains all
- | An index into the population state table that contains all
| individuals that may respond to the event.
* - | time
- | The time at which the event will resolve. The current simulation
Expand Down Expand Up @@ -89,14 +89,14 @@ these phases.
Interacting with Events
-----------------------

The :class:`EventInterface <vivarium.framework.event.EventInterface>` is
The :class:`~ <vivarium.framework.event.interface.EventInterface>` is
available off the :ref:`Builder <builder_concept>` and provides two options for
interacting with the event system:

1. :func:`register_listener <vivarium.framework.event.EventInterface.register_listener()>` to add a
1. :func:`~ <vivarium.framework.event.interface.EventInterface.register_listener()>` to add a
listener to a given event to be called on emission

2. :func:`get_emitter <vivarium.framework.event.EventInterface.get_emitter()>`
2. :func:`~ <vivarium.framework.event.interface.EventInterface.get_emitter()>`
to retrieve a callable emitter for a given event

Although methods for both getting emitters and registering listeners are
Expand All @@ -109,9 +109,9 @@ Registering Listeners

In order to register a listener to an event to respond when that event is
emitted, we can use the
:func:`register_listener <vivarium.framework.event.EventInterface.register_listener()>`. The listener
:func:`~ <vivarium.framework.event.interface.EventInterface.register_listener()>`. The listener
itself should be a callable function that takes as its only argument
the :class:`Event <vivarium.framework.event.Event>` that is emitted.
the :class:`~ <vivarium.framework.event.manager.Event>` that is emitted.

Suppose we wish to track how many simulants are affected each time step. We
could do this by creating an observer component with an ``on_time_step`` method
Expand Down Expand Up @@ -144,11 +144,18 @@ another row to our dataframe tracking the number of affected simulants.
simulation at the beginning of the next time step should only depend on the
current state of the system.

.. note::

If a new component is being created that inherits from :class:`vivarium.component.Component`,
listeners are registered automatically if the component defines methods named
``on_<event_name>``, where ``<event_name>`` is one of the lifecycle names
(e.g. ``time_step``, ``collect_metrics``, etc.).


Emitting Events
+++++++++++++++

The :func:`get_emitter <vivarium.framework.event.EventInterface.get_emitter()>`
The :func:`~ <vivarium.framework.event.interface.EventInterface.get_emitter()>`
provides a way to get a callable emitter for a given named event. It can be
used as follows:

Expand Down
4 changes: 2 additions & 2 deletions docs/source/concepts/lifecycle.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ the simulation components will have their ``setup`` method called with
the simulation :ref:`builder <builder_concept>` as an argument. The
builder allows the components to request services like
:ref:`randomness <crn_concept>` or views into the
:term:`population state table <State Table>` or to register themselves
:term:`state table <Population State Table>` or to register themselves
with various simulation subsystems. Setting up components may also involve
loading data, registering or getting :ref:`pipelines <values_concept>`,
creating :ref:`lookup tables <lookup_concept>`, and registering
Expand Down Expand Up @@ -173,7 +173,7 @@ the state transitions by emitting a series of events for each
simulation outputs.

By listening for these events, individual components can perform actions,
including manipulating the :ref:`state table <population_concept>`. This
including manipulating the :ref:`population state table <population_concept>`. This
sequence of events is repeated until the simulation clock passes the
simulation end time.

Expand Down
Loading