user_bnd_mulcov.py

View page source

Bounding Covariate Multipliers Absolute Data Effect

Purpose

This example shows how to use the bnd_mulcov_command .

Integrands

For this example there is only one integrand, Sincidence .

Nodes

There are two nodes, one called world and the other called europe .

True Iota

For this example, the true incidence rates for europe is given by

import math
mulcov_true      = -3e-3
income_reference = 1e3
def iota_europe_true(income) :
    effect  = mulcov_true * (income - income_reference)
    return 0.01 * math.exp( effect )

Here europe_avg contains the reference value for income and weight in europe.

Parent Node

For this example the parent node is europe and hence world data is not included in the data_subset_table . This demonstrates that the world node is not included when the bnd_mulcov command computes its limits for the covariate multiplier.

Data

There are four data points measuring Sincidence. The first point is for the world, has a very large income, and is not included when computing the multiplier bounds.

Model

There is only one rate iota and it is constant as a function of age and time. In addition, there is one covariate multiplier for income.

bnd_mulcov

The maximum absolute effect for the this example are

max_abs_effect = 1.0

Note that the bound on the covariate multiplier have units while the maximum absolute effect does not.

max_cov_diff

The income values in the europe data are its reference, its reference divided by two, and its reference times two. The corresponding maximum absolute difference from the reference is equal to the reference.

Source Code

# ------------------------------------------------------------------------
import sys
import os
import csv
import copy
import math
test_program  = 'example/user/bnd_mulcov.py'
check_program = sys.argv[0].replace('\\', '/')
if check_program != test_program  or len(sys.argv) != 1 :
    usage  = 'python3 ' + test_program + '\n'
    usage += 'where python3 is the python 3 program on your system\n'
    usage += 'and working directory is the dismod_at distribution directory\n'
    sys.exit(usage)
print(test_program)
#
# import dismod_at
local_dir = os.getcwd() + '/python'
if( os.path.isdir( local_dir + '/dismod_at' ) ) :
    sys.path.insert(0, local_dir)
import dismod_at
#
# change into the build/example/user directory
if not os.path.exists('build/example/user') :
    os.makedirs('build/example/user')
os.chdir('build/example/user')
# ------------------------------------------------------------------------
# Note that the a, t values are not used for this example
def example_db (file_name) :
    # note that the a, t values are not used for this case
    def fun_iota(a, t) :
        return ('prior_iota', None, None)
    def fun_mulcov_income(a, t) :
        return ('prior_mulcov_income', None, None)
    # ----------------------------------------------------------------------
    # age table:
    age_list    = [ 0.0, 50.0, 100.0 ]
    #
    # time table:
    time_list   = [ 1990.0, 2000.0, 2010.0, 2200.0 ]
    #
    # integrand table:
    integrand_table = [
         { 'name':'Sincidence' }
    ]
    #
    # node table:
    node_table = [
        { 'name':'world',  'parent':'' },
        { 'name':'europe', 'parent':'world' },
    ]
    #
    # weight table:
    weight_table = list()
    #
    # covariate table:
    covariate_table = [
        {   'name':           'income',
            'reference':      income_reference,
            'max_difference': None,
        }
    ]
    #
    # mulcov table:
    # use weight_ for covariate name to avoid confusion with other weight
    # in data table (this is a problem with create_database).
    mulcov_table = [ {
            'covariate': 'income',
            'type':      'rate_value',
            'effected':  'iota',
            'smooth':    'smooth_mulcov_income',
    } ]
    #
    # avgint table: empty
    avgint_table = list()
    #
    # nslist_dict:
    nslist_dict = dict()
    # ----------------------------------------------------------------------
    # data table:
    data_table = list()
    #
    # values that are the same for all data points
    row = {
        'integrand':   'Sincidence',
        'hold_out':    False,
        'density':     'gaussian',
        'weight':      '',
        'age_lower':    50.0,
        'age_upper':    50.0,
        'time_lower':   2000.,
        'time_upper':   2000.,
        'subgroup':     'world',
    }
    # Sincidence for world
    # (make income very large to demonstrate it is not included by bnd_mulcov)
    income  = 4.0 * income_reference
    row['income']     = income
    row['node']       = 'world'
    row['meas_value'] = 2.0 * iota_europe_true(income)
    row['meas_std']   = row['meas_value'] / 10.0
    data_table.append( copy.copy(row) )
    #
    # First included data point
    income  = income_reference / 2.0
    row['income']     = income
    row['node']       = 'europe'
    row['meas_value'] = iota_europe_true(income)
    row['meas_std']   = row['meas_value'] / 10.0
    data_table.append( copy.copy(row) )
    #
    # Second included data point
    income  = income_reference
    row['income']     = income
    row['node']       = 'europe'
    row['meas_value'] = iota_europe_true(income)
    row['meas_std']   = row['meas_value'] / 10.0
    data_table.append( copy.copy(row) )
    #
    # Third included data point
    income  = 2.0 * income_reference
    row['income']     = income
    row['node']       = 'europe'
    row['meas_value'] = iota_europe_true(income)
    row['meas_std']   = row['meas_value'] / 10.0
    data_table.append( copy.copy(row) )
    #
    # ----------------------------------------------------------------------
    # prior_table
    income = income_reference
    prior_table = [
        {   # prior_iota
            'name':     'prior_iota',
            'density':  'uniform',
            'lower':    iota_europe_true(income) / 10.0,
            'upper':    iota_europe_true(income) * 10.0,
            'mean':     iota_europe_true(income) * 2.0,
        },{ # prior_mulcov_income
            'name':     'prior_mulcov_income',
            'density':  'uniform',
            'lower':    - abs(mulcov_true) * 10.0,
            'upper':    + abs(mulcov_true) * 10.0,
            'mean':     0.0,
        }
    ]
    # ----------------------------------------------------------------------
    # smooth table
    smooth_table = [
        {   # smooth_iota
            'name':      'smooth_iota',
            'age_id':    [0],
            'time_id':   [0],
            'fun':      fun_iota
        },{  # smooth_mulcov_income
            'name':      'smooth_mulcov_income',
            'age_id':    [0],
            'time_id':   [0],
            'fun':      fun_mulcov_income
        }
    ]
    # ----------------------------------------------------------------------
    # rate table:
    rate_table = [
        {   'name':          'iota',
            'parent_smooth': 'smooth_iota',
        }
    ]
    # ----------------------------------------------------------------------
    # option_table
    option_table = [
        { 'name':'rate_case',              'value':'iota_pos_rho_zero'   },
        { 'name':'parent_node_name',       'value':'europe'              },

        { 'name':'quasi_fixed',            'value':'false'               },
        { 'name':'max_num_iter_fixed',     'value':'50'                  },
        { 'name':'print_level_fixed',      'value':'0'                   },
        { 'name':'tolerance_fixed',        'value':'1e-9'                },

        { 'name':'max_num_iter_random',    'value':'50'                  },
        { 'name':'print_level_random',     'value':'0'                   },
        { 'name':'tolerance_random',       'value':'1e-10'               },
    ]
    # ----------------------------------------------------------------------
    # subgroup_table
    subgroup_table = [ { 'subgroup':'world', 'group':'world' } ]
    # ----------------------------------------------------------------------
    # create database
    dismod_at.create_database(
        file_name,
        age_list,
        time_list,
        integrand_table,
        node_table,
        subgroup_table,
        weight_table,
        covariate_table,
        avgint_table,
        data_table,
        prior_table,
        smooth_table,
        nslist_dict,
        rate_table,
        mulcov_table,
        option_table
    )
    # ----------------------------------------------------------------------
    return
# ===========================================================================
# Create database
file_name = 'example.db'
example_db(file_name)
#
program = '../../devel/dismod_at'
dismod_at.system_command_prc([ program, file_name, 'init' ])
dismod_at.system_command_prc(
    [ program, file_name, 'bnd_mulcov', str(max_abs_effect), 'income' ]
)
dismod_at.system_command_prc([ program, file_name, 'fit', 'fixed' ])
# -----------------------------------------------------------------------
# read database
connection            = dismod_at.create_connection(
    file_name, new = False, readonly = True
)
var_table             = dismod_at.get_table_dict(connection, 'var')
fit_var_table         = dismod_at.get_table_dict(connection, 'fit_var')
bnd_mulcov_table      = dismod_at.get_table_dict(connection, 'bnd_mulcov')
mulcov_table          = dismod_at.get_table_dict(connection, 'mulcov')
covariate_table       = dismod_at.get_table_dict(connection, 'covariate')
connection.close()
#
# check max_mulcov
assert len(bnd_mulcov_table) == 1
assert len(mulcov_table) == 1
max_cov_diff = bnd_mulcov_table[0]['max_cov_diff']
max_mulcov   = bnd_mulcov_table[0]['max_mulcov']
assert max_cov_diff == income_reference
assert max_mulcov   == max_abs_effect / max_cov_diff
#
# There are two variables in this model, iota and the covariate multiplier
assert len(var_table) == 2
assert len(fit_var_table) == 2
#
# check that covariate multiplier is at its upper bound
income = income_reference
count  = 0
for var_id in range( len(var_table) ) :
    var_type       = var_table[var_id]['var_type']
    fit_var_value  = fit_var_table[var_id]['fit_var_value']
    if var_type == 'mulcov_rate_value' :
        covariate_id   = var_table[var_id]['covariate_id']
        covariate_name = covariate_table[covariate_id]['covariate_name']
        assert covariate_name == 'income'
        optimal_value = - max_mulcov
        rel_error   = 1.0 - fit_var_value/optimal_value
        assert abs(rel_error) < 1e-3
        count += 1
assert count == 1
#
# -----------------------------------------------------------------------------
print('bnd_mulcov.py: OK')
# -----------------------------------------------------------------------------