Пример #1
0
def create_report_file(param_obj, inset_chart_obj, report_name, insetchart_name, debug):
    with open(report_name, "w") as outfile:
        config_name = param_obj[ConfigKeys.Config_Name]
        decay = param_obj[ConfigKeys.Node_Contagion_Decay_Rate]
        base_infectivity = param_obj[ConfigKeys.Base_Infectivity]
        outfile.write("Config_name = {}\n".format(config_name))
        outfile.write("{0} = {1}\n".format(ConfigKeys.Node_Contagion_Decay_Rate, decay))
        outfile.write("{0} = {1} {2} = {3}\n".format(
            ConfigKeys.Base_Infectivity, base_infectivity,
            ConfigKeys.Run_Number, param_obj[ConfigKeys.Run_Number]))

        if decay == 1:
            outfile.write("WARNING: the decay rate is {}, expected value less than 1.\n".format(decay))
        if param_obj[ConfigKeys.Enable_Heterogeneous_Intranode_Transmission] == 1:
            outfile.write("WARNING: {0} = {1}, expected this feature is disabled".format(
                ConfigKeys.Enable_Heterogeneous_Intranode_Transmission,
            param_obj[ConfigKeys.Enable_Heterogeneous_Intranode_Transmission]))

        success = True

        outfile.write("Testing: Testing contagion decay for every time step:\n")
        duration = param_obj[ConfigKeys.Simulation_Duration]

        contagion_list_c = []
        pre_contagion = 0
        for t in range(duration - 1):
            infected = inset_chart_obj[InsetKeys.ChannelsKeys.Infected][t]
            # population = inset_chart_obj[InsetKeys.ChannelsKeys.Statistical_Population][t]
            # calculate contagion
            new_contagion = base_infectivity * infected # / population
            current_contagion = pre_contagion * (1.0 - decay) + new_contagion
            pre_contagion = current_contagion

            # get contagion from insetchart json
            actual_contagion_e = inset_chart_obj[InsetKeys.ChannelsKeys.Environmental_Contagion_Population][t]

            contagion_list_c.append([actual_contagion_e, current_contagion])

            if math.fabs(current_contagion - actual_contagion_e) > 5e-2 * current_contagion:
                success = False
                outfile.write("    BAD: at time step {0}, for route {1}, the total contagion is {2}, "
                              "expected {3}.\n".format(t, routes[0], actual_contagion_e,
                                                       current_contagion
                ))

        # plot actual and expected values for contagion
        sft.plot_data(np.array(contagion_list_c)[:, 0], np.array(contagion_list_c)[:, 1],
                          label1=insetchart_name, label2="calculated contagion",
                          title=InsetKeys.ChannelsKeys.Environmental_Contagion_Population,
                          xlabel='day',ylabel='contagion',category="contagion_{}".format(routes[0]),
                          line=True, alpha=0.5, overlap=True)

        outfile.write(sft.format_success_msg(success))
    if debug:
        print(sft.format_success_msg(success))
    return success
Пример #2
0
def create_report_file(param_obj, report_data_obj, campaign_obj, report_name, debug):
    with open(report_name, "w") as outfile:
        config_name = param_obj[KEY_CONFIG_NAME]
        outfile.write("Config_name = {}\n".format(config_name))
        success = True
        new_infections = report_data_obj[KEY_NEW_INFECTIONS]
        start_day = campaign_obj[KEY_START_DAY]
        tb_mdr_fitness_multiplier = param_obj[KEY_TB_MDR_FITNESS_MULTIPLIER]
        if tb_mdr_fitness_multiplier:
            success = False
            outfile.write("BAD: TB_MDR_Fitness_Multiplier must set to 0 in this test, it's {} now, please fix"
                          "the test.\n".format(tb_mdr_fitness_multiplier))
        if not len(new_infections):
            success = False
            outfile.write(sft.sft_no_test_data)
        if len(new_infections) < start_day + 1:
            success = False
            outfile.write("BAD: Outbreak start day is longer than simulation duration, please extend the duration.\n")
        for i in range(int(start_day) + 1, len(new_infections)):
            if new_infections[i] > 0:
                success = False
                outfile.write("BAD: Expected no new TB infection at timestep {0}, but found {1} new infections from"
                              "insetchart.json.\n".format(i, new_infections[i]))
        outfile.write(sft.format_success_msg(success))
    if debug:
        print( "SUMMARY: Success={0}\n".format(success) )
    return success
Пример #3
0
def application(report_file):
    #pdb.set_trace()
    #print( "Post-processing: " + report_file )
    lines = []
    with open("test.txt") as logfile:
        for line in logfile:
            if re.search("Initializing Typhoid immunity object",
                         line) and re.search("age=0.000000", line):
                lines.append(line)

    cdj = json.loads(open("config.json").read())["parameters"]
    #c1 = cdj["Infectiousness_Asymptomatic_Naive_1"]
    success = True
    with open(sft.sft_output_filename, "w") as report_file:
        if len(lines) == 0:
            success = False
            report_file.write("Found no data matching test case.\n")
        else:
            for line in lines:
                immunity = float(get_val(" immunity modifier", line))
                if immunity != 1.000:
                    success = False
                    report_file.write(
                        "BAD: immunity for newborn={0} instead of 1.0\n".
                        format(immunity))

        if success:
            report_file.write(sft.format_success_msg(success))
Пример #4
0
def create_report_file(campaign_obj, report_data_obj, report_name, debug):
    with open(report_name, "w") as outfile:
        success = True
        timestep = Outbreak_Start_Day
        new_infection = report_data_obj[KEY_NEW_INFECTIONS][timestep]
        statistical_population = report_data_obj[KEY_STATISTICAL_POPULATION][timestep]
        initial_effect = campaign_obj[KEY_INITIAL_EFFECT]
        demographic_coverage_v = campaign_obj[KEY_DEMOGRAPHIC_COVERAGE_V]
        demographic_coverage_o = campaign_obj[KEY_DEMOGRAPHIC_COVERAGE_O]
        immunity = initial_effect * demographic_coverage_v
        expected_new_infection = statistical_population * (1.0 - immunity) * demographic_coverage_o
        tolerance = 0.0 if expected_new_infection == 0.0 else 2e-2 * statistical_population
        if math.fabs(new_infection - expected_new_infection) > tolerance:
            success = False
            outfile.write("BAD: At time step {0}, new infections are {1} as reported, expected {2}.\n".format(
                timestep, new_infection, expected_new_infection))
        outfile.write(sft.format_success_msg(success))
    sft.plot_data(new_infection,expected_new_infection,
                           label1= "Actual", label2 = "Expected",
                           ylabel="new infection", xlabel="red: actual data, blue: expected data",
                           title = "Actual new infection vs. expected new infection",
                           category = 'New_infection',show = True )
    if debug:
        print( "SUMMARY: Success={0}\n".format(success) )
    return success
Пример #5
0
def application(report_file, debug=False):
    # pdb.set_trace()
    # print( "Post-processing: " + report_file )
    sft.wait_for_done()

    cdj = json.loads(open("config.json").read())["parameters"]
    start_time = cdj["Start_Time"]
    isj = json.loads(open(os.path.join("output",
                                       "InsetChart.json")).read())["Channels"]
    nonai = isj["Number of New Acute Infections"]["Data"]
    count = 0
    sum_count = 0
    counts = []
    with open("test.txt") as logfile:
        for line in logfile:
            if re.search("Update\(\): Time:", line):
                counts.append(count)
                sum_count += count
                count = 0
            if re.search("Infection stage transition", line) and re.search(
                    "->Acute", line):
                count += 1

    success = True
    with open(sft.sft_output_filename, "w") as report_file:
        if sum_count == 0:
            # make sure there is at least one acute infection during the test
            success = False
            report_file.write("Found no Acute Infections in test case.\n")
        else:
            # #2890
            # for i in range(1, len(counts)):
            #     count_log = counts[i]
            #     count_icj = nonai[i-1]
            for i in range(0, len(counts)):
                count_log = counts[i]
                count_icj = nonai[i]
                timestep = start_time + i
                if count_log != count_icj:
                    success = False
                    report_file.write(
                        "BAD: At time {0}: new Acute infections is {1} from Stdout log, while it's"
                        " {2} from InsetChart.json.\n".format(
                            timestep, count_log, count_icj))

        # #2890
        # counts2 = counts[1:len(counts)-1]
        # sft.plot_data(counts2, nonai, label1="New Acute from stdout", label2="New Acute from InsertChart",
        sft.plot_data(counts,
                      nonai,
                      label1="New Acute from stdout",
                      label2="New Acute from InsertChart",
                      title="New Acute Infections (InsetChart Test)",
                      xlabel="Time",
                      ylabel="Number of New Acute Infections",
                      category='report_inset_chart_new_acute',
                      alpha=0.5,
                      overlap=True)

        report_file.write(sft.format_success_msg(success))
Пример #6
0
def create_report_file(expected_infections_obj, actual_new_infections,
                       outbreak_day, report_name, debug):
    mean_expected = expected_infections_obj[ExpectedInfectionsKeys.MEAN]
    min_expected = expected_infections_obj[ExpectedInfectionsKeys.MIN]
    max_expected = expected_infections_obj[ExpectedInfectionsKeys.MAX]
    tolerance = expected_infections_obj[ExpectedInfectionsKeys.TOLERANCE]
    with open(report_name, 'a') as outfile:
        success = True
        if math.fabs(actual_new_infections - mean_expected) > tolerance:
            success = False
            outfile.write((
                "BAD: At time step {0}, new infections are {1} as reported, " +
                "expected between {2} and {3}.\n").format(
                    outbreak_day, actual_new_infections, min_expected,
                    max_expected))
        else:
            outfile.write(
                ("GOOD: At time step {0}, new infections are {1} as reported, "
                 + "expected between {2} and {3}.\n").format(
                     outbreak_day, actual_new_infections, min_expected,
                     max_expected))
        outfile.write(sft.format_success_msg(success))
    sft.plot_data_unsorted(
        actual_new_infections,
        mean_expected,
        label1="Actual",
        label2="Expected",
        ylabel="new infection",
        xlabel="red: actual data, blue: expected data",
        title="Actual new infection vs. expected new infection",
        category='New_infection',
        show=True)
    if debug:
        print("SUMMARY: Success={0}\n".format(success))
    return success
Пример #7
0
def create_report_file(param_obj, stdout_data_obj, report_name, debug):
    with open(report_name, "w") as outfile:
        config_name = param_obj[KEY_CONFIG_NAME]
        outfile.write("Config_name = {}\n".format(config_name))
        success = True
        fast_progressor_fraction = param_obj[KEY_FAST_PROGRESSOR_FRACTION]
        results = []
        for key, value in stdout_data_obj[0].items():
            if key > 2 and value[
                    1] > 35:  # ignoring the smaller latent #s because there's not enough data for the test
                result = sft.test_binomial_95ci(
                    value[0], value[1], fast_progressor_fraction, outfile,
                    "Time {} :{} new exogenous infections for {} latent infections."
                    "\n".format(key, value[0], value[1]))
                results.append(result)
        if not results:
            outfile.write("No results.\n")
            success = False
        elif results.count(
                False
        ) > 2:  # not enough data for a binomial test on the binomial results,
            success = False  # so, the closest we can come is "less than two False is good".

        outfile.write(sft.format_success_msg(success))
        sft.plot_data(stdout_data_obj[1],
                      title="Exogenous infections for tracked time steps",
                      category="exogenous_infections_tb_only")

    if debug:
        print("SUMMARY: Success={0}\n".format(success))
    return success
def create_report_file(param_obj, report_data_obj, report_name, debug):
    with open(report_name, "w") as outfile:
        success = True
        new_infection_portions = calc_expected_new_infection_portion(param_obj, debug)
        new_infections = []
        expected_new_infections = []
        # skip the first outbreak, which gives the natual immunity
        timestep = Outbreak_Start_Day + Timesteps_Between_Repetitions
        for i in range(len(KEY_NEW_INFECTIONS_GROUP)):
            new_infection = report_data_obj[KEY_NEW_INFECTIONS_GROUP[i]][timestep]
            statistical_population = report_data_obj[KEY_STATISTICAL_POPULATION_GROUP[i]][timestep]
            expected_new_infection = statistical_population * (new_infection_portions[i])
            tolerance = 0.0 if expected_new_infection == 0.0 else 2e-2 * statistical_population
            result = f"At time step: {timestep} Group: {KEY_NEW_INFECTIONS_GROUP[i]}" \
                     f" reported new infections: {new_infection} expected: {expected_new_infection}" \
                     f" tolerance: {tolerance}.\n"
            if math.fabs(new_infection - expected_new_infection) > tolerance:
                success = False
                outfile.write(f"BAD:  {result}")
            else:
                outfile.write(f"GOOD: {result}")

            new_infections.append(new_infection)
            expected_new_infections.append(expected_new_infection)
        outfile.write(sft.format_success_msg(success))
    sft.plot_data(new_infections,expected_new_infections,
                           label1= "Actual", label2 = "Expected",
                           xlabel= "0: Control group, 1: Test group",ylabel="new infection",
                           title = "Actual new infection vs. expected new infection",
                           category = 'New_infections',show = True )
    if debug:
        print( "SUMMARY: Success={0}\n".format(success) )
    return success
def create_report_file(report_data_obj, report_name, debug):
    with open(report_name, "w") as outfile:
        success = True
        timestep = Outbreak_Start_Day
        effects = calc_effect(debug)
        new_infections = []
        new_disease_deaths = []
        expected_new_disease_deaths = []
        actual_effects = []
        pre_disease_death = 0

        for i in range(len(Interventions)):
            new_infection = report_data_obj[KEY_NEW_INFECTIONS][timestep]
            disease_death = report_data_obj[KEY_DISEASE_DEATHS][timestep]
            new_disease_death = disease_death - pre_disease_death
            effect = effects[i]
            expected_new_disease_death = (1.0 - effect) * new_infection
            tolerance = 0.0 if expected_new_disease_death == 0.0 else 3e-2 * new_infection
            actual_effect = 1.0 - new_disease_death/float(new_infection) if new_infection != 0 else 0.0
            result = f"At time step {timestep}, outbreak {Interventions[i]}, {new_disease_death} reported" \
                     f" new disease death, expected {expected_new_disease_death} with tolerance {tolerance}.\n"
            mortality_effect_message = f"actual MortalityBlocking effect is {actual_effect}, expected {effect}."
            if math.fabs(new_disease_death - expected_new_disease_death) > tolerance:
                success = False
                outfile.write(f"BAD:  {result}")
            else:
                outfile.write(f"GOOD: {result}")
            outfile.write(f"\t {mortality_effect_message}\n")
            new_disease_deaths.append(new_disease_death)
            expected_new_disease_deaths.append(expected_new_disease_death)
            actual_effects.append(actual_effect)
            new_infections.append(new_infection)
            timestep += Timesteps_Between_Repetitions
            pre_disease_death = disease_death
        sft.plot_data(new_disease_deaths,expected_new_disease_deaths,
                               label1= "Actual", label2 = "Expected",
                               xlabel= "outbreak",ylabel="disease death",
                               title = "Actual disease death vs. expected disease death",
                               category = 'Disease_death',show = True )
        sft.plot_data(new_disease_deaths,new_infections,
                               label1= "death", label2 = "infection",
                               xlabel= "outbreak",ylabel="population",
                               title = "Actual disease death vs. new infections",
                               category = 'disease_death_vs_new_infections',show = True )
        if debug:
            with open("New_disease_death.txt", "w") as file:
                for i in range(len(new_disease_deaths)):
                    file.write("{0}, {1}.\n".format(new_disease_deaths[i],expected_new_disease_deaths[i]))
            with open("Effects.txt", "w") as file:
                for i in range(len(actual_effects)):
                    file.write("{0}, {1}.\n".format(actual_effects[i],effects[i]))

        outfile.write(sft.format_success_msg(success))
        if debug:
            print( "SUMMARY: Success={0}\n".format(success) )
        return success
Пример #10
0
def create_report_file(data, inset_days, report_name=sft.sft_output_filename):

    lines_c = data[0]
    lines_e = data[1]
    typhoid_acute_infectiousness = data[2]
    ALPHA = 0.175
    N50 = 1.11e6
    dose_response_data_c = []
    dose_response_data_e = []
    dose_response_data_theoretic_c = []
    dose_response_data_theoretic_e = []
    success = True
    with open(report_name, "w") as report_file:
        if len(lines_c) == 0:
            success = False
            report_file.write("Found no individual exposed from route contact.\n" )
        else:
            for line in lines_c:
                dose_response_c = float(sft.get_val("infects=", line))
                dose_response_data_c.append(dose_response_c)
                ind_id_c = int(sft.get_val("individual ", line))
                timestep_c = int(sft.get_val("TimeStep: ", line))
                fContact = float(sft.get_val("fContact=", line))
                dose_response_theoretic_c = float(fContact / typhoid_acute_infectiousness)
                dose_response_data_theoretic_c.append(dose_response_theoretic_c)
                if math.fabs(dose_response_theoretic_c - dose_response_c) > 5e-2:
                    success = False
                    report_file.write(
                        "BAD: Dose-response probability for individual {0} at time {1}, route contact is {2}, "
                        "expected {3}.\n".format(ind_id_c, timestep_c, dose_response_c, dose_response_theoretic_c))
        if len(lines_e) == 0:
            success = False
            report_file.write("Found no individual exposed from route environment.\n")
        else:
            for line in lines_e:
                dose_response_e = float(sft.get_val("infects=", line))
                dose_response_data_e.append(dose_response_e)
                ind_id = int(sft.get_val("individual ", line))
                timestep = int(sft.get_val("TimeStep: ", line))
                exposure = float(sft.get_val("exposure=", line))
                dose_response_theoretic_e = 1.0 - math.pow(1.0 + exposure *
                                                           (math.pow(2.0, 1.0 / ALPHA) - 1.0) / N50, -1.0 * ALPHA)
                dose_response_data_theoretic_e.append(dose_response_theoretic_e)
                if math.fabs(dose_response_theoretic_e - dose_response_e) > 5e-2:
                    success = False
                    report_file.write(
                        "BAD: Dose-response probability for individual {0} at time {1}, route environment is {2}, "
                        "expected {3}.\n".format(ind_id, timestep, dose_response_e, dose_response_theoretic_e))

        report_file.write("Sample size of dose response is {0} for route contact and {1} for route environment."
                          "\n".format(len(lines_c), len(lines_e)))
        report_file.write(sft.format_success_msg(success))

        return [dose_response_data_c, dose_response_data_theoretic_c,
                dose_response_data_e, dose_response_data_theoretic_e]
Пример #11
0
def create_report_file(param_obj, campaign_obj, report_data_obj, report_name, debug):
    with open(report_name, "w") as outfile:
        config_name = param_obj[KEY_CONFIG_NAME]
        outfile.write("Config_name = {}\n".format(config_name))
        success = True
        base_infectivity = param_obj[KEY_BASE_INFECTIVITY]
        initial_effect = campaign_obj[KEY_INITIAL_EFFECT]
        start_day = campaign_obj[KEY_START_DAY]
        new_infection = report_data_obj[KEY_NEW_INFECTION]
        # calculate expected number of infections for a time period of 3 months:
        number_of_month = 3
        expected_new_infection = base_infectivity * sft.DAYS_IN_MONTH * number_of_month * (1.0 - initial_effect)
        # testing for one year
        expected = [expected_new_infection] * (sft.MONTHS_IN_YEAR // number_of_month)
        # group new infections for every 3 months:
        value_to_test = []
        if len(new_infection) < 2 * sft.DAYS_IN_YEAR:
            # the infected individual is imported at the end of first year, so simulation
            # duration need to be at least 2 years.
            success = False
            outfile.write("BAD: the simulation duration is too short, please make sure it's at least 2 years.\n")
        outfile.write("running chi-squared test for expected new infections for {0} {1}-months time bins: \n"
                      "base_infectivity = {2}, initial_effect = {3}.\n".format(sft.MONTHS_IN_YEAR // number_of_month,
                                                                               number_of_month, base_infectivity,
                                                                               initial_effect))
        actual_new_infection = 0
        i = 0
        for t in range(start_day, len(new_infection)):
            actual_new_infection += new_infection[t]
            i += 1
            if not i % (number_of_month * sft.DAYS_IN_MONTH): # at the end of every 3 month
                value_to_test.append(actual_new_infection)
                actual_new_infection = 0
        sft.plot_data(value_to_test, dist2=expected, label1="actual_new_infections",
                                   label2="expected_new_infection",
                                   title="actual vs. expected new infection for every {} months".format(number_of_month),
                                   xlabel="every {} months".format(number_of_month), ylabel="# of new infections",
                                   category='actual_vs_expected_new_infections',
                                   show=True, line=True)
        result = sft.test_multinomial(dist=value_to_test, proportions=expected, report_file=outfile, prob_flag=False)
        if not result:
            success = False
            outfile.write(
                "BAD: The Chi-squared test for number of new infections in every {} months failed.\n".format(number_of_month))
        else:
            outfile.write(
                "GOOD: The Chi-squared test for number of new infections in every {} months passed.\n".format(
                    number_of_month))
        outfile.write(sft.format_success_msg(success))

    if debug:
        print( "SUMMARY: Success={0}\n".format(success) )
    return success
def create_report_file(report_data_obj, report_name, debug):
    with open(report_name, "w") as outfile:
        success = True
        timestep = Outbreak_Start_Day
        tb_effects = calc_tb_effect(debug)
        tb_effect_baseline = float(tb_effects[0]) # use the number of new infection from the 1st outbreak as a baseline
        new_infection_baseline = report_data_obj[KEY_NEW_INFECTIONS_GROUP[1]][timestep]
        statistical_population = report_data_obj[KEY_STATISTICAL_POPULATION_GROUP[1]][timestep] # no any death
        new_infections = []
        expected_new_infections = []
        new_infections.append(new_infection_baseline)
        expected_new_infections.append(new_infection_baseline)
        actual_tb_effects = []
        actual_tb_effects.append(tb_effect_baseline)

        for i in range(1, len(Interventions)): # no need to test the 1st outbreak
            timestep += Timesteps_Between_Repetitions
            new_infection = report_data_obj[KEY_NEW_INFECTIONS_GROUP[1]][timestep]
            tb_effect = tb_effects[i]
            # because expected_new_infection / (1.0 - tb_effect) = new_infection_baseline / (1.0- tb_effect_baseline), so
            expected_new_infection = (1.0 - tb_effect) * new_infection_baseline / (1.0- tb_effect_baseline)
            tolerance = 0.0 if expected_new_infection == 0.0 else 2e-2 * statistical_population
            actual_tb_effect = 1.0 - (new_infection * (1.0 - tb_effect_baseline) / new_infection_baseline)
            result = f"At time step: {timestep}, outbreak: {Interventions[i]}," \
                     f" {new_infection} reported new infections, expected {expected_new_infection}" \
                     f" with tolerance {tolerance}\n"
            if math.fabs(new_infection - expected_new_infection) > tolerance:
                success = False
                outfile.write(f"BAD:  {result}")
            else:
                outfile.write(f"GOOD: {result}")
            outfile.write("\tactual TransmissionBlocking effect is {0}, expected {1}.\n".format(actual_tb_effect, tb_effect))
            new_infections.append(new_infection)
            expected_new_infections.append(expected_new_infection)
            actual_tb_effects.append(actual_tb_effect)
        sft.plot_data(new_infections,expected_new_infections,
                               label1= "Actual", label2 = "Expected",
                               xlabel= "outbreak",ylabel="new infection",
                               title = "Actual new infection vs. expected new infection",
                               category = 'New_infections',show = True )
        if debug:
            with open("New_infections.txt", "w") as file:
                for i in range(len(new_infections)):
                    file.write("{0}, {1}.\n".format(new_infections[i],expected_new_infections[i]))
            with open("Effects.txt", "w") as file:
                for i in range(len(actual_tb_effects)):
                    file.write("{0}, {1}.\n".format(actual_tb_effects[i],tb_effects[i]))

        outfile.write(sft.format_success_msg(success))
        if debug:
            print( "SUMMARY: Success={0}\n".format(success) )
        return success
Пример #13
0
def create_report_file(report_data_obj, report_name, debug):
    with open(report_name, "w") as outfile:
        success = True

        timestep = Outbreak_Start_Day
        tb_effect = prime
        baseline = 2  # group 3_Control is the baseline
        test = 3  # group 4_Test is the test group
        # first outbreak
        pre_new_infection_baseline = report_data_obj[
            KEY_NEW_INFECTIONS_GROUP[baseline]][timestep]
        pre_new_infection_test = report_data_obj[
            KEY_NEW_INFECTIONS_GROUP[test]][timestep]
        # second outbreak
        timestep += Timesteps_Between_Repetitions
        new_infection_baseline = report_data_obj[
            KEY_NEW_INFECTIONS_GROUP[baseline]][timestep]
        statistical_population_baseline = report_data_obj[
            KEY_STATISTICAL_POPULATION_GROUP[baseline]][timestep]
        new_infection_test = report_data_obj[
            KEY_NEW_INFECTIONS_GROUP[test]][timestep]
        statistical_population_test = report_data_obj[
            KEY_STATISTICAL_POPULATION_GROUP[test]][timestep]
        # because expected_new_infection_test / ((1.0 - tb_effect)* statistical_population_test)= new_infection_baseline / statistical_population_baseline, so
        expected_new_infection_test = (
            1.0 - tb_effect
        ) * new_infection_baseline * statistical_population_test / statistical_population_baseline
        tolerance = 0.0 if expected_new_infection_test == 0.0 else 2e-2 * statistical_population_test
        result = f"At time step {timestep}, {new_infection_test} reported new infections in Group 4_Test," \
                 f"expected {expected_new_infection_test} tolerance: {tolerance}.\n"
        if math.fabs(new_infection_test -
                     expected_new_infection_test) > tolerance:
            success = False
            outfile.write(f"BAD:  {result}")
        else:
            outfile.write(f"GOOD: {result}")

        sft.plot_data([pre_new_infection_baseline, new_infection_baseline],
                      [pre_new_infection_test, new_infection_test],
                      label1="control_group",
                      label2="test_group",
                      xlabel="0: first outbreak, 1: second outbreak",
                      ylabel="new infection",
                      title="control vs. test",
                      category='New_infections',
                      show=True)

        outfile.write(sft.format_success_msg(success))
        if debug:
            print("SUMMARY: Success={0}\n".format(success))
        return success
Пример #14
0
def create_report_file(states_df, config_obj, report_name):
    with open(report_name, "w") as outfile:
        outfile.write("{}\n".format(config_obj["Config_Name"]))
        success = True
        # ideally we would get this from campaign.json
        campaign_day = 50
        campaign_day_plus = campaign_day + 1
        # checking that all chronic people that were sick on day of campaign have been cured,
        # there should be no overlapping ids
        common_ids = set(states_df.at[campaign_day, "CHR"]) & set(
            states_df.at[campaign_day_plus, "CHR"])
        if common_ids:
            success = False
            outfile.write(
                "BAD: The following individuals were chronic and should've been cured, "
                "but they are still sick the day after the campaign:\n")
            for ind in common_ids:
                outfile.write("{} ".format(ind))
            outfile.write("\n")
        else:
            outfile.write(
                "GOOD: Everyone who was chronic on the day of campaign has been cured the next day.\n"
            )

        # checking that none of the of the non-chronic sick people was cured
        sick_campaign_day = set(states_df.at[campaign_day, "PRE"] +
                                states_df.at[campaign_day, "ACU"] +
                                states_df.at[campaign_day, "SUB"])
        # chronic and susceptible added in case someone went chronic after the campaign or healed on their own
        sick_campaign_day_plus = set(states_df.at[campaign_day_plus, "PRE"] +
                                     states_df.at[campaign_day_plus, "ACU"] +
                                     states_df.at[campaign_day_plus, "SUB"] +
                                     states_df.at[campaign_day_plus, "SUS"] +
                                     states_df.at[campaign_day_plus, "CHR"])
        # verifying no one else got cured by checking that those still sick are still sick (or went chronic or healed)
        if not sick_campaign_day.issubset(sick_campaign_day_plus):
            outfile.write(
                "BAD: List of those non-chronically sick the day before is not a subset of people sick the "
                "following day. Please check the logs for following ids: \n")
            for individual in sick_campaign_day.difference(
                    sick_campaign_day_plus):
                outfile.write("{} ".format(str(individual)))
            outfile.write("\n")
        else:
            outfile.write(
                "GOOD: People who were not chronic were not cured by the intervention.\n"
            )

        outfile.write(sft.format_success_msg(success))
def create_report_file(n_nodes, s_nodes, e_nodes, w_nodes,
                       debug=False, sft_filename=sft.sft_output_filename):
    with open(sft_filename, "a") as report_file:
        success = True

        old_east_count = e_nodes[e_nodes['AgeYears'] == 62]['NumIndividuals'].sum()
        old_west_count = w_nodes[w_nodes['AgeYears'] == 62]['NumIndividuals'].sum()
        young_east_count = e_nodes[e_nodes['AgeYears'] == 22]['NumIndividuals'].sum()
        young_west_count = w_nodes[w_nodes['AgeYears'] == 22]['NumIndividuals'].sum()
        report_file.write("Old people should go east.\n")
        report_file.write(f"There were {old_east_count} E old people and {old_west_count} W old.\n")
        report_file.write(f"There were {old_east_count} E old peple and {young_east_count} E young.\n")
        if old_east_count <= old_west_count:
            report_file.write(f"BAD: There were {old_east_count} E old people and {old_west_count} W old.\n")
            success = False
        if old_east_count <= young_east_count:
            report_file.write(f"BAD: There were {old_east_count} E old peple and {young_east_count} E young.\n")
            success = False
        report_file.write("Young people should go west.\n")
        report_file.write(f"There were {young_west_count} W young people and {young_east_count} E young.\n")
        report_file.write(f"There were {young_west_count} W young people and {old_west_count} W old.\n")
        if young_west_count <= young_east_count:
            report_file.write(f"BAD: There were {young_west_count} W young people and {young_east_count} E young.\n")
            success = False
        if young_west_count <= old_west_count:
            report_file.write(f"BAD: There were {young_west_count} W young people and {old_west_count} W old.\n")
        north_men_count = n_nodes[n_nodes['Gender'] == 'M']['NumIndividuals'].sum()
        north_women_count = n_nodes[n_nodes['Gender'] == 'F']['NumIndividuals'].sum()
        south_men_count = s_nodes[s_nodes['Gender'] == 'M']['NumIndividuals'].sum()
        south_women_count = s_nodes[s_nodes['Gender'] == 'F']['NumIndividuals'].sum()
        report_file.write("Men should go north.\n")
        report_file.write(f"There were {north_men_count} N Men and {north_women_count} N Women.\n")
        report_file.write(f"There were {north_men_count} N Men and {south_men_count} S Men.\n")
        if north_men_count <= north_women_count:
            report_file.write(f"BAD: There were {north_men_count} N Men and {north_women_count} S Women.\n")
            success = False
        if north_men_count <= south_men_count:
            report_file.write(f"BAD: There were {north_men_count} N Men and {south_men_count} S Men.\n")
            success = False
        report_file.write("Women should go south.\n")
        report_file.write(f"There were {south_women_count} S Women and {south_men_count} S Men.\n")
        report_file.write(f"There were {south_women_count} S Women and {north_women_count} N Women.\n")
        if south_women_count <= south_men_count:
            report_file.write(f"BAD: There were {south_women_count} S Women and {south_men_count} S Men.\n")
            success = False
        if south_women_count <= north_women_count:
            report_file.write(f"BAD: There were {south_women_count} S Women and {north_women_count} N Men.\n")
            success = False
        report_file.write(sft.format_success_msg(success))
Пример #16
0
def create_report_file(param_obj, actual_infections, inset_days, report_name):
    success = True
    error_tolerance = 2.5e-2
    with open(report_name, "w") as outfile:
        # Test HIV infections
        test_tstep_hiv = param_obj[CampaignKeys.Start_Day][0] + 1
        actual_hiv_infections = actual_infections[0]
        expected_hiv_infections_fraction = param_obj[CampaignKeys.Coverage][0]
        actual_hiv_infection_fraction = 1.0 * actual_hiv_infections / inset_days[
            test_tstep_hiv]
        outfile.write("Total HIV infections fraction expected: {0} \n".format(
            expected_hiv_infections_fraction))
        outfile.write(
            "Total HIV infections: {0} \n".format(actual_hiv_infections))
        outfile.write("Total HIV infection fraction: {0} \n".format(
            actual_hiv_infection_fraction))
        total_error_hiv = math.fabs(expected_hiv_infections_fraction -
                                    actual_hiv_infection_fraction)

        if total_error_hiv > error_tolerance:
            success = False
            outfile.write(
                "BAD: Total error is {0} for HIV, error tolerance is {1}\n".
                format(total_error_hiv, error_tolerance))

        # Test TB infections
        test_tstep_tb = param_obj[CampaignKeys.Start_Day][1] + 1
        actual_tb_infections = actual_infections[1]
        expected_tb_infections_fraction = param_obj[CampaignKeys.Coverage][1]
        actual_tb_infection_fraction = 1.0 * actual_tb_infections / inset_days[
            test_tstep_tb]
        outfile.write("Total TB infections fraction expected: {0} \n".format(
            expected_tb_infections_fraction))
        outfile.write(
            "Total TB infections: {0} \n".format(actual_tb_infections))
        outfile.write("Total TB infection fraction: {0} \n".format(
            actual_tb_infection_fraction))
        total_error_tb = math.fabs(expected_tb_infections_fraction -
                                   actual_tb_infection_fraction)
        success = True

        if total_error_tb > error_tolerance:
            success = False
            outfile.write(
                "BAD: Total error is {0} for TB, error tolerance is {1}\n".
                format(total_error_tb, error_tolerance))

        outfile.write(sft.format_success_msg(success))
Пример #17
0
def create_report_file(data):
    total_susceptible_daily = data[0]
    population = data[1]
    simulation_duration = data[2]
    typhoid_exposure_lambda = data[3]
    report_name = data[4]

    # by the end of the sim, everyone should be susceptible, so I'm taking the last data point.
    total_susceptible = total_susceptible_daily[-1]

    theoretical_total_susceptible_daily = []
    # off by one by because newborns are already 1 day old on day 1
    for i in range(1, simulation_duration + 1):
        theoretical_total_susceptible_daily.append(
            int(population * inf_calc(i, typhoid_exposure_lambda)))

    success = True
    with open(report_name, "w") as report_file:
        if not total_susceptible == population:
            success = False
            report_file.write(
                "Not everyone converted to susceptible! Expecting {}, got {}"
                "\n".format(population, total_susceptible))
        else:
            # leaving this in case the test fails and you want to look at the data directly, commenting to keep
            # final clean
            # for i in range(0, simulation_duration):
            # report_file.write("data - {}, theory - {} \n".format(total_susceptible_daily[i],
            # theoretical_total_susceptible_daily[i]))

            result = stats.ks_2samp(theoretical_total_susceptible_daily,
                                    total_susceptible_daily)
            p = sft.get_p_s_from_ksresult(result)['p']
            s = sft.get_p_s_from_ksresult(result)['s']

            P_EPSILON = 5e-2
            critical_value_s = sft.calc_ks_critical_value(population)
            if p >= P_EPSILON or s <= critical_value_s:
                success = True
            else:
                report_file.write(
                    "BAD: Either p-value of {} is less than {} and/or s-value of {} is smaller "
                    "than {}.\n".format(p, P_EPSILON, s, critical_value_s))
                success = False

        report_file.write(sft.format_success_msg(success))

    return theoretical_total_susceptible_daily
Пример #18
0
def create_report_file( active_TB_treatments,relapses, tb_drug_relapse_rate_hiv,drug_start_timestep, report_name ):
    with open(report_name, "w") as outfile:
        print(str(relapses), str(tb_drug_relapse_rate_hiv))
        success = True
        if sum(active_TB_treatments)==0 or sum(relapses)==0:
            success = False
            outfile.write(sft.sft_no_test_data)
        for x in range (drug_start_timestep + 1, len(active_TB_treatments) - 1):
            active_TB_treatment = int(active_TB_treatments[x])
            relapse = relapses[x + 1]
            result = sft.test_binomial_99ci( relapse, active_TB_treatment, tb_drug_relapse_rate_hiv, outfile, category="time step {}".format(x+1) )
            if not result:
                success = False
                outfile.write("BAD: test fails for rate = {0} at time step {1}.\n".format(tb_drug_relapse_rate_hiv, x +1))

        outfile.write(sft.format_success_msg(success))
        return success
Пример #19
0
def create_report_file(report_data_obj, report_name, debug):
    with open(report_name, "w") as outfile:
        success = True
        immunity = calc_immunity(debug)
        new_infections = []
        expected_new_infections = []
        timestep = Outbreak_Start_Day
        if not report_data_obj:
            success = False
            outfile.write("BAD: There is no data in the PropertyReport report")
        else:
            for i in range(Number_Repetitions):
                for j in range(len(KEY_NEW_INFECTIONS_GROUP)):
                    new_infection = report_data_obj[
                        KEY_NEW_INFECTIONS_GROUP[j]][timestep]
                    statistical_population = report_data_obj[
                        KEY_STATISTICAL_POPULATION_GROUP[j]][timestep]
                    expected_new_infection = statistical_population * (
                        1.0 - immunity[j][i])
                    tolerance = 0.0 if expected_new_infection == 0.0 else 2e-2 * statistical_population
                    result = f"At time step {timestep}, {KEY_NEW_INFECTIONS_GROUP[j]}" \
                             f" new infections: {new_infection}, expected infections: {expected_new_infection}" \
                             f"  with tolerance {tolerance}.\n"
                    if math.fabs(new_infection -
                                 expected_new_infection) > tolerance:
                        success = False
                        outfile.write(f"BAD:  {result}")
                    else:
                        outfile.write(f"GOOD: {result}")
                    new_infections.append(new_infection)
                    expected_new_infections.append(expected_new_infection)
                timestep += Timesteps_Between_Repetitions
        outfile.write(sft.format_success_msg(success))
    sft.plot_data(new_infections,
                  expected_new_infections,
                  label1="Actual",
                  label2="Expected",
                  xlabel="group: 0-4 outbreak 1, 5-9 outbreak 2",
                  ylabel="new infection",
                  title="Actual new infection vs. expected new infection",
                  category='New_infections',
                  show=True)
    if debug:
        print("SUMMARY: Success={0}\n".format(success))
    return success
Пример #20
0
def create_report_file(param_obj, report_data_obj, report_name, debug):
    with open(report_name, "w") as outfile:
        success = True
        new_infection_portions = calc_expected_new_infection_portion(
            param_obj, debug)
        new_infections = []
        expected_new_infections = []
        # skip the first outbreak, which gives the natual immunity
        timestep = Outbreak_Start_Day + Timesteps_Between_Repetitions
        for i in range(len(KEY_NEW_INFECTIONS_GROUP)):
            new_infection = report_data_obj[
                KEY_NEW_INFECTIONS_GROUP[i]][timestep]
            statistical_population = report_data_obj[
                KEY_STATISTICAL_POPULATION_GROUP[i]][timestep]
            expected_new_infection = statistical_population * (
                new_infection_portions[i])
            tolerance = 0.0 if expected_new_infection == 0.0 else 2e-2 * statistical_population
            result = f"At time step: {timestep} Group: {KEY_NEW_INFECTIONS_GROUP[i]}" \
                     f" reported new infections: {new_infection} expected: {expected_new_infection}" \
                     f" tolerance: {tolerance}.\n"
            if math.fabs(new_infection - expected_new_infection) > tolerance:
                success = False
                outfile.write(f"BAD:  {result}")
            else:
                outfile.write(f"GOOD: {result}")

            new_infections.append(new_infection)
            expected_new_infections.append(expected_new_infection)
        outfile.write(sft.format_success_msg(success))
    sft.plot_data(new_infections,
                  expected_new_infections,
                  label1="Actual",
                  label2="Expected",
                  xlabel="0: Control group, 1: Test group",
                  ylabel="new infection",
                  title="Actual new infection vs. expected new infection",
                  category='New_infections',
                  show=True)
    if debug:
        print("SUMMARY: Success={0}\n".format(success))
    return success
def create_report_file(report_data_obj, report_name, debug):
    with open(report_name, "w") as outfile:
        success = True

        timestep = Outbreak_Start_Day
        tb_effect = prime
        baseline = 2 # group 3_Control is the baseline
        test = 3 # group 4_Test is the test group
        # first outbreak
        pre_new_infection_baseline = report_data_obj[KEY_NEW_INFECTIONS_GROUP[baseline]][timestep]
        pre_new_infection_test= report_data_obj[KEY_NEW_INFECTIONS_GROUP[test]][timestep]
        # second outbreak
        timestep +=  Timesteps_Between_Repetitions
        new_infection_baseline = report_data_obj[KEY_NEW_INFECTIONS_GROUP[baseline]][timestep]
        statistical_population_baseline = report_data_obj[KEY_STATISTICAL_POPULATION_GROUP[baseline]][timestep]
        new_infection_test= report_data_obj[KEY_NEW_INFECTIONS_GROUP[test]][timestep]
        statistical_population_test = report_data_obj[KEY_STATISTICAL_POPULATION_GROUP[test]][timestep]
        # because expected_new_infection_test / ((1.0 - tb_effect)* statistical_population_test)= new_infection_baseline / statistical_population_baseline, so
        expected_new_infection_test = (1.0 - tb_effect) * new_infection_baseline * statistical_population_test / statistical_population_baseline
        tolerance = 0.0 if expected_new_infection_test == 0.0 else 2e-2 * statistical_population_test
        result = f"At time step {timestep}, {new_infection_test} reported new infections in Group 4_Test," \
                 f"expected {expected_new_infection_test} tolerance: {tolerance}.\n"
        if math.fabs(new_infection_test - expected_new_infection_test) > tolerance:
            success = False
            outfile.write(f"BAD:  {result}")
        else:
            outfile.write(f"GOOD: {result}")

        sft.plot_data([pre_new_infection_baseline, new_infection_baseline],[pre_new_infection_test, new_infection_test],
                               label1= "control_group", label2 = "test_group",
                               xlabel= "0: first outbreak, 1: second outbreak",ylabel="new infection",
                               title = "control vs. test",
                               category = 'New_infections',show = True )

        outfile.write(sft.format_success_msg(success))
        if debug:
            print( "SUMMARY: Success={0}\n".format(success) )
        return success
def create_report_file(report_data_obj, report_name, debug):
    with open(report_name, "w") as outfile:
        success = True
        immunity = calc_immunity(debug)
        new_infections = []
        expected_new_infections = []
        timestep = Outbreak_Start_Day
        if not report_data_obj:
            success = False
            outfile.write("BAD: There is no data in the PropertyReport report")
        else:
            for i in range(Number_Repetitions):
                for j in range(len(KEY_NEW_INFECTIONS_GROUP)):
                    new_infection = report_data_obj[KEY_NEW_INFECTIONS_GROUP[j]][timestep]
                    statistical_population = report_data_obj[KEY_STATISTICAL_POPULATION_GROUP[j]][timestep]
                    expected_new_infection = statistical_population * (1.0 - immunity[j][i])
                    tolerance = 0.0 if expected_new_infection == 0.0 else 2e-2 * statistical_population
                    result = f"At time step {timestep}, {KEY_NEW_INFECTIONS_GROUP[j]}" \
                             f" new infections: {new_infection}, expected infections: {expected_new_infection}" \
                             f"  with tolerance {tolerance}.\n"
                    if math.fabs(new_infection - expected_new_infection) > tolerance:
                        success = False
                        outfile.write(f"BAD:  {result}")
                    else:
                        outfile.write(f"GOOD: {result}")
                    new_infections.append(new_infection)
                    expected_new_infections.append(expected_new_infection)
                timestep += Timesteps_Between_Repetitions
        outfile.write(sft.format_success_msg(success))
    sft.plot_data(new_infections,expected_new_infections,
                           label1= "Actual", label2 = "Expected",
                           xlabel= "group: 0-4 outbreak 1, 5-9 outbreak 2",ylabel="new infection",
                           title = "Actual new infection vs. expected new infection",
                           category = 'New_infections',show = True )
    if debug:
        print( "SUMMARY: Success={0}\n".format(success) )
    return success
Пример #23
0
def application(report_file):
    sft.wait_for_done()
    lines = []
    with open("test.txt") as logfile:
        for line in logfile:
            if re.search("Initializing Typhoid immunity object",
                         line) and re.search("age=0.000000", line):
                lines.append(line)

    success = True
    actual_newborn_immunity_data = []
    expected_newborn_immunity_data = []
    with open(sft.sft_output_filename, "w") as report_file:
        if not lines:
            success = False
            report_file.write("BAD: Found no data matching test case.\n")
        else:
            for line in lines:
                immunity = float(sft.get_val(" immunity modifier", line))
                actual_newborn_immunity_data.append(immunity)
                expected_newborn_immunity_data.append(1)
                if immunity != 1.000:
                    success = False
                    report_file.write(
                        "BAD: immunity for newborn={0} instead of 1.0\n".
                        format(immunity))

        report_file.write(sft.format_success_msg(success))

        sft.plot_data_sorted(actual_newborn_immunity_data,
                             expected_newborn_immunity_data,
                             label1="Actual",
                             label2="Expected",
                             title="Newborn Immunity Data",
                             xlabel="Individuals",
                             ylabel="Immunity",
                             category='multi_mode_intervention')
Пример #24
0
def create_report_file(report_data_obj, report_name, debug):
    with open(report_name, "w") as outfile:
        success = True
        immunity = calc_immunity(debug)
        new_infections = []
        expected_new_infections = []
        timestep = Outbreak_Start_Day
        for i in range(len(KEY_NEW_INFECTIONS_GROUP)):
            new_infection = report_data_obj[
                KEY_NEW_INFECTIONS_GROUP[i]][timestep]
            statistical_population = report_data_obj[
                KEY_STATISTICAL_POPULATION_GROUP[i]][timestep]
            expected_new_infection = statistical_population * (1.0 -
                                                               immunity[i])
            tolerance = 0.0 if expected_new_infection == 0.0 else 2e-2 * statistical_population
            if math.fabs(new_infection - expected_new_infection) > tolerance:
                success = False
                outfile.write(
                    "BAD: At time step {0}, {1} has {2} reported, expected {3}.\n"
                    .format(timestep, KEY_NEW_INFECTIONS_GROUP[i],
                            new_infection, expected_new_infection))
            new_infections.append(new_infection)
            expected_new_infections.append(expected_new_infection)
        outfile.write(sft.format_success_msg(success))
    sft.plot_data(
        new_infections,
        expected_new_infections,
        label1="Actual",
        label2="Expected",
        xlabel="0: VaccineOnly, 1: 2Vaccines, 2: 3Vaccines, 3: 5Vaccines",
        ylabel="new infection",
        title="Actual new infection vs. expected new infection",
        category='New_infections',
        show=True)
    if debug:
        print("SUMMARY: Success={0}\n".format(success))
    return success
def create_report_file(param_obj, multipliers, infectiousness, report_name, debug):
    with open(report_name, "w") as outfile:
        success = True
        if not multipliers:
            outfile.write(sft.sft_no_test_data)
        sigma = param_obj[Param_keys.LOGNORMAL_SCALE]
        base_infectivity = param_obj[Param_keys.BASE_INFECTIVITY]
        if sigma > 0:
            mu = - sigma**2 / 2.0
            # test log_normal distribution
            success = sft.test_lognorm(multipliers,mu=mu, sigma=sigma,report_file=outfile,round = False)

            # test mean_l = 1
            mean_l = np.mean(multipliers)
            mean_infectiousness = np.mean(infectiousness)
            outfile.write("mean of the multipliers is {}, expected 1.0.\n".format(mean_l))
            outfile.write("mean of the Infectiousness is {0}, while base infectivity is {1}.\n".format(mean_infectiousness,
                                                                                           base_infectivity))

            tolerance  = 3e-2
            if math.fabs(mean_l - 1.0) > tolerance:
                outfile.write("BAD: mean of the multipliers is {}, expected 1.0.\n".format(mean_l))
                success = False
            # plotting
            size = len(multipliers)
            outfile.write("size is {}\n".format(size))
            scale = math.exp(mu)
            dist_lognormal = stats.lognorm.rvs(sigma, 0, scale, size)
            sft.plot_data_sorted(multipliers, dist_lognormal,
                          label1="Emod", label2="Scipy",
                          ylabel="Multiplier", xlabel="data point",
                          category="Emod_vs_Scipy",
                          title="Emod_vs_Scipy, sigma = {}".format(sigma),
                          show=True)
            sft.plot_probability(multipliers, dist_lognormal,
                                 precision=1, label1="Emod", label2="Scipy",
                                 category="Probability_mass_function_Emod_vs_Scipy",
                                 title="Emod_vs_Scipy, sigma = {}".format(sigma),
                                 show=True)
            sft.plot_cdf(multipliers,dist_lognormal,label1="Emod", label2="Scipy",
                                 category="cdf",
                                 title="cdf, sigma = {}".format(sigma),
                                 show=True, line = False)
            if debug:
                with open("scipy_data.txt", "w") as file:
                    for n in sorted(dist_lognormal):
                        file.write(str(n) + "\n")
                with open("emod_data.txt", "w") as file:
                    for n in sorted(multipliers):
                        file.write(str(n) + "\n")
        else:
            # sigma = 0, this feature is disabled
            for multiplier in multipliers:
                if multiplier != 1.0:
                    success = False
                    outfile.write("BAD: multiplier is {0} when {1} set to {2}, expected 1.0.\n".format(multiplier, Param_keys.LOGNORMAL_SCALE, sigma))
            # plotting
            sft.plot_data_sorted(multipliers, label1="Multiplier", label2="NA",
                          category="Multiplier", title="Multiplier_Sigma={}".format(sigma),
                          ylabel="Multiplier", xlabel="data point",
                          show=True)
            sft.plot_data_sorted(infectiousness, label1="Infectiousness",
                          label2="NA",category="Infectiousness",
                          title="Infectiousness_Sigma={0}_BaseInfectivity={1}".format(sigma,base_infectivity),
                          ylabel="Infectiousness",xlabel="data point",
                          show=True)
        outfile.write(sft.format_success_msg(success))

    if debug:
        print( "SUMMARY: Success={0}\n".format(success) )
    return success
Пример #26
0
def application(report_file):
    sft.wait_for_done()
    # print( "Post-processing: " + report_file )
    cdj = json.loads(open("config.json").read())["parameters"]
    ncdr = cdj["Node_Contagion_Decay_Rate"]
    start_time = cdj["Start_Time"]
    simulation_duration = int(cdj["Simulation_Duration"])
    isj = json.loads(open("output/InsetChart.json").read())["Channels"]
    environmental_contagion_population = isj[
        "Environmental Contagion Population"]["Data"]

    timestep = start_time
    lines = []
    cum_all = []
    cum = 0
    Statpop = []
    adding_cp_log = []
    adding_cp = 0
    shedding = 0
    with open("test.txt") as logfile:
        for line in logfile:
            if "Update(): Time:" in line:
                # calculate time step
                timestep += 1
                pop = float(sft.get_val("StatPop: ", line))
                Statpop.append(pop)

                # append the accumulated shedding and reset the counter at the end of each time step.
                # data for timestep 1 is stored in cum_all[1]
                cum_all.append(cum)
                # environmental cp decay
                cum *= 1.0 - ncdr
                adding_cp_log.append(adding_cp)
                # resetting shedding and adding_cp variables
                shedding = 0
                adding_cp = 0
            elif "[MultiRouteTransmissionGroups] Adding " in line and "route:1" in line:
                # append time step and total shedding line to lists
                # line = "TimeStep: " + str(timestep) + " " + line
                # lines.append(line)
                line = "TimeStep: " + str(timestep) + " " + line
                lines.append(line)
                adding_cp = float(sft.get_val("Adding ", line))
            elif "Exposing " in line and "route 'environment'" in line:
                # append time step and Exposing line to lists
                line = "TimeStep: " + str(timestep) + " " + line
                lines.append(line)
            elif "depositing" in line and "route environment" in line:
                # get shedding of contact route and add it to accumulated shedding
                shedding = float(sft.get_val("depositing ", line))
                cum += shedding
                line = "TimeStep: " + str(timestep) + " " + line
                lines.append(line)
            # elif "scaled by " in line and "route:1" in line:
            #     # get population
            #     if timestep > 0:
            #         # start collecting population at time 1
            #         pop = float(sft.get_val("scaled by ", line))
            #         Statpop.append(pop)
    with open("DEBUG_filtered_from_StdOut.txt", "w") as file:
        file.write("".join(lines))
    expected_cp_insetchart = []
    cp_stdout_dict = {}
    success = True
    with open(sft.sft_output_filename, "w") as report_file:
        if len(lines) == 0:
            success = False
            report_file.write("Found no data matching test case.\n")
        else:
            if len(cum_all) != simulation_duration or len(
                    Statpop) != simulation_duration:
                report_file.write(
                    "WARNING: the test.txt file is incomplete. len(cum_all)={0},  len(Statpop)={1},"
                    " expected {2}.\n".format(len(cum_all), len(Statpop),
                                              simulation_duration))
            for line in lines:
                if re.search("Exposing", line):
                    environment = float(sft.get_val("environment=", line))
                    timestep = int(sft.get_val("TimeStep: ", line))
                    expected_cp = cum_all[timestep -
                                          start_time] / Statpop[timestep -
                                                                start_time - 1]
                    if timestep not in cp_stdout_dict:
                        cp_stdout_dict[timestep] = [environment, expected_cp]
                        if math.fabs(environment -
                                     expected_cp) > 1e-2 * expected_cp:
                            success = False
                            ind_id = int(sft.get_val("inividual ", line))
                            report_file.write(
                                "BAD: at time {0}, individuals are exposed on route environment with contagion "
                                "population = {1} StatPop = {2}, expected {3}."
                                "\n".format(timestep, environment,
                                            Statpop[timestep - start_time - 1],
                                            expected_cp))
            pre_cum = 0
            for timestep in range(len(cum_all) - 1):
                # report_file.write("timestep={0}, StatPop = {1}, cum_all= {2}, adding_cp_log = {3}.
                # \n".format(x,Statpop[x+1],cum_all[x], adding_cp_log[x]))

                # the InsetChart is missing the first time step, so we're taking it out from the log. #2890
                # cur_cum = cum_all[timestep + 1]
                cur_cum = cum_all[timestep]

                # comment out these code since we are no longer logging the accumulated shedding in StdOut file.
                # adding_cp = cur_cum - pre_cum * (1.0 - ncdr)
                # # pass cur_cum to pre_cum for next time step
                # pre_cum = cur_cum
                # if math.fabs(adding_cp - adding_cp_log[x]) > 1e-1:
                #     success = False
                #     report_file.write(
                #         "BAD: At time {0}, the accumulated shedding is {1} from StdOut, expected {2}."
                #         "\n".format(timestep, adding_cp_log[x], adding_cp))

                expected_cp = cur_cum / Statpop[timestep]
                expected_cp_insetchart.append(expected_cp)
                if math.fabs(expected_cp -
                             environmental_contagion_population[timestep]
                             ) > 1e-2 * expected_cp:
                    success = False
                    report_file.write(
                        "BAD: At time {0}, the environmental contagion population is {1} from InsetChart.json, "
                        "expected {2}.\n".format(
                            timestep,
                            environmental_contagion_population[timestep],
                            expected_cp))

        report_file.write(sft.format_success_msg(success))

        sft.plot_data(
            environmental_contagion_population,
            expected_cp_insetchart,
            label1="InsetChart",
            label2="expected data",
            title=
            "Environmental Contagion Population\n InsetChart vs. expected",
            xlabel="Day",
            ylabel="Environmental Contagion Population",
            category='environmental_contagion_population_InsetChart',
            alpha=0.5,
            overlap=True)

        sft.plot_data(np.array(list(cp_stdout_dict.values()))[:, 0],
                      np.array(list(cp_stdout_dict.values()))[:, 1],
                      label1="StdOut",
                      label2="expected data",
                      title="Exposure(Contagion)\n StdOut vs. expected",
                      xlabel="Day",
                      ylabel="Contagion",
                      category='exposure_StdOut',
                      alpha=0.5,
                      overlap=True)

        cp_list_for_plot = []
        for key in sorted(cp_stdout_dict):
            cp_list_for_plot.append([
                cp_stdout_dict[key][0],
                environmental_contagion_population[key - 1]
            ])
        sft.plot_data(
            np.array(cp_list_for_plot)[:, 1][1:],
            np.array(cp_list_for_plot)[:, 0],
            label1="InsetChart",
            label2="StdOut",
            title="Environmental Contagion Population\n InsetChart vs. StdOut",
            xlabel="Day",
            ylabel="Contagion",
            category='environmental_contagion_population',
            alpha=0.5,
            overlap=True)
Пример #27
0
def create_report_file(
    param_obj,
    campaign_obj,
    demographics_obj,
    report_data_obj,
    report_name,
    debug=False,
):
    """creates report file from data_obj structures
    :returns: scientific feature report with details of the tests
    """
    with open(report_name, "w") as outfile:
        total_timesteps = param_obj[KEY_TOTAL_TIMESTEPS]
        start_timestep = param_obj[KEY_START_TIME]
        initial_population = demographics_obj[KEY_INITIAL_POPULATION]
        rates = campaign_obj[KEY_CAMPAIGN_DIP]
        durations = campaign_obj[KEY_CAMPAIGN_DURATIONS]
        outfile.write(
            "# Test name: " + str(param_obj["Config_Name"]) +
            ", Run number: " + str(param_obj["Run_Number"]) +
            "\n# Test compares the statistical population with the"
            " calculated population and tests the Poisson distribution for new infections.\n"
        )
        try:
            new_infections = report_data_obj[KEY_NEW_INFECTIONS]
            statistical_population = report_data_obj[
                KEY_STATISTICAL_POPULATION]
            length = len(rates)
            start_duration = start_timestep
            new_infections_dict = {}
            calculate_new_population = initial_population
            for i in range(length):
                rate = rates[i]
                duration = durations[i]
                calculate_new_population = rate * duration + calculate_new_population
                end_duration = duration + start_duration
                if rate not in new_infections_dict:
                    new_infections_dict[rate] = []
                for j in range(start_duration + 1, end_duration + 1):
                    if j < total_timesteps + start_timestep:
                        new_infections_dict[rate].append(new_infections[j])
                        j += 1
                    else:
                        break
                if end_duration > total_timesteps + start_timestep:
                    calculate_new_population -= rate * (
                        end_duration - total_timesteps - start_timestep)
                    break
                start_duration = end_duration
            if end_duration < total_timesteps + start_timestep:
                rate = 0.0
                if rate not in new_infections_dict:
                    new_infections_dict[rate] = []
                for j in range(end_duration + 1, len(new_infections)):
                    new_infections_dict[rate].append(new_infections[j])
            if debug:
                with open("DEBUG_new_infections_parsed.json",
                          "w") as new_infections_file:
                    json.dump(new_infections_dict,
                              new_infections_file,
                              indent=4)

            # test statistical population channel
            diff_population = math.fabs(calculate_new_population -
                                        statistical_population[-1])
            if debug:
                print("calculated population is {0}, statistical population "
                      "from InsetChart is {1}.".format(
                          calculate_new_population,
                          statistical_population[-1]))
            error_tolerance = math.fabs(calculate_new_population -
                                        initial_population) * 0.1
            low_acceptance_bound = round(calculate_new_population -
                                         error_tolerance)
            high_acceptance_bound = round(calculate_new_population +
                                          error_tolerance)
            if debug:
                print("diff_population is {0}, error_tolerance is {1}".format(
                    diff_population, error_tolerance))
            success = diff_population < error_tolerance
            result_string = "GOOD" if success else "BAD"
            within_acceptance_bounds = " " if success else " not "
            outfile.write(
                "{0}: statistical population is {1}, which is{2}within range ({3}, {4})"
                ".  Expected about {5}.\n".format(result_string,
                                                  statistical_population[-1],
                                                  within_acceptance_bounds,
                                                  low_acceptance_bound,
                                                  high_acceptance_bound,
                                                  calculate_new_population))
            # test poisson distribution for new infections
            for rate in new_infections_dict:
                dist = new_infections_dict[rate]
                title = "rate = " + str(rate)
                result = sft.test_poisson(dist,
                                          rate,
                                          route=title,
                                          report_file=outfile,
                                          normal_approximation=False)
                if not result:
                    success = False
                numpy_distro = np.random.poisson(rate, len(dist))
                sft.plot_data(
                    dist,
                    numpy_distro,
                    title="new infections for {}".format(title),
                    label1="new infection from model, {}".format(title),
                    label2="Poisson distro from numpy",
                    xlabel="data points",
                    ylabel="new infection",
                    category="plot_data_{0}".format(title),
                    show=True)
                sft.plot_probability(
                    dist,
                    numpy_distro,
                    title="probability mass function for {}".format(title),
                    label1="new infection probability from model",
                    label2="new infection probability from numpy distro",
                    category="plot_probability_{0}".format(title),
                    show=True)
        except IndexError:
            success = False
            outfile.write("BAD: There is no data in the InsetChart report")
            print("IndexError: There is no data in the InsetChart report")
        outfile.write(sft.format_success_msg(success))
        if debug:
            print("SUMMARY: Success={0}\n".format(success))
        return success
def create_report_file(param_obj, campaign_obj, stdout_df, report_name, debug):
    with open(report_name, "w") as outfile:
        for name, param in param_obj.items():
            outfile.write("{0} = {1}\n".format(name, param))
        success = True
        sample_threshold = float(campaign_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold])
        base_sensitivity = float(campaign_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity])
        base_specificity = float(campaign_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity])
        ip_key_value = campaign_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value]
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold, sample_threshold))
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity, base_sensitivity))
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity, base_specificity))
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value,
                                           ip_key_value))

        if base_sensitivity != 1:
            success = False
            outfile.write("BAD: the {0} is {1}, expected value is 1.\n".format(
                CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity, base_sensitivity))
        if base_specificity != 1:
            success = False
            outfile.write("BAD: the {0} is {1}, expected value is 1.\n".format(
                CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity, base_specificity))
        if ip_key_value:
            success = False
            outfile.write("BAD: {0} should be empty in this test, got {1} from compaign file. Please fix the test.\n"
                          "".format(CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value, ip_key_value))

        duration = param_obj[ConfigKeys.Simulation_Duration]
        base_infectivity = param_obj[ConfigKeys.Base_Infectivity]

        if base_infectivity <= sample_threshold:
            outfile.write("WARNING: {0}({1}) is larger than {2}({3}), please check the test.\n".format(
                ConfigKeys.Base_Infectivity, base_infectivity,
                CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold, sample_threshold
            ))

        positive_list = []
        negative_list = []
        # tolerance is 0 in this test.
        tolerance = 0 if base_sensitivity == 1 and base_specificity == 1 else 5e-2
        contagion_list = []
        contagion = 0
        for t in range(1, duration):
            stdout_t_df = stdout_df[stdout_df[Diagnostic_Support.ConfigKeys.Simulation_Timestep] == t]
            infected = stdout_t_df[Diagnostic_Support.Stdout.infected].iloc[0]
            stat_pop = stdout_t_df[Diagnostic_Support.Stdout.stat_pop].iloc[0]
            test_positive = stdout_t_df[Diagnostic_Support.Stdout.test_positive].iloc[0]
            test_negative = stdout_t_df[Diagnostic_Support.Stdout.test_negative].iloc[0]
            test_default = stdout_t_df[Diagnostic_Support.Stdout.test_default].iloc[0]
            envi_sample = stdout_t_df[Diagnostic_Support.Stdout.sample].iloc[0]

            susceptible = stat_pop - infected
            message = "BAD: at time {0}, total infected individuals = {1} and total susceptible individuals = {2}," \
            " expected {3} {4} test result, got {5} from logging.\n"

            # calculated environmental contagion
            contagion = base_infectivity * infected /stat_pop
            if math.fabs(contagion - envi_sample) > envi_sample * 1e-2:
                success = False
                outfile.write("BAD: at time step {0} the environmental sample is {1}, expected value is {2}.\n".format(
                    t, envi_sample, contagion
                ))
            if contagion > sample_threshold:
                expected_test_positive = 1
                expected_test_negative = 0
            else:
                expected_test_positive = 0
                expected_test_negative = 1

            contagion_list.append(contagion)

            # tolerance is 0 in this test, so we are looking for a 100% match in this test.
            if math.fabs(test_positive - expected_test_positive) > tolerance * expected_test_positive:
                success = False
                outfile.write(message.format(
                    t, infected, susceptible, expected_test_positive, "positive", test_positive))
            if math.fabs(test_negative - expected_test_negative) > tolerance * expected_test_negative:
                success = False
                outfile.write(message.format(
                    t, infected, susceptible, expected_test_negative, "negative", test_negative))

            expected_test_default = 0
            if test_default != expected_test_default:
                success = False
                outfile.write(message.format(
                        t, infected, susceptible, expected_test_default, "default", test_default))

            positive_list.append([test_positive, expected_test_positive])
            negative_list.append([test_negative, expected_test_negative])
        sft.plot_data(stdout_df[Diagnostic_Support.Stdout.sample].tolist()[1:], contagion_list,
                          label1="Actual",
                          label2="Expected",
                          title="Environmental_Contagion", xlabel="Day",
                          ylabel="Environmental_Contagion",
                          category='Environmental_Contagion', overlap=True, alpha=0.5)

        sft.plot_data(np.array(positive_list)[:, 0], np.array(positive_list)[:, 1],
                      label1="Actual",
                      label2="Expected",
                      title="Test Positive\n infectivity = {0}, threshold = {1}".format(
                          base_infectivity, sample_threshold), xlabel="Day",
                      ylabel="Positive count",
                      category='Test_Positive', overlap=True, alpha=0.5)
        sft.plot_data(np.array(negative_list)[:, 0], np.array(negative_list)[:, 1],
                      label1="Actual",
                      label2="Expected",
                      title="Test Negative\n infectivity = {0}, threshold = {1}".format(
                          base_infectivity, sample_threshold), xlabel="Day",
                      ylabel="Negative count",
                      category='Test_Negative', overlap=True, alpha=0.5)
        outfile.write(sft.format_success_msg(success))
        if debug:
            print(sft.format_success_msg(success))
        return success
Пример #29
0
def create_report_file(param_obj, campaign_obj, stdout_df, report_name, debug):
    with open(report_name, "w") as outfile:
        for name, param in param_obj.items():
            outfile.write("{0} = {1}\n".format(name, param))
        success = True
        sample_threshold = float(campaign_obj[
            CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold])
        base_sensitivity = float(campaign_obj[
            CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity])
        base_specificity = float(campaign_obj[
            CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity])
        ip_key_value = campaign_obj[
            CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value]
        outfile.write("{0} = {1}\n".format(
            CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold,
            sample_threshold))
        outfile.write("{0} = {1}\n".format(
            CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity,
            base_sensitivity))
        outfile.write("{0} = {1}\n".format(
            CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity,
            base_specificity))
        outfile.write("{0} = {1}\n".format(
            CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value,
            ip_key_value))

        if base_sensitivity != 1:
            success = False
            outfile.write("BAD: the {0} is {1}, expected value is 1.\n".format(
                CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity,
                base_sensitivity))
        if base_specificity != 1:
            success = False
            outfile.write("BAD: the {0} is {1}, expected value is 1.\n".format(
                CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity,
                base_specificity))
        if ip_key_value:
            success = False
            outfile.write(
                "BAD: {0} should be empty in this test, got {1} from compaign file. Please fix the test.\n"
                "".format(
                    CampaignKeys.EnvironmentalDiagnosticKeys.
                    Environment_IP_Key_Value, ip_key_value))

        duration = param_obj[ConfigKeys.Simulation_Duration]
        base_infectivity = param_obj[ConfigKeys.Base_Infectivity]

        if base_infectivity >= sample_threshold:
            outfile.write(
                "WARNING: {0}({1}) is not less than {2}({3}), please check the test.\n"
                .format(
                    ConfigKeys.Base_Infectivity, base_infectivity,
                    CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold,
                    sample_threshold))

        positive_list = []
        negative_list = []
        # tolerance is 0 in this test.
        tolerance = 0 if base_sensitivity == 1 and base_specificity == 1 else 5e-2
        contagion_list = []
        contagion = 0
        for t in range(1, duration):
            stdout_t_df = stdout_df[stdout_df[
                Diagnostic_Support.ConfigKeys.Simulation_Timestep] == t]
            infected = stdout_t_df[Diagnostic_Support.Stdout.infected].iloc[0]
            stat_pop = stdout_t_df[Diagnostic_Support.Stdout.stat_pop].iloc[0]
            test_positive = stdout_t_df[
                Diagnostic_Support.Stdout.test_positive].iloc[0]
            test_negative = stdout_t_df[
                Diagnostic_Support.Stdout.test_negative].iloc[0]
            test_default = stdout_t_df[
                Diagnostic_Support.Stdout.test_default].iloc[0]
            envi_sample = stdout_t_df[Diagnostic_Support.Stdout.sample].iloc[0]

            susceptible = stat_pop - infected
            message = "BAD: at time {0}, total infected individuals = {1} and total susceptible individuals = {2}," \
            " expected {3} {4} test result, got {5} from logging.\n"

            # calculated environmental contagion
            contagion = base_infectivity * infected / stat_pop
            if math.fabs(contagion - envi_sample) > envi_sample * 1e-2:
                success = False
                outfile.write(
                    "BAD: at time step {0} the environmental sample is {1}, expected value is {2}.\n"
                    .format(t, envi_sample, contagion))
            if contagion > sample_threshold:
                expected_test_positive = 1
                expected_test_negative = 0
            else:
                expected_test_positive = 0
                expected_test_negative = 1

            contagion_list.append(contagion)

            # tolerance is 0 in this test, so we are looking for a 100% match in this test.
            if math.fabs(test_positive - expected_test_positive
                         ) > tolerance * expected_test_positive:
                success = False
                outfile.write(
                    message.format(t, infected, susceptible,
                                   expected_test_positive, "positive",
                                   test_positive))
            if math.fabs(test_negative - expected_test_negative
                         ) > tolerance * expected_test_negative:
                success = False
                outfile.write(
                    message.format(t, infected, susceptible,
                                   expected_test_negative, "negative",
                                   test_negative))

            expected_test_default = 0
            if test_default != expected_test_default:
                success = False
                outfile.write(
                    message.format(t, infected, susceptible,
                                   expected_test_default, "default",
                                   test_default))

            positive_list.append([test_positive, expected_test_positive])
            negative_list.append([test_negative, expected_test_negative])
        sft.plot_data(stdout_df[Diagnostic_Support.Stdout.sample].tolist()[1:],
                      contagion_list,
                      label1="Actual",
                      label2="Expected",
                      title="Environmental_Contagion",
                      xlabel="Day",
                      ylabel="Environmental_Contagion",
                      category='Environmental_Contagion',
                      overlap=True,
                      alpha=0.5)

        sft.plot_data(
            np.array(positive_list)[:, 0],
            np.array(positive_list)[:, 1],
            label1="Actual",
            label2="Expected",
            title="Test Positive\n infectivity = {0}, threshold = {1}".format(
                base_infectivity, sample_threshold),
            xlabel="Day",
            ylabel="Positive count",
            category='Test_Positive',
            overlap=True,
            alpha=0.5)
        sft.plot_data(
            np.array(negative_list)[:, 0],
            np.array(negative_list)[:, 1],
            label1="Actual",
            label2="Expected",
            title="Test Negative\n infectivity = {0}, threshold = {1}".format(
                base_infectivity, sample_threshold),
            xlabel="Day",
            ylabel="Negative count",
            category='Test_Negative',
            overlap=True,
            alpha=0.5)
        outfile.write(sft.format_success_msg(success))
        if debug:
            print(sft.format_success_msg(success))
        return success
def create_report_file(param_obj, campaign_obj, stdout_df, property_df, property_obj, inset_chart_obj,
                       insetchart_name, property_report_name, report_name, debug):
    with open(report_name, "w") as sft_report_file :
        config_name = param_obj[ConfigKeys.Config_Name]
        base_infectivity = param_obj[ConfigKeys.Base_Infectivity]
        sft_report_file.write("Config_name = {}\n".format(config_name))
        sft_report_file.write("{0} = {1} {2} = {3}\n".format(
            ConfigKeys.Base_Infectivity, base_infectivity,
            ConfigKeys.Run_Number, param_obj[ConfigKeys.Run_Number]))

        success = True

        sft_report_file.write("Test 1: checking test conditions/setup in config.json and campaign.json:\n")
        if int(param_obj[ConfigKeys.Enable_Heterogeneous_Intranode_Transmission]) != 1:
            success = False
            sft_report_file.write("BAD: HINT is not enabled, please check the test.\n")
        else:
            if float(param_obj[ConfigKeys.Node_Contagion_Decay_Rate]) != 1:
                success = False
                sft_report_file.write("BAD: Expect Environmental contagion decay 100%, but Node_Contagion_Decay_Rate = {}"
                              ", please check the test.\n".format(param_obj[ConfigKeys.Node_Contagion_Decay_Rate]))

            if not all(x == 0 for x in campaign_obj[CampaignKeys.Start_Day]):
                success = False
                sft_report_file.write("BAD: All intervention should start at day 0, please check campaign.json.\n")

            if not all(x == 0.05 for x in campaign_obj[CampaignKeys.Demographic_Coverage]):
                success = False
                sft_report_file.write("BAD: {} should be 0.05, please check campaign.json."
                              "\n".format(CampaignKeys.Demographic_Coverage))

            expected_property_restrictions = [[]]
            if campaign_obj[CampaignKeys.Property_Restrictions] != expected_property_restrictions:
                success = False
                sft_report_file.write(
                    "BAD: {0} should be be empty list(target everyone), got {1} in campaign.json, please check "
                    "campaign.json.\n".format(
                        CampaignKeys.Property_Restrictions,
                        campaign_obj[CampaignKeys.Property_Restrictions]))
        sft_report_file.write("Test 1: campaign and config met preconditions: {}.\n".format(success))

        if success:
            sft_report_file.write("Test 2: Testing contagion and probability with calculated values for every time step:\n")
            sft_report_file.write("Test 3: Testing New Infection channel from property report based on transmission matrix "
                          "for every timestep:\n")
            sft_report_file.write("Test 4: testing total new infection by routes match the total expected new infections"
                          "for each group.\n".format(
                InsetKeys.ChannelsKeys.New_Infections_By_Route_ENVIRONMENT,
                InsetKeys.ChannelsKeys.New_Infections_By_Route_CONTACT, insetchart_name, property_report_name))
            sft_report_file.write("Test 2, 3 and 4 and running at the same time:\n")
            result_2 = result_3 = result_4 = True
            stat_pop = stdout_df[Stdout.stat_pop]
            duration = param_obj[ConfigKeys.Simulation_Duration]
            transmission_matrix_e = property_obj[DemographicsKeys.PropertyKeys.TransmissionMatrix][routes[0]]
            transmission_matrix_c = property_obj[DemographicsKeys.PropertyKeys.TransmissionMatrix][routes[1]]
            # get all the column names that contains the seed group
            property_values = property_obj[DemographicsKeys.PropertyKeys.Values]
            for group in property_values:
                # get all the column names that contains the group
                cols = [c for c in property_df.columns if group in c]

                # test data for susceptible group
                infected = property_df[[c for c in cols if channels[0] in c]]
                new_infection_e = property_df[[c for c in cols if channels[1] in c]]
                new_infection_c = property_df[[c for c in cols if channels[2] in c]]
                contagion_e = property_df[[c for c in cols if channels[3] in c]]
                contagion_c = property_df[[c for c in cols if channels[4] in c]]
                population = property_df[[c for c in cols if channels[5] in c]]

                expected_new_infection_list_e = []
                expected_new_infection_list_c = []
                contagion_list_e = [[contagion_e.iloc[0][0], 0]]
                contagion_list_c = [[contagion_e.iloc[0][0], 0]]

                failed_count_e = 0
                failed_count_c = 0
                with open("DEBUG_binomial_test_{}.txt".format(group), 'w') as group_file:
                    for t in range(duration - 1):
                        infectivity_seed = base_infectivity * infected.iloc[t][0]
                        # calculate contagion of susceptible group
                        # environmental contagion decay 100% at each time step so it works as contact contagion
                        # "contact" route will be normalized by total population
                        # "environmental" route will be normalized by group population
                        calculated_contagion_e = infectivity_seed * transmission_matrix_e[property_values.index(group)][
                            property_values.index(group)] / population.iloc[t][0]
                        calculated_contagion_c = infectivity_seed * transmission_matrix_c[property_values.index(group)][
                            property_values.index(group)] / stat_pop[t]

                        # get contagion of susceptible group from property report
                        actual_contagion_e = contagion_e.iloc[t + 1][0]
                        actual_contagion_c = contagion_c.iloc[t + 1][0]

                        contagion_list_e.append([actual_contagion_e, calculated_contagion_e])
                        contagion_list_c.append([actual_contagion_c, calculated_contagion_c])

                        if math.fabs(calculated_contagion_e - actual_contagion_e) > 5e-2 * calculated_contagion_e:
                            result_2 = success = False
                            sft_report_file.write("    BAD: at time step {0}, for group {1} route {2}, the contagion is {3}, "
                                          "expected {4}.\n".format(t + 1, group, routes[0], actual_contagion_e,
                                                                   calculated_contagion_e
                            ))

                        if math.fabs(calculated_contagion_c - actual_contagion_c) > 5e-2 * calculated_contagion_c:
                            result_2 = success = False
                            sft_report_file.write("    BAD: at time step {0}, for group {1} route {2}, the contagion is {3}, "
                                          "expected {4}.\n".format(t + 1, group, routes[1], actual_contagion_c,
                                                                   calculated_contagion_c
                            ))

                        # calculate infection probability based on contagion
                        calculated_prob_e = 1.0 - math.exp(-1 * calculated_contagion_e *
                                                           param_obj[ConfigKeys.Simulation_Timestep])
                        calculated_prob_c = 1.0 - math.exp(-1 * calculated_contagion_c *
                                                           param_obj[ConfigKeys.Simulation_Timestep])

                        # calculate expected new infection for susceptible group
                        susceptible_population_c = population.iloc[t][0] - infected.iloc[t][0]
                        expected_new_infection_c = susceptible_population_c * calculated_prob_c

                        # Superinfection is not supported, so individuals may not be infected from both the environmental and the contact route.
                        susceptible_population_e = susceptible_population_c - new_infection_c.iloc[t + 1][0]
                        expected_new_infection_e = susceptible_population_e * calculated_prob_e

                        expected_new_infection_list_e.append(expected_new_infection_e)
                        expected_new_infection_list_c.append(expected_new_infection_c)

                        actual_new_infection_e = new_infection_e.iloc[t + 1][0]
                        actual_new_infection_c = new_infection_c.iloc[t + 1][0]

                        # run the same test for both routes
                        failed_count_e = hint_support.test_new_infections(
                            expected_new_infection_e, actual_new_infection_e, calculated_prob_e, failed_count_e,
                            routes[0], t + 1, group, sft_report_file, susceptible_population_e, group_file)

                        failed_count_c = hint_support.test_new_infections(
                            expected_new_infection_c, actual_new_infection_c, calculated_prob_c, failed_count_c,
                            routes[1], t + 1, group, sft_report_file, susceptible_population_c, group_file)

                message_template = "{0}: (route {1}) binomial test for {2} failed {3} times within {4} total " \
                                   "timesteps, which is {5}% fail rate, test is {6}. Please see " \
                                   "'DEBUG_binomial_test_{7}.txt' for details.\n"
                for failed_count, new_infection_sus, route in [(failed_count_e, new_infection_e, routes[0]),
                                            (failed_count_c, new_infection_c, routes[1])]:
                    if failed_count / duration > 5e-2:
                        result_3 = success = False
                        sft_report_file.write(message_template.format("BAD", route, new_infection_sus.columns.values,
                                                              failed_count, duration, (failed_count / duration) * 100,
                                                              "failed", group))
                    else:
                        sft_report_file.write(message_template.format("GOOD", route, new_infection_sus.columns.values,
                                                              failed_count, duration, (failed_count / duration) * 100,
                                                              "passed", group))

                # check the total new infection
                # plot actual and expected values for contagion and new infeciton for each routes and each group
                message = "{0}: for route {1} and group {2}, the total new infection is {3}, expected {4}.\n"
                for contagion_list, new_infection_sus, expected_new_infection_list, route in \
                        [(contagion_list_e, new_infection_e, expected_new_infection_list_e, routes[0]),
                         (contagion_list_c, new_infection_c, expected_new_infection_list_c, routes[1])]:
                    tolerance = 0
                    total_expected_new_infections = sum(expected_new_infection_list)
                    total_new_infections = new_infection_sus.ix[1:, 0].sum()
                    if total_expected_new_infections > 1000:
                        tolerance = 5e-2
                    elif total_expected_new_infections > 500:
                        tolerance = 1e-1
                    elif total_expected_new_infections > 50:
                        tolerance = 2e-1
                    else:
                        tolerance = -1
                        sft_report_file.write("WARNING: the new infection size for route {0} and group {1} is too "
                                              "small, skip it in this test. Expected {2} total new infectuins " 
                                              "got {3}.\n".format(route, group,
                                                                  total_expected_new_infections,
                                                                  total_new_infections
                                                                  ))
                    if tolerance > 0:
                        if math.fabs(total_new_infections - total_expected_new_infections) > \
                                tolerance * total_expected_new_infections:
                            result_4 = success = False
                            sft_report_file.write(message.format("BAD", route, group, total_new_infections,
                                                                 total_expected_new_infections))
                        else:
                            sft_report_file.write(message.format("GOOD", route, group, total_new_infections,
                                                                 total_expected_new_infections))

                    sft.plot_data(np.array(contagion_list)[:, 0], np.array(contagion_list)[:, 1],
                                      label1=property_report_name, label2="calculated contagion",
                                      title="contagion\nroute {0}, group {1}".format(route, group),
                                      xlabel='day', ylabel='contagion', category="contagion_{0}_{1}"
                                                                                 "".format(group, route),
                                      line=True, alpha=0.5, overlap=True, sort=False)
                    sft.plot_data(new_infection_sus.ix[1:, 0].tolist(), expected_new_infection_list,
                                      label1=property_report_name,
                                      label2="expected new infection",
                                      title="new infections\nroute {0}, group {1}".format(route, group),
                                      xlabel='day', ylabel='new_infections',
                                      category="new_infections_{0}_{1}".format(group, route),
                                      line=False, alpha=0.5, overlap=True, sort=False)

            sft_report_file.write("Test 2: result is: {}.\n".format(result_2))
            sft_report_file.write("Test 3: result is: {}.\n".format(result_3))
            sft_report_file.write("Test 4: result is: {}.\n".format(result_4))

            sft_report_file.write("Test 5: testing {0} and {1} in {2} and data collected form {3} for every time step.\n".format(
                InsetKeys.ChannelsKeys.New_Infections_By_Route_ENVIRONMENT,
                InsetKeys.ChannelsKeys.New_Infections_By_Route_CONTACT, insetchart_name, property_report_name))
            result_5 = hint_support.compare_new_infections_channels(inset_channels[:2], property_df, duration,
                                                                    inset_chart_obj, sft_report_file, insetchart_name,
                                                                    property_report_name)
            if not result_5:
                success = False
            sft_report_file.write("Test 5: result is: {}.\n".format(result_5))

            sft_report_file.write("Test 6: testing {0} and {1} in {2} and data collected form {3} for every time step.\n".format(
                InsetKeys.ChannelsKeys.Environmental_Contagion_Population,
                InsetKeys.ChannelsKeys.Contact_Contagion_Population, insetchart_name, property_report_name))
            result_6 = hint_support.compare_contagion_channels(inset_channels[2:], channels[3:5], property_df, duration,
                                                               inset_chart_obj, sft_report_file, insetchart_name,
                                                               property_report_name)
            if not result_6:
                success = False
            sft_report_file.write("Test 6: result is: {}.\n".format(result_6))

        sft_report_file.write(sft.format_success_msg(success))
    if debug:
        print(sft.format_success_msg(success))
    return success
def create_report_file(param_obj, property_df, property_obj, inset_chart_obj, insetchart_name, property_report_name,
                       report_name, debug):
    with open(report_name, "w") as outfile:
        config_name = param_obj[ConfigKeys.Config_Name]
        base_infectivity = param_obj[ConfigKeys.Base_Infectivity]
        outfile.write("Config_name = {}\n".format(config_name))
        outfile.write("{0} = {1} {2} = {3}\n".format(
            ConfigKeys.Base_Infectivity, base_infectivity,
            ConfigKeys.Run_Number, param_obj[ConfigKeys.Run_Number]))

        success = True

        outfile.write("Testing contagion in each groups for every time step:\n")
        duration = param_obj[ConfigKeys.Simulation_Duration]
        transmission_matrix_c = property_obj[DemographicsKeys.PropertyKeys.TransmissionMatrix][routes[1]]
        groups = property_obj[DemographicsKeys.PropertyKeys.Values]
        contagion = []
        for group in groups:
            outfile.write("  Testing group: {}.\n".format(group))
            contagion_list_c = []
            # get list of column names that contains the group that we are testing
            cols = [c for c in property_df.columns if group in c]
            # get the list of the other group
            other_group = [x for x in groups if x is not group][0]
            # get all the column names that contains the other group
            cols_others = [c for c in property_df.columns if group not in c]

            # test data for test group
            infected = property_df[[c for c in cols if channels[0] in c]]
            contagion_c = property_df[[c for c in cols if channels[4] in c]]
            population = property_df[[c for c in cols if channels[5] in c]]

            # test data for the other group
            infected_other = property_df[[c for c in cols_others if channels[0] in c]]
            population_other = property_df[[c for c in cols_others if channels[5] in c]]

            for t in range(duration - 1):
                if t == 0:
                    contagion_list_c.append([contagion_c.iloc[t][0], 0])
                    if contagion_c.iloc[t][0]:
                        success = False
                        outfile.write("    BAD: at time step {0}, for group {1} route {2}, the contagion is {3}, "
                                      "expected {4}.\n".format(t, group, routes[1], contagion_c.iloc[t][0],
                                                               0
                                                               ))

                infectivity = base_infectivity * infected.iloc[t][0] / \
                              (population.iloc[t][0] + population_other.iloc[t][0])
                infectivity_other = base_infectivity * infected_other.iloc[t][0] / \
                                    (population.iloc[t][0] + population_other.iloc[t][0])

                # calculate contagion
                calculated_contagion = infectivity * transmission_matrix_c[groups.index(group)][
                    groups.index(group)] + infectivity_other * transmission_matrix_c[groups.index(other_group)][
                    groups.index(group)]

                # get contagion from property report
                actual_contagion_c = contagion_c.iloc[t + 1][0]

                contagion_list_c.append([actual_contagion_c, calculated_contagion])

                if math.fabs(calculated_contagion - actual_contagion_c) > 5e-2 * calculated_contagion:
                    success = False
                    outfile.write("    BAD: at time step {0}, for group {1} route {2}, the contagion is {3}, "
                                  "expected {4}.\n".format(t + 1, group, routes[1], actual_contagion_c,
                                                           calculated_contagion
                    ))


            contagion.append(contagion_list_c)
            # plot actual and expected values for contagion
            sft.plot_data(np.array(contagion_list_c)[:, 0], np.array(contagion_list_c)[:, 1],
                              label1=property_report_name, label2="calculated contagion",
                              title="contagion for group {0}\n route {1}".format(group, routes[1]),
                              xlabel='day',ylabel='contagion',category="contagion_{0}_{1}"
                                                                       "".format(group, routes[1]),
                              line=True, alpha=0.5, overlap=True)

        outfile.write("Checking if contagion data from insetchart matches sum of group contagion from property report"
                      " for every time step:\n")
        total_contagion_list = []
        for t in range(duration - 1):
            total_contagion = 0
            for contagion_list_c in contagion:
                total_contagion += contagion_list_c[t][0]
            total_contagion_list.append(total_contagion)
            insetchart_contagion = inset_chart_obj[InsetKeys.ChannelsKeys.Contact_Contagion_Population][t]
            if math.fabs(total_contagion - insetchart_contagion) > 5e-2 * total_contagion:
                success = False
                outfile.write("    BAD: at time step {0}, for route {1}, the total contagion from {2} is {3}, "
                              "expected {4}(sum of group contagion in {5}).\n".format(
                                    t, routes[1], insetchart_name, insetchart_contagion, total_contagion,
                                    property_report_name
                                                       ))
        sft.plot_data(inset_chart_obj[InsetKeys.ChannelsKeys.Contact_Contagion_Population],
                          total_contagion_list,
                          label1=insetchart_name, label2="sum calculated from {}".format(property_report_name),
                          title=InsetKeys.ChannelsKeys.Contact_Contagion_Population,
                          xlabel='day', ylabel='contagion', category=InsetKeys.ChannelsKeys.Contact_Contagion_Population,
                          line=True, alpha=0.5, overlap=True)


        outfile.write(sft.format_success_msg(success))
    if debug:
        print(sft.format_success_msg(success))
    return success
def create_report_file(param_obj, campaign_obj, stdout_df, property_df, property_obj, report_name, debug):
    with open(report_name, "w") as outfile:
        config_name = param_obj[ConfigKeys.Config_Name]
        base_infectivity = param_obj[ConfigKeys.Base_Infectivity]
        outfile.write("Config_name = {}\n".format(config_name))
        outfile.write("{0} = {1} {2} = {3}\n".format(
            ConfigKeys.Base_Infectivity, base_infectivity,
            ConfigKeys.Run_Number, param_obj[ConfigKeys.Run_Number]))

        success = True

        outfile.write("Test 1: checking test conditions/setup in config.json and campaign.json:\n")
        if int(param_obj[ConfigKeys.Enable_Heterogeneous_Intranode_Transmission]) != 1:
            success = False
            outfile.write("BAD: HINT is not enabled, please check the test.\n")
        else:
            if not all(x == 0 for x in campaign_obj[CampaignKeys.Start_Day]):
                success = False
                outfile.write("BAD: All intervention should start at day 0, please check campaign.json.\n")

            if not all(x == 1 for x in campaign_obj[CampaignKeys.Demographic_Coverage]):
                success = False
                outfile.write("BAD: {} should be 1, please check campaign.json.\n".format(CampaignKeys.Demographic_Coverage))

            expected_property_restrictions = []
            # seed_groups = list(filter(lambda value: 'seed' in value.lower(),
            #                           property_obj[DemographicsKeys.PropertyKeys.Values]))
            # easier to read
            property_values = property_obj[DemographicsKeys.PropertyKeys.Values]
            seed_groups = [value for value in property_values if 'seed' in value.lower()]
            for value in seed_groups:
                expected_property_restrictions.append(["{0}:{1}".format(
                    property_obj[DemographicsKeys.PropertyKeys.Property], value)])
            if campaign_obj[CampaignKeys.Property_Restrictions] != expected_property_restrictions:
                success = False
                outfile.write(
                    "BAD: {0} should be {1}, got {2} in campaign.json, please check campaign.json.\n".format(
                        CampaignKeys.Property_Restrictions, expected_property_restrictions,
                        campaign_obj[CampaignKeys.Property_Restrictions]))
        outfile.write("Test 1: campaign and config met preconditions: {}.\n".format(success))

        if success:
            outfile.write("Test 2: Testing contagion and probability with calculated values for every time step:\n")
            outfile.write("Test 3: Testing New Infection channel from property report based on transmission matrix:\n")
            outfile.write("Test 2 and 3 and running at the same time:\n")
            result_2 = result_3 = True
            stat_pop = stdout_df[Stdout.stat_pop]
            infected = stdout_df[Stdout.infected]
            duration = param_obj[ConfigKeys.Simulation_Duration]
            transmission_matrix = property_obj[DemographicsKeys.PropertyKeys.Matrix]
            for seed_group in seed_groups:
                contagion_list = []
                prob_list = []
                # get the name of susceptible group, there should be only one susceptible group based on the query
                susceptible_group = [value for value in property_obj[DemographicsKeys.PropertyKeys.Values
                ] if "susceptible" in value.lower() and seed_group.split('_')[-1] in value][0]
                # get all the column names that contains the seed group
                seed_cols = [c for c in property_df.columns if seed_group in c]
                # get all the column names that contains the susceptible group
                susceptible_cols = [c for c in property_df.columns if susceptible_group in c]

                # test data for seed group
                infected_seed = property_df[[c for c in seed_cols if channels[0] in c]]
                # population_seed = property_df[[c for c in seed_cols if channels[2] in c]]

                # test data for susceptible group
                infected_sus = property_df[[c for c in susceptible_cols if channels[0] in c]]
                new_infection_sus = property_df[[c for c in susceptible_cols if channels[1] in c]]
                population_sus = property_df[[c for c in susceptible_cols if channels[2] in c]]

                expected_new_infection_list = []
                failed_count = 0
                for t in range(duration):
                    # calculate infectivity of seed group
                    # infectivity_seed = base_infectivity * infected_seed.iloc[t][0] / population_seed.iloc[t][0]
                    # nomalized with total population
                    infectivity_seed = base_infectivity * infected_seed.iloc[t][0] / stat_pop[t]

                    # calculate contagion of susceptible group
                    calculated_contagion = infectivity_seed * transmission_matrix[property_values.index(seed_group)][
                        property_values.index(susceptible_group)]

                    # get contagion of susceptible group from stdout_df
                    group_id = property_values.index(susceptible_group)
                    actual_contagion = stdout_df[(stdout_df[ConfigKeys.Simulation_Timestep] == t) &
                                                 (stdout_df[Stdout.group_id] == group_id)][Stdout.contagion].values[0]
                    contagion_list.append([actual_contagion, calculated_contagion])
                    if math.fabs(calculated_contagion - actual_contagion) > 5e-2 * calculated_contagion:
                        result_2 = success = False
                        outfile.write("    BAD: at time step {0}, for group {1} id {2}, the total contagion is {3}, "
                                      "expected {4}.\n".format(t, susceptible_group, group_id, actual_contagion,
                                                               calculated_contagion
                        ))

                    # calculate infection probability based on contagion
                    calculated_prob = 1.0 - math.exp(-1 * calculated_contagion * param_obj[ConfigKeys.Simulation_Timestep])
                    # get infection probability of susceptible group from stdout_df
                    actual_prob = stdout_df[(stdout_df[ConfigKeys.Simulation_Timestep] == t) &
                                                 (stdout_df[Stdout.group_id] == group_id)][Stdout.prob].values[0]
                    prob_list.append([actual_prob, calculated_prob])
                    if math.fabs(calculated_prob - actual_prob) > 5e-2 * calculated_prob:
                        result_2 = success = False
                        outfile.write("    BAD: at time step {0}, for group {1} id {2}, the infected probability is "
                                      "{3}, expected {4}.\n".format( t, susceptible_group, group_id, actual_prob,
                                                                     calculated_prob
                        ))

                    # calculate expected new infection for susceptible group
                    susceptible_population = population_sus.iloc[t][0] - infected_sus.iloc[t][0]
                    expected_new_infection = susceptible_population * calculated_prob
                    expected_new_infection_list.append(expected_new_infection)
                    actual_new_infection = new_infection_sus.iloc[t][0]
                    with open("DEBUG_binomial_test_{}.txt".format(susceptible_group), 'w') as file:
                        if expected_new_infection < 5 or susceptible_population * (1 - calculated_prob) < 5:
                            binom_pmf = stats.binom.pmf(k=actual_new_infection, n=susceptible_population, p=calculated_prob)
                            if binom_pmf < 1e-3:
                                failed_count += 1
                                outfile.write("WARNING: at timestep {0}, new infections for {1} group is {2}, expected "
                                              " = {3}, calculated binomial pmf is {4}.\n"
                                              "".format(t, susceptible_group, actual_new_infection,
                                                        expected_new_infection, binom_pmf))

                        elif not sft.test_binomial_99ci(num_success=actual_new_infection, num_trials=susceptible_population,
                                                   prob=calculated_prob, report_file=file,
                                                   category="new infections for {0} at time {1}".format(susceptible_group, t)):
                            failed_count += 1
                            standard_deviation = math.sqrt(
                                calculated_prob * (1 - calculated_prob) * susceptible_population)
                            # 99% confidence interval
                            lower_bound = expected_new_infection - 3 * standard_deviation
                            upper_bound = expected_new_infection + 3 * standard_deviation
                            outfile.write("WARNING: at timestep {0}, new infections for {1} group is {2}, expected "
                                          "within 99% binomial interval ({3}, {4}) with mean = {5}\n".format(t, susceptible_group,
                                                                                          actual_new_infection,
                                                                                          lower_bound, upper_bound,
                                                                                          expected_new_infection))


                sft.plot_data(np.array(contagion_list)[:, 0], np.array(contagion_list)[:, 1], label1='contagion from logging', label2="calculated contagion",
                                  title="actual vs. expected contagion", xlabel='day',ylabel='contagion',category="contagion_{}".format(susceptible_group),
                                  line=True, alpha=0.5, overlap=True)
                sft.plot_data(np.array(prob_list)[:, 0], np.array(prob_list)[:, 1], label1='probability from logging', label2="calculated probability",
                                  title="actual vs. expected probability", xlabel='day',ylabel='probability',category="probability_{}".format(susceptible_group),
                                  line=True, alpha=0.5, overlap=True)

                sft.plot_data(new_infection_sus.ix[:, 0].tolist(), expected_new_infection_list,
                                  label1='from property report',
                                  label2="calculated data",
                                  title="new infections for {}".format(susceptible_group),
                                  xlabel='day', ylabel='new_infections',
                                  category="new_infections_{}".format(susceptible_group),
                                  line=False, alpha=0.5, overlap=True, sort=False)

                message_template = "{0}: binomial test for {1} failed {2} times within {3} total timesteps, which is " \
                                   "{4}% fail rate, test is {5}.\n"
                if failed_count / duration > 5e-2:
                    result_3 = success = False
                    outfile.write(message_template.format("BAD", new_infection_sus.columns.values, failed_count,
                                                          duration, (failed_count / duration) * 100, "failed"))
                else:
                    outfile.write(message_template.format("GOOD", new_infection_sus.columns.values, failed_count,
                                                          duration, (failed_count / duration) * 100, "passed"))

            outfile.write("Test 2: result is: {}.\n".format(result_2))
            outfile.write("Test 3: result is: {}.\n".format(result_3))

        outfile.write(sft.format_success_msg(success))
    if debug:
        print(sft.format_success_msg(success))
    return success
def create_report_file(param_obj, intervention_obj, outbreak_obj, stdout_df, report_name, debug):
    with open(report_name, "w") as outfile:
        for name, param in param_obj.items():
            outfile.write("{0} = {1}\n".format(name, param))
        success = True
        sample_threshold = float(intervention_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold])
        base_sensitivity = float(intervention_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity])
        base_specificity = float(intervention_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity])
        ip_key_value = intervention_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value]
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold, sample_threshold))
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity, base_sensitivity))
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity, base_specificity))
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value,
                                           ip_key_value))

        # make sure no outbreak in this test, so the sample should not be greater than threshold at all time
        if outbreak_obj:
            success = False
            outfile.write("BAD: Campaign.json should not have {0}, got {1} from the json file.\n".format(
                CampaignKeys.InterventionClassKeys.OutbreakIndividual, outbreak_obj
            ))
        if sample_threshold:
            outfile.write("WARNING: {0} should be 0 in this test, got {1} from compaign file. Please fix the test.\n"
                          "".format(CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold, sample_threshold))
        if base_sensitivity != 1:
            outfile.write("WARNING: the {0} is {1}, expected value is 1.\n".format(
                CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity, base_sensitivity))
        if ip_key_value:
            success = False
            outfile.write("BAD: {0} should be empty in this test, got {1} from compaign file. Please fix the test.\n"
                          "".format(CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value, ip_key_value))

        duration = param_obj[ConfigKeys.Simulation_Duration]
        base_infectivity = param_obj[ConfigKeys.Base_Infectivity]
        expected_positive_count = expected_negative_count = 0
        contagion_list = []
        contagion = 0
        for t in range(1, duration):
            stdout_t_df = stdout_df[stdout_df[Diagnostic_Support.ConfigKeys.Simulation_Timestep] == t]
            infected = stdout_t_df[Diagnostic_Support.Stdout.infected].iloc[0]
            stat_pop = stdout_t_df[Diagnostic_Support.Stdout.stat_pop].iloc[0]
            envi_sample = stdout_t_df[Diagnostic_Support.Stdout.sample].iloc[0]

            # calculated environmental contagion
            contagion = base_infectivity * infected /stat_pop
            if math.fabs(contagion - envi_sample) > envi_sample * 1e-2:
                success = False
                outfile.write("BAD: at time step {0} the environmental sample is {1}, expected value is {2}.\n".format(
                    t, envi_sample, contagion
                ))
            if contagion > sample_threshold:
                expected_test_positive = base_sensitivity
                expected_test_negative = 1.0 - base_sensitivity
            else:
                expected_test_positive = 1.0 - base_specificity
                expected_test_negative = base_specificity
            contagion_list.append(contagion)

            expected_positive_count += expected_test_positive
            expected_negative_count += expected_test_negative

        stdout_sum = stdout_df.sum()

        result = sft.test_multinomial([stdout_sum[Diagnostic_Support.Stdout.test_positive],
                                  stdout_sum[Diagnostic_Support.Stdout.test_negative]],
                                 proportions=[expected_positive_count, expected_negative_count],
                                 report_file=outfile,
                                 prob_flag=False, )

        message = "{0}: the total test positive and negative counts from StdOut.txt are {1} and {2}, expected values" \
                  " are {3} and {4}.\n"

        if result:
            outfile.write(message.format("GOOD", stdout_sum[Diagnostic_Support.Stdout.test_positive],
                                         stdout_sum[Diagnostic_Support.Stdout.test_negative],
                                         expected_positive_count, expected_negative_count))
        else:
            success = False
            outfile.write(message.format("BAD", stdout_sum[Diagnostic_Support.Stdout.test_positive],
                                         stdout_sum[Diagnostic_Support.Stdout.test_negative],
                                         expected_positive_count, expected_negative_count))

        sft.plot_data(stdout_df[Diagnostic_Support.Stdout.sample].tolist()[1:], contagion_list,
                          label1="Actual",
                          label2="Expected",
                          title="Environmental_Contagion", xlabel="Day",
                          ylabel="Environmental_Contagion",
                          category='Environmental_Contagion', overlap=True, alpha=0.5)
        outfile.write(sft.format_success_msg(success))
        if debug:
            print(sft.format_success_msg(success))
        return success
def create_report_file(param_obj, campaign_obj, stdout_df, recorder_obj, report_name, report_event_recorder, debug):
    with open(report_name, "w") as outfile:
        for name, param in param_obj.items():
            outfile.write("{0} = {1}\n".format(name, param))
        sample_threshold = float(campaign_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold])
        base_sensitivity = float(campaign_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity])
        base_specificity = float(campaign_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity])
        ip_key_value = campaign_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value]
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold, sample_threshold))
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity, base_sensitivity))
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity, base_specificity))
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value,
                                           ip_key_value))
        success = recorder_obj[1]

        if not success:
            error_message = recorder_obj[0]
            outfile.write("Failed to parse report file: {0}, get exception: {1}.\n".format(report_event_recorder,
                                                                                           error_message
                                                                                           ))
        else:
            # the following condition checks throw warning messages instead of fail the test.
            if sample_threshold:
                outfile.write("WARNING: {0} should be 0 in this test, got {1} from compaign file. Please fix the test.\n"
                              "".format(CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold, sample_threshold))
            if base_specificity != 1:
                outfile.write("WARNING: the {0} is {1}, expected value is 1.\n".format(
                    CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity, base_specificity))
            if base_sensitivity != 1:
                outfile.write("WARNING: the {0} is {1}, expected value is 1.\n".format(
                    CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity, base_sensitivity))
            if ip_key_value:
                outfile.write(
                    "WARNING: {0} should be empty in this test, got {1} from compaign file. Please fix the test.\n"
                    "".format(CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value, ip_key_value))

            # group by time and event name, then count how many event in each time step and put the value into a new
            # column named: "Test result counts"
            event_df = recorder_obj[0]
            event_df = event_df.groupby([Diagnostic_Support.ReportColumn.time, Diagnostic_Support.ReportColumn.event]).size().reset_index()
            event_df.rename(columns={0: Diagnostic_Support.ReportColumn.counts}, inplace=True)

            #event_df[ReportColumn.counts] = event_df.groupby(ReportColumn.time)[ReportColumn.event].transform('count')

            duration = param_obj[ConfigKeys.Simulation_Duration]
            positive_list = []
            negative_list = []
            for t in range(1, duration):
                # get values of how many test positive and test negative for each time step from stdout file
                stdout_t_df = stdout_df[stdout_df[Diagnostic_Support.ConfigKeys.Simulation_Timestep] == t]
                test_positive = stdout_t_df[Diagnostic_Support.Stdout.test_positive].iloc[0]
                test_negative = stdout_t_df[Diagnostic_Support.Stdout.test_negative].iloc[0]

                message = "BAD: at time {0}, {1} records {2} {3}, got {4} {5} result from logging.\n"

                # get the positive event count from data frame
                positive_event = event_df[
                    (event_df[Diagnostic_Support.ReportColumn.time] == t) &
                    (event_df[Diagnostic_Support.ReportColumn.event] == Diagnostic_Support.ReportColumn.positive)] \
                [Diagnostic_Support.ReportColumn.counts].values
                if len(positive_event):
                    positive_event = positive_event[0]
                else:
                    positive_event = 0

                # StdOut.txt should match ReportEventRecorder.csv
                if test_positive != positive_event:
                    success = False
                    outfile.write(message.format(
                        t, report_event_recorder, positive_event, Diagnostic_Support.ReportColumn.positive, test_positive,
                        Diagnostic_Support.Stdout.test_positive))

                # get the negative event count from data frame
                negative_event = event_df[(event_df[Diagnostic_Support.ReportColumn.time] == t) &
                                          (event_df[Diagnostic_Support.ReportColumn.event] == Diagnostic_Support.ReportColumn.negative)][
                    Diagnostic_Support.ReportColumn.counts].values
                if len(negative_event):
                    negative_event = negative_event[0]
                else:
                    negative_event = 0

                # StdOut.txt should match ReportEventRecorder.csv
                if test_negative != negative_event:
                    success = False
                    outfile.write(message.format(
                        t, report_event_recorder, negative_event, Diagnostic_Support.ReportColumn.negative, test_negative,
                        Diagnostic_Support.Stdout.test_negative))

                positive_list.append([test_positive, positive_event])
                negative_list.append([test_negative, negative_event])
            sft.plot_data(np.array(positive_list)[:, 0], np.array(positive_list)[:, 1],
                              label1="Stdout",
                              label2=report_event_recorder,
                              title="Test Positive vs. {}".format(Diagnostic_Support.ReportColumn.positive),
                              xlabel="Day",
                              ylabel="Positive count",
                              category='Test_Positive', overlap=True, alpha=0.5)
            sft.plot_data(np.array(negative_list)[:, 0], np.array(negative_list)[:, 1],
                              label1="Stdout",
                              label2=report_event_recorder,
                              title="Test Negative vs. {}".format(Diagnostic_Support.ReportColumn.negative),
                              xlabel="Day",
                              ylabel="Negative count",
                              category='Test_Negative', overlap=True, alpha=0.5)
        outfile.write(sft.format_success_msg(success))
        if debug:
            print(sft.format_success_msg(success))
        return success
def create_report_file(param_obj, campaign_obj, stdout_df, report_name, debug):
    with open(report_name, "w") as outfile:
        for name, param in param_obj.items():
            outfile.write("{0} = {1}\n".format(name, param))
        success = True
        sample_threshold = float(campaign_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold])
        base_sensitivity = float(campaign_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity])
        base_specificity = float(campaign_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity])
        ip_key_value = campaign_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value]
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold, sample_threshold))
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity, base_sensitivity))
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity, base_specificity))
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value,
                                           ip_key_value))

        if sample_threshold:
            outfile.write("WARNING: {0} should be 0 in this test, got {1} from compaign file. Please fix the test.\n"
                          "".format(CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold, sample_threshold))
        if base_specificity != 1:
            outfile.write("WARNING: the {0} is {1}, expected value is 1.\n".format(
                CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity, base_specificity))
        if ip_key_value:
            success = False
            outfile.write("BAD: {0} should be empty in this test, got {1} from compaign file. Please fix the test.\n"
                          "".format(CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value, ip_key_value))

        duration = param_obj[ConfigKeys.Simulation_Duration]
        base_infectivity = param_obj[ConfigKeys.Base_Infectivity]
        expected_positive_count = expected_negative_count = 0
        contagion_list = []
        contagion = 0

        for t in range(1, duration):
            stdout_t_df = stdout_df[stdout_df[Diagnostic_Support.ConfigKeys.Simulation_Timestep] == t]
            infected = stdout_t_df[Diagnostic_Support.Stdout.infected].iloc[0]
            stat_pop = stdout_t_df[Diagnostic_Support.Stdout.stat_pop].iloc[0]
            envi_sample = stdout_t_df[Diagnostic_Support.Stdout.sample].iloc[0]

            # calculated environmental contagion for next time step
            contagion = base_infectivity * infected /stat_pop
            if math.fabs(contagion - envi_sample) > envi_sample * 1e-2:
                success = False
                outfile.write("BAD: at time step {0} the environmental sample is {1}, expected value is {2}.\n".format(
                    t, envi_sample, contagion
                ))
            if contagion > sample_threshold:
                expected_test_positive = base_sensitivity
                expected_test_negative = 1.0 - base_sensitivity
            else:
                expected_test_positive = 1.0 - base_specificity
                expected_test_negative = base_specificity

            contagion_list.append(contagion)

            expected_positive_count += expected_test_positive
            expected_negative_count += expected_test_negative

        stdout_sum = stdout_df.sum()

        result = sft.test_multinomial([stdout_sum[Diagnostic_Support.Stdout.test_positive],
                                  stdout_sum[Diagnostic_Support.Stdout.test_negative]],
                                 proportions=[expected_positive_count, expected_negative_count],
                                 report_file=outfile,
                                 prob_flag=False, )

        message = "{0}: the total test positive and negative counts from StdOut.txt are {1} and {2}, expected values" \
                  " are {3} and {4}.\n"

        if result:
            outfile.write(message.format("GOOD", stdout_sum[Diagnostic_Support.Stdout.test_positive],
                                         stdout_sum[Diagnostic_Support.Stdout.test_negative],
                                         expected_positive_count, expected_negative_count))
        else:
            success = False
            outfile.write(message.format("BAD", stdout_sum[Diagnostic_Support.Stdout.test_positive],
                                         stdout_sum[Diagnostic_Support.Stdout.test_negative],
                                         expected_positive_count, expected_negative_count))

        sft.plot_data(stdout_df[Diagnostic_Support.Stdout.sample].tolist()[1:], contagion_list,
                          label1="Actual",
                          label2="Expected",
                          title="Environmental_Contagion", xlabel="Day",
                          ylabel="Environmental_Contagion",
                          category='Environmental_Contagion', overlap=True, alpha=0.5)

        # positive_list = []
        # negative_list = []
        # for t in range(1, duration):
        #     infected = stdout_df[Stdout.infected].iloc[t]
        #     stat_pop = stdout_df[Stdout.stat_pop].iloc[t]
        #     test_positive = stdout_df[Stdout.test_positive].iloc[t]
        #     test_negative = stdout_df[Stdout.test_negative].iloc[t]
        #     test_default = stdout_df[Stdout.test_default].iloc[t]
        #
        #     susceptible = stat_pop - infected
        #     message = "BAD: at time {0}, total infected individuals = {1} and total susceptible individuals = {2}, " \
        #               "expected {3} ± {4} individuals receive a {5} test result, got {6} from logging.\n"
        #
        #     expected_test_positive = infected * base_sensitivity + susceptible * (1.0 - base_specificity)
        #     if math.fabs(test_positive - expected_test_positive) > 5e-2 * expected_test_positive:
        #         success = False
        #         outfile.write(message.format(
        #             t, infected, susceptible, expected_test_positive, 5e-2 * expected_test_positive, "positive",
        #             test_positive))
        #
        #     expected_test_negative = infected * (1.0 - base_sensitivity) + susceptible * base_specificity
        #     if math.fabs(test_negative - expected_test_negative) > 5e-2 * expected_test_negative:
        #         success = False
        #         outfile.write(message.format(
        #             t, infected, susceptible, expected_test_negative, 5e-2 * expected_test_negative, "negative",
        #             test_negative))
        #
        #     expected_test_default = 0
        #     if test_default != expected_test_default:
        #         success = False
        #         outfile.write(message.format(
        #                 t, infected, susceptible, expected_test_default, 0, "default", test_default))
        #
        #     positive_list.append([test_positive, expected_test_positive])
        #     negative_list.append([test_negative, expected_test_negative])
        # sft.plot_data(np.array(positive_list)[:, 0], np.array(positive_list)[:, 1],
        #               label1="Actual",
        #               label2="Expected",
        #               title="Test Positive", xlabel="Day",
        #               ylabel="Positive count",
        #               category='Test_Positive', overlap=True, alpha=0.5)
        # sft.plot_data(np.array(negative_list)[:, 0], np.array(negative_list)[:, 1],
        #               label1="Actual",
        #               label2="Expected",
        #               title="Test Negative", xlabel="Day",
        #               ylabel="Negative count",
        #               category='Test_Negative', overlap=True, alpha=0.5)
        outfile.write(sft.format_success_msg(success))
        if debug:
            print(sft.format_success_msg(success))
        return success
def create_report_file(param_obj, stdout_df, report_name, debug):
    with open(report_name, "w") as outfile:
        for name, param in param_obj.items():
            outfile.write("{0} = {1}\n".format(name, param))
        success = True
        start_day = param_obj[ConfigKeys.Environmental_Peak_Start]
        ramp_up = param_obj[ConfigKeys.Environmental_Ramp_Up_Duration]
        ramp_down = param_obj[ConfigKeys.Environmental_Ramp_Down_Duration]
        cut_off = param_obj[ConfigKeys.Environmental_Cutoff_Days]
        duration = param_obj[ConfigKeys.Simulation_Duration]

        peak_duration = sft.DAYS_IN_YEAR - ramp_up - ramp_down - cut_off
        # adjust peak start time to day in year
        peak_starttime = start_day % sft.DAYS_IN_YEAR
        peak_endtime = peak_starttime + peak_duration
        cutoff_starttime = peak_starttime + peak_duration + ramp_down
        cutoff_endtime = peak_starttime + peak_duration + ramp_down + cut_off

        amp = []
        expected_amp = []
        # adjust the times so that the ramp up starts at time 0, which means the cut off ends at time 0 too.
        adjust_time = peak_starttime - ramp_up
        peak_starttime -= adjust_time
        peak_endtime -= adjust_time
        cutoff_starttime -= adjust_time
        cutoff_endtime -= adjust_time
        cutoff_endtime %= sft.DAYS_IN_YEAR

        for t in range(1, duration):
            amplification = stdout_df[Stdout.amplification].iloc[t]
            day_in_year = stdout_df[Stdout.day_of_year].iloc[t]
            if day_in_year != t % sft.DAYS_IN_YEAR:
                success = False
                outfile.write("BAD: at time step {0}, day_in_year is {1}, it should be {2}.\n".format(
                    t, day_in_year, t % sft.DAYS_IN_YEAR))
                day_in_year = t % sft.DAYS_IN_YEAR
            day_in_year -= adjust_time
            day_in_year %= sft.DAYS_IN_YEAR
            # Environment Ramp Up
            if cutoff_endtime < day_in_year < peak_starttime:
                expected_amplification = day_in_year / ramp_up
            # Environment peak
            elif peak_starttime <= day_in_year <= peak_endtime:
                expected_amplification = 1
            # Environment Ramp Down
            elif peak_endtime < day_in_year < cutoff_starttime:
                expected_amplification = (cutoff_starttime - day_in_year) / ramp_down
            # Environment cutoff
            else:
                expected_amplification = 0
            if not math.fabs(amplification - expected_amplification) <= 5e-2 * expected_amplification:
                success = False
                outfile.write(
                    "BAD: at time {0}, day of year = {1}, the environmental amplification is {2}, expected {3}.\n".format(
                        t, t % sft.DAYS_IN_YEAR, amplification, expected_amplification))
            amp.append(amplification)
            expected_amp.append(expected_amplification)
        sft.plot_data(amp, expected_amp,
                          label1="Actual amplification",
                          label2="Expected amplification",
                          title="Seasonality", xlabel="Day",
                          ylabel="Environmental amplification",
                          category='Environmental_amplification', overlap=True, alpha=0.5)
        outfile.write(sft.format_success_msg(success))
        if debug:
            print(sft.format_success_msg(success))
        return success
Пример #37
0
def create_report_file(param_obj, campaign_obj, stdout_df, report_name, debug):
    with open(report_name, "w") as outfile:
        for name, param in param_obj.items():
            outfile.write("{0} = {1}\n".format(name, param))
        success = True
        sample_threshold = float(campaign_obj[
            CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold])
        base_sensitivity = float(campaign_obj[
            CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity])
        base_specificity = float(campaign_obj[
            CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity])
        ip_key_value = campaign_obj[
            CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value]
        outfile.write("{0} = {1}\n".format(
            CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold,
            sample_threshold))
        outfile.write("{0} = {1}\n".format(
            CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity,
            base_sensitivity))
        outfile.write("{0} = {1}\n".format(
            CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity,
            base_specificity))
        outfile.write("{0} = {1}\n".format(
            CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value,
            ip_key_value))

        if sample_threshold:
            outfile.write(
                "WARNING: {0} should be 0 in this test, got {1} from compaign file. Please fix the test.\n"
                "".format(
                    CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold,
                    sample_threshold))
        if base_specificity != 1:
            outfile.write(
                "WARNING: the {0} is {1}, expected value is 1.\n".format(
                    CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity,
                    base_specificity))
        if ip_key_value:
            success = False
            outfile.write(
                "BAD: {0} should be empty in this test, got {1} from compaign file. Please fix the test.\n"
                "".format(
                    CampaignKeys.EnvironmentalDiagnosticKeys.
                    Environment_IP_Key_Value, ip_key_value))

        duration = param_obj[ConfigKeys.Simulation_Duration]
        base_infectivity = param_obj[ConfigKeys.Base_Infectivity]
        expected_positive_count = expected_negative_count = 0
        contagion_list = []
        contagion = 0

        for t in range(1, duration):
            stdout_t_df = stdout_df[stdout_df[
                Diagnostic_Support.ConfigKeys.Simulation_Timestep] == t]
            infected = stdout_t_df[Diagnostic_Support.Stdout.infected].iloc[0]
            stat_pop = stdout_t_df[Diagnostic_Support.Stdout.stat_pop].iloc[0]
            envi_sample = stdout_t_df[Diagnostic_Support.Stdout.sample].iloc[0]

            # calculated environmental contagion for next time step
            contagion = base_infectivity * infected / stat_pop
            if math.fabs(contagion - envi_sample) > envi_sample * 1e-2:
                success = False
                outfile.write(
                    "BAD: at time step {0} the environmental sample is {1}, expected value is {2}.\n"
                    .format(t, envi_sample, contagion))
            if contagion > sample_threshold:
                expected_test_positive = base_sensitivity
                expected_test_negative = 1.0 - base_sensitivity
            else:
                expected_test_positive = 1.0 - base_specificity
                expected_test_negative = base_specificity

            contagion_list.append(contagion)

            expected_positive_count += expected_test_positive
            expected_negative_count += expected_test_negative

        stdout_sum = stdout_df.sum()

        result = sft.test_multinomial(
            [
                stdout_sum[Diagnostic_Support.Stdout.test_positive],
                stdout_sum[Diagnostic_Support.Stdout.test_negative]
            ],
            proportions=[expected_positive_count, expected_negative_count],
            report_file=outfile,
            prob_flag=False,
        )

        message = "{0}: the total test positive and negative counts from StdOut.txt are {1} and {2}, expected values" \
                  " are {3} and {4}.\n"

        if result:
            outfile.write(
                message.format(
                    "GOOD",
                    stdout_sum[Diagnostic_Support.Stdout.test_positive],
                    stdout_sum[Diagnostic_Support.Stdout.test_negative],
                    expected_positive_count, expected_negative_count))
        else:
            success = False
            outfile.write(
                message.format(
                    "BAD", stdout_sum[Diagnostic_Support.Stdout.test_positive],
                    stdout_sum[Diagnostic_Support.Stdout.test_negative],
                    expected_positive_count, expected_negative_count))

        sft.plot_data(stdout_df[Diagnostic_Support.Stdout.sample].tolist()[1:],
                      contagion_list,
                      label1="Actual",
                      label2="Expected",
                      title="Environmental_Contagion",
                      xlabel="Day",
                      ylabel="Environmental_Contagion",
                      category='Environmental_Contagion',
                      overlap=True,
                      alpha=0.5)

        # positive_list = []
        # negative_list = []
        # for t in range(1, duration):
        #     infected = stdout_df[Stdout.infected].iloc[t]
        #     stat_pop = stdout_df[Stdout.stat_pop].iloc[t]
        #     test_positive = stdout_df[Stdout.test_positive].iloc[t]
        #     test_negative = stdout_df[Stdout.test_negative].iloc[t]
        #     test_default = stdout_df[Stdout.test_default].iloc[t]
        #
        #     susceptible = stat_pop - infected
        #     message = "BAD: at time {0}, total infected individuals = {1} and total susceptible individuals = {2}, " \
        #               "expected {3} ± {4} individuals receive a {5} test result, got {6} from logging.\n"
        #
        #     expected_test_positive = infected * base_sensitivity + susceptible * (1.0 - base_specificity)
        #     if math.fabs(test_positive - expected_test_positive) > 5e-2 * expected_test_positive:
        #         success = False
        #         outfile.write(message.format(
        #             t, infected, susceptible, expected_test_positive, 5e-2 * expected_test_positive, "positive",
        #             test_positive))
        #
        #     expected_test_negative = infected * (1.0 - base_sensitivity) + susceptible * base_specificity
        #     if math.fabs(test_negative - expected_test_negative) > 5e-2 * expected_test_negative:
        #         success = False
        #         outfile.write(message.format(
        #             t, infected, susceptible, expected_test_negative, 5e-2 * expected_test_negative, "negative",
        #             test_negative))
        #
        #     expected_test_default = 0
        #     if test_default != expected_test_default:
        #         success = False
        #         outfile.write(message.format(
        #                 t, infected, susceptible, expected_test_default, 0, "default", test_default))
        #
        #     positive_list.append([test_positive, expected_test_positive])
        #     negative_list.append([test_negative, expected_test_negative])
        # sft.plot_data(np.array(positive_list)[:, 0], np.array(positive_list)[:, 1],
        #               label1="Actual",
        #               label2="Expected",
        #               title="Test Positive", xlabel="Day",
        #               ylabel="Positive count",
        #               category='Test_Positive', overlap=True, alpha=0.5)
        # sft.plot_data(np.array(negative_list)[:, 0], np.array(negative_list)[:, 1],
        #               label1="Actual",
        #               label2="Expected",
        #               title="Test Negative", xlabel="Day",
        #               ylabel="Negative count",
        #               category='Test_Negative', overlap=True, alpha=0.5)
        outfile.write(sft.format_success_msg(success))
        if debug:
            print(sft.format_success_msg(success))
        return success
def create_report_file(param_obj, campaign_obj, stdout_df, property_df, property_list, report_name, debug):
    with open(report_name, "w") as outfile:
        config_name = param_obj[ConfigKeys.Config_Name]
        base_infectivity = param_obj[ConfigKeys.Base_Infectivity]
        outfile.write("Config_name = {}\n".format(config_name))
        outfile.write("{0} = {1} {2} = {3}\n".format(
            ConfigKeys.Base_Infectivity, base_infectivity,
            ConfigKeys.Run_Number, param_obj[ConfigKeys.Run_Number]))

        success = True

        outfile.write("Test 1: checking test conditions/setup in config.json and campaign.json:\n")
        if int(param_obj[ConfigKeys.Enable_Heterogeneous_Intranode_Transmission]) != 1:
            success = False
            outfile.write("BAD: HINT is not enabled, please check the test.\n")
        else:
            if not all(x == 0 for x in campaign_obj[CampaignKeys.Start_Day]):
                success = False
                outfile.write("BAD: All intervention should start at day 0, please check campaign.json.\n")

            if not all(x == 1 for x in campaign_obj[CampaignKeys.Demographic_Coverage]):
                success = False
                outfile.write("BAD: {} should be 1, please check campaign.json.\n".format(CampaignKeys.Demographic_Coverage))

            expected_property_restrictions = []
            seed_groups = []
            susceptible_groups = []
            for property_obj in property_list:
                property_values = property_obj[DemographicsKeys.PropertyKeys.Values]
                seed_groups.append(property_values[0])
                susceptible_groups.append(property_values[1])
                expected_property_restrictions.append(["{0}:{1}".format(
                    property_obj[DemographicsKeys.PropertyKeys.Property], property_values[0])])
            if campaign_obj[CampaignKeys.Property_Restrictions] != expected_property_restrictions:
                success = False
                outfile.write(
                    "BAD: {0} should be {1}, got {2} in campaign.json, please check campaign.json.\n".format(
                        CampaignKeys.Property_Restrictions, expected_property_restrictions,
                        campaign_obj[CampaignKeys.Property_Restrictions]))

        outfile.write("Test 1: campaign and config met preconditions: {}.\n".format(success))

        if success:
            outfile.write("Test 2: Testing contagion and probability with calculated values for every time step:\n")
            outfile.write("Test 3: Testing New Infection channel from property report based on transmission matrix:\n")
            outfile.write("Test 2 and 3 and running at the same time:\n")
            result_2 = result_3 = True
            stat_pop = stdout_df[hint_support.Stdout.stat_pop]
            # infected = stdout_df[Stdout.infected]
            duration = param_obj[ConfigKeys.Simulation_Duration]

            contagion_list = []
            prob_list = []
            seed_cols = []
            for seed_group in seed_groups:
                # get all the column names that contains the seed group
                seed_cols += [c for c in property_df.columns if seed_group in c]
            # remove duplicates
            seed_cols = list(set(seed_cols))
            # get all the column names that only contains the susceptible group, which should be property_df.columns - seed_cols
            susceptible_only_cols = [c for c in property_df.columns if c not in seed_cols]

            susceptible_cols = []
            for susceptible_group in susceptible_groups:
                susceptible_cols += [c for c in property_df.columns if susceptible_group in c]
            susceptible_cols = list(set(susceptible_cols))
            # get all the column names that only contains the seed group, which should be property_df.columns - susceptible_cols
            seed_only_cols = [c for c in property_df.columns if c not in susceptible_cols]

            # test data for seed group
            infected_seed = property_df[[c for c in seed_only_cols if hint_support.channels[0] in c]]
            # population_seed = property_df[[c for c in seed_cols if channels[2] in c]]

            # test data for susceptible group
            infected_sus = property_df[[c for c in susceptible_only_cols if hint_support.channels[0] in c]]
            new_infection_sus = property_df[[c for c in susceptible_only_cols if hint_support.channels[1] in c]]
            population_sus = property_df[[c for c in susceptible_only_cols if hint_support.channels[2] in c]]

            expected_new_infection_list = []
            failed_count = 0
            for t in range(duration):
                calculated_contagion = 0
                for col in infected_seed:
                    # calculate infectivity of seed group
                    # nomalized with total population
                    infectivity_seed = base_infectivity * infected_seed[col].iloc[t] / stat_pop[t]
                    infectivity_mod = 1
                    for i in range(len(seed_groups)):
                        seed_group = seed_groups[i]
                        susceptible_group = susceptible_groups[i]
                        if seed_group in col:
                            for property_obj in property_list:
                                property_values = property_obj[DemographicsKeys.PropertyKeys.Values]
                                if seed_group in property_values:
                                    transmission_matrix = property_obj[DemographicsKeys.PropertyKeys.Matrix]
                                    infectivity_mod *= transmission_matrix[property_values.index(seed_group)][
                                                       property_values.index(susceptible_group)]

                    # calculate contagion of susceptible group
                    calculated_contagion += infectivity_seed * infectivity_mod

                # round the calculated value to 6 Decimal numbers
                calculated_contagion = round(calculated_contagion, 6)

                # get contagion of susceptible group from stdout
                # group_id is the last element in all group_ids
                group_id = -1
                for property_obj in property_list:
                    group_id += len(property_obj[DemographicsKeys.PropertyKeys.Values])
                actual_contagion = stdout_df[(stdout_df[ConfigKeys.Simulation_Timestep] == t) &
                                             (stdout_df[hint_support.Stdout.group_id] == group_id)][hint_support.Stdout.contagion].values[0]
                contagion_list.append([actual_contagion, calculated_contagion])
                if math.fabs(calculated_contagion - actual_contagion) > 5e-2 * calculated_contagion:
                    result_2 = success = False
                    outfile.write("    BAD: at time step {0}, for group {1} id {2}, the total contagion is {3}, "
                                  "expected {4}.\n".format(t, susceptible_group, group_id, actual_contagion,
                                                           calculated_contagion
                    ))

                # calculate infection probability based on contagion
                calculated_prob = 1.0 - math.exp(-1 * calculated_contagion * param_obj[ConfigKeys.Simulation_Timestep])
                # round the calculated value to 6 Decimal numbers
                calculated_prob = round(calculated_prob, 6)
                # get infection probability of susceptible group from stdout_df
                actual_prob = stdout_df[(stdout_df[ConfigKeys.Simulation_Timestep] == t) &
                                             (stdout_df[hint_support.Stdout.group_id] == group_id)][hint_support.Stdout.prob].values[0]
                prob_list.append([actual_prob, calculated_prob])
                if math.fabs(calculated_prob - actual_prob) > 5e-2 * calculated_prob:
                    result_2 = success = False
                    outfile.write("    BAD: at time step {0}, for group {1} id {2}, the infected probability is "
                                  "{3}, expected {4}.\n".format( t, susceptible_group, group_id, actual_prob,
                                                                 calculated_prob
                    ))

                # calculate expected new infection for susceptible group
                susceptible_population = population_sus.iloc[t][0] - infected_sus.iloc[t][0]
                expected_new_infection = susceptible_population * calculated_prob
                expected_new_infection_list.append(expected_new_infection)
                actual_new_infection = new_infection_sus.iloc[t][0]
                with open("DEBUG_binomial_test_{}.txt".format(susceptible_group), 'w') as file:
                    if expected_new_infection < 5 or susceptible_population * (1 - calculated_prob) < 5:
                        binom_pmf = stats.binom.pmf(k=actual_new_infection, n=susceptible_population, p=calculated_prob)
                        if binom_pmf < 1e-3:
                            failed_count += 1
                            outfile.write("WARNING: at timestep {0}, new infections for {1} group is {2}, expected "
                                          " = {3}, calculated binomial pmf is {4}.\n"
                                          "".format(t, susceptible_group, actual_new_infection,
                                                    expected_new_infection, binom_pmf))

                    elif not sft.test_binomial_99ci(num_success=actual_new_infection, num_trials=susceptible_population,
                                               prob=calculated_prob, report_file=file,
                                               category="new infections for {0} at time {1}".format(susceptible_group, t)):
                        failed_count += 1
                        standard_deviation = math.sqrt(
                            calculated_prob * (1 - calculated_prob) * susceptible_population)
                        # 99% confidence interval
                        lower_bound = expected_new_infection - 3 * standard_deviation
                        upper_bound = expected_new_infection + 3 * standard_deviation
                        outfile.write("WARNING: at timestep {0}, new infections for {1} group is {2}, expected "
                                      "within 99% binomial interval ({3}, {4}) with mean = {5}\n".format(t, susceptible_group,
                                                                                      actual_new_infection,
                                                                                      lower_bound, upper_bound,
                                                                                      expected_new_infection))

            # make sure non-susceptible groups has no new infections after outbreak
            new_infection_non_susceptible = property_df[
                [c for c in seed_cols if hint_support.channels[1] in c]]
            message_template = "{0}: total new infection after outbreak for {1} is {2}, expected 0.\n"
            for col in new_infection_non_susceptible:
                total_new_infection = new_infection_non_susceptible.ix[1:, col].sum()
                if total_new_infection != 0:
                    success = False
                    outfile.write(message_template.format("BAD", col, total_new_infection))
                else:
                    outfile.write(message_template.format("GOOD", col, total_new_infection))

            # plotting
            # get the group name for the susceptible only group
            group_name = susceptible_only_cols[0].replace(":"," ", 1).split()[-1]
            # ":" is not allowed in filename, replace it with "-" to avoid OSError
            group_name_modified = group_name.replace(":", "-")
            sft.plot_data(np.array(contagion_list)[:, 0], np.array(contagion_list)[:, 1], label1='contagion from logging', label2="calculated contagion",
                              title="{}\ncontagion".format(group_name), xlabel='day',ylabel='contagion',category="contagion_{}".format(group_name_modified),
                              line=True, alpha=0.5, overlap=True)
            sft.plot_data(np.array(prob_list)[:, 0], np.array(prob_list)[:, 1], label1='probability from logging', label2="calculated probability",
                              title="{}\nprobability".format(group_name), xlabel='day',ylabel='probability',category="probability_{}".format(group_name_modified),
                              line=True, alpha=0.5, overlap=True)

            sft.plot_data(new_infection_sus.ix[:, 0].tolist(), expected_new_infection_list,
                              label1='from property report',
                              label2="calculated data",
                              title="{}\nnew infections".format(group_name),
                              xlabel='day', ylabel='new_infections',
                              category="new_infections_{}".format(group_name_modified),
                              line=False, alpha=0.5, overlap=True, sort=False)

            message_template = "{0}: binomial test for {1} failed {2} times within {3} total timesteps, which is " \
                               "{4}% fail rate, test is {5}.\n"
            if failed_count / duration > 5e-2:
                result_3 = success = False
                outfile.write(message_template.format("BAD", new_infection_sus.columns.values, failed_count,
                                                      duration, (failed_count / duration) * 100, "failed"))
            else:
                outfile.write(message_template.format("GOOD", new_infection_sus.columns.values, failed_count,
                                                      duration, (failed_count / duration) * 100, "passed"))

            outfile.write("Test 2: result is: {}.\n".format(result_2))
            outfile.write("Test 3: result is: {}.\n".format(result_3))

        outfile.write(sft.format_success_msg(success))
    if debug:
        print(sft.format_success_msg(success))
    return success
Пример #39
0
def application(report_file, debug=True):
    sft.wait_for_done()
    """
    Parse this line from test.txt:
    00:00:00 [0] [V] [IndividualTyphoid] amplification calculated as 0.997059: day of year=1, start=360.000000,
    end=365.000000, ramp_up=30.000000, ramp_down=170.000000, cutoff=160.000000.
    00:00:00 [0] [V] [IndividualTyphoid] Exposing individual 2 age 8582.488281 on route 'environment': prob=0.000000,
    infects=0.000008, immunity=1.000000, num_exposures=0, exposure=0.997059, environment=1.000000, iv_mult=1.000000.
    """
    #print( "Post-processing: " + report_file )
    # get params from config.json
    cdj = json.loads( open( "config.json" ).read() )["parameters"]
    ncdr = cdj["Node_Contagion_Decay_Rate"]
    start_time=cdj["Start_Time"]
    lines = []
    timestep=start_time
    count =0
    amp = {}
    exposure = {}
    environment = {}
    cum_shedding = cum = 0
    cum_shedding_all = {}
    Statpop = []

    with open( "test.txt" ) as logfile:
        for line in logfile:
            if "Update(): Time:" in line:
                # store the accumulated shedding and reset the counter at the end of each time step.
                cum_shedding_all[timestep] = cum_shedding
                pop = float(sft.get_val("StatPop: ", line))
                Statpop.append(pop)
                # environmental cp decay
                cum_shedding *= 1.0 - ncdr
                # resetting shedding variables
                shedding = 0
                #calculate time step
                timestep += 1
                line = "TimeStep: " + str(timestep) + " " + line
                lines.append(line)
            elif "amplification calculated as" in line:
                count += 1
                line = "TimeStep: " + str(timestep) + " " + line
                lines.append(line)
                amp[timestep] = float(sft.get_val("amplification calculated as ", line))
            elif ("Exposing" in line) and ("environment" in line):
                line = "TimeStep: " + str(timestep) + " " + line
                lines.append(line)
                if timestep not in exposure:
                    exposure[timestep] = float(sft.get_val("exposure=", line))
                    environment[timestep] = float(sft.get_val("environment=", line))
            elif ("depositing" in line) and ("route environment" in line):
                # get shedding of contact route and add it to accumulated shedding
                shedding = float(sft.get_val("depositing ", line))
                cum_shedding += shedding
                line = "TimeStep: " + str(timestep) + " " + line
                lines.append(line)

    if debug:
        with open("DEBUG_filtered_line.txt","w") as filter_file:
            filter_file.write("".join(lines))

    #more params from config file
    rud=cdj["Environmental_Ramp_Up_Duration"]
    rdd=cdj["Environmental_Ramp_Down_Duration"]
    ecd=cdj["Environmental_Cutoff_Days"]
    eps=cdj["Environmental_Peak_Start"]

    peak_duration=365-rud-rdd-ecd
    # for eps > 365
    peak_starttime = eps % 365
    peak_endtime = peak_starttime + peak_duration
    cutoff_starttime = peak_starttime + peak_duration + rdd
    #cutoff_endtime = peak_starttime + peak_duration + rdd + ecd

    success = True

    expected_e_contagion = {}
    environmental_amp = {}

    inset_chart_obj = general_support.parse_inset_chart("output", "InsetChart.json",
                                                        insetkey_list=[InsetKeys.ChannelsKeys.Environmental_Contagion_Population])
    with open( sft.sft_output_filename, "w" ) as report_file:
        report_file.write("Peak_Start={0}, Peak_Duration={1}, Peak_End={2}, Ramp_Down={3}, Ramp_Up={4},"
                          "Cutoff_Start={5}, Cutoff_Duration={6}.\n".format(peak_starttime, peak_duration, peak_endtime,
                                                                            rdd, rud, cutoff_starttime, ecd))
        if ncdr != 1:
            report_file.write("WARNING: Node_Contagion_Decay_Rate is {}, suggest to set it to 1.\n".format(
                ncdr
            ))
        if count == 0:
            success = False
            report_file.write( "Found no data matching test case.\n" )
        elif peak_duration < 0:
            success = False
            report_file.write("BAD: Environmental peak duration should be larger or equal to 0, the actual value is {}."
                              "\n The ramp durations and cutoff days need to follow a rule where: ramp_up_duration + "
                              "ramp_down_duration + cutoff_days < 365.\n".format(peak_duration))
        else:
            # adjust the times so that the ramp up starts at time 0, which means the cut off ends at time 0 too.
            adjust_time = peak_starttime - rud
            peak_starttime -= adjust_time
            peak_endtime -= adjust_time
            cutoff_starttime -= adjust_time
            # cutoff_endtime -= adjust_time
            with open("DEBUG_contagion_data.txt", "w") as debug_file:

                for t in range(timestep - 2):
                    amplification = environmental_amplification = None
                    if t in amp:
                        TimeStep = t - adjust_time
                        day_in_year = TimeStep%365
                        amplification = amp[t]
                        # Environment Ramp Up
                        if day_in_year < peak_starttime:
                            environmental_amplification = day_in_year/float(rud)
                        # Environment peak
                        elif peak_starttime <= day_in_year <= peak_endtime:
                            environmental_amplification = 1
                        # Environment Ramp Down
                        elif peak_endtime < day_in_year < cutoff_starttime:
                            environmental_amplification = (cutoff_starttime - day_in_year) / float(rdd)
                        # Environment cutoff
                        elif day_in_year >= cutoff_starttime:
                            environmental_amplification = 0
                        if math.fabs(amplification - environmental_amplification) > 5e-2 * environmental_amplification:
                            success =False
                            report_file.write("BAD: at time {0}, day of year = {1}, the environmental amplification is {2},"
                                              " expected {3}.\n".format(t, t%365, amplification,
                                                                        environmental_amplification))
                        environmental_amp[t] = environmental_amplification
                    if t in exposure:
                        exposure_t = exposure[t]
                        if amplification is not None:
                            environment_contagion = cum_shedding_all[t-start_time] / Statpop[t -start_time]
                            expected_exposure = environment_contagion * amplification
                            if math.fabs(expected_exposure - exposure_t) > 5e-2 * expected_exposure:
                                success =False
                                report_file.write("BAD: at time {0}, day of year = {1}, the amount of environmental contagion "
                                                  "that individual is exposed is {2}, expected {3}"
                                                  ".\n".format(t, t%365,
                                                               exposure_t, expected_exposure))
                            expected_e_contagion[t] = expected_exposure

                            if debug:
                                environment_t = environment[t]
                                inserchart_contagion_e = inset_chart_obj \
                                    [InsetKeys.ChannelsKeys.Environmental_Contagion_Population][t]
                                debug_file.write("At time step {0}: environment={1}, exposure={2} from loggind, "
                                                 "{3}={4} from InsetChart, expected value={5}."
                                                 "accumulated shedding after decay={6} calculated from logging, "
                                                 "environmental amplification={7}.\n".format(
                                    t, environment_t,exposure_t, InsetKeys.ChannelsKeys.Environmental_Contagion_Population,
                                    inserchart_contagion_e, expected_exposure, environment_contagion, amplification
                                ))

        sft.plot_data(amp.values(), environmental_amp.values(),
                      label1="Actual Seasonal Attenuation",
                      label2="Expected Seasonal Attenuation",
                      title="Seasonal Attenuation", xlabel="Time",
                      ylabel="Attenuation",
                      category='seasonal_attenuation')

        for t in range(len(amp)):
            if t not in exposure:
                exposure[t] = 0
                expected_e_contagion[t] = 0

        sft.plot_data([exposure[key] for key in sorted(exposure.keys())],
                      [expected_e_contagion[key] for key in sorted(expected_e_contagion.keys())],
                             label1="exposure contagion(from StdOut)",
                             label2="Expected",
                             title="Environmental Contagion", xlabel="Time",
                             ylabel="Environmental Contagion",
                             category='Environmental_Contagion')

        report_file.write( sft.format_success_msg( success ) )
def create_report_file(param_obj, stdout_df, property_obj, property_df, report_name, debug):
    with open(report_name, "w") as outfile:
        for name, param in param_obj.items():
            outfile.write("{0} = {1}\n".format(name, param))
        success = True
        start_day = param_obj[ConfigKeys.Environmental_Peak_Start]
        ramp_up = param_obj[ConfigKeys.Environmental_Ramp_Up_Duration]
        ramp_down = param_obj[ConfigKeys.Environmental_Ramp_Down_Duration]
        cut_off = param_obj[ConfigKeys.Environmental_Cutoff_Days]
        duration = param_obj[ConfigKeys.Simulation_Duration]

        peak_duration = sft.DAYS_IN_YEAR - ramp_up - ramp_down - cut_off
        peak_starttime = start_day % sft.DAYS_IN_YEAR
        peak_endtime = peak_starttime + peak_duration
        cutoff_starttime = peak_starttime + peak_duration + ramp_down
        cutoff_endtime = peak_starttime + peak_duration + ramp_down + cut_off

        amp = []
        expected_amp = []
        expected_contagion_e_list = []
        expected_contagion_c_list = []
        # adjust the times so that the ramp up starts at time 0, which means the cut off ends at time 0 too.
        adjust_time = peak_starttime - ramp_up
        peak_starttime -= adjust_time
        peak_endtime -= adjust_time
        cutoff_starttime -= adjust_time
        cutoff_endtime -= adjust_time
        cutoff_endtime %= sft.DAYS_IN_YEAR

        contagion_channels_e = [c for c in property_df.columns if channels[3] in c]
        contagion_channels_c = [c for c in property_df.columns if channels[4] in c]
        property_df[channels[3]] = property_df[contagion_channels_e].sum(axis=1)
        property_df[channels[4]] = property_df[contagion_channels_c].sum(axis=1)

        for t in range(1, duration):
            amplification = stdout_df[Stdout.amplification].iloc[t]
            day_in_year = stdout_df[Stdout.day_of_year].iloc[t]
            if day_in_year != t % sft.DAYS_IN_YEAR:
                success = False
                outfile.write("BAD: at time step {0}, day_in_year is {1}, it should be {2}.\n".format(t, day_in_year,
                                                                                                      t % sft.DAYS_IN_YEAR))
                day_in_year = t % sft.DAYS_IN_YEAR
            day_in_year -= adjust_time
            day_in_year %= sft.DAYS_IN_YEAR
            # Environment Ramp Up
            if cutoff_endtime < day_in_year < peak_starttime:
                expected_amplification = day_in_year / ramp_up
            # Environment peak
            elif peak_starttime <= day_in_year <= peak_endtime:
                expected_amplification = 1
            # Environment Ramp Down
            elif peak_endtime < day_in_year < cutoff_starttime:
                expected_amplification = (cutoff_starttime - day_in_year) / ramp_down
            # Environment cutoff
            else:
                expected_amplification = 0
            if not math.fabs(amplification - expected_amplification) <= 5e-2 * expected_amplification:
                success = False
                outfile.write(
                    "BAD: at time {0}, day of year = {1}, the environmental amplification is {2}, expected {3}.\n".format(
                        t, t % sft.DAYS_IN_YEAR, amplification, expected_amplification))
            amp.append(amplification)
            expected_amp.append(expected_amplification)

            # Sinusoidal scaling
            sinusoidal_multiplier = Sinusoidal_Support.calculate_infectiousness(
                infected_pop=1, index=t, simulation_timestep=param_obj[ConfigKeys.Simulation_Timestep],
                phase=param_obj[ConfigKeys.Infectivity_Sinusoidal_Forcing_Phase],
                base_infectivity=1,
                amplitude=param_obj[ConfigKeys.Infectivity_Sinusoidal_Forcing_Amplitude], debug=debug)
            expected_contagion_e = param_obj[ConfigKeys.Base_Infectivity] * \
                                   expected_amplification * \
                                  (len(property_obj[DemographicsKeys.PropertyKeys.Values]) ** 2)

            # infectivity scaling should only applies to contact route.
            # expected_contagion_e *= sinusoidal_multiplier

            expected_contagion_c = sinusoidal_multiplier * param_obj[ConfigKeys.Base_Infectivity] * \
                                   len(property_obj[DemographicsKeys.PropertyKeys.Values])
            actual_contagion_e = property_df[channels[3]][t]
            actual_contagion_c = property_df[channels[4]][t]
            for expected_contagion, actual_contagion, column_name in [
                (expected_contagion_e, actual_contagion_e, channels[3]),
                (expected_contagion_c, actual_contagion_c, channels[4])]:
                if not math.fabs(actual_contagion - expected_contagion) <= 5e-2 * expected_contagion:
                    success = False
                    outfile.write(
                        "BAD: at time {0}, day of year = {1}, the {2} is {3}, expected {4}.\n".format(
                            t, t % sft.DAYS_IN_YEAR, column_name, actual_contagion, expected_contagion))
            expected_contagion_e_list.append(expected_contagion_e)
            expected_contagion_c_list.append(expected_contagion_c)

        sft.plot_data(amp, expected_amp,
                      label1="Actual amplification",
                      label2="Expected amplification",
                      title="Seasonality", xlabel="Day",
                      ylabel="Environmental amplification",
                      category='seasonal_attenuation', overlap=True, alpha=0.5)

        sft.plot_data(property_df[channels[3]][1:], expected_contagion_e_list[1:],
                      label1="Actual",
                      label2="Expected",
                      title="Environmental Contagion\nSeasonality_Sinusoidal", xlabel="Day",
                      ylabel="Environmental Contagion",
                      category='Environmental_Contagion', overlap=True, alpha=0.5)

        sft.plot_data(property_df[channels[4]][1:], expected_contagion_c_list[1:],
                      label1="Actual",
                      label2="Expected",
                      title="Contact Contagion\nSeasonality_Sinusoidal", xlabel="Day",
                      ylabel="Contact Contagion",
                      category='Contact_Contagion', overlap=True, alpha=0.5)

        outfile.write(sft.format_success_msg(success))
        if debug:
            print(sft.format_success_msg(success))
        return success
Пример #41
0
def create_report_file(param_obj, output_dict, report_name, debug):
    with open(report_name, "w") as outfile:
        config_name = param_obj[KEY_CONFIG_NAME]
        outfile.write("Config_name = {}\n".format(config_name))
        success = True
        slow_progressor_rate = param_obj[KEY_SLOW_PROGRESSOR_RATE]
        fast_progressor_rate = param_obj[KEY_FAST_PROGRESSOR_RATE]
        child_fast_fraction = param_obj[KEY_CHILD_FRACTION]
        adult_fast_fraction = param_obj[KEY_ADULT_FRACTION]
        progression_multiplier = np.mean(param_obj[KEY_CD4_PROGRESSION_MULTIPLIER])
        simulation_duration = param_obj[KEY_DURATION]
        if not len(output_dict):
            success = False
            outfile.write(sft.sft_no_test_data)

        outfile.write("checking test conditions: \n")
        if child_fast_fraction:
            success = False
            outfile.write("BAD: expected {0} = 0, got {1} from config.json. "
                          "Please fix the test.\n".format(KEY_CHILD_FRACTION, child_fast_fraction))
        dist_exponential_np_slow = np.random.exponential(1/slow_progressor_rate, 100)
        if min(dist_exponential_np_slow) < simulation_duration:
            success = False
            outfile.write("BAD: expected a small {0} to distinguish fast and slow progress TB, got {1} from config.json. Please "
                          "fix the test.\n".format(KEY_SLOW_PROGRESSOR_RATE, slow_progressor_rate))
        outfile.write("conditional check result is {}.\n".format(success))

        actual_timer = []
        internal_timer = []
        slow_count = 0
        outfile.write("collecting the actual timestep between latent and presymptomatic:\n")
        outfile.write("checking if the internal timer matches the PreSymptomatic to Cleared duration:\n")

        for id in output_dict:
            presymptomatic_time = timer = latent_time = None
            if KEY_PRESYMPTOMATIC in output_dict[id]:
                presymptomatic_time = output_dict[id][KEY_PRESYMPTOMATIC][0]
                timer = output_dict[id][KEY_PRESYMPTOMATIC][1]
                internal_timer.append(timer)
            if KEY_LATENT in output_dict[id]:
                latent_time = output_dict[id][KEY_LATENT]
            if latent_time:
                if presymptomatic_time: # some individual may not move to presymptomatic state at the end of the simulation
                    actual_timer.append(presymptomatic_time - latent_time)
                    if presymptomatic_time - latent_time != math.ceil(timer):
                        success = False
                        outfile.write("BAD: individual {0} has internal timer = {1} but the actual timer is {2} (enter "
                                      "latent state at timestep {3}, enter presymptomatic active state at "
                                      "timestep {4}).\n".format(id, timer, presymptomatic_time - latent_time,
                                                                latent_time, presymptomatic_time))
                else:
                    slow_count += 1
                    if debug:
                        outfile.write("Individual {0} moved to latent state at timestep {1} and is not move to "
                                      "presymptomatic active yet at the end of simulation (duration = {2})."
                                      "\n".format(id, latent_time, simulation_duration))
            else:
                success = False
                outfile.write("BAD: individual {0} moved to presymptomatic active state at timerstep {1} before entering "
                              "latent state.\n".format(id, presymptomatic_time))
        if not len(actual_timer):
            success = False
            outfile.write("BAD: There is no latent to presymptomatic state transition in this test, please fix the test.\n")

        outfile.write("Running ks test for latent to presymptomatic internal timer and numpy exponential distribution: \n")
        size = len(internal_timer)
        scale = 1.0 / fast_progressor_rate
        dist_exponential_np = np.random.exponential(scale, size)
        sft.plot_data_sorted(internal_timer, dist2=np.array(dist_exponential_np), label1="internal timer",
                          label2="numpy exponential", title="exponential rate = {}".format(fast_progressor_rate),
                          xlabel="data point", ylabel="latent to presymptomatic internal timer",
                          category='latent_to_presymptomatic_internal_timer', show=True, line=False, overlap=True)
        result = sft.test_exponential(internal_timer, p1=fast_progressor_rate, report_file=outfile, integers=True, roundup=True,
                                          round_nearest=False)
        outfile.write("ks test result is {0}, exponential rate = {1}, # of data point = {2}.\n".format(result, fast_progressor_rate, size))
        if not result:
            success = False
            outfile.write("BAD: test exponential for latent to presymptomatic duration failed with fast_progressor_rate "
                          "= {}.\n".format(fast_progressor_rate))
        else:
            outfile.write(
                "GOOD: test exponential for latent to presymptomatic duration passed with fast_progressor_rate "
                "= {}.\n".format(fast_progressor_rate))

        outfile.write("running binomial test with 95% confidence for Fast_Progressor_Fraction_Adult:\n")
        result2 = sft.test_binomial_95ci(num_success=len(internal_timer), num_trials=len(internal_timer) + slow_count,
                                             prob=adult_fast_fraction * progression_multiplier, report_file=outfile,
                                             category="Fast_Progressor_Fraction_Adult")
        outfile.write("number of slow progressor is {0} and number of fast progressor is {1}.\n".format(slow_count, len(internal_timer)))
        if not result2:
            success = False
            outfile.write("BAD: binomial test for Fast_Progressor_Fraction_Adult = {0} and TB_CD4_Primary_Progression= {1} failed"
                          ".\n".format(adult_fast_fraction, progression_multiplier))
        else:
            outfile.write("GOOD: binomial test for Fast_Progressor_Fraction_Adult = {0} and TB_CD4_Primary_Progression= {1} passed"
                          ".\n".format(adult_fast_fraction, progression_multiplier))

        outfile.write(sft.format_success_msg(success))
    if debug:
        print( "SUMMARY: Success={0}\n".format(success) )
    return success
def create_report_file(param_obj, campaign_obj, property_obj, property_df, stdout_df, recorder_obj,
                       report_name, report_event_recorder, stdout_filename, debug):
    with open(report_name, "w") as outfile:
        for name, param in param_obj.items():
            outfile.write("{0} = {1}\n".format(name, param))
        sample_threshold = float(campaign_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold])
        base_sensitivity = float(campaign_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity])
        base_specificity = float(campaign_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity])
        ip_key_value = campaign_obj[CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value]
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold, sample_threshold))
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity, base_sensitivity))
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity, base_specificity))
        outfile.write("{0} = {1}\n".format(CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value,
                                           ip_key_value))
        success = recorder_obj[1]

        if not success:
            error_message = recorder_obj[0]
            outfile.write("Failed to parse report file: {0}, get exception: {1}.\n".format(report_event_recorder,
                                                                                           error_message
                                                                                           ))
        else:
            # Throw warning messages for condition checks. Make sure all features are enabled.
            if not sample_threshold:
                outfile.write("WARNING: {0} should not be 0 in this test, got {1} from compaign file. Please fix the test.\n"
                              "".format(CampaignKeys.EnvironmentalDiagnosticKeys.Sample_Threshold, sample_threshold))
            if base_specificity == 1:
                outfile.write("WARNING: the {0} is {1}, expected value is less than 1.\n".format(
                    CampaignKeys.EnvironmentalDiagnosticKeys.Base_Specificity, base_specificity))
            if base_sensitivity == 1:
                outfile.write("WARNING: the {0} is {1}, expected value is less than 1.\n".format(
                    CampaignKeys.EnvironmentalDiagnosticKeys.Base_Sensitivity, base_sensitivity))
            if not ip_key_value:
                outfile.write(
                    "WARNING: {0} should not be empty in this test, got '{1}' from compaign file. Please fix the test.\n"
                    "".format(CampaignKeys.EnvironmentalDiagnosticKeys.Environment_IP_Key_Value, ip_key_value))

            duration = param_obj[ConfigKeys.Simulation_Duration]
            base_infectivity = param_obj[ConfigKeys.Base_Infectivity]

            positive_list = []
            negative_list = []
            positive_event_list = []
            negative_event_list = []

            # get infected and stat_pop channels for the selected IP group from property report
            infected_ip_group_list = property_df[[c for c in property_df.columns if Diagnostic_Support.channels[0] in c]]
            stat_pop_ip_group_list = property_df[[c for c in property_df.columns if Diagnostic_Support.channels[-1] in c]]

            # group by time and event name, then count how many event in each time step and put the value into a new
            # column named: "Test result counts"
            event_df = recorder_obj[0]
            event_df = event_df.groupby([Diagnostic_Support.ReportColumn.time,
                                         Diagnostic_Support.ReportColumn.event]).size().reset_index()
            event_df.rename(columns={0: Diagnostic_Support.ReportColumn.counts}, inplace=True)

            contagion_list = []
            expected_positive_count = expected_negative_count = 0
            for t in range(1, duration):
                # Test 1: make sure we get the correct contagion sample and
                # number of positive and negative results in StdOut.txt
                stdout_t_df = stdout_df[stdout_df[Diagnostic_Support.ConfigKeys.Simulation_Timestep] == t]

                #stdout_next_t_df = stdout_df[stdout_df[Diagnostic_Support.ConfigKeys.Simulation_Timestep] == t + 1]

                infected = stdout_t_df[Diagnostic_Support.Stdout.infected].iloc[0]
                stat_pop = stdout_t_df[Diagnostic_Support.Stdout.stat_pop].iloc[0]

                test_positive = stdout_t_df[Diagnostic_Support.Stdout.test_positive].iloc[0]
                test_negative = stdout_t_df[Diagnostic_Support.Stdout.test_negative].iloc[0]
                test_default = stdout_t_df[Diagnostic_Support.Stdout.test_default].iloc[0]
                envi_sample = stdout_t_df[Diagnostic_Support.Stdout.sample].iloc[0]
                ip = stdout_t_df[Diagnostic_Support.Stdout.ip_value].iloc[0]

                infected_ip_group = infected_ip_group_list.iloc[t - 1][0]
                stat_pop_ip_group = stat_pop_ip_group_list.iloc[t - 1][0]
                if stat_pop == stat_pop_ip_group and infected == infected_ip_group:
                    success = False
                    outfile.write("BAD: at time step {0} the total stat_pop = {1} and total infect = {2}, we got "
                                  "stat_pop_ip_group = {3} and infected_ip_group = {4} in group {5}, we expect to "
                                  "see less stat_pop and infected individual in the IP group , this is not a valid test "
                                  "for Environment_IP_Key_Value, please check the test condition.\n".format(t, stat_pop,
                                   infected, stat_pop_ip_group, infected_ip_group, ip_key_value))
                if ip_key_value != ip:
                    success = False
                    outfile.write("BAD: at time step {0}, IP={1} from StdOut.txt, expected IP={2}.\n".format(
                        t, ip, ip_key_value))
                susceptible = stat_pop_ip_group - infected_ip_group
                message = "BAD: at time {0}, group {1} has infected individuals = {2} and susceptible individuals = {3}," \
                " expected {4} individuals receive a {5} test result, got {6} from logging.\n"

                # calculated environmental contagion
                contagion = base_infectivity * infected_ip_group / stat_pop_ip_group
                contagion_list.append(contagion)
                if math.fabs(contagion - envi_sample) > envi_sample * 1e-2:
                    success = False
                    outfile.write(
                        "BAD: at time step {0} the environmental sample for IP group {1} is {2}, expected value is {3}"
                        ".\n".format(
                            t, ip_key_value, envi_sample, contagion
                        ))
                # positive = real positive or false positive
                # negative = false negative or real negative
                if contagion > sample_threshold:
                    expected_test_positive = base_sensitivity
                    expected_test_negative = 1.0 - base_sensitivity
                else:
                    expected_test_positive = 1.0 - base_specificity
                    expected_test_negative = base_specificity

                expected_positive_count += expected_test_positive
                expected_negative_count += expected_test_negative

                # no test default in this intervention
                expected_test_default = 0
                if test_default != expected_test_default:
                    success = False
                    outfile.write(message.format(
                        t, ip_key_value, infected_ip_group, susceptible, expected_test_default,
                        "default", test_default))
                positive_list.append([test_positive, expected_test_positive])
                negative_list.append([test_negative, expected_test_negative])
                # End of Test 1 at this time step

                # Test 2: make sure events reported in ReportEventRecorder.csv and test results from StdOut.txt are matched.
                message = "BAD: at time {0}, {1} records {2} {3} events, got {4} {5} results from {5}.\n"

                # get the positive event count from data frame
                positive_event = event_df[
                    (event_df[Diagnostic_Support.ReportColumn.time] == t) &
                    (event_df[Diagnostic_Support.ReportColumn.event] == Diagnostic_Support.ReportColumn.positive)][
                    Diagnostic_Support.ReportColumn.counts].values
                if len(positive_event):
                    positive_event = positive_event[0]
                else:
                    positive_event = 0

                # StdOut.txt should match ReportEventRecorder.csv
                if test_positive != positive_event:
                    success = False
                    outfile.write(message.format(
                        t, report_event_recorder, positive_event, Diagnostic_Support.ReportColumn.positive, test_positive,
                        Diagnostic_Support.Stdout.test_positive, stdout_filename))

                # get the negative event count from data frame
                negative_event = event_df[
                    (event_df[Diagnostic_Support.ReportColumn.time] == t) &
                    (event_df[Diagnostic_Support.ReportColumn.event] == Diagnostic_Support.ReportColumn.negative)][
                    Diagnostic_Support.ReportColumn.counts].values
                if len(negative_event):
                    negative_event = negative_event[0]
                else:
                    negative_event = 0

                # StdOut.txt should match ReportEventRecorder.csv
                if test_negative != negative_event:
                    success = False
                    outfile.write(message.format(
                        t, report_event_recorder, negative_event, Diagnostic_Support.ReportColumn.negative, test_negative,
                        Diagnostic_Support.Stdout.test_negative, stdout_filename))

                positive_event_list.append(positive_event)
                negative_event_list.append(negative_event)
                # End of Test 2 at this time step

            stdout_sum = stdout_df.sum()

            result = sft.test_multinomial([stdout_sum[Diagnostic_Support.Stdout.test_positive],
                                               stdout_sum[Diagnostic_Support.Stdout.test_negative]],
                                              proportions=[expected_positive_count, expected_negative_count],
                                              report_file=outfile,
                                              prob_flag=False, )

            message = "{0}: the total test positive and negative counts from StdOut.txt are {1} and {2}, expected values" \
                      " are {3} and {4}.\n"

            if result:
                outfile.write(message.format("GOOD", stdout_sum[Diagnostic_Support.Stdout.test_positive],
                                             stdout_sum[Diagnostic_Support.Stdout.test_negative],
                                             expected_positive_count, expected_negative_count))
            else:
                success = False
                outfile.write(message.format("BAD", stdout_sum[Diagnostic_Support.Stdout.test_positive],
                                             stdout_sum[Diagnostic_Support.Stdout.test_negative],
                                             expected_positive_count, expected_negative_count))


            # these two plots are replaced with the scatter with fit line plots
            # sft.plot_data(np.array(positive_list)[:, 0], np.array(positive_list)[:, 1],
            #                   label1="Actual",
            #                   label2="Probability of Positive",
            #                   title="Test Positive\n Group {}".format(ip_key_value), xlabel="Day",
            #                   ylabel="Positive count",
            #                   category='Test_Positive_Probability', overlap=False)
            # sft.plot_data(np.array(negative_list)[:, 0], np.array(negative_list)[:, 1],
            #                   label1="Actual",
            #                   label2="Probability of Negative",
            #                   title="Test Negative\n Group {}".format(ip_key_value), xlabel="Day",
            #                   ylabel="Negative count",
            #                   category='Test_Negative_Probability', overlap=False)

            sft.plot_scatter_fit_line(np.array(positive_list)[:, 0], dist2=np.array(positive_list)[:, 1],
                                          label1="Actual", label2="Probability of Positive",
                                          title="Test Positive\n Group {}".format(ip_key_value),
                                          xlabel="Day",
                                          ylabel="Positive count",
                                          category='Test_Positive_Probability_Scatter_Fit_Line')

            sft.plot_scatter_fit_line(np.array(negative_list)[:, 0], dist2=np.array(negative_list)[:, 1],
                                          label1="Actual", label2="Probability of Negative",
                                          title="Test Negative\n Group {}".format(ip_key_value),
                                          xlabel="Day",
                                          ylabel="Negative count",
                                          category='Test_Negative_Probability_Scatter_Fit_Line')

            sft.plot_data(np.array(positive_list)[:, 0], positive_event_list,
                              label1=stdout_filename,
                              label2=report_event_recorder,
                              title="Test Positive\n Group {}".format(ip_key_value), xlabel="Day",
                              ylabel="Positive count",
                              category='Test_Positive_stdout_vs_event_recorder', overlap=True, alpha=0.5)
            sft.plot_data(np.array(negative_list)[:, 0], negative_event_list,
                              label1=stdout_filename,
                              label2=report_event_recorder,
                              title="Test Negative\n Group {}".format(ip_key_value), xlabel="Day",
                              ylabel="Negative count",
                              category='Test_Negative_stdout_vs_event_recorder', overlap=True, alpha=0.5)
            sft.plot_data(stdout_df[Diagnostic_Support.Stdout.sample].tolist()[1:], contagion_list,
                              label1="Actual",
                              label2="Expected",
                              title="Environmental_Contagion", xlabel="Day",
                              ylabel="Environmental_Contagion",
                              category='Environmental_Contagion', overlap=True, alpha=0.5)
        outfile.write(sft.format_success_msg(success))
        if debug:
            print(sft.format_success_msg(success))
        return success
Пример #43
0
def create_report_file(param_obj, stdout_df, property_obj, property_df,
                       report_name, debug):
    with open(report_name, "w") as outfile:
        for name, param in param_obj.items():
            outfile.write("{0} = {1}\n".format(name, param))
        success = True
        start_day = param_obj[ConfigKeys.Environmental_Peak_Start]
        ramp_up = param_obj[ConfigKeys.Environmental_Ramp_Up_Duration]
        ramp_down = param_obj[ConfigKeys.Environmental_Ramp_Down_Duration]
        cut_off = param_obj[ConfigKeys.Environmental_Cutoff_Days]
        duration = param_obj[ConfigKeys.Simulation_Duration]

        peak_duration = sft.DAYS_IN_YEAR - ramp_up - ramp_down - cut_off
        peak_starttime = start_day % sft.DAYS_IN_YEAR
        peak_endtime = peak_starttime + peak_duration
        cutoff_starttime = peak_starttime + peak_duration + ramp_down
        cutoff_endtime = peak_starttime + peak_duration + ramp_down + cut_off

        amp = []
        expected_amp = []
        expected_contagion_e_list = []
        expected_contagion_c_list = []
        # adjust the times so that the ramp up starts at time 0, which means the cut off ends at time 0 too.
        adjust_time = peak_starttime - ramp_up
        peak_starttime -= adjust_time
        peak_endtime -= adjust_time
        cutoff_starttime -= adjust_time
        cutoff_endtime -= adjust_time
        cutoff_endtime %= sft.DAYS_IN_YEAR

        contagion_channels_e = [
            c for c in property_df.columns if channels[3] in c
        ]
        contagion_channels_c = [
            c for c in property_df.columns if channels[4] in c
        ]
        property_df[channels[3]] = property_df[contagion_channels_e].sum(
            axis=1)
        property_df[channels[4]] = property_df[contagion_channels_c].sum(
            axis=1)

        for t in range(1, duration):
            amplification = stdout_df[Stdout.amplification].iloc[t]
            day_in_year = stdout_df[Stdout.day_of_year].iloc[t]
            if day_in_year != t % sft.DAYS_IN_YEAR:
                success = False
                outfile.write(
                    "BAD: at time step {0}, day_in_year is {1}, it should be {2}.\n"
                    .format(t, day_in_year, t % sft.DAYS_IN_YEAR))
                day_in_year = t % sft.DAYS_IN_YEAR
            day_in_year -= adjust_time
            day_in_year %= sft.DAYS_IN_YEAR
            # Environment Ramp Up
            if cutoff_endtime < day_in_year < peak_starttime:
                expected_amplification = day_in_year / ramp_up
            # Environment peak
            elif peak_starttime <= day_in_year <= peak_endtime:
                expected_amplification = 1
            # Environment Ramp Down
            elif peak_endtime < day_in_year < cutoff_starttime:
                expected_amplification = (cutoff_starttime -
                                          day_in_year) / ramp_down
            # Environment cutoff
            else:
                expected_amplification = 0
            if not math.fabs(amplification - expected_amplification
                             ) <= 5e-2 * expected_amplification:
                success = False
                outfile.write(
                    "BAD: at time {0}, day of year = {1}, the environmental amplification is {2}, expected {3}.\n"
                    .format(t, t % sft.DAYS_IN_YEAR, amplification,
                            expected_amplification))
            amp.append(amplification)
            expected_amp.append(expected_amplification)

            # Exponential scaling
            exp_delay = param_obj[ConfigKeys.Infectivity_Exponential_Delay]
            exp_baseline = param_obj[
                ConfigKeys.Infectivity_Exponential_Baseline]
            exp_rate = param_obj[ConfigKeys.Infectivity_Exponential_Rate]
            if t < exp_delay:
                exponential_multiplier = exp_baseline
            else:
                exponential_multiplier = 1.0 - (
                    (1.0 - exp_baseline) * math.exp(
                        (exp_delay - t) / exp_rate))
            # TODO: change to the following equation when changes in Generic_Ongoing are merged
            # if t + 1 < exp_delay:
            #     exponential_multiplier = exp_baseline
            # else:
            #     exponential_multiplier = 1.0 - ((1.0 - exp_baseline) * math.exp((exp_delay - t - 1) * exp_rate))

            expected_contagion_e = param_obj[ConfigKeys.Base_Infectivity] * \
                                   expected_amplification * \
                                  (len(property_obj[DemographicsKeys.PropertyKeys.Values]) ** 2)
            # infectivity scaling should only applies to contact route.
            # expected_contagion_e *= exponential_multiplier

            expected_contagion_c = exponential_multiplier * param_obj[ConfigKeys.Base_Infectivity] * \
                                   len(property_obj[DemographicsKeys.PropertyKeys.Values])
            actual_contagion_e = property_df[channels[3]][t]
            actual_contagion_c = property_df[channels[4]][t]
            for expected_contagion, actual_contagion, column_name in [
                (expected_contagion_e, actual_contagion_e, channels[3]),
                (expected_contagion_c, actual_contagion_c, channels[4])
            ]:
                if not math.fabs(actual_contagion - expected_contagion
                                 ) <= 5e-2 * expected_contagion:
                    success = False
                    outfile.write(
                        "BAD: at time {0}, day of year = {1}, the {2} is {3}, expected {4}.\n"
                        .format(t, t % sft.DAYS_IN_YEAR, column_name,
                                actual_contagion, expected_contagion))
            expected_contagion_e_list.append(expected_contagion_e)
            expected_contagion_c_list.append(expected_contagion_c)

        sft.plot_data(amp,
                      expected_amp,
                      label1="Actual amplification",
                      label2="Expected amplification",
                      title="Seasonality",
                      xlabel="Day",
                      ylabel="Environmental amplification",
                      category='seasonal_attenuation',
                      overlap=True,
                      alpha=0.5)

        sft.plot_data(property_df[channels[3]][1:],
                      expected_contagion_e_list[1:],
                      label1="Actual",
                      label2="Expected",
                      title="Environmental Contagion\nSeasonality_Exponential",
                      xlabel="Day",
                      ylabel="Environmental Contagion",
                      category='Environmental_Contagion',
                      overlap=True,
                      alpha=0.5)

        sft.plot_data(property_df[channels[4]][1:],
                      expected_contagion_c_list[1:],
                      label1="Actual",
                      label2="Expected",
                      title="Contact Contagion\nSeasonality_Exponential",
                      xlabel="Day",
                      ylabel="Contact Contagion",
                      category='Contact_Contagion',
                      overlap=True,
                      alpha=0.5)

        outfile.write(sft.format_success_msg(success))
        if debug:
            print(sft.format_success_msg(success))
        return success
Пример #44
0
def create_report_file(param_obj, output_dict, report_name, debug):
    with open(report_name, "w") as outfile:
        config_name = param_obj[KEY_CONFIG_NAME]
        outfile.write("Config_name = {}\n".format(config_name))
        success = True
        slow_progressor_rate = param_obj[KEY_SLOW_PROGRESSOR_RATE]
        simulation_duration = param_obj[KEY_DURATION]
        if not len(output_dict):
            success = False
            outfile.write(sft.sft_no_test_data)
        actual_timer = []
        internal_timer = []
        outfile.write("collecting the actual timestep between latent and presymptomatic:\n")
        outfile.write("checking if the internal timer matches the PreSymptomatic to Cleared duration:\n")
        for id in output_dict:
            presymptomatic_time = timer = latent_time = None
            if KEY_PRESYMPTOMATIC in output_dict[id]:
                presymptomatic_time = output_dict[id][KEY_PRESYMPTOMATIC][0]
                timer = output_dict[id][KEY_PRESYMPTOMATIC][1]
                internal_timer.append(timer)
            if KEY_LATENT in output_dict[id]:
                latent_time = output_dict[id][KEY_LATENT]
            if latent_time:
                if presymptomatic_time: # some individual may not move to presymptomatic state at the end of the simulation
                    actual_timer.append(presymptomatic_time - latent_time)
                    if presymptomatic_time - latent_time != math.ceil(timer):
                        success = False
                        outfile.write("BAD: individual {0} has internal timer = {1} but the actual timer is {2} (enter "
                                      "latent state at timestep {3}, enter presymptomatic active state at "
                                      "timestep {4}).\n".format(id, timer, presymptomatic_time - latent_time,
                                                                latent_time, presymptomatic_time))
                else:
                    outfile.write("Individual {0} moved to latent state at timestep {1} and is not move to "
                                  "presymptomatic active yet at the end of simulation (duration = {2})."
                                  "\n".format(id, latent_time, simulation_duration))
            else:
                success = False
                outfile.write("BAD: individual {0} moved to presymptomatic active state at timerstep {1} before entering "
                              "latent state.\n".format(id, presymptomatic_time))
        if not len(actual_timer):
            success = False
            outfile.write("BAD: There is no latent to presymptomatic state transition in this test, please fix the test.\n")

        outfile.write("Running ks test for latent to presymptomatic internal timer and numpy exponential distribution: \n")
        size = len(internal_timer)
        scale = 1.0 / slow_progressor_rate
        dist_exponential_np = np.random.exponential(scale, size)
        sft.plot_data_sorted(internal_timer, dist2=np.array(dist_exponential_np), label1="latent to presymptomatic internal timer",
                          label2="numpy exponential", title="exponential rate = {}".format(slow_progressor_rate),
                          xlabel="data point", ylabel="latent to presymptomatic internal timer",
                          category='latent_to_presymptomatic_internal_timer', show=True, line=False, overlap=True)
        result = sft.test_exponential(internal_timer, p1=slow_progressor_rate, report_file=outfile, integers=True, roundup=True,
                                          round_nearest=False)
        outfile.write("ks test result is {0}, exponential rate = {1}, # of data point = {2}.\n".format(result, slow_progressor_rate, size))
        if not result:
            success = False
            outfile.write("BAD: test exponential for latent to presymptomatic internal timer failed with slow_progressor_rate "
                          "= {}.\n".format(slow_progressor_rate))
        else:
            outfile.write("GOOD: test exponential for latent to presymptomatic internal timer passed with slow_progressor_rate "
                          "= {}.\n".format(slow_progressor_rate))

        outfile.write(sft.format_success_msg(success))
    if debug:
        print( "SUMMARY: Success={0}\n".format(success) )
    return success
def create_report_file(param_obj, campaign_obj, demographics_obj, report_data_obj, report_name, debug=False):
    with open(report_name, "w") as outfile:
        total_timesteps = param_obj[KEY_TOTAL_TIMESTEPS]
        start_timestep = param_obj[KEY_START_TIME]
        initial_population = demographics_obj[KEY_INITIAL_POPULATION]
        rates = [x * campaign_obj[KEY_NODE_LIST_COUNT] for x in campaign_obj[KEY_CAMPAIGN_DIP]]
        durations = campaign_obj[KEY_CAMPAIGN_DURATIONS]
        new_infections = report_data_obj[KEY_NEW_INFECTIONS]
        statistical_population = report_data_obj[KEY_STATISTICAL_POPULATION]
        length = len(rates)
        start_duration = start_timestep
        new_infections_dict = {}
        calculate_new_population = initial_population
        outfile.write("# Test name: " + str(param_obj[KEY_CONFIG_NAME]) + ", Run number: " +
                      str(param_obj[KEY_RUN_NUMBER]) +
                      "\n# Test compares the statistical population with the"
                      " calculated population and tests the Poisson distribution for new infections.\n")
        for i in range(length):
            rate = rates[i]
            duration = durations[i]
            calculate_new_population = rate * duration + calculate_new_population
            end_duration = duration + start_duration
            if rate not in new_infections_dict:
                new_infections_dict[rate] = []
            for j in range(start_duration + 1, end_duration + 1):
                new_infections_dict[rate].append(new_infections[j])
            start_duration = end_duration
        if end_duration < total_timesteps + start_timestep:
            rate = 0.0
            if rate not in new_infections_dict:
                new_infections_dict[rate] = []
            for j in range(end_duration + 1, len(new_infections)):
                new_infections_dict[rate].append(new_infections[j])
        if debug:
            with open("DEBUG_new_infections_parsed.json", "w") as new_infections_file:
                json.dump(new_infections_dict, new_infections_file, indent=4)

        # test statistical population channel
        diff_population = math.fabs(calculate_new_population - statistical_population[-1])
        if debug:
            print("calculated population is {0}, statistical population "
                  "from InsetChart is {1}.".format(calculate_new_population,
                                                   statistical_population[-1]))
        error_tolerance = math.fabs(calculate_new_population - initial_population) * 0.1
        low_acceptance_bound = round(calculate_new_population - error_tolerance)
        high_acceptance_bound = round(calculate_new_population + error_tolerance)
        if debug:
            print("diff_population is {0}, error_tolerance is {1}".format(diff_population, error_tolerance))
        success = diff_population < error_tolerance
        result_string = "GOOD" if success else "BAD"
        within_acceptance_bounds = " " if success else " not "
        outfile.write("{0}: statistical population is {1}, which is{2}within range of ({3}, {4}).  "
                      "Expected about {5}.\n".format(result_string, statistical_population[-1],
                                                     within_acceptance_bounds, low_acceptance_bound,
                                                     high_acceptance_bound, calculate_new_population))
        # test poisson distribution for new infections
        for rate in new_infections_dict:
            dist = new_infections_dict[rate]
            title = "rate = " + str(rate)
            result = sft.test_poisson(dist, rate, route=title, report_file=outfile, normal_approximation=False)
            if not result:
                success = False
            numpy_distro = np.random.poisson(rate, len(dist))
            sft.plot_data(dist, numpy_distro,
                          title="new infections for {}".format(title),
                          label1="new infection from model, {}".format(title),
                          label2="Poisson distro from numpy",
                          xlabel="data points", ylabel="new infection",
                          category="plot_data_{0}".format(title), show=True,
                          sort=True)
            sft.plot_probability(dist, numpy_distro,
                                 title="probability mass function for {}".format(title),
                                 label1="new infection probability from model",
                                 label2="new infection probability from numpy distro",
                                 category="plot_probability_{0}".format(title), show=True)

        outfile.write(sft.format_success_msg(success))
        if debug:
            print("SUMMARY: Success={0}\n".format(success))
        return success
Пример #46
0
def application(report_file, debug=False):
    # pdb.set_trace()
    # print( "Post-processing: " + report_file )
    sft.wait_for_done()

    cdj = json.loads(open("config.json").read())["parameters"]
    start_time = cdj["Start_Time"]
    isj = json.loads(open(os.path.join("output",
                                       "InsetChart.json")).read())["Channels"]
    nocc = isj["Number of Chronic Carriers"]["Data"]
    count = 0
    chronics_from_diagnostic = 0
    sum_count = 0
    counts = []
    counts2 = {}
    sum_counts = []
    with open("test.txt") as logfile:
        for line in logfile:
            if re.search("Update\(\): Time:", line):
                counts.append(count)
                sum_count += count
                sum_counts.append(sum_count)
                count = 0

                if chronics_from_diagnostic > 0:  # not a good test if none are found, but we can fix that
                    counts2[len(sum_counts) - 1] = chronics_from_diagnostic
                    chronics_from_diagnostic = 0

            if re.search("just went chronic", line):
                count += 1
            elif re.search("positive from God", line):
                chronics_from_diagnostic += 1

    success = True
    with open(sft.sft_output_filename, "w") as report_file:
        if not sum_count:
            success = False
            report_file.write(
                "BAD: Found no Chronic Infections in test case.\n")
        else:
            pre_sum_count_icj = 0
            debug_count = []
            for timestep in counts2.keys():
                if counts2[timestep] != sum_counts[timestep]:
                    print("BAD!")
                    success = False
                    pdb.set_trace()
                    report_file.write(
                        "BAD: Total Chronic infections is {0} from InsetChart.json at time {1}, it's {2} "
                        "at previous time step, expected {3} more based on Stdout log."
                        "\n".format(cur_sum_count_icj, timestep,
                                    pre_sum_count_icj, count_log))

            non_sparse_diagnostic_array = []
            for tstep in range(len(sum_counts)):
                if tstep in counts2.keys():
                    non_sparse_diagnostic_array.append(counts2[tstep])
                else:
                    non_sparse_diagnostic_array.append(0)

            sft.plot_data(sum_counts,
                          non_sparse_diagnostic_array,
                          label1="Total Chronic from stdout",
                          label2="Chronic counts from periodic diagnostic",
                          title="Chronic Infections (Diagnostic)",
                          xlabel="Time",
                          ylabel="Total Number of Chronic Carriers",
                          category='report_diagnostic_chronic')

            report_file.write(sft.format_success_msg(success))
Пример #47
0
def create_report_file(drug_start_timestep, disease_deaths, cum_deaths, deaths, infected_individuals, death_times, drug_mortality_rate_HIV, report_name ):
    with open(report_name, "w") as outfile:
        success = True
        length = len(cum_deaths)
        if sum(disease_deaths)==0 or sum(cum_deaths)==0 or len(death_times)==0:
            success = False
            outfile.write(sft.no_test_data)
        for x in range(length):
            if disease_deaths[x] != cum_deaths[x]:
                success = False
                outfile.write("BAD: at timestep {0}, disease deaths is {1} in InsetChart.json and {2} in stdout.txt.\n".format(x+1, disease_deaths[x], cum_deaths[x]))
        # ks exponential test doesn't work very well with large rate, use chi squared test instead
        # while rate is small ks test for exponential distribution is more sensitive to catch the difference
        if drug_mortality_rate_HIV < 0.1:
            outfile.write("Testing death times as draws from exponential distrib with rate {0}. "
                          "Dataset size = {1}.\n".format(drug_mortality_rate_HIV, len(death_times)))
            ks_result = sft.test_exponential( death_times, drug_mortality_rate_HIV, report_file = outfile,
                                                  integers=True, roundup=True, round_nearest=False )
            if not ks_result:
                success = False
                outfile.write("BAD: ks test reuslt is False.\n")
            size = len(death_times)
            scale = 1.0 / drug_mortality_rate_HIV
            dist_exponential_np = numpy.random.exponential(scale, size)
            dist_exponential_np = [math.ceil(x) for x in dist_exponential_np]
            sft.plot_data_sorted(death_times, dist_exponential_np,
                              label1="death times", label2="numpy data",
                              title="death_times_actual_vs_numpy",
                              xlabel="data points", ylabel="death times",
                              category="death_times", show=True, line = True, overlap=True)
            sft.plot_cdf(death_times, dist_exponential_np,
                             label1="death times", label2="numpy data",
                             title="death_times_cdf",
                             xlabel="days", ylabel="probability",
                             category="death_times_cdf", show=True)
        else:
            outfile.write("Testing death count per day with rate {0}. \n".format(drug_mortality_rate_HIV))
            expected_mortality = []
            for t in range( len(deaths)):
                if t < drug_start_timestep + 1:
                    if deaths[t] > 0:
                        success = False
                        outfile.write("BAD: expected no disease death on drugs before day {0}, get {1} cases at timestep {2}.\n"
                                      "".format(drug_start_timestep + 1, deaths[t], t))
                elif infected_individuals[t] > 0:
                    expected_mortality.append(drug_mortality_rate_HIV * infected_individuals[t])
            expected_mortality.pop(0) # the Infected is off by one day
            test_death_dates = deaths[drug_start_timestep + 1:drug_start_timestep + 1 + len(expected_mortality)]
            sft.plot_data(test_death_dates, expected_mortality,
                                     label1="actual death", label2="expected death",
                                     title="death per day",
                                     xlabel="date after drug start day", ylabel="death per day",
                                     category="death_counts", show=True, line=True, overlap=True, sort=False)

            chi_result = sft.test_multinomial(dist=test_death_dates, proportions=expected_mortality,
                                                  report_file=outfile, prob_flag=False)
            if not chi_result:
                success = False
                outfile.write("BAD: Chi-squared test reuslt is False.\n")

        outfile.write(sft.format_success_msg(success))
        return success
def create_report_file(report_data_obj, csv_df, report_name, debug):
    with open(report_name, "w") as outfile:
        success = True
        timestep = Outbreak_Start_Day
        effect_a = Prime_Acquire
        effect_t = Prime_Transmit
        effect_m = Prime_Mortality
        new_infections = []
        statistical_populations = []
        new_disease_deaths = []
        for x in range(Number_Repetitions):
            num_group = len(KEY_NEW_INFECTIONS_GROUP)
            for i in range(num_group):
                new_infection = report_data_obj[KEY_NEW_INFECTIONS_GROUP[i]][timestep]
                statistical_population = report_data_obj[KEY_STATISTICAL_POPULATION_GROUP[i]][timestep]
                # disease death in the last two groups happen 1 day later than the first two groups.
                pre_disease_death = len(csv_df[(csv_df['Time'] == int(timestep + i / 2 - 1)) &
                                           (csv_df['QualityOfCare'] == PROPERTY_GROUP[i]) &
                                           (csv_df['Event_Name'] == 'DiseaseDeaths')])
                disease_death = len(csv_df[(csv_df['Time'] == int(timestep + i / 2)) &
                                           (csv_df['QualityOfCare'] == PROPERTY_GROUP[i]) &
                                           (csv_df['Event_Name'] == 'DiseaseDeaths')])
                new_disease_death = disease_death - pre_disease_death
                new_infections.append(new_infection)
                statistical_populations.append(statistical_population)
                new_disease_deaths.append(new_disease_death)
            # test acquisition blocking
            new_infection_seed_test = new_infections[1 + x * num_group]
            statistical_population_seed_test = statistical_populations[1 + x * num_group]
            expected_new_infection_seed_test = statistical_population_seed_test * (1.0 - effect_a) * Outbreak_Demographic_Coverage
            tolerance_1 = 0.0 if expected_new_infection_seed_test == 0.0 else 2e-2 * statistical_population_seed_test
            if math.fabs(new_infection_seed_test - expected_new_infection_seed_test) > tolerance_1:
                success = False
                outfile.write("BAD: At time step {0}, {1} reported new infections in Group 2_Seed_Test, expected {2}.\n".format(
                    timestep, new_infection_seed_test, expected_new_infection_seed_test))
            # test transmission blocking
            new_infection_seed_control = new_infections[0 + x * num_group]
            new_infection_control = new_infections[2 + x * num_group]
            new_infection_test = new_infections[3+ x * num_group]
            expected_new_infection_test = (1.0 - effect_t) * new_infection_control * new_infection_seed_test/float(new_infection_seed_control)
            statistical_population_test = statistical_populations[3]
            tolerance_2 = 0.0 if expected_new_infection_test == 0.0 else 2e-2 * statistical_population_test
            if math.fabs(new_infection_test - expected_new_infection_test) > tolerance_2:
                success = False
                outfile.write("BAD: At time step {0}, {1} reported new infections in Group 4_Test, expected {2}.\n".format(
                    timestep, new_infection_test, expected_new_infection_test))
            #test mortality blocking
            disease_death_seed_test = new_disease_deaths[1 + x * num_group]
            expected_disease_death_seed_test = new_infection_seed_test * (1.0 - effect_m)
            tolerance_3 = 0.0 if expected_disease_death_seed_test == 0.0 else 2e-2 * new_infection_seed_test
            if math.fabs(disease_death_seed_test - expected_disease_death_seed_test) > tolerance_3:
                success = False
                outfile.write("BAD: At time step {0}, {1} reported disease deaths in Group 2_Seed_Test, expected {2}.\n".format(
                    timestep, disease_death_seed_test, expected_disease_death_seed_test))
            timestep += Timesteps_Between_Repetitions
            effect_a = effect_a + (1.0 - effect_a) * Boost_Acquire
            effect_t = effect_t + (1.0 - effect_t) * Boost_Transmit
            effect_m = effect_m + (1.0 - effect_m) * Boost_Mortality
        outfile.write(sft.format_success_msg(success))
    sft.plot_data(new_infections,new_disease_deaths,
                           label1= "new_infections", label2 = "disease_death",
                           xlabel= "0&4:Seed_Control, 1&5:Seed_Test, 2&6:Control, 4&7:Test",
                           title = "new_infections vs. new_disease_death",
                           category = 'New_infections_vs_new_disease_death',show = True )
    if debug:
        print( "SUMMARY: Success={0}\n".format(success) )
    return success
Пример #49
0
def application(report_file, debug=False):
    sft.wait_for_done()

    cdj = json.loads(open("config.json").read())["parameters"]
    tcer = float(cdj["Typhoid_Contact_Exposure_Rate"])
    teer = float(cdj["Typhoid_Environmental_Exposure_Rate"])

    num_exposures_contact = []
    num_exposures_enviro = []
    with open("test.txt") as logfile:
        for line in logfile:
            if "Exposing " in line and "route 'environment'" in line:
                # collect # of exposures for route contact
                num_exp_e = int(sft.get_val("num_exposures=", line))
                num_exposures_enviro.append(num_exp_e)
            elif "Exposing " and "route 'contact'" in line:
                # collect # of exposures for route environment
                num_exp_c = int(sft.get_val("num_exposures=", line))
                num_exposures_contact.append(num_exp_c)

    success = True
    with open(sft.sft_output_filename, "w") as report_file:
        # report_file.write("len1={0}, len2={1}, teer = {2}, tcer = {3}.\n".format(len(num_exposures_enviro),
        # len(num_exposures_contact), teer, tcer))
        if not num_exposures_enviro:
            success = False
            report_file.write(
                "BAD: Found no individual exposed from route environment.\n")
        elif not sft.test_poisson(num_exposures_enviro, teer, report_file,
                                  'environment'):
            success = False
        if not num_exposures_contact:
            success = False
            report_file.write(
                "BAD: Found no individual exposed from route contact.\n")
        elif not sft.test_poisson(num_exposures_contact, tcer, report_file,
                                  'contact'):
            success = False
        report_file.write(
            "num_exposures_enviro = {0}, num_exposures_contact = {1}"
            "\n".format(len(num_exposures_enviro), len(num_exposures_contact)))

        # Write summary message to report file
        report_file.write(sft.format_success_msg(success))

        with open("error_larger_than_tolerance_log.txt", "w") as my_file:
            sft.plot_poisson_probability(
                teer,
                num_exposures_enviro,
                my_file,
                'environmental route',
                xlabel="Number of Exposures",
                ylabel="Probability",
                label2="Emod data",
                title="Poisson Probability Mass Funciton\n"
                "environmental route: Exposure_Rate = {}".format(teer))
            sft.plot_poisson_probability(
                tcer,
                num_exposures_contact,
                my_file,
                'contact route',
                xlabel="Number of Exposures",
                ylabel="Probability",
                label2="Emod data",
                title="Poisson Probability Mass Funciton\n"
                "contact route: Exposure_Rate = {}".format(tcer))
def create_report_file(param_obj, inset_chart_obj, report_name, insetchart_name, debug):
    with open(report_name, "w") as outfile:
        for param in param_obj:
            outfile.write("{0} = {1}\n".format(param, param_obj[param]))

        # base_infectivity = param_obj[ConfigKeys.Base_Infectivity]

        if param_obj[ConfigKeys.Enable_Heterogeneous_Intranode_Transmission] == 1:
            outfile.write("WARNING: {0} = {1}, expected this feature is disabled".format(
                ConfigKeys.Enable_Heterogeneous_Intranode_Transmission,
            param_obj[ConfigKeys.Enable_Heterogeneous_Intranode_Transmission]))

        success = True

        outfile.write("Test 1: Testing new infections for every time step:\n")
        duration = param_obj[ConfigKeys.Simulation_Duration]

        new_infection_list_c = []
        new_infection_list_e = []

        failed_count_c = failed_count_e = 0

        with open("DEBUG_binomial_test.txt", "w") as binomial_test_file:
            for t in range(duration):
                infected = inset_chart_obj[InsetKeys.ChannelsKeys.Infected][t]
                stat_pop = inset_chart_obj[InsetKeys.ChannelsKeys.Statistical_Population][t]
                susceptible = stat_pop * (1.0 - infected)

                contagion_e = inset_chart_obj[InsetKeys.ChannelsKeys.Environmental_Contagion_Population][t]
                contagion_c = inset_chart_obj[InsetKeys.ChannelsKeys.Contact_Contagion_Population][t]

                probability_e = 1.0 - math.exp(-1 * contagion_e)
                probability_c = 1.0 - math.exp(-1 * contagion_c)

                expected_new_infections_c = probability_c * susceptible
                actual_new_infection_c = inset_chart_obj[InsetKeys.ChannelsKeys.New_Infections_By_Route_CONTACT][t]
                if actual_new_infection_c > math.ceil(susceptible):
                    success = False
                    outfile.write("BAD: at time step {0} the {1} is {2} while calculated susceptible individual is"
                                  " {3}, {1} should be less than calculated susceptible individual, please check the "
                                  "test.\n".format(t, InsetKeys.ChannelsKeys.New_Infections_By_Route_CONTACT,
                                                   actual_new_infection_c, susceptible))

                susceptible_e = susceptible - actual_new_infection_c
                expected_new_infections_e = probability_e * susceptible_e
                actual_new_infection_e = inset_chart_obj[InsetKeys.ChannelsKeys.New_Infections_By_Route_ENVIRONMENT][t]
                if actual_new_infection_e > math.ceil(susceptible_e):
                    success = False
                    outfile.write("BAD: at time step {0} the {1} is {2} while calculated susceptible individual is"
                                  "{3}, {1} should be less than calculated susceptible individual, please check the "
                                  "test.\n".format(t, InsetKeys.ChannelsKeys.New_Infections_By_Route_ENVIRONMENT,
                                                   actual_new_infection_e, susceptible_e))

                new_infection_list_c.append([actual_new_infection_c, expected_new_infections_c])
                new_infection_list_e.append([actual_new_infection_e, expected_new_infections_e])

                failed_count_c = test_new_infections(expected_new_infections_c, actual_new_infection_c, susceptible,
                                                     probability_c, failed_count_c, routes[1],insetchart_name,
                                                     binomial_test_file, t)
                failed_count_e = test_new_infections(expected_new_infections_e, actual_new_infection_e, susceptible_e,
                                                     probability_e, failed_count_e, routes[0], insetchart_name,
                                                     binomial_test_file, t)

                # actual_total_new_infection = inset_chart_obj[InsetKeys.ChannelsKeys.New_Infections][t + 1]
                # new_infection_list.append(actaul_new_infection_c + actaul_new_infection_e)
                # if actaul_new_infection_c + actaul_new_infection_e != actual_total_new_infection:
                #     success = False
                #     outfile.write("BAD: at time step {0}, in {1} the {2} channel reports {3} new infections, while "
                #                   "{4} and {5} are {6} and {7} respectively.\n".format(
                #                     t + 1, insetchart_name, InsetKeys.ChannelsKeys.New_Infections,
                #                     actual_total_new_infection,
                #                     InsetKeys.ChannelsKeys.New_Infections_By_Route_ENVIRONMENT,
                #                     InsetKeys.ChannelsKeys.New_Infections_By_Route_CONTACT,
                #                     actaul_new_infection_e,
                #                     actaul_new_infection_c))

        message_template = "\t{0}: (route {1}) binomial test for new infections channel failed {2} times within {3} " \
                           "total timesteps, which is {4}% fail rate, test is {5}. Please see " \
                           "'DEBUG_binomial_test.txt' for details.\n"
        for failed_count, route in [(failed_count_e, routes[0]),
                                    (failed_count_c, routes[1])]:
            if failed_count / duration > 5e-2:
                success = False
                outfile.write(message_template.format("BAD", route,
                                                      failed_count, duration, (failed_count / duration) * 100,
                                                      "failed"))
            else:
                outfile.write(message_template.format("GOOD", route,
                                                      failed_count, duration, (failed_count / duration) * 100,
                                                      "passed"))
        # plot actual and expected values for new infections
        sft.plot_data(np.array(new_infection_list_c)[:, 0], np.array(new_infection_list_c)[:, 1],
                          label1=insetchart_name, label2="expected new infections",
                          title=InsetKeys.ChannelsKeys.New_Infections_By_Route_CONTACT,
                          xlabel='day', ylabel='new infections', category="new_infections_{}".format(routes[1]),
                          line=True, alpha=0.5, overlap=True)

        sft.plot_data(np.array(new_infection_list_e)[:, 0], np.array(new_infection_list_e)[:, 1],
                          label1=insetchart_name, label2="expected new infections",
                          title=InsetKeys.ChannelsKeys.New_Infections_By_Route_ENVIRONMENT,
                          xlabel='day', ylabel='new infections', category="new_infections_{}".format(routes[0]),
                          line=True, alpha=0.5, overlap=True)
        outfile.write("Test 1: result is {}.\n".format(success))

        outfile.write("Test 2: Testing sums of new infections by routes match expected values.\n")
        result = True
        message_template = "\t{0}: sum of {1} is {2}, it should be closed to expected value {3}.\n"
        for new_infection_list, channel_name in [(new_infection_list_c,
                                                  InsetKeys.ChannelsKeys.New_Infections_By_Route_CONTACT),
                                                 (new_infection_list_e,
                                                  InsetKeys.ChannelsKeys.New_Infections_By_Route_ENVIRONMENT)]:
            new_infection_sum = np.array(new_infection_list)[:, 0].sum()
            expected_new_infections_sum = np.array(new_infection_list)[:, 1].sum()
            if math.fabs(new_infection_sum - expected_new_infections_sum) > 5e-2 * expected_new_infections_sum:
                success = result = False
                outfile.write(message_template.format("BAD", channel_name, new_infection_sum,
                                                      expected_new_infections_sum))
            else:
                outfile.write(message_template.format("GOOD", channel_name, new_infection_sum,
                                                      expected_new_infections_sum))
        outfile.write("Test 2: result is {}.\n".format(result))

        outfile.write("Test 3: Testing if {0} = {1} + {2} in {3} for every time step.\n".format(
            InsetKeys.ChannelsKeys.New_Infections,
            InsetKeys.ChannelsKeys.New_Infections_By_Route_ENVIRONMENT,
            InsetKeys.ChannelsKeys.New_Infections_By_Route_CONTACT,
            insetchart_name
        ))
        result = True
        expected_new_infection_list = []
        # skip the first time step t = 0, when outbreak happens, this is OK for now, next step:
        # ToDO: load stdout.txt for outbreak new infections and add it to expected_total_new_infection
        for t in range(1, duration):
            actual_total_new_infection = inset_chart_obj[InsetKeys.ChannelsKeys.New_Infections][t]
            actaul_new_infection_c = inset_chart_obj[InsetKeys.ChannelsKeys.New_Infections_By_Route_CONTACT][t]
            actaul_new_infection_e = inset_chart_obj[InsetKeys.ChannelsKeys.New_Infections_By_Route_ENVIRONMENT][t]
            expected_total_new_infection = actaul_new_infection_c + actaul_new_infection_e
            expected_new_infection_list.append(expected_total_new_infection)
            if expected_total_new_infection != actual_total_new_infection:
                success = result = False
                outfile.write("\tBAD: at time step {0}, in {1} the {2} channel reports {3} new infections, while "
                              "{4} and {5} are {6} and {7} respectively.\n".format(
                    t + 1, insetchart_name, InsetKeys.ChannelsKeys.New_Infections,
                    actual_total_new_infection,
                    InsetKeys.ChannelsKeys.New_Infections_By_Route_ENVIRONMENT,
                    InsetKeys.ChannelsKeys.New_Infections_By_Route_CONTACT,
                    actaul_new_infection_e,
                    actaul_new_infection_c))

        outfile.write("Test 3: '{0} = {1} + {2}' is {3}.\n".format(
            InsetKeys.ChannelsKeys.New_Infections,
            InsetKeys.ChannelsKeys.New_Infections_By_Route_ENVIRONMENT,
            InsetKeys.ChannelsKeys.New_Infections_By_Route_CONTACT,
            result
        ))

        sft.plot_data(inset_chart_obj[InsetKeys.ChannelsKeys.New_Infections][1:], expected_new_infection_list,
                          label1=InsetKeys.ChannelsKeys.New_Infections, label2="{0} + \n{1}".format(
                                InsetKeys.ChannelsKeys.New_Infections_By_Route_CONTACT,
                                InsetKeys.ChannelsKeys.New_Infections_By_Route_ENVIRONMENT),
                          title="{0}_{1}".format(InsetKeys.ChannelsKeys.New_Infections, insetchart_name),
                          xlabel='day(t-1, skip the first time step)', ylabel='new infections', category="total_new_infections",
                          line=True, alpha=0.5, overlap=True)

        outfile.write(sft.format_success_msg(success))
    if debug:
        print(sft.format_success_msg(success))
    return success
Пример #51
0
def create_report_file(param_obj, output_dict, report_name, debug):
    with open(report_name, "w") as outfile:
        config_name = param_obj[KEY_CONFIG_NAME]
        outfile.write("Config_name = {}\n".format(config_name))
        success = True
        slow_progressor_rate = param_obj[KEY_SLOW_PROGRESSOR_RATE]
        latent_cure_rate = param_obj[KEY_LATENT_CURE_RATE]
        presymptomatic_cure_rate = param_obj[KEY_PRESYMPTOMATIC_CURE_RATE]
        presymptomatic_rate = param_obj[KEY_PRESYMPTOMATIC_RATE]
        base_infectivity = param_obj[KEY_BASE_INFECTIVITY]
        simulation_duration = param_obj[KEY_DURATION]
        if not len(output_dict):
            success = False
            outfile.write(sft.sft_no_test_data)

        outfile.write("checking test conditions: \n")
        dist_exponential_np_slow = np.random.exponential(
            1 / slow_progressor_rate, 100)
        if min(dist_exponential_np_slow) < simulation_duration:
            success = False
            outfile.write(
                "BAD: expected a small {0} to avoid moving individual to active disease state, got {1} from config.json. Please "
                "fix the test.\n".format(KEY_SLOW_PROGRESSOR_RATE,
                                         slow_progressor_rate))
        dist_exponential_np_latent_cure = np.random.exponential(
            1 / latent_cure_rate, 100)
        if min(dist_exponential_np_latent_cure) < simulation_duration:
            success = False
            outfile.write(
                "BAD: expected a small {0} to avoid Latent to Cleared state transition(all Latent state will progress to "
                "PreSymptomatic), got {1} from config.json. Please fix the test.\n"
                .format(KEY_LATENT_CURE_RATE, latent_cure_rate))
        dist_exponential_np_presymptomatic = np.random.exponential(
            1 / presymptomatic_rate, 100)
        if min(dist_exponential_np_presymptomatic) < simulation_duration:
            success = False
            outfile.write(
                "BAD: expected a small {0} to avoid PreSymptomatic to Symptomatic state transition(all PreSymptomatic "
                "state will progress to Cleared), got {1} from config.json. Please fix the test.\n"
                .format(KEY_PRESYMPTOMATIC_RATE, presymptomatic_rate))
        if base_infectivity:
            success = False
            outfile.write(
                "BAD: expected {0} = 0 to look only at progression, got {1} from config.json. Please fix"
                "the test.\n".format(KEY_BASE_INFECTIVITY, base_infectivity))
        outfile.write("conditional check result is {}.\n".format(success))

        actual_timer = []
        internal_timer = []
        outfile.write(
            "collecting the actual timestep between PreSymptomatic and Cleared:\n"
        )
        outfile.write(
            "checking if the internal timer matches the PreSymptomatic to Cleared duration:\n"
        )
        for id in output_dict:
            cleared_time = presymptomatic_time = timer = None
            if KEY_CLEARED in output_dict[id]:
                cleared_time = output_dict[id][KEY_CLEARED][0]
                timer = output_dict[id][KEY_CLEARED][1]
                internal_timer.append(timer)
            if KEY_PRESYMPTOMATIC in output_dict[id]:
                presymptomatic_time = output_dict[id][KEY_PRESYMPTOMATIC][0]
            if presymptomatic_time:
                if cleared_time:  # some individual may not move to cleared state at the end of the simulation
                    actual_timer.append(cleared_time - presymptomatic_time)
                    if cleared_time - presymptomatic_time != math.ceil(timer):
                        success = False
                        outfile.write(
                            "BAD: individual {0} has internal timer = {1} but the actual timer is {2} (enter "
                            "PreSymptomatic state at timestep {3}, moved to Cleared state at "
                            "timestep {4}).\n".format(
                                id, timer, cleared_time - presymptomatic_time,
                                presymptomatic_time, cleared_time))
                else:
                    outfile.write(
                        "Individual {0} moved to PreSymptomatic state at timestep {1} and is not cleared yet at the "
                        "end of simulation (duration = {2})."
                        "\n".format(id, presymptomatic_time,
                                    simulation_duration))
            else:
                success = False
                outfile.write(
                    "BAD: individual {0} moved to cleared state at timerstep {1} before entering "
                    "PreSymptomatic state.\n".format(id, cleared_time))

        if not len(actual_timer):
            success = False
            outfile.write(
                "BAD: There is no PreSymptomatic to cleared transition in this test, please fix the test.\n"
            )

        outfile.write(
            "Running ks test for PreSymptomatic to cleared internal timer and numpy exponential distribution: \n"
        )
        size = len(internal_timer)
        scale = 1.0 / presymptomatic_cure_rate
        dist_exponential_np = np.random.exponential(scale, size)
        sft.plot_data_sorted(
            internal_timer,
            dist2=np.array(dist_exponential_np),
            label1="PreSymptomatic to cleared duration",
            label2="numpy exponential",
            title="exponential rate = {}".format(presymptomatic_cure_rate),
            xlabel="data point",
            ylabel="PreSymptomatic to cleared duration",
            category='PreSymptomatic_to_cleared_duration',
            show=True,
            line=True,
            overlap=True)
        result = sft.test_exponential(internal_timer,
                                      p1=presymptomatic_cure_rate,
                                      report_file=outfile,
                                      integers=False,
                                      roundup=False,
                                      round_nearest=False)
        outfile.write(
            "ks test result is {0}, exponential rate = {1}, # of data point = {2}.\n"
            .format(result, presymptomatic_cure_rate, size))
        if not result:
            success = False
            outfile.write(
                "BAD: test exponential for PreSymptomatic to cleared duration failed with {0} "
                "= {1}.\n".format(KEY_PRESYMPTOMATIC_CURE_RATE,
                                  presymptomatic_cure_rate))
        else:
            outfile.write(
                "GOOD: test exponential for PreSymptomatic to cleared duration passed with {0} "
                "= {1}.\n".format(KEY_PRESYMPTOMATIC_CURE_RATE,
                                  presymptomatic_cure_rate))

        outfile.write(sft.format_success_msg(success))
    if debug:
        print("SUMMARY: Success={0}\n".format(success))
    return success
def create_report_file(report_data_obj, csv_df, report_name, debug):
    with open(report_name, "w") as outfile:
        success = True
        timestep = Outbreak_Start_Day
        effect = prime
        new_infections = []
        statistical_populations = []
        disease_deaths = []
        for i in range(len(PROPERTY_GROUP)):
            new_infection = report_data_obj[KEY_NEW_INFECTIONS_GROUP[i]][timestep]
            statistical_population = report_data_obj[KEY_STATISTICAL_POPULATION_GROUP[i]][timestep]
            # disease death in the last two groups happen 1 day later than the first two groups.
            disease_death = len(csv_df[(csv_df['Time'] == int(timestep + i / 2)) &
                                       (csv_df['QualityOfCare'] == PROPERTY_GROUP[i]) &
                                       (csv_df['Event_Name'] == 'DiseaseDeaths')])
            new_infections.append(new_infection)
            statistical_populations.append(statistical_population)
            disease_deaths.append(disease_death)
        # test acquisition blocking
        new_infection_seed_test = new_infections[1]
        statistical_population_seed_test = statistical_populations[1]
        expected_new_infection_seed_test = statistical_population_seed_test * (1.0 - effect)
        tolerance_1 = 0.0 if expected_new_infection_seed_test == 0.0 else 2e-2 * statistical_population_seed_test
        result_1 = f"At time step {timestep}, {new_infection_seed_test}" \
                   f" reported new infections in Group 2_Seed_Test, expected" \
                   f" {expected_new_infection_seed_test} with tolerance {tolerance_1}.\n"
        if math.fabs(new_infection_seed_test - expected_new_infection_seed_test) > tolerance_1:
            success = False
            outfile.write(f"BAD: {result_1}")
        else:            
            outfile.write(f"GOOD: {result_1}")
        # test transmission blocking
        new_infection_seed_control = new_infections[0]
        new_infection_control = new_infections[2]
        new_infection_test = new_infections[3]
        expected_new_infection_test = (1.0 - effect) * new_infection_control * new_infection_seed_test/float(new_infection_seed_control)
        statistical_population_test = statistical_populations[3]
        tolerance_2 = 0.0 if expected_new_infection_test == 0.0 else 2e-2 * statistical_population_test
        result_2 = f"At time step {timestep}, {new_infection_test} reported" \
                   f" disease deaths in Group 4_Test, expected" \
                   f" {expected_new_infection_test}, tolerance {tolerance_2}.\n"
        if math.fabs(new_infection_test - expected_new_infection_test) > tolerance_2:
            success = False
            outfile.write(f"BAD:  {result_2}")
        else:
            outfile.write(f"GOOD: {result_2}")
        #test mortality blocking
        disease_death_seed_test = disease_deaths[1]
        expected_disease_death_seed_test = new_infection_seed_test * (1.0 - effect)
        tolerance_3 = 0.0 if expected_disease_death_seed_test == 0.0 else 2e-2 * new_infection_seed_test
        result_3 = f"At time step {timestep}, {disease_death_seed_test} reported" \
                   f" disease deaths in Group 2_Seed_Test, expected" \
                   f" {expected_disease_death_seed_test}, tolerance {tolerance_3}.\n"
        if math.fabs(disease_death_seed_test - expected_disease_death_seed_test) > tolerance_3:
            success = False
            outfile.write(f"BAD:  {result_3}")
        else:
            outfile.write(f"GOOD: {result_3}")
        outfile.write(sft.format_success_msg(success))
    sft.plot_data(new_infections,disease_deaths,
                           label1= "new_infections", label2 = "disease_death",
                           xlabel= "0:1_Seed_Control, 1:2_Seed_Test, 2:3_Control, 4:3_Test",
                           title = "new_infections vs. disease_death",
                           category = 'New_infections_vs_disease_death',show = True )
    if debug:
        print( "SUMMARY: Success={0}\n".format(success) )
    return success