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
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
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))
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
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))
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
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
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]
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
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(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))
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))
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
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
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
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
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')
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
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)
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
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
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
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
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
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
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
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))
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
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
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