Helipad 0.7 is here with two big features: stackplots, and parameter sweeps.
Stackplots
If you’ve wanted to plot things where the total matters, or maybe where the values add up to a constant total and you’re interested in the relative proportions, stackplots can improve the visualization.
The Deme Selection sample model introduced in Helipad 0.6 is a good example (and see that page for the “before” screenshot): the top plot depicts the proportion of altruistic versus selfish phenotypes. But the plots are mirror images of one another. A stackplot eliminates the redundancy and makes it easier to scan the model output.
To turn a plot into a stackplot, just add a stack=True
argument when calling model.addPlot()
.
Parameter Sweeps
A parameter sweep is a common way to exploring the sensitivity of an agent-based model to its parameter values by running the model repeatedly and systematically varying one or more parameters. In NetLogo, for example, this is called BehaviorSpace.
This is now possible with Helipad’s new paramSweep
function. Because possible values of any parameter are nailed down when instantiated with the addParameter
function, even for numerical variables (because the min, the max, and the step are set for sliders), all paramSweep needs to know is the variable(s) to sweep and how long to run each instance. The former can sweep n-dimensional parameter spaces (i.e. every combination of possible values from n different parameters), and the latter can specify either a fixed time, or a function with arbitrary stop conditions, for example if you’re trying to see if the variable affects how long it takes to get to equilibrium.
Sweeping hundreds or thousands of parameter combinations is a time-consuming task, so to make it as fast as possible, the parameter sweep bypasses the GUI and returns the results of each run as a Pandas dataframe, whose columns can optionally be narrowed just to the data of interest.
Other Changes
Helipad 0.7 has a new createNetwork
function that automatically generates an undirected and unweighted network of a specific density among agents. Helipad’s support for network types means that multiple distinct networks can be created this way, even over the same agents.
More significantly, to support the new parameter sweep functionality and to simplify the internals, the way parameters are handled internally has changed. The upshot is two things:
- More consistency in how callbacks and updating parameters are handled. For example, updating a parameter value in code will always update the parameter value in the GUI, where previously this was not true for sliders due to a Tkinter inconsistency.
- A new pattern for identifying parameters to functions.
This second feature is backward-incompatible and entails a few function removals and signature changes. First, functions that need to identify a parameter (for example model.param
, model.paramSweep
, and Shocks.register
) now all do so with a single tuple-argument pattern, rather than the ad hoc list of optional arguments like obj
, prim
, breed
, good
, and so on.
The new parameter identification pattern looks like this:
- A global parameter can be identified using a string or a one-element tuple.
model.param('pSmooth')
retrieves the value of the globalpSmooth
parameter. - The parameter values for all items – for example a per-breed or a per-good parameter – can be retrieved using a two-element tuple.
model.param(('productivity', 'good'))
retrieves adict
of theproductivity
parameter values for all goods. Note that parameters cannot be set this way. - The parameter value for a particular item of a per-breed or per-good tuple can be referred to using a three-element tuple.
model.param(('demand', 'breed', 'hobbit'), 50)
sets thedemand
parameter for thehobbit
breed to 50. - Finally, because breeds apply only to specific agent primitives, when there are multiple primitives, the relevant primitive is specified using a fourth element of the tuple (this is optional when there is only one primitive). The previous example could also be specified
model.param(('demand', 'breed', 'hobbit', 'agent), 50)
. - The second case can also be achieved in the event of multiple primitives by putting
None
as the third element.model.param(('demand', 'breed', None, 'agent))
returns adict
of thedemand
breed parameter values for all breeds of theagent
primitive.
This simplifies the internals a good bit, and standardizes the parameter interface across several different functions. It also obviates the goodParameter
and breedParameter
functions, which have been removed. Your code should replace them with the new and more powerful param
function.
The full list of API changes follows.
API Changes in Version 0.7
- ⚠️ TimeSeriesRemoved
Graph.graph
(the list of MatplotlibAxesSubplot
objects) andGraph.series
(the list of MatplotlibLine
objects). These are now kept track of in the Plot objects stored inGraph.plots
. - ⚠️ HelipadRemoved the
updateVar
,breedParam
, andgoodParam
methods. The latter two are replaced by a more flexibleparam
method that can take parameter ID tuples now. - ⚠️ CpanelRemoved the
sliders
property. Parameter widgets are now stored inParam.element
. - ⚠️ ShockReplaced the
var
,paramType
, andprim
properties, which stored attributes of the parameter, with theparam
property, which stores the parameter object itself. - ⚠️ addReplaced the
var
,paramType
, andprim
arguments with theparam
argument, a standard parameter identification tuple or string. - ⚠️ paramReplaced the
name
and several undocumented arguments with theparam
argument, to increase flexibility and accommodate the new parameter identification pattern. - ⚠️ GUICloseRenamed
GUIPostLaunch
toGUIClose
to more accurately reflect the hook's place in the flow, and passed the model instead of the GUI object. - TimeSeriesPlotKeep track of the Matplotlib
AxesSubplot
object here rather than in a separate list inGraph
. - SeriesKeep track of the Matplotlib
Line
object here rather than in a separate list inGraph
, and the output series here rather than in theLine
object. - addReturns a
Good
object. - addBreedReturns a
Breed
object. - createNetworkIntroduced.
- ParamAdded the
obj
,range
, andelement
properties, and theget
,set
,reset
, andaddKey
methods. - paramSweepIntroduced.