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)
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
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
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
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
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
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.")
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
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')
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(
) 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)
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
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",
''' 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")
''' 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
""" 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,
''' 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__))
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")
# 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
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
# 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")
''' 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()