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 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(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(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 application(output_folder="output", config_filename="config.json", campaign_filename="campaign.json", demographics_filename="demographics_100_overlay.json", insetchart_name="InsetChart.json", report_name=sft.sft_output_filename, debug=False): if debug: print("output_folder: " + output_folder) print("config_filename: " + config_filename+"\n") print("campaign_filename: " + campaign_filename+"\n") print("demographics_filename: " + demographics_filename+"\n") print("insetchart_name: " + insetchart_name+"\n") print("report_name: " + report_name+"\n") print("debug: " + str(debug)+"\n") sft.wait_for_done() param_obj = ips.load_emod_parameters(config_filename, debug) campaign_obj = ips.load_campaign_file(param_obj[KEY_CAMPAIGN_NAME], debug) demographics_obj = ips.load_demographics_file(param_obj[KEY_DEMOGRAPHICS_NAME][-1], debug) report_data_obj = ips.parse_json_report(output_folder, insetchart_name, debug) sft.plot_data(report_data_obj[KEY_NEW_INFECTIONS], title="new infections", label1="New Infections", label2="NA", xlabel="time steps", ylabel="new infection", category='New_infections', show=True) sft.plot_data(report_data_obj[KEY_STATISTICAL_POPULATION], title="Statistical Population", label1="Statistical Population", label2="NA", xlabel="time steps", ylabel="Statistical Population", category='Statistical_population', show=True, line=True) ips.create_report_file(param_obj, campaign_obj, demographics_obj, report_data_obj, report_name, debug)
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 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
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 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, 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) # 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, 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, 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, inset_chart_obj, report_name, insetchart_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])) 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 for every time step:\n") duration = param_obj[ConfigKeys.Simulation_Duration] contagion_list_c = [] 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 # The Infected channel in InsetChart is normalized data calculated_contagion = base_infectivity * infected # / population # get contagion from insetchart file actual_contagion_c = inset_chart_obj[ InsetKeys.ChannelsKeys.Contact_Contagion_Population][t] 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 route {1}, the total contagion is {2}, " "expected {3}.\n".format(t, routes[1], actual_contagion_c, calculated_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.Contact_Contagion_Population, xlabel='day', ylabel='contagion', category="contagion_{}".format(routes[1]), 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, 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 = [] 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 sft_report_file.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])) 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 for each Routes 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]] for seed_group in seed_groups: # 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() ][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 ]] contagion_seed_e = property_df[[ c for c in seed_cols if channels[3] in c ]] contagion_seed_c = property_df[[ c for c in seed_cols if channels[4] 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_e = property_df[[ c for c in susceptible_cols if channels[1] in c ]] new_infection_sus_c = property_df[[ c for c in susceptible_cols if channels[2] in c ]] contagion_sus_e = property_df[[ c for c in susceptible_cols if channels[3] in c ]] contagion_sus_c = property_df[[ c for c in susceptible_cols if channels[4] in c ]] population_sus = property_df[[ c for c in susceptible_cols if channels[5] in c ]] expected_new_infection_list_e = [] expected_new_infection_list_c = [] contagion_list_e = [[contagion_sus_e.iloc[0][0], 0]] contagion_list_c = [[contagion_sus_c.iloc[0][0], 0]] failed_count_e = 0 failed_count_c = 0 with open( "DEBUG_binomial_test_{}.txt".format(susceptible_group), 'w') as group_file: for t in range(duration - 1): infectivity_seed = base_infectivity * infected_seed.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(seed_group)][ property_values.index(susceptible_group)] / population_sus.iloc[t][0] calculated_contagion_c = infectivity_seed * \ transmission_matrix_c[property_values.index(seed_group)][ property_values.index(susceptible_group)] / stat_pop[t] # get contagion of susceptible group from property report actual_contagion_e = contagion_sus_e.iloc[t + 1][0] actual_contagion_c = contagion_sus_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, susceptible_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, susceptible_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_sus.iloc[t][ 0] - infected_sus.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_sus_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_sus_e.iloc[t + 1][0] actual_new_infection_c = new_infection_sus_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, susceptible_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, susceptible_group, sft_report_file, susceptible_population_c, group_file) # make sure the seed group has no contagion to itself message_template = "{0}: (route {1}) contagion pool for seed group is {2}, expected 0 contagion, " \ "test is {3}.\n" for contagion_seed, route in [(contagion_seed_e, routes[0]), (contagion_seed_c, routes[1])]: contagion_sum = contagion_seed.values.sum() if contagion_sum: result_2 = success = False sft_report_file.write( message_template.format("BAD", route, contagion_sum, "failed")) else: sft_report_file.write( message_template.format("GOOD", route, contagion_sum, "passed")) 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_sus_e, routes[0]), (failed_count_c, new_infection_sus_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", susceptible_group)) else: sft_report_file.write( message_template.format( "GOOD", route, new_infection_sus.columns.values, failed_count, duration, (failed_count / duration) * 100, "passed", susceptible_group)) # check the total new infection # plot actual and expected values for contagion and new infeciton for each route 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_sus_e, expected_new_infection_list_e, routes[0]), (contagion_list_c, new_infection_sus_c, expected_new_infection_list_c, routes[1])]: if math.fabs(new_infection_sus.ix[1:, 0].sum() - sum(expected_new_infection_list)) > \ 5e-2 * sum(expected_new_infection_list): result_4 = success = False sft_report_file.write( message.format("BAD", route, susceptible_group, new_infection_sus.ix[1:, 0].sum(), sum(expected_new_infection_list))) else: sft_report_file.write( message.format("GOOD", route, susceptible_group, new_infection_sus.ix[1:, 0].sum(), sum(expected_new_infection_list))) 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, susceptible_group), xlabel='day', ylabel='contagion', category="contagion_{0}_{1}".format( susceptible_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, susceptible_group), xlabel='day', ylabel='new_infections', category="new_infections_{0}_{1}".format( susceptible_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(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(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] decay_rate = param_obj[ConfigKeys.Node_Contagion_Decay_Rate] outfile.write("Config_name = {}\n".format(config_name)) outfile.write("{0} = {1} {2} = {3}\n".format( ConfigKeys.Node_Contagion_Decay_Rate, decay_rate, ConfigKeys.Run_Number, param_obj[ConfigKeys.Run_Number])) success = True outfile.write( "Testing: Testing contagion and decay in each groups for every time step:\n" ) duration = param_obj[ConfigKeys.Simulation_Duration] transmission_matrix_e = property_obj[ DemographicsKeys.PropertyKeys.TransmissionMatrix][routes[0]] base_infectivity = param_obj[ConfigKeys.Base_Infectivity] groups = property_obj[DemographicsKeys.PropertyKeys.Values] contagion = [] for group in groups: outfile.write(" Testing group: {}.\n".format(group)) contagion_list_e = [] # 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_e = property_df[[c for c in cols if channels[3] 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]] pre_contagion = 0 for t in range(duration - 1): if t == 0: contagion_list_e.append([contagion_e.iloc[t][0], 0]) if contagion_e.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[0], contagion_e.iloc[t][0], 0)) infectivity = base_infectivity * infected.iloc[t][ 0] / population.iloc[t][0] infectivity_other = base_infectivity * infected_other.iloc[t][ 0] / population.iloc[t][0] # calculate contagion for environmental group new_contagion = infectivity * transmission_matrix_e[ groups.index(group)][groups.index( group)] + infectivity_other * transmission_matrix_e[ groups.index(other_group)][groups.index(group)] current_contagion = pre_contagion * ( 1 - decay_rate) + new_contagion # for next time step pre_contagion = current_contagion # get contagion from property report actual_contagion_e = contagion_e.iloc[t + 1][0] contagion_list_e.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 group {1} route {2}, the contagion is {3}, " "expected {4}.\n".format(t + 1, group, routes[0], actual_contagion_e, current_contagion)) contagion.append(contagion_list_e) # plot actual and expected values for contagion sft.plot_data(np.array(contagion_list_e)[:, 0], np.array(contagion_list_e)[:, 1], label1=property_report_name, label2="calculated contagion", title="contagion for group {0}\n route {1}".format( group, routes[0]), xlabel='day', ylabel='contagion', category="contagion_{0}_{1}".format( group, routes[0]), 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_e in contagion: total_contagion += contagion_list_e[t][0] total_contagion_list.append(total_contagion) insetchart_contagion = inset_chart_obj[ InsetKeys.ChannelsKeys.Environmental_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[0], insetchart_name, insetchart_contagion, total_contagion, property_report_name)) sft.plot_data( inset_chart_obj[ InsetKeys.ChannelsKeys.Environmental_Contagion_Population], total_contagion_list, label1=insetchart_name, label2="sum calculated from {}".format(property_report_name), title=InsetKeys.ChannelsKeys.Environmental_Contagion_Population, xlabel='day', ylabel='contagion', category=InsetKeys.ChannelsKeys.Environmental_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, 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, 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, output_df, report_df, report_name, debug): total_timesteps = int(param_obj[KEY_TOTAL_TIMESTEPS]) simulation_timestep = float(param_obj[KEY_SIMULATION_TIMESTEP]) base_infectivity = float(param_obj[KEY_BASE_INFECTIVITY]) amplitude = float(param_obj[KEY_AMPLITUDE]) phase = float(param_obj[KEY_PHASE]) infected = output_df[KEY_INFECTED] infectiousness = output_df[KEY_INFECTIOUSNESS] statpop = output_df[KEY_STAT_POP] new_infections = report_df[KEY_NEW_INFECTIONS] if debug: sft.plot_data( new_infections, label1="new infections", label2="NA", title="Phase: {0} day, amplitude: {1}, base_infectivity: {2}". format(phase, amplitude, base_infectivity), xlabel="Time_Step_{0}_Days".format(simulation_timestep), ylabel=None, category='New_infections', show=True, line=True) with open(report_name, "w") as outfile: expected_infectiousness = [] for index in range(len(infected)): infected_pop = int(infected[index]) expected_infectiousness.append( calculate_infectiousness(infected_pop, index, simulation_timestep, phase, base_infectivity, amplitude, debug)) success = True actual_infectiousness_all = [] calc_infectiousness_all = [] for index in range(len(infectiousness)): timestep = index * simulation_timestep actual_infectiousness = float(infectiousness[index]) calc_infectiousness = expected_infectiousness[index] / float( statpop[index]) actual_infectiousness_all.append(actual_infectiousness) calc_infectiousness_all.append(calc_infectiousness) tolerance = 0 if calc_infectiousness == 0 else 5e-2 * calc_infectiousness if math.fabs(actual_infectiousness - calc_infectiousness) > tolerance: success = False outfile.write( "BAD: actual infectiousness at time step {0} is {1}, expected {2}.\n" .format(timestep, actual_infectiousness, calc_infectiousness)) outfile.write(sft.format_success_msg(success)) sft.plot_data( actual_infectiousness_all, calc_infectiousness_all, label1="actual infectiousness", label2="calc infectiousness", title="Phase: {0} day, amplitude: {1}, base_infectivity: {2}".format( phase, amplitude, base_infectivity), xlabel="Time_Step_{0}_Days".format(simulation_timestep), ylabel="Infectiousness", category='Infectiousness', show=True, line=True) 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 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(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): sft.wait_for_done() regex = "immunity calculated as" lines = [] with open("test.txt") as logfile: for line in logfile: if re.search(regex, line): lines.append(line) cdj = json.loads(open("config.json").read())["parameters"] protection_per_infection = cdj["Typhoid_Protection_Per_Infection"] immunity_observed_data = [] immunity_predicted_data = [] immunity_based_on_infection_count = {} success = True 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(line.split()[8]) immunity_observed_data.append(immunity) infection_count = int((sft.get_val("_infection_count=", line)).rstrip('.')) immunity_predicted = float( format( math.pow(1 - protection_per_infection, infection_count), '0.6f')) immunity_predicted_data.append(immunity_predicted) if abs(immunity - immunity_predicted) > 1e-5: success = False report_file.write( "BAD: Immunity is {} instead of predicted {}\n".format( immunity, immunity_predicted)) if infection_count not in immunity_based_on_infection_count: immunity_based_on_infection_count[ infection_count] = immunity_predicted report_file.write(sft.format_success_msg(success)) sft.plot_data(immunity_observed_data, immunity_predicted_data, label1="Actual", label2="Expected", title="Immunity based on Infection Count, TPPI={0}" "".format(protection_per_infection), xlabel="Occurrence", ylabel="Immunity Level", category='immunity_based_on_infection_data', alpha=0.5, overlap=True, sort=True) # plot for Typhod spec: lists = sorted(immunity_based_on_infection_count.items() ) # sorted by key, return a list of tuples x, y = zip(*lists) # unpack a list of pairs into two tuples fig = plt.figure() plt.plot(x, y, "b*", markersize=6) plt.title("Immunity based on Infection Count, TPPI={0}".format( protection_per_infection)) plt.xlabel("Infection Count") plt.ylabel("Immunity") if sft.check_for_plotting(): plt.show() fig.savefig('immunity_based_on_infection_count.png')
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, 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) # Boxcar scaling boxcar_multiplier = Boxcar_Support.calculate_infectiousness( infected_pop=1, index=t, simulation_timestep=param_obj[ConfigKeys.Simulation_Timestep], start_time=param_obj[ ConfigKeys.Infectivity_Boxcar_Forcing_Start_Time], end_time=param_obj[ ConfigKeys.Infectivity_Boxcar_Forcing_End_Time], base_infectivity=1, amplitude=param_obj[ ConfigKeys.Infectivity_Boxcar_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 *= boxcar_multiplier expected_contagion_c = boxcar_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_Boxcar", 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_Boxcar", 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, 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, 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 == 0.05 for x in campaign_obj[CampaignKeys.Demographic_Coverage]): success = False outfile.write( "BAD: {} should be 0.05, please check campaign.json.\n". format(CampaignKeys.Demographic_Coverage)) expected_property_restrictions = [] test_groups = [] non_test_groups = [] for property_obj in property_list: property_values = property_obj[ DemographicsKeys.PropertyKeys.Values] test_groups.append(property_values[0]) non_test_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 = [] non_test_cols = [] for non_test_group in non_test_groups: non_test_cols += [ c for c in property_df.columns if non_test_group in c ] non_test_cols = list(set(non_test_cols)) # get all the column names that only contains the test group, which should be property_df.columns - non_test_groups test_only_cols = [ c for c in property_df.columns if c not in non_test_cols ] # test data for test groups infected_test = property_df[[ c for c in test_only_cols if hint_support.channels[0] in c ]] population_test = property_df[[ c for c in test_only_cols if hint_support.channels[2] in c ]] new_infection_test = property_df[[ c for c in test_only_cols if hint_support.channels[1] in c ]] expected_new_infection_list = [] failed_count = 0 for t in range(duration - 1): calculated_contagion = 0 for col in infected_test: # calculate infectivity of seed group # nomalized with total population infectivity_seed = base_infectivity * infected_test[ col].iloc[t] / stat_pop[t] infectivity_mod = 1 for i in range(len(test_groups)): test_group = test_groups[i] if test_group in col: for property_obj in property_list: property_values = property_obj[ DemographicsKeys.PropertyKeys.Values] if test_group in property_values: transmission_matrix = property_obj[ DemographicsKeys.PropertyKeys.Matrix] infectivity_mod *= transmission_matrix[ property_values.index(test_group)][ property_values.index(test_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 first element in all group_ids group_id = 0 # actual contagion is for next time step actual_contagion = stdout_df[ (stdout_df[ConfigKeys.Simulation_Timestep] == t + 1) & (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 + 1, test_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 + 1) & (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 + 1, test_group, group_id, actual_prob, calculated_prob)) # calculate expected new infection for test group susceptible_population = population_test.iloc[t][ 0] - infected_test.iloc[t][0] expected_new_infection = susceptible_population * calculated_prob expected_new_infection_list.append(expected_new_infection) actual_new_infection = new_infection_test.iloc[t + 1][0] with open("DEBUG_binomial_test_{}.txt".format(test_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 + 1, test_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(test_group, t + 1)): 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 + 1, test_group, actual_new_infection, lower_bound, upper_bound, expected_new_infection)) # make sure other groups has no new infections after outbreak new_infection_non_test = property_df[[ c for c in non_test_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_test: total_new_infection = new_infection_non_test.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 test group group_name = test_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_test.ix[1:, 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_test.columns.values, failed_count, duration, (failed_count / duration) * 100, "failed")) else: outfile.write( message_template.format("GOOD", new_infection_test.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