Skip to content

Commit

Permalink
datacollector: store separate snapshots of model data per step (proje…
Browse files Browse the repository at this point in the history
…ctmesa#2129)

* datecollector: store separate snapshots of model data per step
- Ensure `DataCollector` stores unique copies of the data at each model step.
- Use `deepcopy` in `collect` method to avoid storing references that lead to each step holding the same data.
- Fixes the issue where PropertyLayer data was stored identically for all steps, preventing accurate visualization and analysis of model progression.

* datacollection: Add deepcopy comment
  • Loading branch information
EwoutH authored May 8, 2024
1 parent a2d4afe commit abac825
Showing 1 changed file with 11 additions and 6 deletions.
17 changes: 11 additions & 6 deletions mesa/datacollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import contextlib
import itertools
import types
from copy import deepcopy
from functools import partial

with contextlib.suppress(ImportError):
Expand Down Expand Up @@ -197,17 +198,21 @@ def collect(self, model):
for var, reporter in self.model_reporters.items():
# Check if lambda or partial function
if isinstance(reporter, types.LambdaType | partial):
self.model_vars[var].append(reporter(model))
# Use deepcopy to store a copy of the data,
# preventing references from being updated across steps.
self.model_vars[var].append(deepcopy(reporter(model)))
# Check if model attribute
elif isinstance(reporter, str):
self.model_vars[var].append(getattr(model, reporter, None))
self.model_vars[var].append(
deepcopy(getattr(model, reporter, None))
)
# Check if function with arguments
elif isinstance(reporter, list):
self.model_vars[var].append(reporter[0](*reporter[1]))
# TODO: Check if method of a class, as of now it is assumed
# implicitly if the other checks fail.
self.model_vars[var].append(deepcopy(reporter[0](*reporter[1])))
# Assume it's a callable otherwise (e.g., method)
# TODO: Check if method of a class explicitly
else:
self.model_vars[var].append(reporter())
self.model_vars[var].append(deepcopy(reporter()))

if self.agent_reporters:
agent_records = self._record_agents(model)
Expand Down

0 comments on commit abac825

Please sign in to comment.