Beispiel #1
0
def test_uuid():
    ''' Test UID generation '''
    import uuid
    u0 = uuid.uuid4()
    u1 = sc.uuid()
    u2 = sc.uuid()
    u3 = sc.uuid(length=4)
    assert u1 != u2
    assert isinstance(u1, type(u0))
    assert isinstance(u3, str)
    with pytest.raises(ValueError):
        sc.uuid(length=400)
    print(f'UIDs:\n{u0}\n{u1}\n{u2}\n{u3}')
    return u3
Beispiel #2
0
    def __init__(self,
                 username=None,
                 password=None,
                 displayname=None,
                 email=None,
                 uid=None,
                 raw_password=None,
                 is_admin=False):
        # Handle general properties
        if not username: username = '******'
        if not password: password = '******'
        if not displayname: displayname = username
        if not uid: uid = sc.uuid()

        # Set user-specific properties
        self.username = username  # Set the username.
        self.displayname = displayname  # Set the displayname (what the browser will show).
        self.email = email  # Set the user's email.
        self.uid = uid  # The user's UID
        self.is_authenticated = True  # Set the user to be authentic.
        self.is_active = True  # Set the account to be active.
        self.is_anonymous = False  # The user is not anonymous.
        self.is_admin = is_admin  # Set whether this user has admin rights.

        # Handle the password
        if raw_password is not None:
            if six.PY3: raw_password = raw_password.encode('utf-8')
            password = sc.sha(raw_password).hexdigest()
        self.password = password
        return None
Beispiel #3
0
def plot_people(sim) -> dict:
    z, states = get_individual_states(sim)

    fig = go.Figure()

    for state in states[::-1]:  # Reverse order for plotting
        fig.add_trace(go.Scatter(
            x=sim.tvec, y=(z == state['value']).sum(axis=0),
            stackgroup='one',
            line=dict(width=0.5, color=state['color']),
            fillcolor=state['color'],
            hoverinfo="y+name",
            name=state['name']
        ))

    if sim['interventions']:
        interv_day = sim['interventions'][0].days[0]
        if interv_day > 0 and interv_day < sim['n_days']:
            fig.add_shape(dict(type="line", xref="x", yref="paper", x0=interv_day, x1=interv_day, y0=0, y1=1, name='Intervention', line=dict(width=0.5, dash='dash')))
            fig.update_layout(annotations=[dict(x=interv_day, y=1.07, xref="x", yref="paper", text="Intervention start", showarrow=False)])

    fig.update_layout(yaxis_range=(0, sim.n))
    fig.update_layout(title={'text': 'Numbers of people by health state'}, xaxis_title='Day', yaxis_title='People', autosize=True)

    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
Beispiel #4
0
def save_new_project(proj, username=None, uid=None):
    """
    If we're creating a new project, we need to do some operations on it to
    make sure it's valid for the webapp.
    """
    # Preliminaries
    new_project = sc.dcp(proj)  # Copy the project, only save what we want...
    new_project.uid = sc.uuid(uid)

    # Get unique name
    user = get_user(username)
    current_project_names = []
    for project_key in user.projects:
        proj = load_project(project_key)
        current_project_names.append(proj.name)
    new_project_name = sc.uniquename(new_project.name,
                                     namelist=current_project_names)
    new_project.name = new_project_name

    # Ensure it's a valid webapp project
    if not hasattr(new_project, 'webapp'):
        new_project.webapp = sc.prettyobj()
        new_project.webapp.username = username  # If we ever use Celery with HealthPrior: new_project.webapp.tasks = []
    new_project.webapp.username = username  # Make sure we have the current username

    # Save all the things
    key = save_project(new_project)
    if key not in user.projects:  # Let's not allow multiple copies
        user.projects.append(key)
        datastore.saveuser(user)
    return key, new_project
Beispiel #5
0
    def __init__(self, name=None, project=None, filename=None, folder=None):
        if name is None: name = 'Default'
        self.projectref = sc.Link(project)  # Store pointer for the project
        self.name = sc.uniquename(
            name, namelist=self.projectref().burdensets.keys(
            ))  # Name of the parameter set, e.g. 'default'
        self.uid = sc.uuid()  # ID
        self.created = sc.now()  # Date created
        self.modified = sc.now()  # Date modified

        # Define hard-coded column names
        self.colnames = sc.odict([
            ('active', 'Active'),
            #('code',       'Code'),
            ('cause', 'Cause'),
            ('dalys', 'DALYs'),
            ('deaths', 'Deaths'),
            ('prevalence', 'Prevalence')
        ])

        # Load data, if provided
        self.data = None
        if filename is not None:
            self.loaddata(filename=filename, folder=folder)

        return None
Beispiel #6
0
def make_randpop(sim, id_len=6):
    ''' Make a random population, without contacts '''

    # Load age data based on 2018 Seattle demographics
    age_data = np.array([
        [0, 4, 0.0605],
        [5, 9, 0.0607],
        [10, 14, 0.0566],
        [15, 19, 0.0557],
        [20, 24, 0.0612],
        [25, 29, 0.0843],
        [30, 34, 0.0848],
        [35, 39, 0.0764],
        [40, 44, 0.0697],
        [45, 49, 0.0701],
        [50, 54, 0.0681],
        [55, 59, 0.0653],
        [60, 64, 0.0591],
        [65, 69, 0.0453],
        [70, 74, 0.0312],
        [75, 79, 0.02016],  # Calculated based on 0.0504 total for >=75
        [80, 84, 0.01344],
        [85, 89, 0.01008],
        [90, 99, 0.00672],
    ])

    # Handle sex and UID
    n_people = int(sim['n'])  # Number of people
    uids = sc.uuid(which='ascii', n=n_people, length=id_len)
    sexes = cvu.rbt(0.5, n_people)

    # Handle ages
    age_data_min = age_data[:, 0]
    age_data_max = age_data[:, 1] + 1  # Since actually e.g. 69.999
    age_data_range = age_data_max - age_data_min
    age_data_prob = age_data[:, 2]
    age_data_prob /= age_data_prob.sum()  # Ensure it sums to 1
    age_bins = cvu.mt(age_data_prob, n_people)  # Choose age bins
    ages = age_data_min[age_bins] + age_data_range[age_bins] * np.random.random(
        n_people)  # Uniformly distribute within this age bin

    # Make contacts
    contacts = []
    for p in range(n_people):
        n_contacts = cvu.pt(
            sim['contacts']
        )  # Draw the number of Poisson contacts for this person
        contact_inds = cvu.choose(
            max_n=n_people,
            n=n_contacts)  # Choose people at random, assigning to household
        contacts.append(contact_inds)

    # Store output; data duplicated as per-person and list-like formats for convenience
    popdict = {}
    popdict['uid'] = uids
    popdict['age'] = ages
    popdict['sex'] = sexes
    popdict['contacts'] = contacts

    return popdict
Beispiel #7
0
def assign_uids_by_homes(homes, id_len=16, use_int=True):
    """
    Assign IDs to everyone in order by their households.

    Args:
        homes (array)  : The generated synthetic ages of household members.
        id_len (int)   : The length of the UID.
        use_int (bool) : If True, use ints for the uids of individuals; otherwise use strings of length 'id_len'.

    Returns:
        A copy of the generated households with IDs in place of ages, and a dictionary mapping ID to age.
    """
    age_by_uid_dic = dict()
    homes_by_uids = []

    for h, home in enumerate(homes):

        home_ids = []
        for a in home:
            if use_int:
                uid = len(age_by_uid_dic)
            else:
                uid = sc.uuid(length=id_len)
            age_by_uid_dic[uid] = a
            home_ids.append(uid)

        homes_by_uids.append(home_ids)

    return homes_by_uids, age_by_uid_dic
Beispiel #8
0
 def __init__(self):
     """
     Constructor: create an empty class.
     """
     self.id = sc.uuid()
     self.teachers = set()
     self.students = set()
Beispiel #9
0
 def process_graphs(figs):
     jsons = []
     for fig in sc.promotetolist(figs):
         fig.update_layout(paper_bgcolor=bgcolor, plot_bgcolor=plotbg)
         output = {'json': fig.to_json(), 'id': str(sc.uuid())}
         d = json.loads(output['json'])
         d['config'] = {'responsive': True}
         output['json'] = json.dumps(d)
         jsons.append(output)
     return jsons
Beispiel #10
0
    def __init__(self, obj=None, key=None, objtype=None, uid=None, force=True):
        # Handle input arguments
        if uid is None:
            if force:
                uid = sc.uuid()
            else:
                errormsg = 'DataStore: Not creating a new Blob UUID since force is set to False: key=%s, objtype=%s, uid=%s, obj=%s' % (
                    key, objtype, uid, obj)
                raise Exception(errormsg)
        if not key: key = '%s%s%s' % (objtype, default_separator, uid)

        # Set attributes
        self.key = key
        self.objtype = objtype
        self.uid = uid
        self.created = sc.now()
        self.modified = [self.created]
        self.obj = obj
        return None
Beispiel #11
0
    def __init__(self,
                 project=None,
                 name=None,
                 burdenset=None,
                 intervset=None,
                 makepackage=None):
        self.name = name  # Name of the parameter set, e.g. 'default'
        self.uid = sc.uuid()  # ID
        self.projectref = sc.Link(
            project)  # Store pointer for the project, if available
        self.created = sc.now()  # Date created
        self.modified = sc.now()  # Date modified
        self.eps = 1e-4  # A nonzero value to help with division
        self.burdenset = burdenset
        self.intervset = intervset
        self.budget = None
        self.frpwt = None
        self.equitywt = None
        self.data = None  # The data

        if makepackage: self.makepackage()
        return None
Beispiel #12
0
    def __init__(self,
                 name='Default',
                 burdenfile=None,
                 interventionsfile=None,
                 country=None,
                 makepackage=True,
                 verbose=2):
        ''' Initialize the project '''

        ## Define the structure sets
        self.burdensets = sc.odict()
        self.intervsets = sc.odict()
        self.packagesets = sc.odict()

        ## Define other quantities
        self.name = name
        self.country = country
        self.uid = sc.uuid()
        self.created = sc.now()
        self.modified = sc.now()
        self.version = hp.version
        self.gitinfo = sc.gitinfo(__file__)
        self.filename = None  # File path, only present if self.save() is used

        ## Load burden spreadsheet, if available
        if burdenfile:
            self.loadburden(filename=burdenfile, verbose=verbose)

        ## Load interventions spreadsheet, if available
        if interventionsfile:
            self.loadinterventions(filename=interventionsfile, verbose=verbose)

        ## Combine into health package, if available
        if makepackage and burdenfile and interventionsfile:
            self.makepackage()

        return None
Beispiel #13
0
 def __init__(self, name=None, project=None, filename=None, folder=None):
     if name is None: name = 'Default'
     self.projectref = sc.Link(project) # Store pointer for the project
     self.name       = sc.uniquename(name, namelist=self.projectref().intervsets.keys()) # Name of the parameter set, e.g. 'default'
     self.uid        = sc.uuid() # ID
     self.created    = sc.now() # Date created
     self.modified   = sc.now() # Date modified
     
     # Define hard-coded column names
     self.colnames = sc.odict([('active',   'Active'),
                               ('shortname','Short name'),
                               ('platform', 'Platform'),
                               ('burdencov','Causes of burden (max coverage)'),
                               ('icer',     'ICER'),
                               ('unitcost', 'Unit cost'),
                               ('spend',    'Spending'),
                               ('frp',      'FRP'),
                               ('equity',   'Equity'),
                               ])
     
     self.data       = None
     if filename is not None:
         self.loaddata(filename=filename, folder=folder)
     return None
Beispiel #14
0
def run_sim(sim_pars=None, epi_pars=None, intervention_pars=None, datafile=None, show_animation=False, n_days=90, verbose=True):
    ''' Create, run, and plot everything '''

    err = ''

    try:
        # Fix up things that JavaScript mangles
        orig_pars = cv.make_pars(set_prognoses=True, prog_by_age=False, use_layers=False)

        defaults = get_defaults(merge=True)
        web_pars = {}
        web_pars['verbose'] = verbose # Control verbosity here

        for key,entry in {**sim_pars, **epi_pars}.items():
            print(key, entry)

            best   = defaults[key]['best']
            minval = defaults[key]['min']
            maxval = defaults[key]['max']

            try:
                web_pars[key] = np.clip(float(entry['best']), minval, maxval)
            except Exception:
                user_key = entry['name']
                user_val = entry['best']
                err1 = f'Could not convert parameter "{user_key}", value "{user_val}"; using default value instead\n'
                print(err1)
                err += err1
                web_pars[key] = best
                if die: raise
            if key in sim_pars: sim_pars[key]['best'] = web_pars[key]
            else:               epi_pars[key]['best'] = web_pars[key]

        # Convert durations
        web_pars['dur'] = sc.dcp(orig_pars['dur']) # This is complicated, so just copy it
        web_pars['dur']['exp2inf']['par1']  = web_pars.pop('web_exp2inf')
        web_pars['dur']['inf2sym']['par1']  = web_pars.pop('web_inf2sym')
        web_pars['dur']['crit2die']['par1'] = web_pars.pop('web_timetodie')
        web_dur = web_pars.pop('web_dur')
        for key in ['asym2rec', 'mild2rec', 'sev2rec', 'crit2rec']:
            web_pars['dur'][key]['par1'] = web_dur

        # Add n_days
        web_pars['n_days'] = n_days

        # Add the intervention
        web_pars['interventions'] = []

        switcher = {
            'social_distance': map_social_distance,
            'school_closures': map_school_closures,
            'symptomatic_testing': map_symptomatic_testing,
            'contact_tracing': map_contact_tracing
        }
        if intervention_pars is not None:
            for key,scenario in intervention_pars.items():
                func = switcher.get(key)
                func(scenario, web_pars)


        # Handle CFR -- ignore symptoms and set to 1
        web_pars['prognoses'] = sc.dcp(orig_pars['prognoses'])
        web_pars['rel_symp_prob']   = 1e4 # Arbitrarily large
        web_pars['rel_severe_prob'] = 1e4
        web_pars['rel_crit_prob']   = 1e4
        web_pars['prognoses']['death_probs'][0] = web_pars.pop('web_cfr')
        if web_pars['rand_seed'] == 0:
            web_pars['rand_seed'] = None
        web_pars['timelimit'] = max_time  # Set the time limit
        web_pars['pop_size'] = int(web_pars['pop_size'])  # Set data type
        web_pars['contacts'] = int(web_pars['contacts'])  # Set data type

    except Exception as E:
        err2 = f'Parameter conversion failed! {str(E)}\n'
        print(err2)
        err += err2
        if die: raise

    # Create the sim and update the parameters
    try:
        sim = cv.Sim(pars=web_pars,datafile=datafile)
    except Exception as E:
        err3 = f'Sim creation failed! {str(E)}\n'
        print(err3)
        err += err3
        if die: raise

    if verbose:
        print('Input parameters:')
        print(web_pars)

    # Core algorithm
    try:
        sim.run(do_plot=False)
    except TimeoutError:
        day = sim.t
        err4 = f"The simulation stopped on day {day} because run time limit ({sim['timelimit']} seconds) was exceeded. Please reduce the population size and/or number of days simulated."
        err += err4
        if die: raise
    except Exception as E:
        err4 = f'Sim run failed! {str(E)}\n'
        print(err4)
        err += err4
        if die: raise

    # Core plotting
    graphs = []
    try:
        to_plot = sc.dcp(cv.default_sim_plots)
        for p,title,keylabels in to_plot.enumitems():
            fig = go.Figure()
            for key in keylabels:
                label = sim.results[key].name
                this_color = sim.results[key].color
                y = sim.results[key][:]
                fig.add_trace(go.Scatter(x=sim.results['t'][:], y=y, mode='lines', name=label, line_color=this_color))
                if sim.data is not None and key in sim.data:
                    data_t = (sim.data.index-sim['start_day'])/np.timedelta64(1,'D')
                    print(sim.data.index, sim['start_day'], np.timedelta64(1,'D'), data_t)
                    ydata = sim.data[key]
                    fig.add_trace(go.Scatter(x=data_t, y=ydata, mode='markers', name=label + ' (data)', line_color=this_color))

            if sim['interventions']:
                interv_day = sim['interventions'][0].days[0]
                if interv_day > 0 and interv_day < sim['n_days']:
                    fig.add_shape(dict(type="line", xref="x", yref="paper", x0=interv_day, x1=interv_day, y0=0, y1=1, name='Intervention', line=dict(width=0.5, dash='dash')))
                    fig.update_layout(annotations=[dict(x=interv_day, y=1.07, xref="x", yref="paper", text="Intervention start", showarrow=False)])

            fig.update_layout(title={'text':title}, xaxis_title='Day', yaxis_title='Count', autosize=True)

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

        graphs.append(plot_people(sim))

        if show_animation:
            graphs.append(animate_people(sim))

    except Exception as E:
        err5 = f'Plotting failed! {str(E)}\n'
        print(err5)
        err += err5
        if die: raise


    # Create and send output files (base64 encoded content)
    files = {}
    summary = {}
    try:
        datestamp = sc.getdate(dateformat='%Y-%b-%d_%H.%M.%S')


        ss = sim.to_excel()
        files['xlsx'] = {
            'filename': f'covasim_results_{datestamp}.xlsx',
            'content': 'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,' + base64.b64encode(ss.blob).decode("utf-8"),
        }

        json_string = sim.to_json(verbose=False)
        files['json'] = {
            'filename': f'covasim_results_{datestamp}.json',
            'content': 'data:application/text;base64,' + base64.b64encode(json_string.encode()).decode("utf-8"),
        }

        # Summary output
        summary = {
            'days': sim.npts-1,
            'cases': round(sim.results['cum_infections'][-1]),
            'deaths': round(sim.results['cum_deaths'][-1]),
        }
    except Exception as E:
        err6 = f'File saving failed! {str(E)}\n'
        print(err6)
        err += err6
        if die: raise

    output = {}
    output['err']      = err
    output['sim_pars'] = sim_pars
    output['epi_pars'] = epi_pars
    output['graphs']   = graphs
    output['files']    = files
    output['summary']  = summary

    return output
Beispiel #15
0
    def getkey(self,
               key=None,
               objtype=None,
               uid=None,
               obj=None,
               fulloutput=None,
               forcetype=None):
        '''
        Get a valid database key, either from a given key (do nothing), or else from
        a supplied objtype and uid, or else read them from the object supplied. The
        idea is for this method to be as forgiving as possible for different possible
        combinations of inputs.
        '''
        # Handle optional input arguments
        if fulloutput is None: fulloutput = False
        if forcetype is None: forcetype = True

        # Handle different sources for things
        props = ['key', 'objtype', 'uid']
        args = {
            'key': key,
            'objtype': objtype,
            'uid': uid
        }  # These are what have been supplied by the user
        fromobj = {
            'key': None,
            'objtype': None,
            'uid': None
        }  # This is from the object
        final = {
            'key': None,
            'objtype': None,
            'uid': None
        }  # These will eventually be the output values -- copy of args

        # Look for missing properties from the object
        if obj:
            if hasattr(obj, 'key'): fromobj['key'] = obj.key
            if hasattr(obj, 'objtype'): fromobj['objtype'] = obj.objtype
            if hasattr(obj, 'uid'): fromobj['uid'] = obj.uid

        # Populate all non-None entries from the input arguments
        for p in props:
            if args[p]:
                final[p] = sc.flexstr(
                    args[p]
                )  # Convert to string since you don't know what crazy thing might be passed (using flexstr since str can't handle bytes)

        # Populate what we can from the object, if it hasn't already been populated
        for p in props:
            if fromobj[p] and not final[p]:
                final[p] = fromobj[p]

        # If the key is supplied but other things aren't, try to create them now
        if final['key'] and (not final['objtype'] or not final['uid']):
            splitkey = final['key'].split(self.separator)
            if len(splitkey) == 2:  # Check that the key split properly
                if not final['objtype']: final['objtype'] = splitkey[0]
                if not final['uid']: final['uid'] = splitkey[1]

        # If we're still stuck, try making a new uid
        if not final['key'] and not final['uid']:
            final['uid'] = str(sc.uuid())

        # If everything is supplied except the key, create it
        if not final['key']:
            if final['objtype'] and final[
                    'uid']:  # Construct a key from the object type and UID
                final['key'] = self.makekey(objtype=final['objtype'],
                                            uid=final['uid'])
            elif not final['objtype'] and final[
                    'uid']:  # Otherwise, just use the UID
                final['key'] = final['uid']

        # Check that it's found, and if not, treat the key as a UID and try again
        keyexists = self.exists(
            final['key'])  # Check to see whether a match has been found
        if not keyexists:  # If not, treat the key as a UID instead
            newkey = self.makekey(objtype=final['objtype'], uid=final['key'])
            newkeyexists = self.exists(
                newkey)  # Check to see whether a match has been found
            if newkeyexists:
                final['key'] = newkey

        # Finally, force the type if requested
        if forcetype and final['objtype']:
            splitkey = final['key'].split(self.separator, 1)
            if splitkey[0] != final['objtype']:
                final['key'] = self.makekey(objtype=final['objtype'],
                                            uid=final['key'])

        if len(final['key']) > max_key_length:
            raise Exception('Key is too long')

        # Return what we need to return
        if fulloutput: return final['key'], final['objtype'], final['uid']
        else: return final['key']
Beispiel #16
0
def main_plots(sim):
    ''' Main simulation results '''
    plots = []
    to_plot = sc.dcp(cv.default_sim_plots)
    for p, title, keylabels in to_plot.enumitems():
        fig = go.Figure()
        for key in keylabels:
            label = sim.results[key].name
            this_color = sim.results[key].color
            y = sim.results[key][:]
            fig.add_trace(
                go.Scatter(x=sim.results['t'][:],
                           y=y,
                           mode='lines',
                           name=label,
                           line_color=this_color))
            if sim.data is not None and key in sim.data:
                data_t = (sim.data.index - sim['start_day']) / np.timedelta64(
                    1, 'D')
                print(sim.data.index, sim['start_day'], np.timedelta64(1, 'D'),
                      data_t)
                ydata = sim.data[key]
                fig.add_trace(
                    go.Scatter(x=data_t,
                               y=ydata,
                               mode='markers',
                               name=label + ' (data)',
                               line_color=this_color))

        if sim['interventions']:
            for interv in sim['interventions']:
                if hasattr(interv, 'days'):
                    for interv_day in interv.days:
                        if interv_day > 0 and interv_day < sim['n_days']:
                            fig.add_shape(
                                dict(type="line",
                                     xref="x",
                                     yref="paper",
                                     x0=interv_day,
                                     x1=interv_day,
                                     y0=0,
                                     y1=1,
                                     name='Intervention',
                                     line=dict(width=0.5, dash='dash')))
                            fig.update_layout(annotations=[
                                dict(x=interv_day,
                                     y=1.07,
                                     xref="x",
                                     yref="paper",
                                     text="Intervention change",
                                     showarrow=False)
                            ])

        fig.update_layout(title={'text': title},
                          xaxis_title='Day',
                          yaxis_title='Count',
                          autosize=True,
                          paper_bgcolor=bgcolor,
                          plot_bgcolor=plotbg)

        output = {'json': fig.to_json(), 'id': str(sc.uuid())}
        d = json.loads(output['json'])
        d['config'] = {'responsive': True}
        output['json'] = json.dumps(d)
        plots.append(output)
    return plots
Beispiel #17
0
def run_sim(sim_pars=None, epi_pars=None, show_animation=False, verbose=True):
    ''' Create, run, and plot everything '''

    err = ''

    try:
        # Fix up things that JavaScript mangles
        orig_pars = cv.make_pars()
        defaults = get_defaults(merge=True)
        web_pars = {}
        web_pars['verbose'] = verbose  # Control verbosity here

        for key, entry in {**sim_pars, **epi_pars}.items():
            print(key, entry)

            best = defaults[key]['best']
            minval = defaults[key]['min']
            maxval = defaults[key]['max']

            try:
                web_pars[key] = np.clip(float(entry['best']), minval, maxval)
            except Exception:
                user_key = entry['name']
                user_val = entry['best']
                err1 = f'Could not convert parameter "{user_key}", value "{user_val}"; using default value instead\n'
                print(err1)
                err += err1
                web_pars[key] = best
            if key in sim_pars: sim_pars[key]['best'] = web_pars[key]
            else: epi_pars[key]['best'] = web_pars[key]

        # Convert durations
        web_pars['dur'] = sc.dcp(
            orig_pars['dur'])  # This is complicated, so just copy it
        web_pars['dur']['exp2inf']['par1'] = web_pars.pop('web_exp2inf')
        web_pars['dur']['inf2sym']['par1'] = web_pars.pop('web_inf2sym')
        web_pars['dur']['crit2die']['par1'] = web_pars.pop('web_timetodie')
        web_dur = web_pars.pop('web_dur')
        for key in ['asym2rec', 'mild2rec', 'sev2rec', 'crit2rec']:
            web_pars['dur'][key]['par1'] = web_dur

        # Add the intervention
        web_pars['interventions'] = []
        if web_pars['web_int_day'] is not None:
            web_pars['interventions'] = cv.change_beta(
                days=web_pars.pop('web_int_day'),
                changes=(1 - web_pars.pop('web_int_eff')))

        # Handle CFR -- ignore symptoms and set to 1
        prog_pars = cv.get_default_prognoses(by_age=False)
        web_pars['rel_symp_prob'] = 1.0 / prog_pars.symp_prob
        web_pars['rel_severe_prob'] = 1.0 / prog_pars.severe_prob
        web_pars['rel_crit_prob'] = 1.0 / prog_pars.crit_prob
        web_pars['rel_death_prob'] = web_pars.pop(
            'web_cfr') / prog_pars.death_prob

    except Exception as E:
        err2 = f'Parameter conversion failed! {str(E)}\n'
        print(err2)
        err += err2

    # Create the sim and update the parameters
    try:
        sim = cv.Sim()
        sim['prog_by_age'] = False  # So the user can override this value
        sim['timelimit'] = max_time  # Set the time limit
        if web_pars['seed'] == 0:
            web_pars['seed'] = None  # Reset
        sim.update_pars(web_pars)
    except Exception as E:
        err3 = f'Sim creation failed! {str(E)}\n'
        print(err3)
        err += err3

    if verbose:
        print('Input parameters:')
        print(web_pars)

    # Core algorithm
    try:
        sim.run(do_plot=False)
    except Exception as E:
        err4 = f'Sim run failed! {str(E)}\n'
        print(err4)
        err += err4

    if sim.stopped:
        try:  # Assume it stopped because of the time, but if not, don't worry
            day = sim.stopped['t']
            time_exceeded = f"The simulation stopped on day {day} because run time limit ({sim['timelimit']} seconds) was exceeded. Please reduce the population size and/or number of days simulated."
            err += time_exceeded
        except:
            pass

    # Core plotting
    graphs = []
    try:
        to_plot = sc.dcp(cv.default_sim_plots)
        for p, title, keylabels in to_plot.enumitems():
            fig = go.Figure()
            for key in keylabels:
                label = sim.results[key].name
                this_color = sim.results[key].color
                y = sim.results[key][:]
                fig.add_trace(
                    go.Scatter(x=sim.results['t'][:],
                               y=y,
                               mode='lines',
                               name=label,
                               line_color=this_color))

            if sim['interventions']:
                interv_day = sim['interventions'][0].days[0]
                if interv_day > 0 and interv_day < sim['n_days']:
                    fig.add_shape(
                        dict(type="line",
                             xref="x",
                             yref="paper",
                             x0=interv_day,
                             x1=interv_day,
                             y0=0,
                             y1=1,
                             name='Intervention',
                             line=dict(width=0.5, dash='dash')))
                    fig.update_layout(annotations=[
                        dict(x=interv_day,
                             y=1.07,
                             xref="x",
                             yref="paper",
                             text="Intervention start",
                             showarrow=False)
                    ])

            fig.update_layout(title={'text': title},
                              xaxis_title='Day',
                              yaxis_title='Count',
                              autosize=True)

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

        graphs.append(plot_people(sim))

        if show_animation:
            graphs.append(animate_people(sim))

    except Exception as E:
        err5 = f'Plotting failed! {str(E)}\n'
        print(err5)
        err += err5

    # Create and send output files (base64 encoded content)
    files = {}
    summary = {}
    try:
        datestamp = sc.getdate(dateformat='%Y-%b-%d_%H.%M.%S')

        ss = sim.to_xlsx()
        files['xlsx'] = {
            'filename':
            f'COVASim_results_{datestamp}.xlsx',
            'content':
            'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,'
            + base64.b64encode(ss.blob).decode("utf-8"),
        }

        json_string = sim.to_json()
        files['json'] = {
            'filename':
            f'COVASim_results_{datestamp}.txt',
            'content':
            'data:application/text;base64,' +
            base64.b64encode(json_string.encode()).decode("utf-8"),
        }

        # Summary output
        summary = {
            'days': sim.npts - 1,
            'cases': round(sim.results['cum_infections'][-1]),
            'deaths': round(sim.results['cum_deaths'][-1]),
        }
    except Exception as E:
        err6 = f'File saving failed! {str(E)}\n'
        print(err6)
        err += err6

    output = {}
    output['err'] = err
    output['sim_pars'] = sim_pars
    output['epi_pars'] = epi_pars
    output['graphs'] = graphs
    output['files'] = files
    output['summary'] = summary

    return output
Beispiel #18
0
    return P


def heading(string, style=None):
    divider = '=' * 60
    sc.blank()
    if style == 'big': string = '\n'.join([divider, string, divider])
    sc.colorize('blue', string)
    return None


# Launch app
T = sc.tic()
app = main.make_app()
user = sw.make_default_users(app)[0]
proj_id = sc.uuid(tostring=True)  # These can all be the same
proj = demoproj(proj_id, user.username)

###########################################################################
### Run the tests
###########################################################################

string = 'Starting tests for proj = %s' % proj_id
heading(string, 'big')

if 'project_io' in torun:
    heading('Running project_io', 'big')
    uid = rpcs.save_new_project(proj, user.username)
    P = rpcs.load_project_record(uid)
    print(P)
Beispiel #19
0
def demoproj(proj_id, username):
    P = hp.demo()
    P.name = 'RPCs test %s' % proj_id[:6]
    P.uid = sc.uuid(proj_id)
    rpcs.save_new_project(P, username, uid=P.uid)  # Force a matching uid
    return P
Beispiel #20
0
def animate_people(sim) -> dict:
    z, states = get_individual_states(sim, order=False)

    min_color = min(states, key=lambda x: x['value'])['value']
    max_color = max(states, key=lambda x: x['value'])['value']
    colorscale = [[x['value'] / max_color, x['color']] for x in states]

    aspect = 3
    y_size = int(np.ceil((z.shape[0] / aspect) ** 0.5))
    x_size = int(np.ceil(aspect * y_size))

    z = np.pad(z, ((0, x_size * y_size - z.shape[0]), (0, 0)), mode='constant', constant_values=np.nan)

    days = sim.tvec

    fig_dict = {
        "data": [],
        "layout": {},
        "frames": []
    }

    fig_dict["layout"]["updatemenus"] = [
        {
            "buttons": [
                {
                    "args": [None, {"frame": {"duration": 200, "redraw": True},
                                    "fromcurrent": True}],
                    "label": "Play",
                    "method": "animate"
                },
                {
                    "args": [[None], {"frame": {"duration": 0, "redraw": True},
                                      "mode": "immediate",
                                      "transition": {"duration": 0}}],
                    "label": "Pause",
                    "method": "animate"
                }
            ],
            "direction": "left",
            "pad": {"r": 10, "t": 87},
            "showactive": False,
            "type": "buttons",
            "x": 0.1,
            "xanchor": "right",
            "y": 0,
            "yanchor": "top"
        }
    ]

    sliders_dict = {
        "active": 0,
        "yanchor": "top",
        "xanchor": "left",
        "currentvalue": {
            "font": {"size": 20},
            "prefix": "Day: ",
            "visible": True,
            "xanchor": "right"
        },
        "transition": {"duration": 200},
        "pad": {"b": 10, "t": 50},
        "len": 0.9,
        "x": 0.1,
        "y": 0,
        "steps": []
    }

    # make data
    fig_dict["data"] = [go.Heatmap(z=np.reshape(z[:, 0], (y_size, x_size)),
                                   zmin=min_color,
                                   zmax=max_color,
                                   colorscale=colorscale,
                                   showscale=False,
                                   )]

    for state in states:
        fig_dict["data"].append(go.Scatter(x=[None], y=[None], mode='markers',
                                           marker=dict(size=10, color=state['color']),
                                           showlegend=True, name=state['name']))

    # make frames
    for i, day in enumerate(days):
        frame = {"data": [go.Heatmap(z=np.reshape(z[:, i], (y_size, x_size)))],
                 "name": i}
        fig_dict["frames"].append(frame)
        slider_step = {"args": [
            [i],
            {"frame": {"duration": 5, "redraw": True},
             "mode": "immediate", }
        ],
            "label": i,
            "method": "animate"}
        sliders_dict["steps"].append(slider_step)

    fig_dict["layout"]["sliders"] = [sliders_dict]

    fig = go.Figure(fig_dict)

    fig.update_layout(
    autosize=True,
        xaxis=dict(
            automargin=True,
            range=[-0.5, x_size + 0.5],
            constrain="domain",
            showgrid=False,
            showline=False,
            showticklabels=False,
        ),
        yaxis=dict(
            automargin=True,
            range=[-0.5, y_size + 0.5],
            constrain="domain",
            scaleanchor="x",
            scaleratio=1,
            showgrid=False,
            showline=False,
            showticklabels=False,
        ),
    )

    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
Beispiel #21
0
def test_uuid():
    sc.heading('Test UID generation')
    import uuid

    # Create them
    u = sc.objdict()
    u.u0 = uuid.uuid4()
    u.u1 = sc.uuid()
    u.u2 = sc.uuid()
    u.u3 = sc.uuid(length=4)
    u.u4 = sc.uuid(which='ascii', length=16)
    u.u5 = sc.uuid(n=3)
    u.u6 = sc.uuid(which='hex', length=20)
    u.u7 = sc.uuid(which='numeric', length=10, n=5)

    # Tests
    assert u.u1 != u.u2
    assert isinstance(u.u1, type(u.u0))
    assert isinstance(u.u3, str)
    with pytest.raises(ValueError):
        sc.uuid(length=400)  # UUID is only 16 characters long
    with pytest.raises(ValueError):
        sc.uuid(which='numeric', length=2, n=10)  # Not enough unique choices

    print(
        'NOTE: This is supposed to print warnings and then raise a (caught) exception\n'
    )
    with pytest.raises(ValueError):
        sc.uuid(which='numeric', length=2, n=99, safety=1,
                verbose=True)  # Not enough unique choices

    # Print results
    print(f'UIDs:')
    for key, val in u.items():
        print(f'{key}: {val}')

    return u