Writing Custom Models

The most powerful feature of Epigrass is the ability to use custom models. It allows the user to specify intra-node dynamics and, in doing so, break away from the limitations imposed by the built-in models.

By learning to write his/her own models, the user begins to realize the full potential of Epigrass, which goes beyond being a platform to simulate networked epidemics. In reality Epigrass can be used to model any distributed dynamical system taking place on a set of nodes (connected or not).

Getting Started

The best way to get started in writing custom models is to look at the example distributed with Epigrass. It can be found in demos/CustomModel_example.py:

# This is a custom model to used in place of Epigrass' built-in models. Custom
# models must always be on a file named CustomModel.py and contain at least
# a function named Model. Both the File name and the function Names are case-sensitive,
# so be careful. Please refer to the manual for intructions on how to write your
# own custom models.

def Model(self,vars,par,theta=0, npass=0):
        Calculates the model SIR, and return its values.
        * vars The state variables of the models
        * par  The parameters (Beta, alpha, E,r,delta,B, w, p) see docs.
        * theta = infectious individuals from neighbor sites
        * npass = Total number of people arriving at this node
        # Get state variables' current values

        if self.parentSite.parentGraph.simstep == 1:  # if first step
                # Define variable names to appear in the output
                self.parentSite.vnames = ('Exposed','Infectious','Susceptible')
                # And get state variables's initial values (stored in dict self.bi)

                E,I,S = (self.bi['e'],self.bi['i'],self.bi['s'])
        else:   # if nor first step
                E,I,S = vars

        # Get parameter values
        N = self.parentSite.totpop
        beta,alpha,e,r,delta,B,w,p = (self.bp['beta'],self.bp['alpha'],

        #Vacination event (optional)
        if self.parentSite.vaccineNow:
                S -= self.parentSite.vaccov*S

        # Model
        Lpos = beta*S*((I+theta)/(N+npass))**alpha #Number of new cases
        Ipos = (1-r)*I + Lpos
        Spos = S + B - Lpos
        Rpos = N-(Spos+Ipos)

        # Update stats
        self.parentSite.totalcases += Lpos #update number of cases

        # Raise site infected flag and add parent site to the epidemic history list.
        if not self.parentSite.infected:
                if Lpos > 0:
                        self.parentSite.infected = self.parentSite.parentGraph.simstep


        return [0,Ipos,Spos]

Let’s analyze the above code. The first thing to notice is that an Epigrass custom model is a Python program. So anything you can do with Python in your system, you can do in your custom model. Naturally, your knowledge of the Python programming language will define how far you can go in this customization. There are a few requirements on this Python program in order to make it a valid custom model from Epigrass’s perspective.

  1. It must define a global function named Model. This function will be inserted as a method on every node object, at run time.
    1. This function must declare the following arguments:
      • self: reference to the model object.
      • vars: A list with the values of the model’s state variables in time t-1 in the same order as returned by this function.
      • par: The parameters of the model. Listed in the same order as defined in the .epg file.
      • theta: Number of infectious individuals arriving from neighboring sites. For disconnected models, it is 0.
      • npass: The total number of passengers arriving from neighboring sites. For disconnected models, it is 0.
    2. In the beginning of the function you define a list of strings (self.parentSite.vnames) which will be the names used when storing the resulting time-series in the database. Choose strings that are not very long and are meaningful. You only need to do this once, ate the beginning of the simulation so put it inside an if statement, which will be executed only at time-step 1 (see code above).

    3. After defining variable names, set their initial values in the same if clause. An else clause linked to this one will set variables values for the rest of the simulation.

    4. Define local names for the total population N and fixed parameters.

    5. Proceed to implement your model anyway you see fit.

    6. Feed some site level variables (incidence,) with the result of the simulation.
      • incidence: list of new cases per time step.
      • infected: Boolean stating if the site has been infected, i.e., it has had an autoctonous case.
      • epipath: This variable is at the graph level and contains the path of spread of the simulation.
      • migInf: Number of infectious individuals in this site per time-step.
    7. Finally, this function must return a list/tuple with the values of the state variables in the same order as received in vars.


The strings in self.parentSite.vnames must be valid SQL variable names, or else you will have a insert error at the end of the simulation.

After defining this function with all its required features, you can continue to develop you custom model, writing other functions classes, etc. Note however, that only the Model function will be called by Epigrass, so any other code you add to your program must be called from within that function.


Since CustomModel is imported from within Epigrass, any global code (unindented) in it is also executed. So you may add imports and other initialization code.


The name CustomModel.py is case-sensitive and cannot be changed. The same is true for the Model function.

The Environment


Nesting of the objects inside a Simulate object.

From quickly going through the example Custom model above it probably became clear, to the Python-initiated, that Yous can access variables at the node and graph levels. This is possible because Model becomes a method in a node object which in is turn is contained into a graph object (see figure).

Besides being nested within the graph object, node and edge contain references to their containers. This means that using the introspective abilities of Python the user can access any information at any level of the full graph model and use it in the custom model. In order to help you do this, Let’s establish an API for developing custom models.

Model Development API

All attributes and methods (functions) from all around the simulation must be references from the model’s perspective, denoted by self. The parent objects can be accessed through the following notation:

  • self.parentSite

    Is the Site (node) containing the model.

  • self.parentSite.parentGraph

    Is the Graph containing the parent site of the model.

The following attributes and methods can be accessed by appending them to one one the objects above. For example:


Site Attributes and Methods

Not all attributes and methods are listed, only the most useful. For a complete reference, look at the source code documentation.

class Site

self.parentSite. Actually named siteobj in the source code.


Dictionary with initial values for all of the model’s state variables. Keys are the variable names.


Dictionary with initial values for all of the model’s parameters. Keys are the parameter names.


Initial total population


List containing the model output time series (variables in the same order of the model)


Incidence time series


Has the site been already infected? (logical variable)


Site’s name (provided in the .csv)


Tuple containing extra-variables provided by .csv file


Graph to which Site belongs (see class Graph)


List containing all edge objects connected to Site


List containing all inbound edges


List containing all outbound edges


Site’s geocode


Type of dynamic model running in Site


Time and coverage of vaccination event. Format as in .epg


Flag indicating that it is vaccine day (0 or 1)


Current vaccination coverage


At time t, the population is vaccinated with coverage cov


Returns list of outbound edges


Returns list of inbound edges


Returns a dictionary of neighbor sites as keys and distances as values


Returns the distance in km from a given neighbor


Returns degree of this site, that is, the number of sites connected to it

Graph Attributes and Methods

Not all attributes and methods are listed, only the most useful. For a complete reference, look at the source code documentation.

class Graph



Time-step of the simulation. Use it to keep track of the simulation progress.


The speed of the transportation system


Final time-step of the simulation


Current size of the epidemic, graph-wise.


Full list of nodes in the graph. Each element in this list is a real node object.


Full list of nodes in the graph. Each element in this list is a real node object.


Returns an site object named name

Table Of Contents

Previous topic


This Page