Example #1
0
def tidy_up(fig, figs, sep_figs, do_save, fig_path, do_show, args):
    ''' Handle saving, figure showing, and what value to return '''

    # Handle saving
    if do_save:
        if fig_path is not None:  # No figpath provided - see whether do_save is a figpath
            fig_path = sc.makefilepath(
                fig_path)  # Ensure it's valid, including creating the folder
        cvm.savefig(filename=fig_path)  # Save the figure

    # Show the figure, or close it
    do_show = cvset.handle_show(do_show)
    if cvset.options.close and not do_show:
        if sep_figs:
            for fig in figs:
                pl.close(fig)
        else:
            pl.close(fig)

    # Reset Matplotlib defaults
    for key, value in args.mpl_orig.items():
        cvset.options.set(key, value)

    # Return the figure or figures
    if sep_figs:
        return figs
    else:
        return fig
Example #2
0
def tidy_up(fig, figs, sep_figs, do_save, fig_path, do_show, args):
    ''' Handle saving, figure showing, and what value to return '''

    figlist = sc.mergelists(
        fig, figs)  # Usually just one figure, but here for completeness

    # Optionally maximize -- does not work on all systems
    if args.show['maximize']:
        for f in figlist:
            sc.maximize(fig=f)
        pl.pause(0.01)  # Force refresh

    # Use tight layout for all figures
    if args.show['tight']:
        for f in figlist:
            sc.figlayout(fig=f)

    # Handle saving
    if do_save:
        if isinstance(
                fig_path,
                str):  # No figpath provided - see whether do_save is a figpath
            fig_path = sc.makefilepath(
                fig_path)  # Ensure it's valid, including creating the folder
        cvm.savefig(fig=figlist, filename=fig_path)  # Save the figure

    return handle_show_return(do_show, fig=fig, figs=figs)
Example #3
0
def tidy_up(fig,
            figs,
            sep_figs,
            do_save,
            fig_path,
            do_show,
            default_name='covasim.png'):
    ''' Handle saving, figure showing, and what value to return '''

    # Handle saving
    if do_save:
        if fig_path is None:  # No figpath provided - see whether do_save is a figpath
            fig_path = default_name  # Just give it a default name
        fig_path = sc.makefilepath(
            fig_path)  # Ensure it's valid, including creating the folder
        pl.savefig(fig_path)

    # Show or close the figure
    if do_show:
        pl.show()
    else:
        pl.close(fig)

    # Return the figure or figures
    if sep_figs:
        return figs
    else:
        return fig
Example #4
0
def tidy_up(fig, figs, sep_figs, do_save, fig_path, do_show):
    ''' Handle saving, figure showing, and what value to return '''

    # Handle saving
    if do_save:
        if fig_path is not None:  # No figpath provided - see whether do_save is a figpath
            fig_path = sc.makefilepath(
                fig_path)  # Ensure it's valid, including creating the folder
        cvm.savefig(filename=fig_path)  # Save the figure

    # Show the figure, or close it
    if do_show is None:
        do_show = cvo.show

    if do_show:
        pl.show()
    elif cvo.close:
        if sep_figs:
            for fig in figs:
                pl.close(fig)
        else:
            pl.close(fig)

    # Return the figure or figures
    if sep_figs:
        return figs
    else:
        return fig
Example #5
0
def finalize_figure(fig, plkwargs, **new_plkwargs):
    """
    Update any parameters and then return figpath.

    Args:
        fig (matplotlib.Figure)    : figure
        plkwargs (plotting_kwargs) : plotting kwargs class
        new_plkwargs (dict)        : dictionary of new plotting kwargs to update with

    Returns:
        Matplotlib figure.
    """
    plkwargs = sc.dcp(plkwargs)
    plkwargs.update(new_plkwargs)
    if plkwargs.do_save:
        plkwargs.figpath = sc.makefilepath(filename=plkwargs.figname,
                                           folder=plkwargs.figdir,
                                           ext=plkwargs.format)
        fig.savefig(plkwargs.figpath,
                    format=plkwargs.format,
                    dpi=plkwargs.save_dpi)

    if plkwargs.do_show:
        plt.show()

    return fig
Example #6
0
    def save(self,
             filename=None,
             keep_people=False,
             skip_attrs=None,
             **kwargs):
        '''
        Save to disk as a gzipped pickle.

        Args:
            filename (str or None): the name or path of the file to save to; if None, uses stored
            kwargs: passed to makefilepath()

        Returns:
            filename (str): the validated absolute path to the saved file

        **Example**::

            sim.save() # Saves to a .sim file with the date and time of creation by default
        '''
        if filename is None:
            filename = self.simfile
        filename = sc.makefilepath(filename=filename, **kwargs)
        self.filename = filename  # Store the actual saved filename
        if skip_attrs or not keep_people:
            obj = self.shrink(skip_attrs=skip_attrs, in_place=False)
        else:
            obj = self
        sc.saveobj(filename=filename, obj=obj)
        return filename
def git_info(filename=None, check=False, comments=None, old_info=None, die=False, indent=2, verbose=True, frame=2, **kwargs):
    '''
    Get current git information and optionally write it to disk. Simplest usage
    is cv.git_info(__file__)

    Args:
        filename  (str): name of the file to write to or read from
        check    (bool): whether or not to compare two git versions
        comments (dict): additional comments to include in the file
        old_info (dict): dictionary of information to check against
        die      (bool): whether or not to raise an exception if the check fails
        indent    (int): how many indents to use when writing the file to disk
        verbose  (bool): detail to print
        frame     (int): how many frames back to look for caller info
        kwargs   (dict): passed to sc.loadjson() (if check=True) or sc.savejson() (if check=False)

    **Examples**::

        cv.git_info() # Return information
        cv.git_info(__file__) # Writes to disk
        cv.git_info('covasim_version.gitinfo') # Writes to disk
        cv.git_info('covasim_version.gitinfo', check=True) # Checks that current version matches saved file
    '''

    # Handle the case where __file__ is supplied as the argument
    if isinstance(filename, str) and filename.endswith('.py'):
        filename = filename.replace('.py', '.gitinfo')

    # Get git info
    calling_file = sc.makefilepath(sc.getcaller(frame=frame, tostring=False)['filename'])
    cv_info = {'version':cvv.__version__}
    cv_info.update(sc.gitinfo(__file__, verbose=False))
    caller_info = sc.gitinfo(calling_file, verbose=False)
    caller_info['filename'] = calling_file
    info = {'covasim':cv_info, 'called_by':caller_info}
    if comments:
        info['comments'] = comments

    # Just get information and optionally write to disk
    if not check:
        if filename is not None:
            output = sc.savejson(filename, info, indent=indent, **kwargs)
        else:
            output = info
        return output

    # Check if versions match, and optionally raise an error
    else:
        if filename is not None:
            old_info = sc.loadjson(filename, **kwargs)
        string = ''
        old_cv_info = old_info['covasim'] if 'covasim' in old_info else old_info
        if cv_info != old_cv_info: # pragma: no cover
            string = f'Git information differs: {cv_info} vs. {old_cv_info}'
            if die:
                raise ValueError(string)
            elif verbose:
                print(string)
        return
Example #8
0
def make_students(sim,
                  save_pop=False,
                  popfile=None,
                  verbose=None,
                  die=True,
                  reset=False):
    '''
    An analog to population.make_people. It borrows some code from this function to ensure the simulation runs smoothly.
    '''
    # Set inputs and defaults
    pop_size = int(sim['pop_size'])  # Shorten
    if verbose is None:
        verbose = sim['verbose']
    if popfile is None:
        popfile = sim.popfile

    if sim.people and not reset:
        return sim.people  # If it's already there, just return
    elif sim.popdict and not reset:
        popdict = sim.popdict  # Use stored one
        sim.popdict = None  # Once loaded, remove
    elif sim['pop_type'] == 'campus':
        popdict = make_campus(sim)
    else:
        raise RuntimeWarning(
            "populationCampus.make_students only supports the value \'campus\' for \'pop_type\'"
        )
        popdict = make_campus(sim)

    # Ensure prognoses are set
    if sim['prognoses'] is None:
        sim['prognoses'] = cvpars.get_prognoses(sim['prog_by_age'])

    # Actually create the people
    people = stu.Students(
        sim,
        uid=popdict['uid'],
        age=popdict['age'],
        sex=popdict['sex'],
        contacts=popdict['contacts'])  # List for storing the people

    average_age = sum(popdict['age'] / pop_size)
    sc.printv(
        f'Created {pop_size} people, average age {average_age:0.2f} years', 2,
        verbose)

    if save_pop:
        if popfile is None:
            errormsg = 'Please specify a file to save to using the popfile kwarg'
            raise FileNotFoundError(errormsg)
        else:
            filepath = sc.makefilepath(filename=popfile)
            sc.saveobj(filepath, people)
            if verbose:
                print(
                    f'Saved population of type "{pop_type}" with {pop_size:n} people to {filepath}'
                )

    return people
Example #9
0
    def load_population(self, popfile=None, **kwargs):
        '''
        Load the population dictionary from file -- typically done automatically
        as part of sim.initialize(). Supports loading either saved population
        dictionaries (popdicts, file ending .pop by convention), or ready-to-go
        People objects (file ending .ppl by convention). Either object an also be
        supplied directly. Once a population file is loaded, it is removed from
        the Sim object.

        Args:
            popfile (str or obj): if a string, name of the file; otherwise, the popdict or People object to load
            kwargs (dict): passed to sc.makefilepath()
        '''
        # Set the file path if not is provided
        if popfile is None and self.popfile is not None:
            popfile = self.popfile

        # Handle the population (if it exists)
        if popfile is not None:

            # Load from disk or use directly
            if isinstance(popfile,
                          str):  # It's a string, assume it's a filename
                filepath = sc.makefilepath(filename=popfile, **kwargs)
                obj = cvm.load(filepath)
                if self['verbose']:
                    print(f'Loading population from {filepath}')
            else:
                obj = popfile  # Use it directly

            # Process the input
            if isinstance(obj, dict):
                self.popdict = obj
                n_actual = len(self.popdict['uid'])
                layer_keys = self.popdict['layer_keys']
            elif isinstance(obj, cvb.BasePeople):
                self.people = obj
                self.people.set_pars(
                    self.pars
                )  # Replace the saved parameters with this simulation's
                n_actual = len(self.people)
                layer_keys = self.people.layer_keys()
            else:
                errormsg = f'Cound not interpret input of {type(obj)} as a population file: must be a dict or People object'
                raise ValueError(errormsg)

            # Perform validation
            n_expected = self['pop_size']
            if n_actual != n_expected:
                errormsg = f'Wrong number of people ({n_expected:n} requested, {n_actual:n} actual) -- please change "pop_size" to match or regenerate the file'
                raise ValueError(errormsg)
            self.reset_layer_pars(
                force=False, layer_keys=layer_keys
            )  # Ensure that layer keys match the loaded population
            self.popfile = None  # Once loaded, remove to save memory

        return
Example #10
0
 def save(self, filename=None, folder=None, verbose=2):
     ''' Save the current project, by default using its name, and without results '''
     fullpath = sc.makefilepath(filename=filename,
                                folder=folder,
                                default=[self.filename, self.name],
                                ext='prj',
                                sanitize=True)
     self.filename = fullpath  # Store file path
     sc.saveobj(fullpath, self, verbose=verbose)
     return fullpath
Example #11
0
File: sim.py Project: willf/covasim
    def save_population(self, filename, **kwargs):
        '''
        Save the population dictionary to file.

        Args:
            filename (str): name of the file to save to.
        '''
        filepath = sc.makefilepath(filename=filename, **kwargs)
        sc.saveobj(filepath, self.popdict)
        return filepath
Example #12
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
Example #13
0
    def save(self, filename=None, keep_sims=True, keep_people=False, **kwargs):
        '''
        Save to disk as a gzipped pickle.

        Args:
            filename (str or None): the name or path of the file to save to; if None, uses stored
            keep_sims (bool): whether or not to store the actual Sim objects in the Scenarios object
            keep_people (bool): whether or not to store the population in the Sim objects (NB, very large)
            keywords: passed to makefilepath()

        Returns:
            filename (str): the validated absolute path to the saved file

        **Example**
        ::

            scens.save() # Saves to a .scens file with the date and time of creation by default

        '''
        if filename is None:
            filename = self.filename
        filename = sc.makefilepath(filename=filename, **kwargs)
        self.filename = filename  # Store the actual saved filename

        # Store sims seperately
        sims = self.sims
        self.sims = None  # Remove for now

        obj = sc.dcp(self)  # This should be quick once we've removed the sims
        if not keep_people:
            obj.base_sim.shrink(in_place=True)

        if keep_sims:
            if keep_people:
                if not obj._kept_people:
                    print(
                        'Warning: there are no people because they were not saved during the run. '
                        'If you want people, please rerun with keep_people=True.'
                    )
                obj.sims = sims  # Just restore the object in full
                print('Note: saving people, which may produce a large file!')
            else:
                obj.sims = sc.objdict()
                for key in sims.keys():
                    obj.sims[key] = []
                    for sim in sims[key]:
                        obj.sims[key].append(sim.shrink(in_place=False))

        sc.saveobj(filename=filename, obj=obj)  # Actually save

        self.sims = sims  # Restore
        return filename
Example #14
0
def train(beta: float = 0.015,
          pop_infected: int = 10,
          rel_death_prob: float = 1.0,
          rel_severe_prob: float = 1.0,
          rel_crit_prob: float = 1.0,
          start_day: str = '2019-12-25',
          datafile='tests/example_data.csv') -> None:
    """
    Perform hyperparameter sweep with Weights and Biases
    https://docs.wandb.com/sweeps
    """
    sc.makefilepath(datafile, checkexists=True)

    pars = dict(
        beta=beta,
        pop_infected=pop_infected,
        rel_death_prob=rel_death_prob,
        rel_crit_prob=rel_crit_prob,
        start_day=start_day,
    )

    # instantiate wandb run
    wb_handle = wandb.init(config=pars, project="covasim")
    run_id = wandb.run.id

    # Create and run the simulation
    sc.heading('Hyperparmeter Sweep')
    sim = cv.Sim(pars=pars, datafile=datafile)
    sim.run(verbose=False)
    likelihood = sim.likelihood()

    # log relevant metrics and artifacts
    wandb.log({'likelihood': likelihood})
    sim.plot(do_show=False,
             do_save=True,
             fig_path=sc.makefilepath(folder=wandb.run.dir,
                                      filename=f'{run_id}.png'))
    wandb.save(datafile)
    sc.saveobj(folder=wandb.run.dir, filename=f'pars_{run_id}.pkl', f)
Example #15
0
    def load_people(self, filename, **kwargs):
        '''
        Load the population dictionary from file.

        Args:
            filename (str): name of the file to load.
        '''
        filepath = sc.makefilepath(filename=filename, **kwargs)
        self.popdict = sc.loadobj(filepath)
        n_actual = len(self.popdict['uid'])
        n_expected = self['n']
        if n_actual != n_expected:
            errormsg = f'Wrong number of people ({n_expected} requested, {n_actual} actual) -- please change "n" to match or regenerate the file'
            raise ValueError(errormsg)
        return
Example #16
0
    def load(filename, **kwargs):
        '''
        Load from disk from a gzipped pickle.

        Args:
            filename (str): the name or path of the file to save to
            keywords: passed to makefilepath()

        Returns:
            scens (Scenarios): the loaded scenarios object

        Example:
            sim = cv.Scenarios.load('my-scenarios.scens')
        '''
        filename = sc.makefilepath(filename=filename, **kwargs)
        scens = sc.loadobj(filename=filename)
        return scens
Example #17
0
    def load(filename, **kwargs):
        '''
        Load from disk from a gzipped pickle.

        Args:
            filename (str): the name or path of the file to save to
            keywords: passed to makefilepath()

        Returns:
            sim (Sim): the loaded simulation object

        Example:
            sim = cv.Sim.load('my-simulation.sim')
        '''
        filename = sc.makefilepath(filename=filename, **kwargs)
        sim = sc.loadobj(filename=filename)
        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.")
Example #19
0
    def load_population(self, popfile=None, **kwargs):
        '''
        Load the population dictionary from file -- typically done automatically
        as part of sim.initialize(load_pop=True).

        Args:
            popfile (str): name of the file to load
        '''
        if popfile is None and self.popfile is not None:
            popfile = self.popfile
        if popfile is not None:
            filepath = sc.makefilepath(filename=popfile, **kwargs)
            self.popdict = sc.loadobj(filepath)
            n_actual = len(self.popdict['uid'])
            n_expected = self['pop_size']
            if n_actual != n_expected:
                errormsg = f'Wrong number of people ({n_expected:n} requested, {n_actual:n} actual) -- please change "pop_size" to match or regenerate the file'
                raise ValueError(errormsg)
            if self['verbose']:
                print(f'Loaded population from {filepath}')
        return
Example #20
0
    def save(self, filename=None, **kwargs):
        '''
        Save to disk as a gzipped pickle.

        Args:
            filename (str or None): the name or path of the file to save to; if None, uses stored
            keywords: passed to makefilepath()

        Returns:
            filename (str): the validated absolute path to the saved file

        Example:
            sim.save() # Saves to a .sim file with the date and time of creation by default

        '''
        if filename is None:
            filename = self.filename
        filename = sc.makefilepath(filename=filename, **kwargs)
        self.filename = filename  # Store the actual saved filename
        sc.saveobj(filename=filename, obj=self)
        return filename
Example #21
0
    def save(self, filename=None, keep_people=False, **kwargs):
        '''
        Save to disk as a gzipped pickle. Load with cv.load(filename) or
        cv.MultiSim.load(filename).

        Args:
            filename    (str)  : the name or path of the file to save to; if None, uses default
            keep_people (bool) : whether or not to store the population in the Sim objects (NB, very large)
            kwargs      (dict) : passed to makefilepath()

        Returns:
            scenfile (str): the validated absolute path to the saved file

        **Example**::

            msim.save() # Saves to an .msim file
        '''
        if filename is None:
            filename = 'covasim.msim'
        msimfile = sc.makefilepath(filename=filename, **kwargs)
        self.filename = filename  # Store the actual saved filename

        # Store sims seperately
        sims = self.sims
        self.sims = None  # Remove for now

        obj = sc.dcp(self)  # This should be quick once we've removed the sims
        if keep_people:
            obj.sims = sims  # Just restore the object in full
            print('Note: saving people, which may produce a large file!')
        else:
            obj.base_sim.shrink(in_place=True)
            obj.sims = []
            for sim in sims:
                obj.sims.append(sim.shrink(in_place=False))

        cvm.save(filename=msimfile, obj=obj)  # Actually save

        self.sims = sims  # Restore
        return msimfile
Example #22
0
    def save(self, filename=None, keep_people=None, skip_attrs=None, **kwargs):
        '''
        Save to disk as a gzipped pickle.

        Args:
            filename (str or None): the name or path of the file to save to; if None, uses stored
            kwargs: passed to sc.makefilepath()

        Returns:
            filename (str): the validated absolute path to the saved file

        **Example**::

            sim.save() # Saves to a .sim file with the date and time of creation by default
        '''

        # Set keep_people based on whether or not we're in the middle of a run
        if keep_people is None:
            if self.initialized and not self.results_ready:
                keep_people = True
            else:
                keep_people = False

        # Handle the filename
        if filename is None:
            filename = self.simfile
        filename = sc.makefilepath(filename=filename, **kwargs)
        self.filename = filename # Store the actual saved filename

        # Handle the shrinkage and save
        if skip_attrs or not keep_people:
            obj = self.shrink(skip_attrs=skip_attrs, in_place=False)
        else:
            obj = self
        cvm.save(filename=filename, obj=obj)

        return filename
Example #23
0
def make_people(sim,
                popdict=None,
                save_pop=False,
                popfile=None,
                die=True,
                reset=False,
                verbose=None,
                **kwargs):
    '''
    Make the actual people for the simulation. Usually called via sim.initialize(),
    not directly by the user.

    Args:
        sim      (Sim)  : the simulation object
        popdict  (dict) : if supplied, use this population dictionary rather than generate a new one
        save_pop (bool) : whether to save the population to disk
        popfile  (bool) : if so, the filename to save to
        die      (bool) : whether or not to fail if synthetic populations are requested but not available
        reset    (bool) : whether to force population creation even if self.popdict/self.people exists
        verbose  (bool) : level of detail to print
        kwargs   (dict) : passed to make_randpop() or make_synthpop()

    Returns:
        people (People): people
    '''

    # Set inputs and defaults
    pop_size = int(sim['pop_size'])  # Shorten
    pop_type = sim['pop_type']  # Shorten
    if verbose is None:
        verbose = sim['verbose']
    if popfile is None:
        popfile = sim.popfile

    # Check which type of population to produce
    if pop_type == 'synthpops':
        if not cvreq.check_synthpops():
            errormsg = f'You have requested "{pop_type}" population, but synthpops is not available; please use random, clustered, or hybrid'
            if die:
                raise ValueError(errormsg)
            else:
                print(errormsg)
                pop_type = 'random'

        location = sim['location']
        if location:
            print(
                f'Warning: not setting ages or contacts for "{location}" since synthpops contacts are pre-generated'
            )

    # Actually create the population
    if sim.people and not reset:
        return sim.people  # If it's already there, just return
    elif sim.popdict and not reset:
        popdict = sim.popdict  # Use stored one
        sim.popdict = None  # Once loaded, remove
    elif popdict is None:  # Main use case: no popdict is supplied
        # Create the population
        if pop_type in ['random', 'clustered', 'hybrid']:
            popdict = make_randpop(sim, microstructure=pop_type, **kwargs)
        elif pop_type == 'synthpops':
            popdict = make_synthpop(sim, **kwargs)
        elif pop_type is None:
            errormsg = f'You have set pop_type=None. This is fine, but you must ensure sim.popdict exists before calling make_people().'
            raise ValueError(errormsg)
        else:
            errormsg = f'Population type "{pop_type}" not found; choices are random, clustered, hybrid, or synthpops'
            raise ValueError(errormsg)

    # Ensure prognoses are set
    if sim['prognoses'] is None:
        sim['prognoses'] = cvpars.get_prognoses(sim['prog_by_age'])

    # Actually create the people
    people = cvppl.People(
        sim.pars,
        uid=popdict['uid'],
        age=popdict['age'],
        sex=popdict['sex'],
        contacts=popdict['contacts'])  # List for storing the people

    average_age = sum(popdict['age'] / pop_size)
    sc.printv(
        f'Created {pop_size} people, average age {average_age:0.2f} years', 2,
        verbose)

    if save_pop:
        if popfile is None:
            errormsg = 'Please specify a file to save to using the popfile kwarg'
            raise FileNotFoundError(errormsg)
        else:
            filepath = sc.makefilepath(filename=popfile)
            cvm.save(filepath, people)
            if verbose:
                print(
                    f'Saved population of type "{pop_type}" with {pop_size:n} people to {filepath}'
                )

    return people
Example #24
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")
Example #25
0
    def plot(self,
             to_plot=None,
             do_save=None,
             fig_path=None,
             fig_args=None,
             plot_args=None,
             axis_args=None,
             fill_args=None,
             legend_args=None,
             as_dates=True,
             dateformat=None,
             interval=None,
             n_cols=1,
             font_size=18,
             font_family=None,
             grid=True,
             commaticks=True,
             do_show=True,
             sep_figs=False,
             verbose=None):
        '''
        Plot the results -- can supply arguments for both the figure and the plots.

        Args:
            to_plot     (dict): Dict of results to plot; see default_scen_plots for structure
            do_save     (bool): Whether or not to save the figure
            fig_path    (str):  Path to save the figure
            fig_args    (dict): Dictionary of kwargs to be passed to pl.figure()
            plot_args   (dict): Dictionary of kwargs to be passed to pl.plot()
            axis_args   (dict): Dictionary of kwargs to be passed to pl.subplots_adjust()
            fill_args   (dict): Dictionary of kwargs to be passed to pl.fill_between()
            legend_args (dict): Dictionary of kwargs to be passed to pl.legend()
            as_dates    (bool): Whether to plot the x-axis as dates or time points
            dateformat  (str):  Date string format, e.g. '%B %d'
            interval    (int):  Interval between tick marks
            n_cols      (int):  Number of columns of subpanels to use for subplot
            font_size   (int):  Size of the font
            font_family (str):  Font face
            grid        (bool): Whether or not to plot gridlines
            commaticks  (bool): Plot y-axis with commas rather than scientific notation
            do_show     (bool): Whether or not to show the figure
            sep_figs    (bool): Whether to show separate figures for different results instead of subplots
            verbose     (bool): Display a bit of extra information

        Returns:
            fig: Figure handle
        '''

        if verbose is None:
            verbose = self['verbose']
        sc.printv('Plotting...', 1, verbose)

        if to_plot is None:
            to_plot = cvd.default_scen_plots
        to_plot = sc.dcp(to_plot)  # In case it's supplied as a dict

        # Handle input arguments -- merge user input with defaults
        fig_args = sc.mergedicts({'figsize': (16, 14)}, fig_args)
        plot_args = sc.mergedicts({'lw': 3, 'alpha': 0.7}, plot_args)
        axis_args = sc.mergedicts(
            {
                'left': 0.10,
                'bottom': 0.05,
                'right': 0.95,
                'top': 0.90,
                'wspace': 0.25,
                'hspace': 0.25
            }, axis_args)
        fill_args = sc.mergedicts({'alpha': 0.2}, fill_args)
        legend_args = sc.mergedicts({'loc': 'best'}, legend_args)

        if sep_figs:
            figs = []
        else:
            fig = pl.figure(**fig_args)
        pl.subplots_adjust(**axis_args)
        pl.rcParams['font.size'] = font_size
        if font_family:
            pl.rcParams['font.family'] = font_family

        n_rows = np.ceil(len(to_plot) /
                         n_cols)  # Number of subplot rows to have
        for rk, reskey in enumerate(to_plot):
            title = self.base_sim.results[
                reskey].name  # Get the name of this result from the base simulation
            if sep_figs:
                figs.append(pl.figure(**fig_args))
                ax = pl.subplot(111)
            else:
                ax = pl.subplot(n_rows, n_cols, rk + 1)

            resdata = self.results[reskey]

            for scenkey, scendata in resdata.items():

                pl.fill_between(self.tvec, scendata.low, scendata.high,
                                **fill_args)
                pl.plot(self.tvec,
                        scendata.best,
                        label=scendata.name,
                        **plot_args)
                pl.title(title)
                if rk == 0:
                    pl.legend(**legend_args)

                pl.grid(grid)
                if commaticks:
                    sc.commaticks()

                if self.base_sim.data is not None and reskey in self.base_sim.data:
                    data_t = np.array(
                        (self.base_sim.data.index - self.base_sim['start_day'])
                        / np.timedelta64(1, 'D'))
                    pl.plot(data_t, self.base_sim.data[reskey], 'sk',
                            **plot_args)

                # Optionally reset tick marks (useful for e.g. plotting weeks/months)
                if interval:
                    xmin, xmax = ax.get_xlim()
                    ax.set_xticks(pl.arange(xmin, xmax + 1, interval))

                # Set xticks as dates
                if as_dates:

                    @ticker.FuncFormatter
                    def date_formatter(x, pos):
                        return (self.base_sim['start_day'] +
                                dt.timedelta(days=x)).strftime('%b-%d')

                    ax.xaxis.set_major_formatter(date_formatter)
                    if not interval:
                        ax.xaxis.set_major_locator(
                            ticker.MaxNLocator(integer=True))

        # Ensure the figure actually renders or saves
        if do_save:
            if fig_path is None:  # No figpath provided - see whether do_save is a figpath
                fig_path = 'covasim_scenarios.png'  # Just give it a default name
            fig_path = sc.makefilepath(
                fig_path)  # Ensure it's valid, including creating the folder
            pl.savefig(fig_path)

        if do_show:
            pl.show()
        else:
            pl.close(fig)

        return fig
Example #26
0
    def plot(self,
             to_plot=None,
             do_save=None,
             fig_path=None,
             fig_args=None,
             plot_args=None,
             scatter_args=None,
             axis_args=None,
             as_dates=True,
             interval=None,
             dateformat=None,
             font_size=18,
             font_family=None,
             use_grid=True,
             use_commaticks=True,
             do_show=True,
             verbose=None):
        '''
        Plot the results -- can supply arguments for both the figure and the plots.

        Args:
            to_plot (dict): Nested dict of results to plot; see default_sim_plots for structure
            do_save (bool or str): Whether or not to save the figure. If a string, save to that filename.
            fig_path (str): Path to save the figure
            fig_args (dict): Dictionary of kwargs to be passed to pl.figure()
            plot_args (dict): Dictionary of kwargs to be passed to pl.plot()
            scatter_args (dict): Dictionary of kwargs to be passed to pl.scatter()
            axis_args (dict): Dictionary of kwargs to be passed to pl.subplots_adjust()
            as_dates (bool): Whether to plot the x-axis as dates or time points
            interval (int): Interval between tick marks
            dateformat (str): Date string format, e.g. '%B %d'
            font_size (int): Size of the font
            font_family (str): Font face
            use_grid (bool): Whether or not to plot gridlines
            use_commaticks (bool): Plot y-axis with commas rather than scientific notation
            do_show (bool): Whether or not to show the figure
            verbose (bool): Display a bit of extra information

        Returns:
            fig: Figure handle
        '''

        if verbose is None:
            verbose = self['verbose']
        sc.printv('Plotting...', 1, verbose)

        if to_plot is None:
            to_plot = default_sim_plots
        to_plot = sc.odict(to_plot)  # In case it's supplied as a dict

        # Handle input arguments -- merge user input with defaults
        fig_args = sc.mergedicts({'figsize': (16, 12)}, fig_args)
        plot_args = sc.mergedicts({'lw': 3, 'alpha': 0.7}, plot_args)
        scatter_args = sc.mergedicts({'s': 150, 'marker': 's'}, scatter_args)
        axis_args = sc.mergedicts(
            {
                'left': 0.1,
                'bottom': 0.05,
                'right': 0.9,
                'top': 0.97,
                'wspace': 0.2,
                'hspace': 0.25
            }, axis_args)

        fig = pl.figure(**fig_args)
        pl.subplots_adjust(**axis_args)
        pl.rcParams['font.size'] = font_size
        if font_family:
            pl.rcParams['font.family'] = font_family

        res = self.results  # Shorten since heavily used

        # Plot everything

        colors = sc.gridcolors(max([len(tp) for tp in to_plot.values()]))

        # Define the data mapping. Must be here since uses functions
        if self.data is not None and len(self.data):
            data_mapping = {
                'cum_exposed': pl.cumsum(self.data['new_infections']),
                'cum_diagnosed': pl.cumsum(self.data['new_positives']),
                'cum_tested': pl.cumsum(self.data['new_tests']),
                'infections': self.data['new_infections'],
                'tests': self.data['new_tests'],
                'diagnoses': self.data['new_positives'],
            }
        else:
            data_mapping = {}

        for p, title, keylabels in to_plot.enumitems():
            ax = pl.subplot(2, 1, p + 1)
            for i, key, label in keylabels.enumitems():
                this_color = colors[i]
                y = res[key].values
                pl.plot(res['t'], y, label=label, **plot_args, c=this_color)
                if key in data_mapping:
                    pl.scatter(self.data['day'],
                               data_mapping[key],
                               c=[this_color],
                               **scatter_args)
            if self.data is not None and len(self.data):
                pl.scatter(pl.nan,
                           pl.nan,
                           c=[(0, 0, 0)],
                           label='Data',
                           **scatter_args)

            pl.grid(use_grid)
            cvu.fixaxis(self)
            if use_commaticks:
                sc.commaticks()
            pl.title(title)

            # Optionally reset tick marks (useful for e.g. plotting weeks/months)
            if interval:
                xmin, xmax = ax.get_xlim()
                ax.set_xticks(pl.arange(xmin, xmax + 1, interval))

            # Set xticks as dates
            if as_dates:
                xticks = ax.get_xticks()
                xticklabels = self.inds2dates(xticks, dateformat=dateformat)
                ax.set_xticklabels(xticklabels)

            # Plot interventions
            for intervention in self['interventions']:
                intervention.plot(self, ax)

        # Ensure the figure actually renders or saves
        if do_save:
            if fig_path is None:  # No figpath provided - see whether do_save is a figpath
                if isinstance(do_save, str):
                    fig_path = do_save  # It's a string, assume it's a filename
                else:
                    fig_path = 'covasim.png'  # Just give it a default name
            fig_path = sc.makefilepath(
                fig_path)  # Ensure it's valid, including creating the folder
            pl.savefig(fig_path)

        if do_show:
            pl.show()
        else:
            pl.close(fig)

        return fig
Example #27
0
    def plot(self, to_plot=None, do_save=None, fig_path=None, fig_args=None, plot_args=None,
             axis_args=None, fill_args=None, as_dates=True, interval=None, dateformat=None,
             font_size=18, font_family=None, grid=True, commaticks=True, do_show=True, sep_figs=False,
             verbose=None):
        '''
        Plot the results -- can supply arguments for both the figure and the plots.

        Args:
            to_plot     (dict): Dict of results to plot; see default_scen_plots for structure
            do_save     (bool): Whether or not to save the figure
            fig_path    (str):  Path to save the figure
            fig_args    (dict): Dictionary of kwargs to be passed to pl.figure()
            plot_args   (dict): Dictionary of kwargs to be passed to pl.plot()
            axis_args   (dict): Dictionary of kwargs to be passed to pl.subplots_adjust()
            fill_args   (dict): Dictionary of kwargs to be passed to pl.fill_between()
            as_dates    (bool): Whether to plot the x-axis as dates or time points
            interval    (int):  Interval between tick marks
            dateformat  (str):  Date string format, e.g. '%B %d'
            font_size   (int):  Size of the font
            font_family (str):  Font face
            grid        (bool): Whether or not to plot gridlines
            commaticks  (bool): Plot y-axis with commas rather than scientific notation
            do_show     (bool): Whether or not to show the figure
            sep_figs    (bool): Whether to show separate figures for different results instead of subplots
            verbose     (bool): Display a bit of extra information

        Returns:
            fig: Figure handle
        '''

        if verbose is None:
            verbose = self['verbose']
        sc.printv('Plotting...', 1, verbose)

        if to_plot is None:
            to_plot = default_scen_plots
        to_plot = sc.odict(sc.dcp(to_plot)) # In case it's supplied as a dict

        # Handle input arguments -- merge user input with defaults
        fig_args  = sc.mergedicts({'figsize': (16, 12)}, fig_args)
        plot_args = sc.mergedicts({'lw': 3, 'alpha': 0.7}, plot_args)
        axis_args = sc.mergedicts({'left': 0.10, 'bottom': 0.05, 'right': 0.95, 'top': 0.90, 'wspace': 0.5, 'hspace': 0.25}, axis_args)
        fill_args = sc.mergedicts({'alpha': 0.2}, fill_args)

        if sep_figs:
            figs = []
        else:
            fig = pl.figure(**fig_args)
        pl.subplots_adjust(**axis_args)
        pl.rcParams['font.size'] = font_size
        if font_family:
            pl.rcParams['font.family'] = font_family

        # %% Plotting
        for rk,reskey,title in to_plot.enumitems():
            if sep_figs:
                figs.append(pl.figure(**fig_args))
                ax = pl.subplot(111)
            else:
                ax = pl.subplot(len(to_plot), 1, rk + 1)

            resdata = self.allres[reskey]

            for scenkey, scendata in resdata.items():

                pl.fill_between(self.tvec, scendata.low, scendata.high, **fill_args)
                pl.plot(self.tvec, scendata.best, label=scendata.name, **plot_args)
                pl.title(title)
                if rk == 0:
                    pl.legend(loc='best')

                pl.grid(grid)
                if commaticks:
                    sc.commaticks()

                # Optionally reset tick marks (useful for e.g. plotting weeks/months)
                if interval:
                    xmin,xmax = ax.get_xlim()
                    ax.set_xticks(pl.arange(xmin, xmax+1, interval))

                # Set xticks as dates
                if as_dates:
                    xticks = ax.get_xticks()
                    xticklabels = self.base_sim.inds2dates(xticks, dateformat=dateformat)
                    ax.set_xticklabels(xticklabels)

        # Ensure the figure actually renders or saves
        if do_save:
            if fig_path is None: # No figpath provided - see whether do_save is a figpath
                fig_path = 'covasim_scenarios.png' # Just give it a default name
            fig_path = sc.makefilepath(fig_path) # Ensure it's valid, including creating the folder
            pl.savefig(fig_path)

        if do_show:
            pl.show()
        else:
            pl.close(fig)

        return fig
Example #28
0
File: sim.py Project: willf/covasim
    def plot(self,
             to_plot=None,
             do_save=None,
             fig_path=None,
             fig_args=None,
             plot_args=None,
             scatter_args=None,
             axis_args=None,
             legend_args=None,
             as_dates=True,
             dateformat=None,
             interval=None,
             n_cols=1,
             font_size=18,
             font_family=None,
             use_grid=True,
             use_commaticks=True,
             do_show=True,
             verbose=None):
        '''
        Plot the results -- can supply arguments for both the figure and the plots.

        Args:
            to_plot (dict): Nested dict of results to plot; see default_sim_plots for structure
            do_save (bool or str): Whether or not to save the figure. If a string, save to that filename.
            fig_path (str): Path to save the figure
            fig_args (dict): Dictionary of kwargs to be passed to pl.figure()
            plot_args (dict): Dictionary of kwargs to be passed to pl.plot()
            scatter_args (dict): Dictionary of kwargs to be passed to pl.scatter()
            axis_args (dict): Dictionary of kwargs to be passed to pl.subplots_adjust()
            legend_args (dict): Dictionary of kwargs to be passed to pl.legend()
            as_dates (bool): Whether to plot the x-axis as dates or time points
            dateformat (str): Date string format, e.g. '%B %d'
            interval (int): Interval between tick marks
            n_cols (int): Number of columns of subpanels to use for subplot
            font_size (int): Size of the font
            font_family (str): Font face
            use_grid (bool): Whether or not to plot gridlines
            use_commaticks (bool): Plot y-axis with commas rather than scientific notation
            do_show (bool): Whether or not to show the figure
            verbose (bool): Display a bit of extra information

        Returns:
            fig: Figure handle
        '''

        if verbose is None:
            verbose = self['verbose']
        sc.printv('Plotting...', 1, verbose)

        if to_plot is None:
            to_plot = cvd.default_sim_plots
        to_plot = sc.odict(to_plot)  # In case it's supplied as a dict

        # Handle input arguments -- merge user input with defaults
        fig_args = sc.mergedicts({'figsize': (16, 14)}, fig_args)
        plot_args = sc.mergedicts({'lw': 3, 'alpha': 0.7}, plot_args)
        scatter_args = sc.mergedicts({'s': 70, 'marker': 's'}, scatter_args)
        axis_args = sc.mergedicts(
            {
                'left': 0.1,
                'bottom': 0.05,
                'right': 0.9,
                'top': 0.97,
                'wspace': 0.2,
                'hspace': 0.25
            }, axis_args)
        legend_args = sc.mergedicts({'loc': 'best'}, legend_args)

        fig = pl.figure(**fig_args)
        pl.subplots_adjust(**axis_args)
        pl.rcParams['font.size'] = font_size
        if font_family:
            pl.rcParams['font.family'] = font_family

        res = self.results  # Shorten since heavily used

        # Plot everything
        n_rows = np.ceil(len(to_plot) /
                         n_cols)  # Number of subplot rows to have
        for p, title, keylabels in to_plot.enumitems():
            ax = pl.subplot(n_rows, n_cols, p + 1)
            for key in keylabels:
                label = res[key].name
                this_color = res[key].color
                y = res[key].values
                pl.plot(res['t'], y, label=label, **plot_args, c=this_color)
                if self.data is not None and key in self.data:
                    data_t = (
                        self.data.index - self['start_day']
                    ) / np.timedelta64(
                        1, 'D'
                    )  # Convert from data date to model output index based on model start date
                    pl.scatter(data_t,
                               self.data[key],
                               c=[this_color],
                               **scatter_args)
            if self.data is not None and len(self.data):
                pl.scatter(pl.nan,
                           pl.nan,
                           c=[(0, 0, 0)],
                           label='Data',
                           **scatter_args)

            pl.legend(**legend_args)
            pl.grid(use_grid)
            sc.setylim()
            if use_commaticks:
                sc.commaticks()
            pl.title(title)

            # Optionally reset tick marks (useful for e.g. plotting weeks/months)
            if interval:
                xmin, xmax = ax.get_xlim()
                ax.set_xticks(pl.arange(xmin, xmax + 1, interval))

            # Set xticks as dates
            if as_dates:

                @ticker.FuncFormatter
                def date_formatter(x, pos):
                    return (self['start_day'] +
                            dt.timedelta(days=x)).strftime('%b-%d')

                ax.xaxis.set_major_formatter(date_formatter)
                if not interval:
                    ax.xaxis.set_major_locator(
                        ticker.MaxNLocator(integer=True))

            # Plot interventions
            for intervention in self['interventions']:
                intervention.plot(self, ax)

        # Ensure the figure actually renders or saves
        if do_save:
            if fig_path is None:  # No figpath provided - see whether do_save is a figpath
                if isinstance(do_save, str):
                    fig_path = do_save  # It's a string, assume it's a filename
                else:
                    fig_path = 'covasim.png'  # Just give it a default name
            fig_path = sc.makefilepath(
                fig_path)  # Ensure it's valid, including creating the folder
            pl.savefig(fig_path)

        if do_show:
            pl.show()
        else:
            pl.close(fig)

        return fig
Example #29
0
def plot_school_sizes(pop, **kwargs):
    """
    Plot a comparison of the expected and generated school size distribution for
    each type of school expected.

    Args:
        pop (pop object)                : population, either synthpops.pop.Pop, or dict
        **with_school_types (type)      : If True, plot school size distributions by type, else plot overall school size distributions
        **keys_to_exclude (str or list) : school types to exclude
        **left (float)                  : Matplotlib.figure.subplot.left
        **right (float)                 : Matplotlib.figure.subplot.right
        **top (float)                   : Matplotlib.figure.subplot.top
        **bottom (float)                : Matplotlib.figure.subplot.bottom
        **hspace (float)                : Matplotlib.figure.subplot.hspace
        **subplot_height (float)        : height of subplot in inches
        **subplot_width (float)         : width of subplot in inches
        **screen_height_factor (float)  : fraction of the screen height to use for display
        **location_text_y (float)       : height to add location text to figure
        **fontsize (float)              : Matplotlib.figure.fontsize
        **rotation (float)              : rotation angle for xticklabels
        **cmap (str)                    : colormap
        **figname (str)                 : name to save figure to disk
        **comparison (bool)             : If True, plot comparison to the generated population

    Returns:
        Matplotlib figure and axes.

    Note:
        If using pop with type covasim.people.Pop or dict, args must be supplied
        for the location parameters to get the expected distribution.

    **Example**::

        pars = {'n': 10e3, location='seattle_metro', state_location='Washington', country_location='usa'}
        pop = sp.Pop(**pars)
        fig, ax = pop.plot_school_sizes_by_type()

        popdict = pop.to_dict()
        kwargs = pars.copy()
        kwargs['datadir'] = sp.datadir
        fig, ax = sp.plot_school_sizes(popdict, **kwargs)
    """
    plkwargs = get_plkwargs(pop)

    # method specific plotting defaults
    method_defaults = dict(
        with_school_types=False,
        keys_to_exclude=['uv'],
        left=0.11,
        right=0.94,
        top=0.96,
        bottom=0.08,
        hspace=0.75,
        subplot_height=2.8,
        subplot_width=4.2,
        screen_height_factor=0.85,
        location_text_y=113,
        fontsize=8,
        rotation=25,
        cmap='cmo.curl',
        figname='school_size_distribution_by_type',
        comparison=True,
        school_type_labels=spsch.get_school_type_labels(),
    )

    plkwargs.update_defaults(method_defaults, kwargs)
    plkwargs.set_font()

    if isinstance(plkwargs.keys_to_exclude, str):
        plkwargs.keys_to_exclude = [plkwargs.keys_to_exclude
                                    ]  # ensure this is treated as a list

    # define after plkwargs gets updated
    if isinstance(pop, sppop.Pop):
        plkwargs.loc_pars = pop.loc_pars
        plkwargs.smooth_ages = pop.smooth_ages
        plkwargs.window_length = pop.window_length
        popdict = sc.dcp(pop.to_dict())

    elif isinstance(pop, dict):
        popdict = sc.dcp(pop)

    else:
        raise ValueError(
            f"This method does not support pop objects with the type {type(pop)}. Please look at the notes and try another supported pop type."
        )

    # now check for missing plkwargs and use default values if not found
    plkwargs.set_default_pop_pars()

    if plkwargs.with_school_types:
        expected_school_size_dist = spdata.get_school_size_distr_by_type(
            **plkwargs.loc_pars)
    else:
        plkwargs.school_type_labels = {None: ''}
        expected_school_size_dist = {
            None: spdata.get_school_size_distr_by_brackets(**plkwargs.loc_pars)
        }

    school_size_brackets = spdata.get_school_size_brackets(**plkwargs.loc_pars)
    bins = spsch.get_bin_edges(school_size_brackets)
    bin_labels = spsch.get_bin_labels(school_size_brackets)

    # calculate how many students are in each school
    if plkwargs.comparison:
        enrollment_by_school_type = spsch.get_enrollment_by_school_type(
            popdict,
            **dict(with_school_types=plkwargs.with_school_types,
                   keys_to_exclude=plkwargs.keys_to_exclude))
        generated_school_size_dist = sc.objdict(
            spsch.get_generated_school_size_distributions(
                enrollment_by_school_type, bins))

    for school_type in plkwargs.keys_to_exclude:
        expected_school_size_dist.pop(school_type, None)
        plkwargs.school_type_labels.pop(school_type, None)

    sorted_school_types = sorted(expected_school_size_dist.keys())
    n_school_types = len(sorted_school_types)
    plkwargs.nrows = n_school_types

    # location text
    if plkwargs.location is not None:
        location_text = f"{plkwargs.location.replace('_', ' ').title()}"
    else:
        location_text = f"{cfg.default_location.replace('_', ' ').title()}"

    # create fig, ax, set cmap
    fig, ax = plt.subplots(n_school_types,
                           1,
                           figsize=(plkwargs.display_width,
                                    plkwargs.display_height),
                           dpi=plkwargs.display_dpi)
    cmap = mplt.cm.get_cmap(plkwargs.cmap)

    # readjust figure parameters
    if plkwargs.nrows == 1:
        ax = [ax]
        fig.set_size_inches(plkwargs.display_width,
                            plkwargs.display_height * 0.47)
        plkwargs.update(dict(top=0.88, bottom=0.18, left=0.12))
        plkwargs.location_text_y = 105.5  # default value for singular school type -- you have the ability to change this by supplying the kwarg location_text_y

    # update the fig
    fig.subplots_adjust(**plkwargs.axis)

    for ns, school_type in enumerate(plkwargs.school_type_labels.keys()):
        x = np.arange(
            len(school_size_brackets)
        )  # potentially will use different bins for each school type so placeholder for now
        c = ns / n_school_types
        c2 = min(c + 0.12, 1)

        sorted_bins = sorted(expected_school_size_dist[school_type].keys())

        ax[ns].bar(x, [
            expected_school_size_dist[school_type][b] * 100
            for b in sorted_bins
        ],
                   color=cmap(c),
                   edgecolor=cmap(c2),
                   label='Expected',
                   zorder=0)
        if plkwargs.comparison:
            ax[ns].plot(x, [
                generated_school_size_dist[school_type][b] * 100
                for b in sorted_bins
            ],
                        color=cmap(c2),
                        ls='--',
                        marker='o',
                        markerfacecolor=cmap(c2),
                        markeredgecolor='white',
                        markeredgewidth=.5,
                        markersize=plkwargs.markersize,
                        label='Generated',
                        zorder=1)
            leg = ax[ns].legend(loc=1, fontsize=plkwargs.fontsize)
            leg.draw_frame(False)
        ax[ns].set_xticks(x)
        ax[ns].set_xticklabels(bin_labels,
                               rotation=plkwargs.rotation,
                               fontsize=plkwargs.fontsize,
                               verticalalignment='center_baseline')
        ax[ns].set_xlim(-0.6 + x[0], x[-1] + 0.6)
        ax[ns].set_ylim(0, 100)
        ax[ns].set_ylabel('%', fontsize=plkwargs.fontsize + 1)
        ax[ns].tick_params(labelsize=plkwargs.fontsize - 1)
        if school_type is None:
            title = "Without school types defined"
        else:
            title = f"{plkwargs.school_type_labels[school_type]}"
        if ns == 0:
            ax[ns].text(-0.6,
                        plkwargs.location_text_y,
                        location_text,
                        horizontalalignment='left',
                        fontsize=plkwargs.fontsize + 1,
                        verticalalignment='top')
        ax[ns].set_title(title,
                         fontsize=plkwargs.fontsize + 1,
                         verticalalignment='top')
    ax[ns].set_xlabel('School size',
                      fontsize=plkwargs.fontsize + 1,
                      verticalalignment='center_baseline')

    # for multipanel figures, first display then re-adjust it and save to disk
    if plkwargs.do_show:
        plt.show()

    # update fig before saving to disk since display will modify things
    if plkwargs.do_save:
        if len(ax) == 1:
            fig.set_size_inches(plkwargs.width, plkwargs.height)

        else:
            cfg.logger.info(
                "Setting default plotting parameters to save figure to disk. If these settings produce figures you would prefer to change, this method returns the figure and ax for you to modify and save to disk."
            )
            fig.set_size_inches(plkwargs.display_width,
                                plkwargs.display_height)
            plkwargs.update(dict(bottom=0.075, hspace=0.52, left=0.12))

        fig.subplots_adjust(**plkwargs.axis)

        plkwargs.figpath = sc.makefilepath(filename=plkwargs.figname,
                                           folder=plkwargs.figdir,
                                           ext=plkwargs.format)
        fig.savefig(plkwargs.figpath,
                    format=plkwargs.format,
                    dpi=plkwargs.save_dpi)

    return fig, ax
Example #30
0
def make_people(sim,
                save_pop=False,
                popfile=None,
                verbose=None,
                die=True,
                reset=False):
    '''
    Make the actual people for the simulation.

    Args:
        sim (Sim): the simulation object
        verbose (bool): level of detail to print
        id_len (int): length of ID for each person (default: calculate required length based on the number of people)
        die (bool): whether or not to fail if synthetic populations are requested but not available
        reset (bool): whether to force population creation even if self.popdict exists

    Returns:
        None.
    '''

    # Set inputs and defaults
    pop_size = int(sim['pop_size'])  # Shorten
    pop_type = sim['pop_type']  # Shorten
    if verbose is None:
        verbose = sim['verbose']
    if popfile is None:
        popfile = sim.popfile

    # Check which type of population to produce
    if pop_type == 'synthpops':
        if not cvreq.check_synthpops():
            errormsg = f'You have requested "{pop_type}" population, but synthpops is not available; please use random, clustered, or hybrid'
            if die:
                raise ValueError(errormsg)
            else:
                print(errormsg)
                pop_type = 'random'

        location = sim['location']
        if location:
            print(
                f'Warning: not setting ages or contacts for "{location}" since synthpops contacts are pre-generated'
            )

    # Actually create the population
    if sim.popdict and not reset:
        popdict = sim.popdict  # Use stored one
        layer_keys = list(popdict['contacts']
                          [0].keys())  # Assume there's at least one contact!
        sim.popdict = None  # Once loaded, remove
    else:
        # Create the population
        if pop_type in ['random', 'clustered', 'hybrid']:
            popdict, layer_keys = make_randpop(sim, microstructure=pop_type)
        elif pop_type == 'synthpops':
            popdict, layer_keys = make_synthpop(sim)
        else:
            errormsg = f'Population type "{pop_type}" not found; choices are random, clustered, hybrid, or synthpops'
            raise ValueError(errormsg)

    # Ensure prognoses are set
    if sim['prognoses'] is None:
        sim['prognoses'] = cvpars.get_prognoses(sim['prog_by_age'])

    # Actually create the people
    sim.layer_keys = layer_keys
    people = cvppl.People(sim.pars, **popdict)  # List for storing the people
    sim.people = people

    average_age = sum(popdict['age'] / pop_size)
    sc.printv(
        f'Created {pop_size} people, average age {average_age:0.2f} years', 2,
        verbose)

    if save_pop:
        if popfile is None:
            errormsg = 'Please specify a file to save to using the popfile kwarg'
            raise FileNotFoundError(errormsg)
        else:
            filepath = sc.makefilepath(filename=popfile)
            sc.saveobj(filepath, popdict)
            if verbose:
                print(
                    f'Saved population of type "{pop_type}" with {pop_size:n} people to {filepath}'
                )

    return