def setUpClass(cls):
     cls.n = 20001
     cls.seed = 1001
     # change this to True if you need to re-generate the baseline
     cls.generateBaseline = regenerate
     cls.pdfDir = sc.thisdir(__file__, "regression", "report")
     cls.expectedDir = sc.thisdir(__file__, "regression", "expected")
     cls.datadir = sc.thisdir(__file__, os.pardir, "data")
     shutil.rmtree(cls.pdfDir, ignore_errors=True)
     os.makedirs(cls.pdfDir, exist_ok=True)
Exemple #2
0
def test_api(do_plot=False):

    # Read data
    filename = sc.thisdir(__file__, '..', 'examples', 'du_fig1a_annotated.png')
    xlim = [-10, 20]
    ylim = [0, 15]
    data = dt.datathief(filename, xlim=xlim, ylim=ylim, debug=True)

    # Plotting
    if do_plot:
        import pylab as pl
        pl.figure(figsize=(12, 4))

        ax1 = pl.subplot(1, 2, 1)
        ax1.imshow(pl.imread(filename))
        ax1.set_title('Original')

        ax2 = pl.subplot(1, 2, 2)
        ax2.bar(data.x, data.y)
        ax2.set_title('Extracted')
        ax2.set_xlabel('Serial interval')
        ax2.set_ylabel('Frequency')

        pl.show()

    return data
Exemple #3
0
def load_fonts(folder=None, rebuild=False, verbose=False, **kwargs):
    '''
    Helper function to load custom fonts for plotting -- (usually) not for the user.

    Note: if fonts don't load, try running ``cv.settings.load_fonts(rebuild=True)``,
    and/or rebooting the system.

    Args:
        folder (str): the folder to add fonts from
        rebuild (bool): whether to rebuild the font cache
        verbose (bool): whether to print out progress/errors
    '''

    if folder is None:
        folder = str(sc.thisdir(__file__, aspath=True) / 'data' / 'assets')
    sc.fonts(add=folder, rebuild=rebuild, verbose=verbose, **kwargs)

    # Try to find the font, and if it succeeds, update the styles
    try:
        name = 'Mulish'
        fm.findfont(name, fallback_to_default=False
                    )  # Raise an exception if the font isn't found
        rc_simple['font.family'] = name  # Need to set both
        rc_covasim['font.family'] = name
        if verbose: print(f'Default Covasim font reset to "{name}"')
    except Exception as E:
        if verbose: print(f'Could not find font {name}: {str(E)}')

    return
def test_thisdir():
    sc.heading('Test getting the current file directory')
    import os

    thisdir = sc.thisdir(__file__)
    assert os.path.split(thisdir)[-1] == 'tests'
    print(f'Current folder: {thisdir}')

    return thisdir
def test_data():
    sc.heading('Data loading')
    data = cv.load_data(os.path.join(sc.thisdir(__file__), 'example_data.csv'))
    sc.pp(data)

    # Check that it is looking for the right file
    with pytest.raises(FileNotFoundError):
        data = cv.load_data(datafile='file_not_found.csv')

    return data
Exemple #6
0
def test_baseline():
    ''' Compare the current default sim against the saved baseline '''

    # Load existing baseline
    filepath = sc.makefilepath(filename=baseline_filename,
                               folder=sc.thisdir(__file__))
    baseline = sc.loadjson(filepath)
    old = baseline[baseline_key]

    # Calculate new baseline
    sim = cv.Sim(verbose=0)
    sim.run()
    new = sim.summary

    # Compare keys
    errormsg = ''
    old_keys = set(old.keys())
    new_keys = set(new.keys())
    if old_keys != new_keys:
        errormsg = f"Keys don't match!\n"
        missing = old_keys - new_keys
        extra = new_keys - old_keys
        if missing:
            errormsg += f'  Missing old keys: {missing}\n'
        if extra:
            errormsg += f'  Extra new keys: {extra}\n'

    mismatches = {}
    for key in old_keys.union(new_keys):
        old_val = old[key] if key in old else 'not present'
        new_val = new[key] if key in new else 'not present'
        if old_val != new_val:
            mismatches[key] = {'old': old_val, 'new': new_val}

    if len(mismatches):
        errormsg = '\nThe following values have changed between old and new!\n'
        errormsg += 'Please rerun "tests/unittests/update_baseline" if this is intentional.\n'
        errormsg += 'Mismatches:\n'
        space = ' ' * 17
        for mkey, mval in mismatches.items():
            errormsg += f'  {mkey}:\n'
            errormsg += f'{space}old = {mval["old"]}\n'
            errormsg += f'{space}new = {mval["new"]}\n'

    # Raise an error if mismatches were found
    if errormsg:
        prefix = '\nThe following values have changed between the previous baseline and now!\n'
        prefix += 'If this is intentional, please rerun "update_baseline" and commit.\n\n'
        err = prefix + errormsg
        raise ValueError(err)
    else:
        print('Baseline matches')

    return new
Exemple #7
0
def get_version_pars(version, verbose=True):
    '''
    Function for loading parameters from the specified version.

    Args:
        version (str): the version to load parameters from

    Returns:
        Dictionary of parameters from that version
    '''

    # Define mappings for available sets of parameters -- note that this must be manually updated from the changelog
    match_map = {
        '0.30.4': ['0.30.4'],
        '0.31.0': ['0.31.0'],
        '0.32.0': ['0.32.0'],
        '1.0.0': ['1.0.0'],
        '1.0.1': [f'1.0.{i}' for i in range(1, 4)],
        '1.1.0': ['1.1.0'],
        '1.1.1': [f'1.1.{i}' for i in range(1, 3)],
        '1.1.3': [f'1.1.{i}' for i in range(3, 8)],
        '1.2.0': [f'1.2.{i}' for i in range(4)],
        '1.3.0': [f'1.3.{i}' for i in range(6)],
        '1.4.0': [f'1.4.{i}' for i in range(9)],
        '1.5.0': [f'1.5.{i}' for i in range(4)] +
        [f'1.6.{i}' for i in range(2)] + [f'1.7.{i}' for i in range(7)],
        '2.0.0': [f'2.0.{i}' for i in range(5)] + ['2.1.0'],
        '2.1.1': [f'2.1.{i}' for i in range(1, 3)],
        '3.0.0': ['3.0.0'],
    }

    # Find and check the match
    match = None
    for ver, verlist in match_map.items():
        if version in verlist:
            match = ver
            break
    if match is None:  # pragma: no cover
        options = '\n'.join(sum(match_map.values(), []))
        errormsg = f'Could not find version "{version}" among options:\n{options}'
        raise ValueError(errormsg)

    # Load the parameters
    filename = f'pars_v{match}.json'
    regression_folder = sc.thisdir(__file__, 'regression')
    pars = sc.loadjson(filename=filename, folder=regression_folder)
    if verbose:
        print(f'Loaded parameters from {match}')

    return pars
Exemple #8
0
def get_version_pars(version, verbose=True):
    '''
    Function for loading parameters from the specified version.

    Parameters will be loaded for Covasim 'as at' the requested version i.e. the
    most recent set of parameters that is <= the requested version. Available
    parameter values are stored in the regression folder. If parameters are available
    for versions 1.3, and 1.4, then this function will return the following

    - If parameters for version '1.3' are requested, parameters will be returned from '1.3'
    - If parameters for version '1.3.5' are requested, parameters will be returned from '1.3', since
      Covasim at version 1.3.5 would have been using the parameters defined at version 1.3.
    - If parameters for version '1.4' are requested, parameters will be returned from '1.4'

    Args:
        version (str): the version to load parameters from

    Returns:
        Dictionary of parameters from that version
    '''

    # Construct a sorted list of available parameters based on the files in the regression folder
    regression_folder = sc.thisdir(__file__, 'regression', aspath=True)
    available_versions = [
        x.stem.replace('pars_v', '') for x in regression_folder.iterdir()
        if x.suffix == '.json'
    ]
    available_versions = sorted(available_versions, key=LooseVersion)

    # Find the highest parameter version that is <= the requested version
    version_comparison = [
        sc.compareversions(version, v) >= 0 for v in available_versions
    ]
    try:
        target_version = available_versions[sc.findlast(version_comparison)]
    except IndexError:
        errormsg = f"Could not find a parameter version that was less than or equal to '{version}'. Available versions are {available_versions}"
        raise ValueError(errormsg)

    # Load the parameters
    pars = sc.loadjson(filename=regression_folder /
                       f'pars_v{target_version}.json',
                       folder=regression_folder)
    if verbose:
        print(f'Loaded parameters from {target_version}')

    return pars
Exemple #9
0
def test_sim_data(do_plot=False, do_show=False):
    sc.heading('Data test')

    pars = dict(
        n=2000,
        start_day = '2020-01-01',
        )

    # Create and run the simulation
    sim = cv.Sim(pars=pars, datafile=os.path.join(sc.thisdir(__file__), 'example_data.csv'))
    sim.run()

    # Optionally plot
    if do_plot:
        sim.plot(do_show=do_show)

    return sim
    def output(self):
        self.log.info(f"Final columns: {', '.join(self.df.columns)}")
        self.log.info("First rows of data:")
        self.log.info(self.df.head())
        here = sc.thisdir(__file__)
        data_home = os.path.join(here, self.output_folder)

        for g in self.grouping:
            key_value = g[0]
            filename = f'{sc.sanitizefilename(key_value)}.csv'
            filepath = sc.makefilepath(filename=filename, folder=data_home)
            self.log.info(f'Creating {filepath}')
            mini_df = self.df[self.df.key == key_value]
            mini_df.to_csv(filepath)

        self.log.info(
            f"There are {len(self.grouping)} entities in this dataset.")
        self.log.info(f"Saved {len(self.df)} records.")
Exemple #11
0
def get_version_pars(version, verbose=True):
    '''
    Function for loading parameters from the specified version.

    Args:
        version (str): the version to load parameters from

    Returns:
        Dictionary of parameters from that version
    '''
    regression_folder = sc.thisdir(__file__, 'regression')
    pattern = 'pars_v*.json'
    requested = pattern.replace('*', version)
    filepaths = sc.getfilelist(regression_folder, pattern=pattern)
    files = [os.path.basename(f) for f in filepaths]
    if requested in files:  # If there's an exact match
        match = requested
    else:  # No match, find the nearest matching file
        withmatch = files + [requested]  # Add this version
        withmatch.sort()  # Sort the files
        index = withmatch.index(requested)
        if index > 0:
            match = withmatch[
                index -
                1]  # Get latest earlier version -- note that this assumes versions are in alphabetical order, which they currently are!
        else:
            filestr = '\n'.join(files)
            errormsg = f'Could not find version {version} among options:\n{filestr}'
            raise ValueError(errormsg)

    # Load the parameters
    pars = sc.loadjson(filename=match, folder=regression_folder)
    if verbose:
        if match == requested:
            print(f'Loaded parameters from {match}')
        else:
            print(
                f'No exact match for parameters "{version}" found; using "{match}" instead'
            )

    return pars
Exemple #12
0
 def setUpClass(cls) -> None:
     # for Testconvert_df_to_json_array()
     cls.pars['filepath'] = os.path.join(
         sc.thisdir(__file__, 'testdata'),
         'Washington_age_bracket_distr_16.dat')
Exemple #13
0
import covasim as cv
import sciris as sc

cv.check_version('0.27.9')

do_plot = 1

datafile = sc.thisdir(__file__, '../../example_data.csv')

pars = sc.objdict(diag_factor=1.0, n_days=30, pop_infected=100)

sim = cv.Sim(pars, datafile=datafile)

case = 2
testprobdict = {
    0:
    cv.test_prob(symp_prob=0,
                 asymp_prob=0,
                 test_sensitivity=1.0,
                 loss_prob=0.0,
                 test_delay=0,
                 start_day=0),  # works, no diagnoses
    1:
    cv.test_prob(symp_prob=1,
                 asymp_prob=0,
                 test_sensitivity=1.0,
                 loss_prob=0.0,
                 test_delay=0,
                 start_day=0),  # works, ~half diagnosed
    2:
    cv.test_prob(
Exemple #14
0
    )

    fig.update_layout(
        plot_bgcolor='#fff'
    )

    fig.update_layout(title={'text': 'Epidemic over time'})

    output = {'json': fig.to_json(), 'id': str(sc.uuid())}
    d = json.loads(output['json'])
    d['config'] = {'responsive': True}
    output['json'] = json.dumps(d)

    return output

#%% Run the server using Flask
if __name__ == "__main__":

    os.chdir(sc.thisdir(__file__))

    if len(sys.argv) > 1:
        app.config['SERVER_PORT'] = int(sys.argv[1])
    else:
        app.config['SERVER_PORT'] = 8188
    if len(sys.argv) > 2:
        autoreload = int(sys.argv[2])
    else:
        autoreload = 1

    app.run(autoreload=autoreload)
Exemple #15
0
import sciris as sc
import logging
from . import version as spv

__all__ = [
    'logger', 'checkmem', 'datadir', 'localdatadir', 'version_info',
    'set_datadir', 'set_nbrackets', 'validate'
]

# Declaring this here makes it globally available as synthpops.datadir
datadir = None
localdatadir = None
full_data_available = False  # this is likely not necesary anymore

# Set the local data folder
thisdir = sc.thisdir(__file__)
localdatadir = os.path.join(thisdir, os.pardir, 'data')

# Replace with local data dir if Dropbox folder is not found
if datadir is None:
    full_data_available = True
    datadir = localdatadir

# Number of census age brackets to use
nbrackets = [
    16, 20
][1]  # Choose how many age bins to use -- 20 is only partially supported
matrix_size = 16  # The dimensions of the mixing matrices -- currently only 16 is available

#%% Logger
Exemple #16
0
print('Note -- these tests currently deprecated')

import numpy as np
import pandas as pd
import sciris as sc
import synthpops as sp
import os
import unittest

sp.settings.datadir = sc.thisdir(__file__, 'unittests')

# for Testconvert_df_to_json_array()
pars = sc.objdict(
            location_name = 'usa-Washington',  # name of the location
            property_name = 'population_age_distributions',  # name of the property to compare to
            filepath      = os.path.join(sp.settings.datadir,
                                         'Washington_age_bracket_distr_16.dat'),  # path to the file to convert to array
            cols_ind      = [],  # list of column indices to include in array in conversion
            int_cols_ind  = [],  # list of column induces to convert to ints
            )


class TestLocation(unittest.TestCase):
    """
    These tests need to be run from the root synthpops/tests folder, because some of the tests involve relative
    filepath assumptions based on that.
    """

    def minimal_test_str(self):
        test_str = """{
          "location_name": "test_location",
Exemple #17
0
'''
Run examples/*.py using pytest
'''

import pylab as pl
import sciris as sc
from pathlib import Path
import importlib.util as iu

pl.switch_backend(
    'agg'
)  # To avoid graphs from appearing -- if you want them, run the examples directly
cwd = Path(sc.thisdir(__file__))
examples_dir = cwd.joinpath('../examples')


def run_example(name):
    '''
    Execute an example py script as __main__

    Args:
        name (str): the filename without the .py extension
    '''
    spec = iu.spec_from_file_location("__main__",
                                      examples_dir.joinpath(f"{name}.py"))
    module = iu.module_from_spec(spec)
    spec.loader.exec_module(module)


def test_run_scenarios():
    run_example("run_scenarios")
Exemple #18
0
'''
Tests for things that are not tested in other files, typically because they are
corner cases or otherwise not part of major workflows.
'''

#%% Imports and settings
import os
import pytest
import numpy as np
import sciris as sc
import covasim as cv

do_plot = 1
verbose = -1
debug = 1  # This runs without parallelization; faster with pytest
csv_file = os.path.join(sc.thisdir(), 'example_data.csv')
xlsx_file = os.path.join(sc.thisdir(), 'example_data.xlsx')
cv.options.set(interactive=False)  # Assume not running interactively


def remove_files(*args):
    ''' Remove files that were created '''
    for path in args:
        if os.path.exists(path):
            print(f'Removing {path}')
            os.remove(path)
    return


#%% Define the tests
Exemple #19
0
"""
Compare current results to baseline
"""

import sciris as sc
import covasim as cv

do_save = True
baseline_filename = sc.thisdir(__file__, 'baseline.json')
benchmark_filename = sc.thisdir(__file__, 'benchmark.json')
baseline_key = 'summary'


def save_baseline(do_save=do_save):
    ''' Refresh the baseline results '''
    print('Updating baseline values...')

    sim = cv.Sim(verbose=0)
    sim.run()
    sim.to_json(filename=baseline_filename, keys=baseline_key)

    print('Done.')

    return sim


def test_baseline():
    ''' Compare the current default sim against the saved baseline '''

    # Load existing baseline
    filepath = sc.makefilepath(filename=baseline_filename,
Exemple #20
0
'''
Converts Excel files to binary for faster loading.
'''

import os
import numpy as np
import pandas as pd
import sciris as sc

folder = os.path.join(sc.thisdir(__file__), os.pardir, 'data', 'demographics',
                      'contact_matrices_152_countries')
ext1 = '_1.xlsx'
ext2 = '_2.xlsx'
files1 = sc.getfilelist(folder, pattern=f'*{ext1}')
files2 = sc.getfilelist(folder, pattern=f'*{ext2}')

basefilenames = [f[len(folder) + 1:-len(ext1)]
                 for f in files1]  # 7 is the length of the extension

datadict = {}
for fn in basefilenames:
    datadict[fn] = {}

for fn in basefilenames:
    for i, ext in enumerate([ext1, ext2]):
        thisfile = folder + os.sep + fn + ext
        print(f'Working on {thisfile}...')
        xls = pd.ExcelFile(thisfile)
        for sheet_name in xls.sheet_names:
            if i == 0:
                header = 0
'''
Ensure that the right paths can be found
'''

import sys
import sciris as sc
sys.path.append(sc.thisdir(__file__))
Exemple #22
0
 def setUpClass(cls) -> None:
     cls.example_path = Path(sc.thisdir(__file__)).joinpath('../examples')
     cls.resultdir = os.path.join(os.path.dirname(__file__), 'result')
     os.makedirs(cls.resultdir, exist_ok=True)
#!/usr/bin/env python3
'''
Run the non-tutorial examples using pytest
'''

import pylab as pl
import sciris as sc
from pathlib import Path
import importlib.util as iu

pl.switch_backend(
    'agg'
)  # To avoid graphs from appearing -- if you want them, run the examples directly
examples_dir = Path(sc.thisdir(__file__))


def run_example(name):
    '''
    Execute an example py script as __main__

    Args:
        name (str): the filename
    '''
    spec = iu.spec_from_file_location("__main__", examples_dir.joinpath(name))
    module = iu.module_from_spec(spec)
    spec.loader.exec_module(module)


def test_run_scenarios():
    run_example("run_scenarios.py")
Exemple #24
0
# Select and rename columns
target_columns = [
    'Country or area', 'Reference date (dd/mm/yyyy)',
    'Average household size (number of members)'
]
df = df_raw[target_columns].copy()
df.columns = ['country', 'date', 'size']

# Convert date column to datetime type and replace nodata with NA.
df['date'] = df['date'].apply(lambda d: pd.to_datetime(d, format='%d/%m/%Y'))
df['size'] = df['size'].apply(lambda s: np.nan
                              if isinstance(s, str) and s == '..' else s)
df = df.dropna()

# Take the most recent household size for each country.
df = df.sort_values(by=['country', 'date']).groupby(by=['country']).last()[[
    'size'
]]
un_country_households_dict = df.to_dict()['size'].copy()

# Add to the dictionary commonly used aliases like USA for United States of America.
us_countries = [k.lower() for k in un_country_households_dict]
country_mappings_dict = cv.data.loaders.get_country_aliases()
for alias, name in country_mappings_dict.items():
    if name.lower() in us_countries:
        un_country_households_dict[alias] = un_country_households_dict[name]

pathname = str(
    sc.thisdir(cv.__file__, aspath=True) / 'data' / 'household_size_data.py')
print(f'To update, copy the data below into the following file:\n{pathname}\n')
print(un_country_households_dict)
import sys
import shutil
import fnmatch
import unittest
import tempfile
import sciris as sc
import synthpops as sp
import numpy as np
from examples import plot_age_mixing_matrices
try:
    from fpdf import FPDF
except Exception as E:
    print(f'Note: could not import fpdf, report not available ({E})')

# import utilities from test directory
testdir = sc.thisdir(__file__, os.pardir)
sys.path.append(testdir)
import utilities

# Whether to remove temporary files generated in the process
remove_files = True

# Whether to regenerate files
regenerate = False


class TestRegression(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.n = 20001
        cls.seed = 1001
Exemple #26
0
 def setUpClass(cls) -> None:
     sp.settings.datadir = sc.thisdir(__file__, 'testdata')
"""
Compare current results to baseline
"""

import numpy as np
import pandas as pd
import sciris as sc
import covasim as cv

do_save = False
baseline_filename  = sc.thisdir(__file__, 'baseline.json')
benchmark_filename = sc.thisdir(__file__, 'benchmark.json')
parameters_filename = sc.thisdir(__file__, 'regression', f'parameters_v{cv.__version__}.json')
baseline_key = 'summary'


def save_baseline(do_save=do_save):
    ''' Refresh the baseline results '''
    print('Updating baseline values...')

    sim = cv.Sim(verbose=0)
    sim.run()
    if do_save:
        sim.to_json(filename=baseline_filename, keys=baseline_key)
        sim.export_pars(filename=parameters_filename)

    print('Done.')

    return sim

Exemple #28
0
# Use internal data to create dates; only keep `date` column
df['date'] = pd.to_datetime(df[['year', 'month', 'day']])
df.drop(['dateRep', 'day', 'month', 'year'], inplace=True, axis=1)

# Just to be safe, let's sort by name and date. Probably not
# necessary but better safe than sorry!.
df = df.sort_values(['countriesAndTerritories', 'date'])

# Each data set has a unique name. Let's create groups.
g = df.groupby('countriesAndTerritories')

# The parameter 'day' is the number of days since the first
# day of data collection for the group.
df['day'] = g['date'].transform(lambda x: (x - min(x))).apply(lambda x: x.days)

# We'll 'rename' some of the columns to be consistent
# with the parameters file.
df['new_positives'] = df.cases
df['new_death'] = df.deaths
df['population'] = df.popData2018
df.drop(['cases', 'deaths', 'popData2018'], inplace=True, axis=1)

# And save it to the data directory.
here = sc.thisdir(__file__)
data_home = os.path.join(here, subfolder)
filepath = sc.makefilepath(filename=outputfile, folder=data_home)
log.info(f"Saving to {filepath}")
df.to_csv(filepath)
log.info(f"Script complete")
Exemple #29
0
'''
Confirm that with default settings, all analyzers can be exported as JSONs.
'''

import sciris as sc
import covasim as cv

datafile = sc.thisdir(__file__, aspath=True).parent / 'example_data.csv'

# Create and runt he sim
sim = cv.Sim(analyzers=[
    cv.snapshot(days='2020-04-04'),
    cv.age_histogram(),
    cv.daily_age_stats(),
    cv.daily_stats()
],
             datafile=datafile)
sim.run()

# Compute extra analyzers
tt = sim.make_transtree()
fit = sim.compute_fit()

# Construct list of all analyzers
analyzers = sim['analyzers'] + [tt, fit]

# Make jsons
jsons = {}
for an in analyzers:
    print(f'Working on analyzer {an.label}...')
    jsons[an.label] = an.to_json()