Skip to content

Commit

Permalink
Merge pull request #740 from amath-idm/update-docs
Browse files Browse the repository at this point in the history
Update docs
  • Loading branch information
cliffckerr authored Dec 6, 2020
2 parents 6e4e870 + 6e4a06b commit 0e4ae03
Show file tree
Hide file tree
Showing 24 changed files with 3,670 additions and 3,231 deletions.
2 changes: 1 addition & 1 deletion .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ formats:

# Optionally set the version of Python and requirements required to build your docs
python:
version: 3.7
version: 3.8
install:
- requirements: docs/requirements.txt
- method: setuptools
Expand Down
26 changes: 17 additions & 9 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ This version contains a number of major updates. Note: this version requires Sci
Highlights
^^^^^^^^^^
- **Parameters**: Default infection fatality ratio estimates have been updated in line with the latest literature.
- **Plotting**: Plotting defaults have been updated to support a wider range of systems, and users now have greater control over plotting options.
- **Webapp**: The webapp has been moved to a separate Python package, ``covasim_webapp`` (available `here <https://github.com/institutefordiseasemodeling/covasim_webapp>`__)
- **Plotting**: Plotting defaults have been updated to support a wider range of systems, and users now have greater control over plotting and options.
- **New functions**: New methods have been added to display objects in different levels of detail; new methods have also been added for working with data, adding contacts, and analyzing multisims.
- **Webapp**: The webapp has been moved to a separate Python package, ``covasim_webapp`` (available `here <https://github.com/institutefordiseasemodeling/covasim_webapp>`__).
- **Documentation**: A comprehensive set of tutorials has been added, along with a glossary and FAQ; see https://docs.covasim.org or look in the ``docs/tutorials`` folder.

Parameter updates
Expand Down Expand Up @@ -55,25 +56,32 @@ Bugfixes
^^^^^^^^
- The ``quar_period`` argument is now correctly passed to the ``cv.contact_tracing()`` intervention. (Thanks to Scott McCrae for finding this bug.)
- If the user supplies an incorrect type to ``cv.Layer.find_contacts()``, this is now caught and corrected. (Thanks to user sba5827 for finding this bug.)
- Non-string layer keys no longer raise an exception.
- Non-string ``Layer`` keys no longer raise an exception.
- The ``sim.compute_r_eff()`` error message now gives correct instructions (contributed by `Andrea Cattaneo <https://github.com/InstituteforDiseaseModeling/covasim/pull/295>`__).
- Parallelization in Jupyter notebooks (e.g. ``msim.run()``) should now work without crashing.
- If parallelization (e.g. ``msim.run()``) is called outside a ``main`` block on Windows, this leads to a cryptic error. This error is now caught more elegantly.
- Interventions now print out with their actual name (previously they all printed out as ``InterventionDict``).
- The keyword argument ``test_sensitivity`` for ``cv.test_prob()`` has been renamed ``sensitivity``, for consistency with ``cv.test_num()``.

Other changes
^^^^^^^^^^^^^
New functions and methods
^^^^^^^^^^^^^^^^^^^^^^^^^
- Sims, multisims, scenarios, and people objects now have ``disp()``, ``summarize()``, and ``brief()`` methods, which display full detail, moderate detail, and very little detail about each. If ``cv.options.verbose`` is 0, then ``brief()`` will be used to display objects; otherwise, ``disp()`` will be used.
- Two new functions have been added, ``sim.get_intervention()`` and ``sim.get_analyzer()``. These act very similarly to e.g. ``sim.get_interventions()``, except they return the last matching intervention/analyzer, rather than returning a list of interventions/analyzers.
- There is a new verbose option: ``cv.Sim(verbose='brief').run()`` will print a single line of output when the sim finishes (namely, ``sim.brief()``).
- MultiSims now have a ``shrink()`` method, which shrinks both the base sim and the other sims they contain. MultiSims also have a ``brief()`` method, which prints out one line per sim (even briefer than ``msim.summarize()``).
- MultiSims now have a ``shrink()`` method, which shrinks both the base sim and the other sims they contain.
- MultiSims also provide options to compute statistics using either the mean or the median; this can be done via the ``msim.reduce(use_mean=True)`` method. Two convenience methods, ``msim.mean()`` and ``msim.median()``, have also been added as shortcuts.
- Scenarios now have a ``scens.compare()`` method, which (like the multisim equivalent) creates a dataframe comparing results across scenarios.
- Contacts now have new methods for handling layers, ``sim.people.contacts.add_layer()`` and ``sim.people.contacts.pop_layer()``. Additional validation on layers is also performed.
- There is a new function, ``cv.data.get_valid_locations()``, that lists locations for which demographic data are available.
- There is a new function, ``cv.data.show_locations()``, that lists locations for which demographic data are available. You can also now edit the data dictionaries directly, by modifying e.g. ``cv.data.country_age_data.data`` (suggested by `Andrea Cattaneo <https://github.com/InstituteforDiseaseModeling/covasim/issues/273>`__).

Other changes
^^^^^^^^^^^^^
- There is a new verbose option for sims: ``cv.Sim(verbose='brief').run()`` will print a single line of output when the sim finishes (namely, ``sim.brief()``).
- The argument ``n_cpus`` can now be supplied directly to ``cv.multirun()`` and ``msim.run()``.
- The types ``cv.default_float`` and ``cv.default_int`` are now available at the top level (previously they had to be accessed by e.g. ``cv.defaults.default_float``).
- Transmission trees now contain additional output; after ``tt = sim.make_transtree()``, a dataframe of key results is contained in ``tt.df``.
- The default number of seed infections has been changed from 10 to 20 for greater numerical stability. (Note that this placeholder value should be overridden for all actual applications.)
- ``sim.run()`` no longer returns the results object by default (if you want it, set ``output=True``).
- A migrations module has been added (in ``misc.py``). Objects are now automatically migrated to the current version of Covasim whene loaded The function ``cv.migrate()`` can also be called explicitly on objects if needed.

Documentation
^^^^^^^^^^^^^
Expand All @@ -86,7 +94,7 @@ Regression information
- Any scripts that used ``results = sim.run()`` will need to be updated to ``results = sim.run(output=True)``.
- Any scripts that passed formatting options directly to plots should set these as options instead; e.g. ``sim.plot(font_size=18)`` should now be ``cv.options.set(font_size=18); sim.plot()``.
- Any custom interventions that defined a custom ``plot()`` method should use ``plot_interventions()`` instead.
- *GitHub info*: PR `738 <https://github.com/amath-idm/covasim/pull/738>`__
- *GitHub info*: PRs `738 <https://github.com/amath-idm/covasim/pull/738>`__, `740 <https://github.com/amath-idm/covasim/pull/740>`__



Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ The structure of the ``covasim`` folder is as follows, roughly in the order in w
* ``requirements.py``: A simple module to check that imports succeeded, and turn off features if they didn't.
* ``utils.py``: Functions for choosing random numbers, many based on Numba, plus other helper functions.
* ``misc.py``: Miscellaneous helper functions.
* ``options.py``: User-customizable options for Covasim (e.g. default font size).
* ``settings.py``: User-customizable options for Covasim (e.g. default font size).
* ``defaults.py``: The default colors, plots, etc. used by Covasim.
* ``parameters.py``: Functions for creating the parameters dictionary and loading the input data.
* ``plotting.py``: Plotting scripts, including Plotly graphs for the webapp (used in other Covasim classes, and hence defined first).
Expand Down
131 changes: 123 additions & 8 deletions covasim/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,58 @@
from . import misc as cvm
from . import defaults as cvd
from . import parameters as cvpar
from .settings import options as cvo

# Specify all externally visible classes this file defines
__all__ = ['ParsObj', 'Result', 'BaseSim', 'BasePeople', 'Person', 'FlexDict', 'Contacts', 'Layer']


#%% Define simulation classes

class ParsObj(sc.prettyobj):
class FlexPretty(sc.prettyobj):
'''
A class that by default changes the display type depending on the current level
of verbosity.
'''

def __repr__(self):
''' Set display options based on current level of verbosity '''
try:
if cvo['verbose']:
string = self._disp()
else:
string = self._brief()
except Exception as E:
string = sc.objectid(self)
string += f'Warning, something went wrong printing object:\n{str(E)}'
return string

def _disp(self):
''' Verbose output -- use Sciris' pretty repr by default '''
return sc.prepr(self)

def disp(self, output=False):
''' Print or output verbose representation of the object '''
string = self._disp()
if not output:
print(string)
else:
return string

def _brief(self):
''' Brief output -- use a one-line output, a la Python's default '''
return sc.objectid(self)

def brief(self, output=False):
''' Print or output a brief representation of the object '''
string = self._brief()
if not output:
print(string)
else:
return string


class ParsObj(FlexPretty):
'''
A class based around performing operations on a self.pars dict.
'''
Expand All @@ -29,6 +73,7 @@ def __init__(self, pars):
self.update_pars(pars, create=True)
return


def __getitem__(self, key):
''' Allow sim['par_name'] instead of sim.pars['par_name'] '''
try:
Expand All @@ -48,6 +93,9 @@ def __setitem__(self, key, value):
raise sc.KeyNotFoundError(errormsg)
return




def update_pars(self, pars=None, create=False):
'''
Update internal dict with new pars.
Expand Down Expand Up @@ -129,6 +177,14 @@ def npts(self):
return len(self.values)


def set_metadata(obj):
''' Set standard metadata for an object '''
obj.created = sc.now()
obj.version = cvv.__version__
obj.git_info = cvm.git_info()
return


class BaseSim(ParsObj):
'''
The BaseSim class stores various methods useful for the Sim that are not directly
Expand All @@ -141,6 +197,50 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # Initialize and set the parameters as attributes
return


def _disp(self):
'''
Print a verbose display of the sim object. Used by repr(). See sim.disp()
for the user version. Equivalent to sc.prettyobj().
'''
return sc.prepr(self)


def _brief(self):
'''
Return a one-line description of a sim -- used internally and by repr();
see sim.brief() for the user version.
'''
# Try to get a detailed description of the sim...
try:
if self.results_ready:
infections = self.summary['cum_infections']
deaths = self.summary['cum_deaths']
results = f'{infections:n}⚙, {deaths:n}☠'
else:
results = 'not run'

# Set label string
labelstr = f'"{self.label}"' if self.label else '<no label>'

start = sc.date(self['start_day'], as_date=False)
if self['end_day']:
end = sc.date(self['end_day'], as_date=False)
else:
end = sc.date(self['n_days'], start_date=start)

pop_size = self['pop_size']
pop_type = self['pop_type']
string = f'Sim({labelstr}; {start} to {end}; pop: {pop_size:n} {pop_type}; epi: {results})'

# ...but if anything goes wrong, return the default with a warning
except Exception as E:
string = sc.objectid(self)
string += f'Warning, sim appears to be malformed:\n{str(E)}'

return string


def update_pars(self, pars=None, create=False, **kwargs):
''' Ensure that metaparameters get used properly before being updated '''
pars = sc.mergedicts(pars, kwargs)
Expand All @@ -153,16 +253,12 @@ def update_pars(self, pars=None, create=False, **kwargs):
return


def set_metadata(self, simfile, label):
def set_metadata(self, simfile):
''' Set the metadata for the simulation -- creation time and filename '''
self.created = sc.now()
self.version = cvv.__version__
self.git_info = cvm.git_info()
set_metadata(self)
if simfile is None:
datestr = sc.getdate(obj=self.created, dateformat='%Y-%b-%d_%H.%M.%S')
self.simfile = f'covasim_{datestr}.sim'
if label is not None:
self.label = label
return


Expand Down Expand Up @@ -686,7 +782,7 @@ def get_analyzer(self, label=None, partial=False, first=False, die=True):

#%% Define people classes

class BasePeople(sc.prettyobj):
class BasePeople(FlexPretty):
'''
A class to handle all the boilerplate for people -- note that as with the
BaseSim vs Sim classes, everything interesting happens in the People class,
Expand Down Expand Up @@ -744,6 +840,25 @@ def __add__(self, people2):
return newpeople


def _brief(self):
'''
Return a one-line description of the people -- used internally and by repr();
see people.brief() for the user version.
'''
try:
layerstr = ', '.join([str(k) for k in self.layer_keys()])
string = f'People(n={len(self):0n}; layers: {layerstr})'
except Exception as E:
string = sc.objectid(self)
string += f'Warning, multisim appears to be malformed:\n{str(E)}'
return string


def summarize(self, output=False):
''' Print a summary of the people -- same as brief '''
return self.brief(output=output)


def set(self, key, value, die=True):
''' Ensure sizes and dtypes match '''
current = self[key]
Expand Down
Loading

0 comments on commit 0e4ae03

Please sign in to comment.