From 20a46d2e6f641763e96b80995218cf62324f05b1 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Tue, 11 Jan 2022 00:16:20 -0500 Subject: [PATCH 01/44] add age groups --- .../delphi_quidel_covidtest/constants.py | 10 ++ .../delphi_quidel_covidtest/data_tools.py | 3 +- .../generate_sensor.py | 53 ++++---- .../delphi_quidel_covidtest/geo_maps.py | 12 +- .../delphi_quidel_covidtest/pull.py | 56 ++++++++- .../delphi_quidel_covidtest/run.py | 113 ++++++++++-------- 6 files changed, 165 insertions(+), 82 deletions(-) diff --git a/quidel_covidtest/delphi_quidel_covidtest/constants.py b/quidel_covidtest/delphi_quidel_covidtest/constants.py index abe88c7b1..f99dca028 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/constants.py +++ b/quidel_covidtest/delphi_quidel_covidtest/constants.py @@ -39,3 +39,13 @@ # SMOOTHED_TEST_PER_DEVICE: (True, True), # RAW_TEST_PER_DEVICE: (True, False) } +AGE_GROUPS = [ + "total", + "age_0to5", + "age_5to13", + "age_14to17", + "age_18to49", + "age_50to64", + "age_65to74", + "age_75toOlder" +] diff --git a/quidel_covidtest/delphi_quidel_covidtest/data_tools.py b/quidel_covidtest/delphi_quidel_covidtest/data_tools.py index f89a353ed..fd346a080 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/data_tools.py +++ b/quidel_covidtest/delphi_quidel_covidtest/data_tools.py @@ -112,7 +112,8 @@ def _geographical_pooling(tpooled_tests, tpooled_ptests, min_obs): # Can't borrow more than total no. observations. # Relies on the fact that np.inf > 1 borrow_prop[borrow_prop > 1] = 1 - return borrow_prop + #TODO + return [0 for i in range(len(borrow_prop))] def raw_positive_prop(positives, tests, min_obs): diff --git a/quidel_covidtest/delphi_quidel_covidtest/generate_sensor.py b/quidel_covidtest/delphi_quidel_covidtest/generate_sensor.py index ba6b443c6..ae3304e02 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/generate_sensor.py +++ b/quidel_covidtest/delphi_quidel_covidtest/generate_sensor.py @@ -10,7 +10,8 @@ MIN_OBS = 50 # minimum number of observations in order to compute a proportion. POOL_DAYS = 7 -def generate_sensor_for_nonparent_geo(state_groups, res_key, smooth, device, first_date, last_date): +def generate_sensor_for_nonparent_geo(state_groups, res_key, smooth, device, + first_date, last_date, suffix): """ Fit over geo resolutions that don't use a parent state (nation/hhs/state). @@ -21,6 +22,8 @@ def generate_sensor_for_nonparent_geo(state_groups, res_key, smooth, device, fir Consider raw or smooth device: bool Consider test_per_device or pct_positive + suffix: str + Indicate the age group Returns: df: pd.DataFrame """ @@ -35,27 +38,27 @@ def generate_sensor_for_nonparent_geo(state_groups, res_key, smooth, device, fir # smoothed test per device if device & smooth: stat, se, sample_size = smoothed_tests_per_device( - devices=state_group["numUniqueDevices"].values, + devices=state_group["numUniqueDevices_%s"%suffix].values, tests=state_group['totalTest'].values, min_obs=MIN_OBS, pool_days=POOL_DAYS) # raw test per device elif device & (not smooth): stat, se, sample_size = raw_tests_per_device( - devices=state_group["numUniqueDevices"].values, + devices=state_group["numUniqueDevices_s"%suffix].values, tests=state_group['totalTest'].values, min_obs=MIN_OBS) # smoothed pct positive elif (not device) & smooth: stat, se, sample_size = smoothed_positive_prop( - tests=state_group['totalTest'].values, - positives=state_group['positiveTest'].values, + tests=state_group['totalTest_%s'%suffix].values, + positives=state_group['positiveTest_%s'%suffix].values, min_obs=MIN_OBS, pool_days=POOL_DAYS) stat = stat * 100 # raw pct positive else: stat, se, sample_size = raw_positive_prop( - tests=state_group['totalTest'].values, - positives=state_group['positiveTest'].values, + tests=state_group['totalTest_%s'%suffix].values, + positives=state_group['positiveTest_%s'%suffix].values, min_obs=MIN_OBS) stat = stat * 100 @@ -68,7 +71,7 @@ def generate_sensor_for_nonparent_geo(state_groups, res_key, smooth, device, fir return remove_null_samples(state_df) def generate_sensor_for_parent_geo(state_groups, data, res_key, smooth, - device, first_date, last_date): + device, first_date, last_date, suffix): """ Fit over geo resolutions that use a parent state (county/hrr/msa). @@ -79,6 +82,8 @@ def generate_sensor_for_parent_geo(state_groups, data, res_key, smooth, Consider raw or smooth device: bool Consider test_per_device or pct_positive + suffix: str + Indicate the age group Returns: df: pd.DataFrame """ @@ -104,41 +109,41 @@ def generate_sensor_for_parent_geo(state_groups, data, res_key, smooth, if has_parent: if device: stat, se, sample_size = smoothed_tests_per_device( - devices=res_group["numUniqueDevices"].values, - tests=res_group['totalTest'].values, + devices=res_group["numUniqueDevices_%s"%suffix].values, + tests=res_group['totalTest_%s'%suffix].values, min_obs=MIN_OBS, pool_days=POOL_DAYS, - parent_devices=res_group["numUniqueDevices_parent"].values, - parent_tests=res_group["totalTest_parent"].values) + parent_devices=res_group["numUniqueDevices_%s_parent"%suffix].values, + parent_tests=res_group["totalTest_%s_parent"%suffix].values) else: stat, se, sample_size = smoothed_positive_prop( - tests=res_group['totalTest'].values, - positives=res_group['positiveTest'].values, + tests=res_group['totalTest_%s'%suffix].values, + positives=res_group['positiveTest_%s'%suffix].values, min_obs=MIN_OBS, pool_days=POOL_DAYS, - parent_tests=res_group["totalTest_parent"].values, - parent_positives=res_group['positiveTest_parent'].values) + parent_tests=res_group["totalTest_%s_parent"%suffix].values, + parent_positives=res_group['positiveTest_%s_parent'%suffix].values) stat = stat * 100 else: if device: stat, se, sample_size = smoothed_tests_per_device( - devices=res_group["numUniqueDevices"].values, - tests=res_group['totalTest'].values, + devices=res_group["numUniqueDevices_%s"%suffix].values, + tests=res_group['totalTest_%s'%suffix].values, min_obs=MIN_OBS, pool_days=POOL_DAYS) else: stat, se, sample_size = smoothed_positive_prop( - tests=res_group['totalTest'].values, - positives=res_group['positiveTest'].values, + tests=res_group['totalTest_%s'%suffix].values, + positives=res_group['positiveTest_%s'%suffix].values, min_obs=MIN_OBS, pool_days=POOL_DAYS) stat = stat * 100 else: if device: stat, se, sample_size = raw_tests_per_device( - devices=res_group["numUniqueDevices"].values, - tests=res_group['totalTest'].values, + devices=res_group["numUniqueDevices_%s"%suffix].values, + tests=res_group['totalTest_%s'%suffix].values, min_obs=MIN_OBS) else: stat, se, sample_size = raw_positive_prop( - tests=res_group['totalTest'].values, - positives=res_group['positiveTest'].values, + tests=res_group['totalTest_%s'%suffix].values, + positives=res_group['positiveTest_%s'%suffix].values, min_obs=MIN_OBS) stat = stat * 100 diff --git a/quidel_covidtest/delphi_quidel_covidtest/geo_maps.py b/quidel_covidtest/delphi_quidel_covidtest/geo_maps.py index 7ebdcc834..33b7c4830 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/geo_maps.py +++ b/quidel_covidtest/delphi_quidel_covidtest/geo_maps.py @@ -13,14 +13,22 @@ } -def geo_map(geo_res, df): +def geo_map(geo_res, df, agegroup): """Map a geocode to a new value.""" data = df.copy() geo_key = GEO_KEY_DICT[geo_res] # Add population for each zipcode data = GMPR.add_population_column(data, "zip") # zip -> geo_res - data = GMPR.replace_geocode(data, "zip", geo_key, data_cols=DATA_COLS) + data_cols = [] + for data_col in DATA_COLS: + if data_col != "population": + data_cols.append("_".join([data_col, agegroup])) + else: + data_cols.append(data_col) + data = GMPR.replace_geocode( + data, from_code="zip", new_code=geo_key, date_col = "timestamp", + data_cols=data_cols) if geo_res in ["state", "hhs", "nation"]: return data, geo_key # Add parent state diff --git a/quidel_covidtest/delphi_quidel_covidtest/pull.py b/quidel_covidtest/delphi_quidel_covidtest/pull.py index 3efa9ed23..eb14b2f21 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/pull.py +++ b/quidel_covidtest/delphi_quidel_covidtest/pull.py @@ -163,21 +163,21 @@ def preprocess_new_data(start_date, end_date, params, test_mode, logger): overall_pos = df[df["OverallResult"] == "positive"].groupby( by=["timestamp", "zip"], as_index=False)['OverallResult'].count() - overall_pos["positiveTest"] = overall_pos["OverallResult"] + overall_pos["positiveTest_total"] = overall_pos["OverallResult"] overall_pos.drop(labels="OverallResult", axis="columns", inplace=True) # Compute overallTotal overall_total = df.groupby( by=["timestamp", "zip"], as_index=False)['OverallResult'].count() - overall_total["totalTest"] = overall_total["OverallResult"] + overall_total["totalTest_total"] = overall_total["OverallResult"] overall_total.drop(labels="OverallResult", axis="columns", inplace=True) # Compute numUniqueDevices numUniqueDevices = df.groupby( by=["timestamp", "zip"], as_index=False)["SofiaSerNum"].agg({"SofiaSerNum": "nunique"}).rename( - columns={"SofiaSerNum": "numUniqueDevices"} + columns={"SofiaSerNum": "numUniqueDevices_total"} ) df_merged = overall_total.merge( @@ -185,7 +185,55 @@ def preprocess_new_data(start_date, end_date, params, test_mode, logger): ).merge( overall_pos, on=["timestamp", "zip"], how="left" ).fillna(0).drop_duplicates() - + + # Compute Summary info for age groups + df["PatientAge"]= df["PatientAge"].fillna(-1) + df.loc[df["PatientAge"] == "<1", "PatientAge"] = 0.5 + df.loc[df["PatientAge"] == ">85", "PatientAge"] = 100 + df["PatientAge"] = df["PatientAge"] .astype(float) + + df["label"] = None + df.loc[df["PatientAge"] < 5, "label"] = "age_0to5" + df.loc[((df["PatientAge"] >= 5)) & (df["PatientAge"] < 14), "label"] = "age_5to13" + df.loc[((df["PatientAge"] >= 14)) & (df["PatientAge"] < 18), "label"] = "age_14to17" + df.loc[((df["PatientAge"] >= 18)) & (df["PatientAge"] < 50), "label"] = "age_18to49" + df.loc[((df["PatientAge"] >= 50)) & (df["PatientAge"] < 65), "label"] = "age_50to64" + df.loc[((df["PatientAge"] >= 65)) & (df["PatientAge"] < 75), "label"] = "age_65to74" + df.loc[df["PatientAge"] >= 75, "label"] = "age_75toOlder" + df.loc[df["PatientAge"] == -1, "label"] = "NA" + + for agegroup in df["label"].unique(): + if agegroup == "NA": + continue + # Compute overallPositive + group_pos = df.loc[(df["OverallResult"] == "positive") + & (df["label"] == agegroup)].groupby( + by=["timestamp", "zip"], + as_index=False)['OverallResult'].count() + group_pos["positiveTest_%s"%agegroup] = group_pos["OverallResult"] + group_pos.drop(labels="OverallResult", axis="columns", inplace=True) + + # Compute overallTotal + group_total = df.loc[df["label"] == agegroup].groupby( + by=["timestamp", "zip"], + as_index=False)['OverallResult'].count() + group_total["totalTest_%s"%agegroup] = group_total["OverallResult"] + group_total.drop(labels="OverallResult", axis="columns", inplace=True) + + # Compute numUniqueDevices + group_numUniqueDevices = df.loc[df["label"] == agegroup].groupby( + by=["timestamp", "zip"], + as_index=False)["SofiaSerNum"].agg({"SofiaSerNum": "nunique"}).rename( + columns={"SofiaSerNum": "numUniqueDevices_%s"%agegroup} + ) + + df_merged = df_merged.merge( + group_numUniqueDevices, on=["timestamp", "zip"], how="left" + ).merge( + group_pos, on=["timestamp", "zip"], how="left" + ).merge( + group_total, on=["timestamp", "zip"], how="left" + ).fillna(0).drop_duplicates() return df_merged, time_flag diff --git a/quidel_covidtest/delphi_quidel_covidtest/run.py b/quidel_covidtest/delphi_quidel_covidtest/run.py index 5f084440c..4ef95b795 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/run.py +++ b/quidel_covidtest/delphi_quidel_covidtest/run.py @@ -18,7 +18,8 @@ from .constants import (END_FROM_TODAY_MINUS, SMOOTHED_POSITIVE, RAW_POSITIVE, SMOOTHED_TEST_PER_DEVICE, RAW_TEST_PER_DEVICE, - PARENT_GEO_RESOLUTIONS, SENSORS, SMOOTHERS, NONPARENT_GEO_RESOLUTIONS) + PARENT_GEO_RESOLUTIONS, SENSORS, SMOOTHERS, NONPARENT_GEO_RESOLUTIONS, + AGE_GROUPS) from .generate_sensor import generate_sensor_for_parent_geo, generate_sensor_for_nonparent_geo from .geo_maps import geo_map from .pull import (pull_quidel_covidtest, @@ -80,65 +81,75 @@ def run_module(params: Dict[str, Any]): if _end_date is None: logger.info("The data is up-to-date. Currently, no new data to be ingested.") return - export_end_date = check_export_end_date(export_end_date, _end_date, - END_FROM_TODAY_MINUS) - export_start_date = check_export_start_date(export_start_date, - export_end_date, export_day_range) + export_end_date = check_export_end_date( + export_end_date, _end_date, END_FROM_TODAY_MINUS) + export_start_date = check_export_start_date( + export_start_date, export_end_date, export_day_range) first_date, last_date = df["timestamp"].min(), df["timestamp"].max() - # State Level data = df.copy() # Add prefix, if required sensors = add_prefix(SENSORS, wip_signal=params["indicator"]["wip_signal"], prefix="wip_") smoothers = SMOOTHERS.copy() - for geo_res in NONPARENT_GEO_RESOLUTIONS: - geo_data, res_key = geo_map(geo_res, data) - geo_groups = geo_data.groupby(res_key) - for sensor in sensors: - logger.info("Generating signal and exporting to CSV", - geo_res=geo_res, - sensor=sensor) - if sensor.endswith(SMOOTHED_POSITIVE): - smoothers[sensor] = smoothers.pop(SMOOTHED_POSITIVE) - elif sensor.endswith(RAW_POSITIVE): - smoothers[sensor] = smoothers.pop(RAW_POSITIVE) - elif sensor.endswith(SMOOTHED_TEST_PER_DEVICE): - smoothers[sensor] = smoothers.pop(SMOOTHED_TEST_PER_DEVICE) - else: - smoothers[sensor] = smoothers.pop(RAW_TEST_PER_DEVICE) - state_df = generate_sensor_for_nonparent_geo( - geo_groups, res_key, smooth=smoothers[sensor][1], - device=smoothers[sensor][0], first_date=first_date, - last_date=last_date) - dates = create_export_csv( - state_df, - geo_res=geo_res, - sensor=sensor, - export_dir=export_dir, - start_date=export_start_date, - end_date=export_end_date) - if len(dates) > 0: - stats.append((max(dates), len(dates))) - - # County/HRR/MSA level - for geo_res in PARENT_GEO_RESOLUTIONS: - geo_data, res_key = geo_map(geo_res, data) - for sensor in sensors: - logger.info("Generating signal and exporting to CSV", - geo_res=geo_res, - sensor=sensor) - res_df = generate_sensor_for_parent_geo( - geo_groups, geo_data, res_key, smooth=smoothers[sensor][1], - device=smoothers[sensor][0], first_date=first_date, - last_date=last_date) - dates = create_export_csv(res_df, geo_res=geo_res, sensor=sensor, export_dir=export_dir, - start_date=export_start_date, end_date=export_end_date, - remove_null_samples=True) - if len(dates) > 0: - stats.append((max(dates), len(dates))) + for agegroup in AGE_GROUPS: + for geo_res in ["state"]:#NONPARENT_GEO_RESOLUTIONS: + geo_data, res_key = geo_map(geo_res, data, agegroup) + geo_groups = geo_data.groupby(res_key) + # for sensor in sensors: + # if agegroup == "total": + # sensor_name = sensor + # else: + # sensor_name = "_".join([sensor, agegroup]) + # logger.info("Generating signal and exporting to CSV", + # geo_res=geo_res, + # sensor=sensor) + # if sensor.endswith(SMOOTHED_POSITIVE): + # smoothers[sensor] = smoothers.pop(SMOOTHED_POSITIVE) + # elif sensor.endswith(RAW_POSITIVE): + # smoothers[sensor] = smoothers.pop(RAW_POSITIVE) + # elif sensor.endswith(SMOOTHED_TEST_PER_DEVICE): + # smoothers[sensor] = smoothers.pop(SMOOTHED_TEST_PER_DEVICE) + # else: + # smoothers[sensor] = smoothers.pop(RAW_TEST_PER_DEVICE) + # state_df = generate_sensor_for_nonparent_geo( + # geo_groups, res_key, smooth=smoothers[sensor][1], + # device=smoothers[sensor][0], first_date=first_date, + # last_date=last_date, suffix=agegroup) + # dates = create_export_csv( + # state_df, + # geo_res=geo_res, + # sensor=sensor_name, + # export_dir=export_dir, + # start_date=export_start_date, + # end_date=export_end_date) + # if len(dates) > 0: + # stats.append((max(dates), len(dates))) + + # County/HRR/MSA level + for geo_res in ["county"]:#PARENT_GEO_RESOLUTIONS: + geo_data, res_key = geo_map(geo_res, data, agegroup) + for sensor in sensors: + if agegroup == "total": + sensor_name = sensor + else: + sensor_name = "_".join([sensor, agegroup]) + logger.info("Generating signal and exporting to CSV", + geo_res=geo_res, + sensor=sensor) + res_df = generate_sensor_for_parent_geo( + geo_groups, geo_data, res_key, smooth=smoothers[sensor][1], + device=smoothers[sensor][0], first_date=first_date, + last_date=last_date, suffix=agegroup) + dates = create_export_csv(res_df, geo_res=geo_res, + sensor=sensor_name, export_dir=export_dir, + start_date=export_start_date, + end_date=export_end_date, + remove_null_samples=True) + if len(dates) > 0: + stats.append((max(dates), len(dates))) # Export the cache file if the pipeline runs successfully. # Otherwise, don't update the cache file From 801e2f5a131906d6e61858d4a4613b7a83d4eacb Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Fri, 14 Jan 2022 01:41:27 -0500 Subject: [PATCH 02/44] update code for adding megacounties --- .../delphi_quidel_covidtest/constants.py | 15 ++-- .../delphi_quidel_covidtest/data_tools.py | 3 +- .../generate_sensor.py | 54 +++++++------ .../delphi_quidel_covidtest/geo_maps.py | 45 ++++++++--- .../delphi_quidel_covidtest/pull.py | 19 +++-- .../delphi_quidel_covidtest/run.py | 81 ++++++++++--------- 6 files changed, 122 insertions(+), 95 deletions(-) diff --git a/quidel_covidtest/delphi_quidel_covidtest/constants.py b/quidel_covidtest/delphi_quidel_covidtest/constants.py index f99dca028..af67aa788 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/constants.py +++ b/quidel_covidtest/delphi_quidel_covidtest/constants.py @@ -3,7 +3,7 @@ MIN_OBS = 50 # minimum number of observations in order to compute a proportion. POOL_DAYS = 7 # number of days in the past (including today) to pool over END_FROM_TODAY_MINUS = 5 # report data until - X days -# Signal names +# Signal Types SMOOTHED_POSITIVE = "covid_ag_smoothed_pct_positive" RAW_POSITIVE = "covid_ag_raw_pct_positive" SMOOTHED_TEST_PER_DEVICE = "covid_ag_smoothed_test_per_device" @@ -22,6 +22,7 @@ HRR, ] +# state should be last one NONPARENT_GEO_RESOLUTIONS = [ HHS, NATION, @@ -41,11 +42,9 @@ } AGE_GROUPS = [ "total", - "age_0to5", - "age_5to13", - "age_14to17", - "age_18to49", - "age_50to64", - "age_65to74", - "age_75toOlder" + "age_0to4", + "age_5to17", + "age_18to49", + "age_50to64", + "age_65toOlder" ] diff --git a/quidel_covidtest/delphi_quidel_covidtest/data_tools.py b/quidel_covidtest/delphi_quidel_covidtest/data_tools.py index fd346a080..f89a353ed 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/data_tools.py +++ b/quidel_covidtest/delphi_quidel_covidtest/data_tools.py @@ -112,8 +112,7 @@ def _geographical_pooling(tpooled_tests, tpooled_ptests, min_obs): # Can't borrow more than total no. observations. # Relies on the fact that np.inf > 1 borrow_prop[borrow_prop > 1] = 1 - #TODO - return [0 for i in range(len(borrow_prop))] + return borrow_prop def raw_positive_prop(positives, tests, min_obs): diff --git a/quidel_covidtest/delphi_quidel_covidtest/generate_sensor.py b/quidel_covidtest/delphi_quidel_covidtest/generate_sensor.py index ae3304e02..f43ed3071 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/generate_sensor.py +++ b/quidel_covidtest/delphi_quidel_covidtest/generate_sensor.py @@ -6,9 +6,9 @@ smoothed_tests_per_device, raw_tests_per_device, remove_null_samples) +from .geo_maps import add_megacounties -MIN_OBS = 50 # minimum number of observations in order to compute a proportion. -POOL_DAYS = 7 +from .constants import (MIN_OBS, POOL_DAYS) def generate_sensor_for_nonparent_geo(state_groups, res_key, smooth, device, first_date, last_date, suffix): @@ -38,27 +38,27 @@ def generate_sensor_for_nonparent_geo(state_groups, res_key, smooth, device, # smoothed test per device if device & smooth: stat, se, sample_size = smoothed_tests_per_device( - devices=state_group["numUniqueDevices_%s"%suffix].values, - tests=state_group['totalTest'].values, + devices=state_group[f"numUniqueDevices_{suffix}"].values, + tests=state_group[f'totalTest_{suffix}'].values, min_obs=MIN_OBS, pool_days=POOL_DAYS) # raw test per device elif device & (not smooth): stat, se, sample_size = raw_tests_per_device( - devices=state_group["numUniqueDevices_s"%suffix].values, - tests=state_group['totalTest'].values, + devices=state_group[f"numUniqueDevices_{suffix}"].values, + tests=state_group[f'totalTest_{suffix}'].values, min_obs=MIN_OBS) # smoothed pct positive elif (not device) & smooth: stat, se, sample_size = smoothed_positive_prop( - tests=state_group['totalTest_%s'%suffix].values, - positives=state_group['positiveTest_%s'%suffix].values, + tests=state_group[f'totalTest_{suffix}'].values, + positives=state_group[f'positiveTest_{suffix}'].values, min_obs=MIN_OBS, pool_days=POOL_DAYS) stat = stat * 100 # raw pct positive else: stat, se, sample_size = raw_positive_prop( - tests=state_group['totalTest_%s'%suffix].values, - positives=state_group['positiveTest_%s'%suffix].values, + tests=state_group[f'totalTest_{suffix}'].values, + positives=state_group[f'positiveTest_{suffix}'].values, min_obs=MIN_OBS) stat = stat * 100 @@ -89,6 +89,8 @@ def generate_sensor_for_parent_geo(state_groups, data, res_key, smooth, """ has_parent = True res_df = pd.DataFrame(columns=["geo_id", "val", "se", "sample_size"]) + if res_key == "fips": # Add rest-of-state report for county level + data = add_megacounties(data, smooth) res_groups = data.groupby(res_key) loc_list = list(res_groups.groups.keys()) for loc in loc_list: @@ -109,41 +111,41 @@ def generate_sensor_for_parent_geo(state_groups, data, res_key, smooth, if has_parent: if device: stat, se, sample_size = smoothed_tests_per_device( - devices=res_group["numUniqueDevices_%s"%suffix].values, - tests=res_group['totalTest_%s'%suffix].values, + devices=res_group[f"numUniqueDevices_{suffix}"].values, + tests=res_group[f'totalTest_{suffix}'].values, min_obs=MIN_OBS, pool_days=POOL_DAYS, - parent_devices=res_group["numUniqueDevices_%s_parent"%suffix].values, - parent_tests=res_group["totalTest_%s_parent"%suffix].values) + parent_devices=res_group[f"numUniqueDevices_{suffix}_parent"].values, + parent_tests=res_group[f"totalTest_{suffix}_parent"].values) else: stat, se, sample_size = smoothed_positive_prop( - tests=res_group['totalTest_%s'%suffix].values, - positives=res_group['positiveTest_%s'%suffix].values, + tests=res_group[f'totalTest_{suffix}'].values, + positives=res_group[f'positiveTest_{suffix}'].values, min_obs=MIN_OBS, pool_days=POOL_DAYS, - parent_tests=res_group["totalTest_%s_parent"%suffix].values, - parent_positives=res_group['positiveTest_%s_parent'%suffix].values) + parent_tests=res_group[f"totalTest_{suffix}_parent"].values, + parent_positives=res_group[f'positiveTest_{suffix}_parent'].values) stat = stat * 100 else: if device: stat, se, sample_size = smoothed_tests_per_device( - devices=res_group["numUniqueDevices_%s"%suffix].values, - tests=res_group['totalTest_%s'%suffix].values, + devices=res_group[f"numUniqueDevices_{suffix}"].values, + tests=res_group[f'totalTest_{suffix}'].values, min_obs=MIN_OBS, pool_days=POOL_DAYS) else: stat, se, sample_size = smoothed_positive_prop( - tests=res_group['totalTest_%s'%suffix].values, - positives=res_group['positiveTest_%s'%suffix].values, + tests=res_group[f'totalTest_{suffix}'].values, + positives=res_group[f'positiveTest_{suffix}'].values, min_obs=MIN_OBS, pool_days=POOL_DAYS) stat = stat * 100 else: if device: stat, se, sample_size = raw_tests_per_device( - devices=res_group["numUniqueDevices_%s"%suffix].values, - tests=res_group['totalTest_%s'%suffix].values, + devices=res_group[f"numUniqueDevices_{suffix}"].values, + tests=res_group[f'totalTest_{suffix}'].values, min_obs=MIN_OBS) else: stat, se, sample_size = raw_positive_prop( - tests=res_group['totalTest_%s'%suffix].values, - positives=res_group['positiveTest_%s'%suffix].values, + tests=res_group[f'totalTest_{suffix}'].values, + positives=res_group[f'positiveTest_{suffix}'].values, min_obs=MIN_OBS) stat = stat * 100 diff --git a/quidel_covidtest/delphi_quidel_covidtest/geo_maps.py b/quidel_covidtest/delphi_quidel_covidtest/geo_maps.py index 33b7c4830..20ebde1c2 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/geo_maps.py +++ b/quidel_covidtest/delphi_quidel_covidtest/geo_maps.py @@ -1,7 +1,13 @@ """Contains geographic mapping tools.""" +from itertools import product +from functools import reduce + +import pandas as pd + from delphi_utils import GeoMapper +from .constants import (AGE_GROUPS, MIN_OBS) -DATA_COLS = ['totalTest', 'numUniqueDevices', 'positiveTest', "population"] +DATA_COLS = ['totalTest', 'numUniqueDevices', 'positiveTest'] GMPR = GeoMapper() # Use geo utils GEO_KEY_DICT = { "county": "fips", @@ -12,8 +18,7 @@ "hhs": "hhs" } - -def geo_map(geo_res, df, agegroup): +def geo_map(geo_res, df): """Map a geocode to a new value.""" data = df.copy() geo_key = GEO_KEY_DICT[geo_res] @@ -21,20 +26,42 @@ def geo_map(geo_res, df, agegroup): data = GMPR.add_population_column(data, "zip") # zip -> geo_res data_cols = [] - for data_col in DATA_COLS: - if data_col != "population": - data_cols.append("_".join([data_col, agegroup])) - else: - data_cols.append(data_col) + for col, agegroup in product(DATA_COLS, AGE_GROUPS): + data_cols.append("_".join([col, agegroup])) + data = GMPR.replace_geocode( data, from_code="zip", new_code=geo_key, date_col = "timestamp", - data_cols=data_cols) + data_cols=data_cols+["population"]) if geo_res in ["state", "hhs", "nation"]: return data, geo_key # Add parent state data = add_parent_state(data, geo_res, geo_key) return data, geo_key +def add_megacounties(data, smooth=False): + """Add megacounties to county level report.""" + assert "fips" in data.columns # Make sure the data is at county level + + # For raw signals, the threshold is MIN_OBS + # For raw signals, the threshold is MIN_OBS/2 + if smooth: + threshold_visits = MIN_OBS/2 + else: + threshold_visits = MIN_OBS + pdList = [] + for agegroup in AGE_GROUPS: + data_cols = [f"{col}_{agegroup}" for col in DATA_COLS] + df = GMPR.fips_to_megacounty(data[data_cols + ["timestamp", "fips"]], + threshold_visits, 1, fips_col="fips", + thr_col=f"totalTest_{agegroup}", + date_col="timestamp") + df.rename({"megafips": "fips"}, axis=1, inplace=True) + megacounties = df[df.fips.str.endswith("000")] + pdList.append(megacounties) + mega_df = reduce(lambda x, y: pd.merge( + x, y, on = ["timestamp", "fips"]), pdList) + + return pd.concat([data, mega_df]) def add_parent_state(data, geo_res, geo_key): """ diff --git a/quidel_covidtest/delphi_quidel_covidtest/pull.py b/quidel_covidtest/delphi_quidel_covidtest/pull.py index eb14b2f21..beb37bbb0 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/pull.py +++ b/quidel_covidtest/delphi_quidel_covidtest/pull.py @@ -185,23 +185,22 @@ def preprocess_new_data(start_date, end_date, params, test_mode, logger): ).merge( overall_pos, on=["timestamp", "zip"], how="left" ).fillna(0).drop_duplicates() - + # Compute Summary info for age groups df["PatientAge"]= df["PatientAge"].fillna(-1) df.loc[df["PatientAge"] == "<1", "PatientAge"] = 0.5 df.loc[df["PatientAge"] == ">85", "PatientAge"] = 100 df["PatientAge"] = df["PatientAge"] .astype(float) + # Should match the suffixes of signal names df["label"] = None - df.loc[df["PatientAge"] < 5, "label"] = "age_0to5" - df.loc[((df["PatientAge"] >= 5)) & (df["PatientAge"] < 14), "label"] = "age_5to13" - df.loc[((df["PatientAge"] >= 14)) & (df["PatientAge"] < 18), "label"] = "age_14to17" + df.loc[df["PatientAge"] < 5, "label"] = "age_0to4" + df.loc[((df["PatientAge"] >= 5)) & (df["PatientAge"] < 18), "label"] = "age_5to17" df.loc[((df["PatientAge"] >= 18)) & (df["PatientAge"] < 50), "label"] = "age_18to49" df.loc[((df["PatientAge"] >= 50)) & (df["PatientAge"] < 65), "label"] = "age_50to64" - df.loc[((df["PatientAge"] >= 65)) & (df["PatientAge"] < 75), "label"] = "age_65to74" - df.loc[df["PatientAge"] >= 75, "label"] = "age_75toOlder" + df.loc[(df["PatientAge"] >= 65), "label"] = "age_65toOlder" df.loc[df["PatientAge"] == -1, "label"] = "NA" - + for agegroup in df["label"].unique(): if agegroup == "NA": continue @@ -212,21 +211,21 @@ def preprocess_new_data(start_date, end_date, params, test_mode, logger): as_index=False)['OverallResult'].count() group_pos["positiveTest_%s"%agegroup] = group_pos["OverallResult"] group_pos.drop(labels="OverallResult", axis="columns", inplace=True) - + # Compute overallTotal group_total = df.loc[df["label"] == agegroup].groupby( by=["timestamp", "zip"], as_index=False)['OverallResult'].count() group_total["totalTest_%s"%agegroup] = group_total["OverallResult"] group_total.drop(labels="OverallResult", axis="columns", inplace=True) - + # Compute numUniqueDevices group_numUniqueDevices = df.loc[df["label"] == agegroup].groupby( by=["timestamp", "zip"], as_index=False)["SofiaSerNum"].agg({"SofiaSerNum": "nunique"}).rename( columns={"SofiaSerNum": "numUniqueDevices_%s"%agegroup} ) - + df_merged = df_merged.merge( group_numUniqueDevices, on=["timestamp", "zip"], how="left" ).merge( diff --git a/quidel_covidtest/delphi_quidel_covidtest/run.py b/quidel_covidtest/delphi_quidel_covidtest/run.py index 4ef95b795..7ff61f9c7 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/run.py +++ b/quidel_covidtest/delphi_quidel_covidtest/run.py @@ -94,43 +94,10 @@ def run_module(params: Dict[str, Any]): wip_signal=params["indicator"]["wip_signal"], prefix="wip_") smoothers = SMOOTHERS.copy() - for agegroup in AGE_GROUPS: - for geo_res in ["state"]:#NONPARENT_GEO_RESOLUTIONS: - geo_data, res_key = geo_map(geo_res, data, agegroup) - geo_groups = geo_data.groupby(res_key) - # for sensor in sensors: - # if agegroup == "total": - # sensor_name = sensor - # else: - # sensor_name = "_".join([sensor, agegroup]) - # logger.info("Generating signal and exporting to CSV", - # geo_res=geo_res, - # sensor=sensor) - # if sensor.endswith(SMOOTHED_POSITIVE): - # smoothers[sensor] = smoothers.pop(SMOOTHED_POSITIVE) - # elif sensor.endswith(RAW_POSITIVE): - # smoothers[sensor] = smoothers.pop(RAW_POSITIVE) - # elif sensor.endswith(SMOOTHED_TEST_PER_DEVICE): - # smoothers[sensor] = smoothers.pop(SMOOTHED_TEST_PER_DEVICE) - # else: - # smoothers[sensor] = smoothers.pop(RAW_TEST_PER_DEVICE) - # state_df = generate_sensor_for_nonparent_geo( - # geo_groups, res_key, smooth=smoothers[sensor][1], - # device=smoothers[sensor][0], first_date=first_date, - # last_date=last_date, suffix=agegroup) - # dates = create_export_csv( - # state_df, - # geo_res=geo_res, - # sensor=sensor_name, - # export_dir=export_dir, - # start_date=export_start_date, - # end_date=export_end_date) - # if len(dates) > 0: - # stats.append((max(dates), len(dates))) - - # County/HRR/MSA level - for geo_res in ["county"]:#PARENT_GEO_RESOLUTIONS: - geo_data, res_key = geo_map(geo_res, data, agegroup) + for geo_res in NONPARENT_GEO_RESOLUTIONS: + geo_data, res_key = geo_map(geo_res, data) + geo_groups = geo_data.groupby(res_key) + for agegroup in AGE_GROUPS: for sensor in sensors: if agegroup == "total": sensor_name = sensor @@ -138,14 +105,48 @@ def run_module(params: Dict[str, Any]): sensor_name = "_".join([sensor, agegroup]) logger.info("Generating signal and exporting to CSV", geo_res=geo_res, - sensor=sensor) + sensor=sensor_name) + if sensor.endswith(SMOOTHED_POSITIVE): + smoothers[sensor] = smoothers.pop(SMOOTHED_POSITIVE) + elif sensor.endswith(RAW_POSITIVE): + smoothers[sensor] = smoothers.pop(RAW_POSITIVE) + elif sensor.endswith(SMOOTHED_TEST_PER_DEVICE): + smoothers[sensor] = smoothers.pop(SMOOTHED_TEST_PER_DEVICE) + else: + smoothers[sensor] = smoothers.pop(RAW_TEST_PER_DEVICE) + state_df = generate_sensor_for_nonparent_geo( + geo_groups, res_key, smooth=smoothers[sensor][1], + device=smoothers[sensor][0], first_date=first_date, + last_date=last_date, suffix=agegroup) + dates = create_export_csv( + state_df, + geo_res=geo_res, + sensor=sensor_name, + export_dir=export_dir, + start_date=export_start_date, + end_date=export_end_date) + if len(dates) > 0: + stats.append((max(dates), len(dates))) + + # County/HRR/MSA level + for geo_res in PARENT_GEO_RESOLUTIONS: + geo_data, res_key = geo_map(geo_res, data) + for agegroup in AGE_GROUPS: + for sensor in sensors: + if agegroup == "total": + sensor_name = sensor + else: + sensor_name = "_".join([sensor, agegroup]) + logger.info("Generating signal and exporting to CSV", + geo_res=geo_res, + sensor=sensor_name) res_df = generate_sensor_for_parent_geo( geo_groups, geo_data, res_key, smooth=smoothers[sensor][1], device=smoothers[sensor][0], first_date=first_date, last_date=last_date, suffix=agegroup) - dates = create_export_csv(res_df, geo_res=geo_res, + dates = create_export_csv(res_df, geo_res=geo_res, sensor=sensor_name, export_dir=export_dir, - start_date=export_start_date, + start_date=export_start_date, end_date=export_end_date, remove_null_samples=True) if len(dates) > 0: From 15f7690e69881f661abd065946c6ed969e831bf7 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Fri, 14 Jan 2022 01:42:19 -0500 Subject: [PATCH 03/44] update unit tests --- quidel_covidtest/tests/test_data/msa_data.csv | 2 +- .../tests/test_data/state_data.csv | 2 +- .../tests/test_data/test_data.csv | 850 +++++++++--------- .../tests/test_generate_sensor.py | 16 +- quidel_covidtest/tests/test_geo_maps.py | 130 ++- quidel_covidtest/tests/test_pull.py | 7 +- 6 files changed, 538 insertions(+), 469 deletions(-) diff --git a/quidel_covidtest/tests/test_data/msa_data.csv b/quidel_covidtest/tests/test_data/msa_data.csv index 39593b937..8ff61dd69 100644 --- a/quidel_covidtest/tests/test_data/msa_data.csv +++ b/quidel_covidtest/tests/test_data/msa_data.csv @@ -1,4 +1,4 @@ -timestamp,cbsa_id,state_id,totalTest,numUniqueDevices,positiveTest +timestamp,cbsa_id,state_id,totalTest_total,numUniqueDevices_total,positiveTest_total 2020-06-14,10580,ny,1,1,0.0 2020-06-14,11100,tx,5,2,0.0 2020-06-14,12020,ga,8,1,0.0 diff --git a/quidel_covidtest/tests/test_data/state_data.csv b/quidel_covidtest/tests/test_data/state_data.csv index 6326c60d3..38e22141c 100644 --- a/quidel_covidtest/tests/test_data/state_data.csv +++ b/quidel_covidtest/tests/test_data/state_data.csv @@ -1,4 +1,4 @@ -timestamp,state_id,totalTest,numUniqueDevices,positiveTest +timestamp,state_id,totalTest_total,numUniqueDevices_total,positiveTest_total 2020-06-14,al,6,2,1.0 2020-06-14,ar,4,1,1.0 2020-06-14,ca,53,6,2.0 diff --git a/quidel_covidtest/tests/test_data/test_data.csv b/quidel_covidtest/tests/test_data/test_data.csv index 8b9d18c4f..f3bdeadc5 100644 --- a/quidel_covidtest/tests/test_data/test_data.csv +++ b/quidel_covidtest/tests/test_data/test_data.csv @@ -1,425 +1,425 @@ -SofiaSerNum,TestDate,Facility,City,State,Zip,PatientAge,Result1,Result2,OverallResult,County,FacilityType,Assay,SCO1,SCO2,CLN,CSN,InstrType,StorageDate,ResultId,SarsTestNumber -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,invalid,,invalid,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,invalid,,invalid,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,positive,,positive,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,positive,,positive,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,positive,,positive,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,positive,,positive,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,positive,,positive,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,positive,,positive,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,positive,,positive,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,positive,,positive,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,,positive,,positive,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,,negative,,negative,,,,,,,,,8/17/20,, -4,7/20/20,,McLean,VA,22101,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/21/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -5,7/21/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -6,7/22/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -6,7/22/20,,Tampa,FL,33625,,positive,,positive,,,,,,,,,8/17/20,, -6,7/22/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -6,7/22/20,,Tampa,FL,33625,,positive,,positive,,,,,,,,,8/17/20,, -6,7/22/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -6,7/22/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -6,7/22/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -6,7/22/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -7,7/22/20,,Columbia,SC,29229,,negative,,negative,,,,,,,,,8/17/20,, -8,7/22/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -8,7/22/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -8,7/22/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -8,7/22/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -8,7/22/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -8,7/22/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -8,7/22/20,,Lorton,VA,22079,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,positive,,positive,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,positive,,positive,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,positive,,positive,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,positive,,positive,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,positive,,positive,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,,negative,,negative,,,,,,,,,8/17/20,, \ No newline at end of file +SofiaSerNum,TestDate,Facility,City,State,Zip,PatientAge,Result1,Result2,OverallResult,County,FacilityType,Assay,SCO1,SCO2,CLN,CSN,InstrType,StorageDate,ResultId,SarsTestNumber +1,7/18/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,23,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,27,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,13,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,68,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,56,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,82,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,6,invalid,,invalid,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,13,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,82,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,71,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,53,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,32,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,4,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,47,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,47,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,78,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,31,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,35,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,55,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,Lorton,VA,22079,16,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,83,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,39,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,9,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,13,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,77,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,35,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,7,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,76,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,28,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,34,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,13,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,52,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,34,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,61,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,31,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,67,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,13,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,75,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,58,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,29,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,60,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,22,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,15,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,41,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,43,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,81,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,75,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,40,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,82,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,59,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,45,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,25,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,59,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,46,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,84,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,33,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,24,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,17,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,78,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,4,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,70,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,43,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,55,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,9,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,22,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,46,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,66,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,36,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,46,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,70,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,51,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,5,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,22,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,12,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,71,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,39,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,49,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,75,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,79,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,84,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,72,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,10,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,54,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,31,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,67,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,49,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,1,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,78,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,56,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,5,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,73,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,36,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,66,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,38,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,11,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,42,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,24,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,10,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,74,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,59,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,11,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,77,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,51,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,72,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,62,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,31,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,19,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,8,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,30,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,30,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,62,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,82,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,5,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,20,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,8,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,18,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,34,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,25,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,17,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,16,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,39,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,17,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,20,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,79,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,83,invalid,,invalid,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,27,positive,,positive,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,33,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,55,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,39,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,14,positive,,positive,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,57,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,5,positive,,positive,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,45,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,44,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,83,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,38,positive,,positive,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,39,positive,,positive,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,58,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,9,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,48,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,32,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,77,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,26,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,50,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,64,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,40,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,8,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,55,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,11,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,7,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,53,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,38,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,19,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,82,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,22,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,50,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,45,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,52,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,39,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,51,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,73,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,28,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,2,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,35,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,70,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,12,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,7,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,37,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,80,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,8,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,43,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,3,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,70,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,57,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,38,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,29,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,1,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,2,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,>85,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,22,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,40,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,59,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,70,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,25,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,74,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,41,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,71,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,29,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,54,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,39,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,15,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,48,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,77,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,12,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,18,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,59,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,38,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,1,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,73,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,52,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,3,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,30,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,40,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,77,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,56,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,75,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,73,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,2,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,9,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,44,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,70,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,54,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,14,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,78,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,80,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,56,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,31,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,76,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,84,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,69,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,79,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,42,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,22,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,72,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,54,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,59,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,63,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,80,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,66,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,23,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,61,positive,,positive,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,46,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,37,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,57,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,70,negative,,negative,,,,,,,,,8/17/20,, +4,7/20/20,,McLean,VA,22101,73,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,<1,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,54,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,62,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,71,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,16,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,51,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,63,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,66,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,24,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,9,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,2,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,44,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,72,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,31,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,59,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,<1,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,25,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,69,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,23,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,44,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,51,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,37,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,1,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,80,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,49,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,45,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,16,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,16,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,80,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,18,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,65,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,76,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,76,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,77,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,29,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,26,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,36,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,17,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,80,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,61,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,16,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,79,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,1,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,42,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,60,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,62,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,52,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,2,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,53,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,41,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,66,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,72,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,77,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,38,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,77,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,46,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,42,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,42,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,12,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,75,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,82,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,9,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,58,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,80,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,58,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,84,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,67,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,19,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,54,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,68,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,1,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,48,negative,,negative,,,,,,,,,8/17/20,, +5,7/21/20,,Lorton,VA,22079,2,negative,,negative,,,,,,,,,8/17/20,, +5,7/21/20,,Lorton,VA,22079,29,negative,,negative,,,,,,,,,8/17/20,, +6,7/22/20,,Tampa,FL,33625,20,negative,,negative,,,,,,,,,8/17/20,, +6,7/22/20,,Tampa,FL,33625,68,positive,,positive,,,,,,,,,8/17/20,, +6,7/22/20,,Tampa,FL,33625,>85,negative,,negative,,,,,,,,,8/17/20,, +6,7/22/20,,Tampa,FL,33625,46,positive,,positive,,,,,,,,,8/17/20,, +6,7/22/20,,Tampa,FL,33625,19,negative,,negative,,,,,,,,,8/17/20,, +6,7/22/20,,Tampa,FL,33625,26,negative,,negative,,,,,,,,,8/17/20,, +6,7/22/20,,Tampa,FL,33625,56,negative,,negative,,,,,,,,,8/17/20,, +6,7/22/20,,Tampa,FL,33625,53,negative,,negative,,,,,,,,,8/17/20,, +7,7/22/20,,Columbia,SC,29229,>85,negative,,negative,,,,,,,,,8/17/20,, +8,7/22/20,,Lorton,VA,22079,69,negative,,negative,,,,,,,,,8/17/20,, +8,7/22/20,,Lorton,VA,22079,76,negative,,negative,,,,,,,,,8/17/20,, +8,7/22/20,,Lorton,VA,22079,58,negative,,negative,,,,,,,,,8/17/20,, +8,7/22/20,,Lorton,VA,22079,66,negative,,negative,,,,,,,,,8/17/20,, +8,7/22/20,,Lorton,VA,22079,19,negative,,negative,,,,,,,,,8/17/20,, +8,7/22/20,,Lorton,VA,22079,70,negative,,negative,,,,,,,,,8/17/20,, +8,7/22/20,,Lorton,VA,22079,50,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,14,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,38,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,72,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,5,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,17,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,35,positive,,positive,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,85,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,47,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,62,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,74,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,4,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,60,positive,,positive,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,81,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,7,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,>85,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,>85,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,66,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,55,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,82,positive,,positive,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,29,positive,,positive,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,25,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,83,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,5,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,>85,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,>85,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,77,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,58,positive,,positive,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,6,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,36,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,24,negative,,negative,,,,,,,,,8/17/20,, diff --git a/quidel_covidtest/tests/test_generate_sensor.py b/quidel_covidtest/tests/test_generate_sensor.py index 0b34919c6..0ef82de83 100644 --- a/quidel_covidtest/tests/test_generate_sensor.py +++ b/quidel_covidtest/tests/test_generate_sensor.py @@ -21,7 +21,9 @@ def test_generate_sensor(self): # raw pct_positive state_pct_positive = generate_sensor_for_nonparent_geo( state_groups, "state_id", smooth = False, device = False, - first_date = datetime(2020, 6, 14), last_date = datetime(2020, 6, 20)) + first_date = datetime(2020, 6, 14), + last_date = datetime(2020, 6, 20), + suffix="total") assert (state_pct_positive.dropna()["val"] < 100).all() assert set(state_pct_positive.columns) ==\ @@ -31,7 +33,9 @@ def test_generate_sensor(self): # raw test_per_device state_test_per_device = generate_sensor_for_nonparent_geo( state_groups, "state_id", smooth = False, device = True, - first_date = datetime(2020, 6, 14), last_date = datetime(2020, 6, 20)) + first_date = datetime(2020, 6, 14), + last_date = datetime(2020, 6, 20), + suffix="total") assert state_test_per_device["se"].isnull().all() assert set(state_test_per_device.columns) ==\ @@ -45,7 +49,9 @@ def test_generate_sensor(self): parse_dates=['timestamp']) msa_pct_positive = generate_sensor_for_parent_geo( state_groups, msa_data, "cbsa_id", smooth = True, device = False, - first_date = datetime(2020, 6, 14), last_date = datetime(2020, 6, 20)) + first_date = datetime(2020, 6, 14), + last_date = datetime(2020, 6, 20), + suffix="total") assert (msa_pct_positive.dropna()["val"] < 100).all() assert set(msa_pct_positive.columns) ==\ @@ -55,7 +61,9 @@ def test_generate_sensor(self): # smoothed test_per_device msa_test_per_device = generate_sensor_for_parent_geo( state_groups, msa_data, "cbsa_id", smooth = True, device = True, - first_date = datetime(2020, 6, 14), last_date = datetime(2020, 6, 20)) + first_date = datetime(2020, 6, 14), + last_date = datetime(2020, 6, 20), + suffix="total") assert msa_test_per_device["se"].isnull().all() assert set(msa_test_per_device.columns) ==\ diff --git a/quidel_covidtest/tests/test_geo_maps.py b/quidel_covidtest/tests/test_geo_maps.py index eb1be3796..fae6933bc 100644 --- a/quidel_covidtest/tests/test_geo_maps.py +++ b/quidel_covidtest/tests/test_geo_maps.py @@ -1,29 +1,52 @@ +from datetime import datetime + import pandas as pd -from delphi_quidel_covidtest.geo_maps import geo_map +from delphi_quidel_covidtest.geo_maps import geo_map, add_megacounties +from delphi_quidel_covidtest.constants import AGE_GROUPS +DATA_COLS = ['totalTest', 'numUniqueDevices', 'positiveTest'] class TestGeoMap: def test_county(self): df = pd.DataFrame( { - "zip": [1607, 1740, 98661, 76010, 76012, 76016], - "timestamp": ["2020-06-15", "2020-06-15", "2020-06-15", - "2020-06-15", "2020-06-15", "2020-06-15"], - "totalTest": [100, 50, 200, 200, 250, 500], - "positiveTest": [10, 8, 15, 5, 20, 50], - "numUniqueDevices": [2, 1, 1, 1, 1, 1] + "zip": [1607, 1740, 1001, 1003, 98661, 76010, 76012, 76016], + "timestamp": ["2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15", + "2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15"], + "totalTest_total": [10, 16, 10, 15, 20, 200, 250, 500], + "positiveTest_total": [6, 8, 6, 8, 5, 5, 20, 50], + "numUniqueDevices_total": [2, 1, 2, 1, 1, 1, 1, 1], } ) + + for agegroup in AGE_GROUPS[1:]: + df[f"totalTest_{agegroup}"] = [2, 3, 2, 2, 4, 40, 20, 25] + df[f"positiveTest_{agegroup}"] = [1, 1, 1, 1, 1, 1, 3, 8] + df[f"numUniqueDevices_{agegroup}"] = [2, 1, 2, 1, 1, 1, 1, 1] new_df, res_key = geo_map("county", df) assert res_key == 'fips' - assert set(new_df["fips"].values) == set(['25027', '53011', '48439']) + assert set(new_df["fips"].values) == set(['25027', '25013', '25015', '53011', '48439']) assert set(new_df["timestamp"].values) == set(df["timestamp"].values) - assert set(new_df["totalTest"].values) == set([150, 200, 950]) - assert set(new_df["positiveTest"].values) == set([18, 15, 75]) + assert set(new_df["totalTest_total"].values) == set([26, 10, 15, 20, 950]) + assert set(new_df["positiveTest_total"].values) == set([14, 6, 8, 5, 75]) + + assert set(new_df["totalTest_age_0to4"].values) == set([5, 2, 2, 85, 4]) + assert set(new_df["positiveTest_age_0to4"].values) == set([2, 1, 1, 12, 1]) + + # Test Megacounties + new_df["timestamp"] = [datetime.strptime(x, "%Y-%m-%d") for x in new_df["timestamp"]] + mega_df = add_megacounties(new_df, True) + + assert set(mega_df["totalTest_total"].values) == set([26, 10, 15, 20, 950, 25, 20]) + assert set(mega_df["positiveTest_total"].values) == set([14, 6, 8, 5, 75, 14, 5]) + + assert set(mega_df["totalTest_age_0to4"].values) == set([5, 2, 2, 85, 4, 4, 9, 4]) + assert set(mega_df["positiveTest_age_0to4"].values) == set([2, 1, 1, 12, 1, 4, 1]) + def test_state(self): @@ -32,18 +55,25 @@ def test_state(self): "zip": [1607, 1740, 98661, 76010, 76012, 76016], "timestamp": ["2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15"], - "totalTest": [100, 50, 200, 200, 250, 500], - "positiveTest": [10, 8, 15, 5, 20, 50], - "numUniqueDevices": [2, 1, 1, 1, 1, 1] + "totalTest_total": [100, 50, 200, 200, 250, 500], + "positiveTest_total": [10, 8, 15, 5, 20, 50], + "numUniqueDevices_total": [2, 1, 1, 1, 1, 1] } - ) + ) + for agegroup in AGE_GROUPS[1:]: + df[f"totalTest_{agegroup}"] = [20, 10, 20, 40, 20, 25] + df[f"positiveTest_{agegroup}"] = [2, 1, 3, 1, 3, 8] + df[f"numUniqueDevices_{agegroup}"] = [2, 1, 1, 1, 1, 1] new_df, res_key = geo_map("state", df) assert set(new_df["state_id"].values) == set(['ma', 'tx', 'wa']) assert set(new_df["timestamp"].values) == set(df["timestamp"].values) - assert set(new_df["totalTest"].values) == set([150, 200, 950]) - assert set(new_df["positiveTest"].values) == set([18, 15, 75]) + assert set(new_df["totalTest_total"].values) == set([150, 200, 950]) + assert set(new_df["positiveTest_total"].values) == set([18, 15, 75]) + + assert set(new_df["totalTest_age_0to4"].values) == set([30, 85, 20]) + assert set(new_df["positiveTest_age_0to4"].values) == set([3, 12, 3]) def test_hrr(self): @@ -52,18 +82,25 @@ def test_hrr(self): "zip": [1607, 98661, 76010, 76012, 74435, 74936], "timestamp": ["2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15"], - "totalTest": [100, 50, 200, 200, 250, 500], - "positiveTest": [10, 8, 15, 5, 20, 50], - "numUniqueDevices": [2, 1, 1, 1, 1, 1] + "totalTest_total": [100, 50, 200, 200, 250, 500], + "positiveTest_total": [10, 8, 15, 5, 20, 50], + "numUniqueDevices_total": [2, 1, 1, 1, 1, 1] } ) + for agegroup in AGE_GROUPS[1:]: + df[f"totalTest_{agegroup}"] = [20, 10, 20, 40, 20, 25] + df[f"positiveTest_{agegroup}"] = [2, 1, 3, 1, 3, 8] + df[f"numUniqueDevices_{agegroup}"] = [2, 1, 1, 1, 1, 1] new_df, _ = geo_map("hrr", df) assert set(new_df["hrr"].values) == set(["16", "231", "340", "344", "394"]) assert set(new_df["timestamp"].values) == set(df["timestamp"].values) - assert set(new_df["totalTest"].values) == set([500, 100, 250, 50, 400]) - assert set(new_df["positiveTest"].values) == set([50, 10, 20, 8, 20]) + assert set(new_df["totalTest_total"].values) == set([500, 100, 250, 50, 400]) + assert set(new_df["positiveTest_total"].values) == set([50, 10, 20, 8, 20]) + + assert set(new_df["totalTest_age_0to4"].values) == set([25, 20 ,20, 10, 60]) + assert set(new_df["positiveTest_age_0to4"].values) == set([8, 2, 3, 1, 4]) def test_msa(self): @@ -72,18 +109,25 @@ def test_msa(self): "zip": [1607, 73716, 73719, 76010, 74945, 74936], "timestamp": ["2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15"], - "totalTest": [100, 50, 200, 200, 250, 500], - "positiveTest": [10, 8, 15, 5, 20, 50], - "numUniqueDevices": [2, 1, 1, 1, 1, 1] + "totalTest_total": [100, 50, 200, 200, 250, 500], + "positiveTest_total": [10, 8, 15, 5, 20, 50], + "numUniqueDevices_total": [2, 1, 1, 1, 1, 1] } ) + for agegroup in AGE_GROUPS[1:]: + df[f"totalTest_{agegroup}"] = [20, 10, 20, 40, 20, 25] + df[f"positiveTest_{agegroup}"] = [2, 1, 3, 1, 3, 8] + df[f"numUniqueDevices_{agegroup}"] = [2, 1, 1, 1, 1, 1] new_df, res_key = geo_map("msa", df) assert set(new_df["msa"].values) == set(['19100', '22900', '49340']) assert set(new_df["timestamp"].values) == set(df["timestamp"].values) - assert set(new_df["totalTest"].values) == set([200, 750, 100]) - assert set(new_df["positiveTest"].values) == set([5, 70, 10]) + assert set(new_df["totalTest_total"].values) == set([200, 750, 100]) + assert set(new_df["positiveTest_total"].values) == set([5, 70, 10]) + + assert set(new_df["totalTest_age_0to4"].values) == set([40, 45, 20]) + assert set(new_df["positiveTest_age_0to4"].values) == set([1, 11, 2]) def test_nation(self): df = pd.DataFrame( @@ -91,18 +135,25 @@ def test_nation(self): "zip": [1607, 73716, 73719, 76010, 74945, 74936], "timestamp": ["2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15"], - "totalTest": [100, 50, 200, 200, 250, 500], - "positiveTest": [10, 8, 15, 5, 20, 50], - "numUniqueDevices": [2, 1, 1, 1, 1, 1] + "totalTest_total": [100, 50, 200, 200, 250, 500], + "positiveTest_total": [10, 8, 15, 5, 20, 50], + "numUniqueDevices_total": [2, 1, 1, 1, 1, 1] } ) + for agegroup in AGE_GROUPS[1:]: + df[f"totalTest_{agegroup}"] = [20, 10, 20, 40, 20, 25] + df[f"positiveTest_{agegroup}"] = [2, 1, 3, 1, 3, 8] + df[f"numUniqueDevices_{agegroup}"] = [2, 1, 1, 1, 1, 1] new_df, res_key = geo_map("nation", df) assert set(new_df["nation"].values) == set(["us"]) assert set(new_df["timestamp"].values) == set(df["timestamp"].values) - assert set(new_df["totalTest"].values) == set([1300]) - assert set(new_df["positiveTest"].values) == set([108]) + assert set(new_df["totalTest_total"].values) == set([1300]) + assert set(new_df["positiveTest_total"].values) == set([108]) + + assert set(new_df["totalTest_age_0to4"].values) == set([135]) + assert set(new_df["positiveTest_age_0to4"].values) == set([18]) def test_hhs(self): df = pd.DataFrame( @@ -110,15 +161,22 @@ def test_hhs(self): "zip": [1607, 1740, 98661, 76010, 76012, 76016], "timestamp": ["2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15", "2020-06-15"], - "totalTest": [100, 50, 200, 200, 250, 500], - "positiveTest": [10, 8, 15, 5, 20, 50], - "numUniqueDevices": [2, 1, 1, 1, 1, 1] + "totalTest_total": [100, 50, 200, 200, 250, 500], + "positiveTest_total": [10, 8, 15, 5, 20, 50], + "numUniqueDevices_total": [2, 1, 1, 1, 1, 1] } ) + for agegroup in AGE_GROUPS[1:]: + df[f"totalTest_{agegroup}"] = [20, 10, 20, 40, 20, 25] + df[f"positiveTest_{agegroup}"] = [2, 1, 3, 1, 3, 8] + df[f"numUniqueDevices_{agegroup}"] = [2, 1, 1, 1, 1, 1] new_df, res_key = geo_map("hhs", df) assert set(new_df["hhs"].values) == set(["1", "6", "10"]) assert set(new_df["timestamp"].values) == set(df["timestamp"].values) - assert set(new_df["totalTest"].values) == set([150, 200, 950]) - assert set(new_df["positiveTest"].values) == set([18, 15, 75]) + assert set(new_df["totalTest_total"].values) == set([150, 200, 950]) + assert set(new_df["positiveTest_total"].values) == set([18, 15, 75]) + + assert set(new_df["totalTest_age_0to4"].values) == set([30, 20, 85]) + assert set(new_df["positiveTest_age_0to4"].values) == set([3, 3, 12]) diff --git a/quidel_covidtest/tests/test_pull.py b/quidel_covidtest/tests/test_pull.py index 17ddbb6fd..ae35fc68f 100644 --- a/quidel_covidtest/tests/test_pull.py +++ b/quidel_covidtest/tests/test_pull.py @@ -11,6 +11,7 @@ check_export_end_date, check_export_start_date ) +from delphi_quidel_covidtest.constants import AGE_GROUPS END_FROM_TODAY_MINUS = 5 EXPORT_DAY_RANGE = 40 @@ -60,8 +61,10 @@ def test_pull_quidel_covidtest(self): assert [first_date.month, first_date.day] == [7, 18] assert [last_date.month, last_date.day] == [7, 23] - assert (df.columns ==\ - ['timestamp', 'zip', 'totalTest', 'numUniqueDevices', 'positiveTest']).all() + assert set(['timestamp', 'zip']).issubset(set(df.columns)) + for agegroup in AGE_GROUPS: + set([f'totalTest_{agegroup}', f'numUniqueDevices_{agegroup}', + f'positiveTest_{agegroup}']).issubset(set(df.columns)) def test_check_intermediate_file(self): From 010491dfcec5772136e7134f7567e4f293a672e6 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Fri, 14 Jan 2022 09:56:45 -0500 Subject: [PATCH 04/44] get smoothers out of the complicated loop --- .../delphi_quidel_covidtest/run.py | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/quidel_covidtest/delphi_quidel_covidtest/run.py b/quidel_covidtest/delphi_quidel_covidtest/run.py index 7ff61f9c7..c224b22a1 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/run.py +++ b/quidel_covidtest/delphi_quidel_covidtest/run.py @@ -40,6 +40,20 @@ def log_exit(start_time, stats, logger): csv_export_count = csv_export_count, max_lag_in_days = max_lag_in_days, oldest_final_export_date = formatted_min_max_date) + +def get_smooth_info(sensors, SMOOTHERS): + """Get smooth info from SMOOTHERS. """ + smoothers = SMOOTHERS.copy() + for sensor in sensors: + if sensor.endswith(SMOOTHED_POSITIVE): + smoothers[sensor] = smoothers.pop(SMOOTHED_POSITIVE) + elif sensor.endswith(RAW_POSITIVE): + smoothers[sensor] = smoothers.pop(RAW_POSITIVE) + elif sensor.endswith(SMOOTHED_TEST_PER_DEVICE): + smoothers[sensor] = smoothers.pop(SMOOTHED_TEST_PER_DEVICE) + else: + smoothers[sensor] = smoothers.pop(RAW_TEST_PER_DEVICE) + return smoothers def run_module(params: Dict[str, Any]): """Run the quidel_covidtest indicator. @@ -92,8 +106,8 @@ def run_module(params: Dict[str, Any]): # Add prefix, if required sensors = add_prefix(SENSORS, wip_signal=params["indicator"]["wip_signal"], - prefix="wip_") - smoothers = SMOOTHERS.copy() + prefix="wip_") + smoothers = get_smooth_info(sensors, SMOOTHERS) for geo_res in NONPARENT_GEO_RESOLUTIONS: geo_data, res_key = geo_map(geo_res, data) geo_groups = geo_data.groupby(res_key) @@ -106,14 +120,6 @@ def run_module(params: Dict[str, Any]): logger.info("Generating signal and exporting to CSV", geo_res=geo_res, sensor=sensor_name) - if sensor.endswith(SMOOTHED_POSITIVE): - smoothers[sensor] = smoothers.pop(SMOOTHED_POSITIVE) - elif sensor.endswith(RAW_POSITIVE): - smoothers[sensor] = smoothers.pop(RAW_POSITIVE) - elif sensor.endswith(SMOOTHED_TEST_PER_DEVICE): - smoothers[sensor] = smoothers.pop(SMOOTHED_TEST_PER_DEVICE) - else: - smoothers[sensor] = smoothers.pop(RAW_TEST_PER_DEVICE) state_df = generate_sensor_for_nonparent_geo( geo_groups, res_key, smooth=smoothers[sensor][1], device=smoothers[sensor][0], first_date=first_date, From d215d6c8e906d19d20a1d13fb1ca26b8a9cc41bb Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Fri, 14 Jan 2022 09:58:42 -0500 Subject: [PATCH 05/44] fix a linting --- quidel_covidtest/delphi_quidel_covidtest/run.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/quidel_covidtest/delphi_quidel_covidtest/run.py b/quidel_covidtest/delphi_quidel_covidtest/run.py index c224b22a1..57550d674 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/run.py +++ b/quidel_covidtest/delphi_quidel_covidtest/run.py @@ -40,16 +40,16 @@ def log_exit(start_time, stats, logger): csv_export_count = csv_export_count, max_lag_in_days = max_lag_in_days, oldest_final_export_date = formatted_min_max_date) - -def get_smooth_info(sensors, SMOOTHERS): + +def get_smooth_info(sensors, _SMOOTHERS): """Get smooth info from SMOOTHERS. """ - smoothers = SMOOTHERS.copy() + smoothers = _SMOOTHERS.copy() for sensor in sensors: - if sensor.endswith(SMOOTHED_POSITIVE): - smoothers[sensor] = smoothers.pop(SMOOTHED_POSITIVE) + if sensor.endswith(_SMOOTHED_POSITIVE): + smoothers[sensor] = smoothers.pop(_SMOOTHED_POSITIVE) elif sensor.endswith(RAW_POSITIVE): smoothers[sensor] = smoothers.pop(RAW_POSITIVE) - elif sensor.endswith(SMOOTHED_TEST_PER_DEVICE): + elif sensor.endswith(_SMOOTHED_TEST_PER_DEVICE): smoothers[sensor] = smoothers.pop(SMOOTHED_TEST_PER_DEVICE) else: smoothers[sensor] = smoothers.pop(RAW_TEST_PER_DEVICE) @@ -106,7 +106,7 @@ def run_module(params: Dict[str, Any]): # Add prefix, if required sensors = add_prefix(SENSORS, wip_signal=params["indicator"]["wip_signal"], - prefix="wip_") + prefix="wip_") smoothers = get_smooth_info(sensors, SMOOTHERS) for geo_res in NONPARENT_GEO_RESOLUTIONS: geo_data, res_key = geo_map(geo_res, data) From a120175f463075731fd99748b3a2614ea1fdf120 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Fri, 14 Jan 2022 10:00:15 -0500 Subject: [PATCH 06/44] fix an error --- quidel_covidtest/delphi_quidel_covidtest/run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quidel_covidtest/delphi_quidel_covidtest/run.py b/quidel_covidtest/delphi_quidel_covidtest/run.py index 57550d674..e428a9088 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/run.py +++ b/quidel_covidtest/delphi_quidel_covidtest/run.py @@ -45,11 +45,11 @@ def get_smooth_info(sensors, _SMOOTHERS): """Get smooth info from SMOOTHERS. """ smoothers = _SMOOTHERS.copy() for sensor in sensors: - if sensor.endswith(_SMOOTHED_POSITIVE): + if sensor.endswith(SMOOTHED_POSITIVE): smoothers[sensor] = smoothers.pop(_SMOOTHED_POSITIVE) elif sensor.endswith(RAW_POSITIVE): smoothers[sensor] = smoothers.pop(RAW_POSITIVE) - elif sensor.endswith(_SMOOTHED_TEST_PER_DEVICE): + elif sensor.endswith(SMOOTHED_TEST_PER_DEVICE): smoothers[sensor] = smoothers.pop(SMOOTHED_TEST_PER_DEVICE) else: smoothers[sensor] = smoothers.pop(RAW_TEST_PER_DEVICE) From b199cad55dd0df8b66549ca0d788a0f8f24d30f8 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Fri, 14 Jan 2022 10:04:33 -0500 Subject: [PATCH 07/44] ignore too-many-branches in pylintrc --- quidel_covidtest/.pylintrc | 1 + quidel_covidtest/delphi_quidel_covidtest/run.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/quidel_covidtest/.pylintrc b/quidel_covidtest/.pylintrc index 58c6edbba..854cf38d2 100644 --- a/quidel_covidtest/.pylintrc +++ b/quidel_covidtest/.pylintrc @@ -4,6 +4,7 @@ disable=logging-format-interpolation, too-many-locals, too-many-arguments, + too-many-branches, # Allow pytest functions to be part of a class. no-self-use, # Allow pytest classes to have one test. diff --git a/quidel_covidtest/delphi_quidel_covidtest/run.py b/quidel_covidtest/delphi_quidel_covidtest/run.py index e428a9088..45be70edd 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/run.py +++ b/quidel_covidtest/delphi_quidel_covidtest/run.py @@ -46,7 +46,7 @@ def get_smooth_info(sensors, _SMOOTHERS): smoothers = _SMOOTHERS.copy() for sensor in sensors: if sensor.endswith(SMOOTHED_POSITIVE): - smoothers[sensor] = smoothers.pop(_SMOOTHED_POSITIVE) + smoothers[sensor] = smoothers.pop(SMOOTHED_POSITIVE) elif sensor.endswith(RAW_POSITIVE): smoothers[sensor] = smoothers.pop(RAW_POSITIVE) elif sensor.endswith(SMOOTHED_TEST_PER_DEVICE): From e7870e82885c8ed207196cbf3ee03ff6850002dd Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Fri, 14 Jan 2022 10:07:56 -0500 Subject: [PATCH 08/44] fix a linting error --- quidel_covidtest/delphi_quidel_covidtest/run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quidel_covidtest/delphi_quidel_covidtest/run.py b/quidel_covidtest/delphi_quidel_covidtest/run.py index 45be70edd..5823e8e73 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/run.py +++ b/quidel_covidtest/delphi_quidel_covidtest/run.py @@ -42,7 +42,7 @@ def log_exit(start_time, stats, logger): oldest_final_export_date = formatted_min_max_date) def get_smooth_info(sensors, _SMOOTHERS): - """Get smooth info from SMOOTHERS. """ + """Get smooth info from SMOOTHERS.""" smoothers = _SMOOTHERS.copy() for sensor in sensors: if sensor.endswith(SMOOTHED_POSITIVE): From 07642fa6cbe82b66abd010ede9c12c29721534c7 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Fri, 14 Jan 2022 14:10:40 -0500 Subject: [PATCH 09/44] update signal names, add two super age groups --- .../delphi_quidel_covidtest/constants.py | 12 ++++--- .../delphi_quidel_covidtest/pull.py | 36 +++++++++++-------- quidel_covidtest/tests/test_geo_maps.py | 28 +++++++-------- 3 files changed, 42 insertions(+), 34 deletions(-) diff --git a/quidel_covidtest/delphi_quidel_covidtest/constants.py b/quidel_covidtest/delphi_quidel_covidtest/constants.py index af67aa788..f958f023d 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/constants.py +++ b/quidel_covidtest/delphi_quidel_covidtest/constants.py @@ -42,9 +42,11 @@ } AGE_GROUPS = [ "total", - "age_0to4", - "age_5to17", - "age_18to49", - "age_50to64", - "age_65toOlder" + "age_0_4", + "age_5_17", + "age_18_49", + "age_50_64", + "age_65plus", + "age_0_17", + "age_18_64", ] diff --git a/quidel_covidtest/delphi_quidel_covidtest/pull.py b/quidel_covidtest/delphi_quidel_covidtest/pull.py index beb37bbb0..4a074be19 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/pull.py +++ b/quidel_covidtest/delphi_quidel_covidtest/pull.py @@ -8,6 +8,8 @@ import pandas as pd import numpy as np +from .constants import AGE_GROUPS + def get_from_s3(start_date, end_date, bucket, logger): """ Get raw data from aws s3 bucket. @@ -194,36 +196,40 @@ def preprocess_new_data(start_date, end_date, params, test_mode, logger): # Should match the suffixes of signal names df["label"] = None - df.loc[df["PatientAge"] < 5, "label"] = "age_0to4" - df.loc[((df["PatientAge"] >= 5)) & (df["PatientAge"] < 18), "label"] = "age_5to17" - df.loc[((df["PatientAge"] >= 18)) & (df["PatientAge"] < 50), "label"] = "age_18to49" - df.loc[((df["PatientAge"] >= 50)) & (df["PatientAge"] < 65), "label"] = "age_50to64" - df.loc[(df["PatientAge"] >= 65), "label"] = "age_65toOlder" + df.loc[df["PatientAge"] < 5, "label"] = "age_0_4" + df.loc[((df["PatientAge"] >= 5)) & (df["PatientAge"] < 18), "label"] = "age_5_17" + df.loc[((df["PatientAge"] >= 18)) & (df["PatientAge"] < 50), "label"] = "age_18_49" + df.loc[((df["PatientAge"] >= 50)) & (df["PatientAge"] < 65), "label"] = "age_50_64" + df.loc[(df["PatientAge"] >= 65), "label"] = "age_65plus" df.loc[df["PatientAge"] == -1, "label"] = "NA" - - for agegroup in df["label"].unique(): - if agegroup == "NA": - continue + + for agegroup in AGE_GROUPS[1:]: + if agegroup == "age_0_17": + ages = ["age_0_4", "age_5_17"] + elif agegroup == "age_18_64": + ages = ["age_18_49", "age_50_64"] + else: + ages = [agegroup] # Compute overallPositive group_pos = df.loc[(df["OverallResult"] == "positive") - & (df["label"] == agegroup)].groupby( + & (df["label"].isin(ages))].groupby( by=["timestamp", "zip"], as_index=False)['OverallResult'].count() - group_pos["positiveTest_%s"%agegroup] = group_pos["OverallResult"] + group_pos[f"positiveTest_{agegroup}"] = group_pos["OverallResult"] group_pos.drop(labels="OverallResult", axis="columns", inplace=True) # Compute overallTotal - group_total = df.loc[df["label"] == agegroup].groupby( + group_total = df.loc[df["label"].isin(ages)].groupby( by=["timestamp", "zip"], as_index=False)['OverallResult'].count() - group_total["totalTest_%s"%agegroup] = group_total["OverallResult"] + group_total[f"totalTest_{agegroup}"] = group_total["OverallResult"] group_total.drop(labels="OverallResult", axis="columns", inplace=True) # Compute numUniqueDevices - group_numUniqueDevices = df.loc[df["label"] == agegroup].groupby( + group_numUniqueDevices = df.loc[df["label"].isin(ages)].groupby( by=["timestamp", "zip"], as_index=False)["SofiaSerNum"].agg({"SofiaSerNum": "nunique"}).rename( - columns={"SofiaSerNum": "numUniqueDevices_%s"%agegroup} + columns={"SofiaSerNum": f"numUniqueDevices_{agegroup}"} ) df_merged = df_merged.merge( diff --git a/quidel_covidtest/tests/test_geo_maps.py b/quidel_covidtest/tests/test_geo_maps.py index fae6933bc..dc607df3c 100644 --- a/quidel_covidtest/tests/test_geo_maps.py +++ b/quidel_covidtest/tests/test_geo_maps.py @@ -34,8 +34,8 @@ def test_county(self): assert set(new_df["totalTest_total"].values) == set([26, 10, 15, 20, 950]) assert set(new_df["positiveTest_total"].values) == set([14, 6, 8, 5, 75]) - assert set(new_df["totalTest_age_0to4"].values) == set([5, 2, 2, 85, 4]) - assert set(new_df["positiveTest_age_0to4"].values) == set([2, 1, 1, 12, 1]) + assert set(new_df["totalTest_age_0_4"].values) == set([5, 2, 2, 85, 4]) + assert set(new_df["positiveTest_age_0_4"].values) == set([2, 1, 1, 12, 1]) # Test Megacounties new_df["timestamp"] = [datetime.strptime(x, "%Y-%m-%d") for x in new_df["timestamp"]] @@ -44,8 +44,8 @@ def test_county(self): assert set(mega_df["totalTest_total"].values) == set([26, 10, 15, 20, 950, 25, 20]) assert set(mega_df["positiveTest_total"].values) == set([14, 6, 8, 5, 75, 14, 5]) - assert set(mega_df["totalTest_age_0to4"].values) == set([5, 2, 2, 85, 4, 4, 9, 4]) - assert set(mega_df["positiveTest_age_0to4"].values) == set([2, 1, 1, 12, 1, 4, 1]) + assert set(mega_df["totalTest_age_0_4"].values) == set([5, 2, 2, 85, 4, 4, 9, 4]) + assert set(mega_df["positiveTest_age_0_4"].values) == set([2, 1, 1, 12, 1, 4, 1]) def test_state(self): @@ -72,8 +72,8 @@ def test_state(self): assert set(new_df["totalTest_total"].values) == set([150, 200, 950]) assert set(new_df["positiveTest_total"].values) == set([18, 15, 75]) - assert set(new_df["totalTest_age_0to4"].values) == set([30, 85, 20]) - assert set(new_df["positiveTest_age_0to4"].values) == set([3, 12, 3]) + assert set(new_df["totalTest_age_0_4"].values) == set([30, 85, 20]) + assert set(new_df["positiveTest_age_0_4"].values) == set([3, 12, 3]) def test_hrr(self): @@ -99,8 +99,8 @@ def test_hrr(self): assert set(new_df["totalTest_total"].values) == set([500, 100, 250, 50, 400]) assert set(new_df["positiveTest_total"].values) == set([50, 10, 20, 8, 20]) - assert set(new_df["totalTest_age_0to4"].values) == set([25, 20 ,20, 10, 60]) - assert set(new_df["positiveTest_age_0to4"].values) == set([8, 2, 3, 1, 4]) + assert set(new_df["totalTest_age_0_4"].values) == set([25, 20 ,20, 10, 60]) + assert set(new_df["positiveTest_age_0_4"].values) == set([8, 2, 3, 1, 4]) def test_msa(self): @@ -126,8 +126,8 @@ def test_msa(self): assert set(new_df["totalTest_total"].values) == set([200, 750, 100]) assert set(new_df["positiveTest_total"].values) == set([5, 70, 10]) - assert set(new_df["totalTest_age_0to4"].values) == set([40, 45, 20]) - assert set(new_df["positiveTest_age_0to4"].values) == set([1, 11, 2]) + assert set(new_df["totalTest_age_0_4"].values) == set([40, 45, 20]) + assert set(new_df["positiveTest_age_0_4"].values) == set([1, 11, 2]) def test_nation(self): df = pd.DataFrame( @@ -152,8 +152,8 @@ def test_nation(self): assert set(new_df["totalTest_total"].values) == set([1300]) assert set(new_df["positiveTest_total"].values) == set([108]) - assert set(new_df["totalTest_age_0to4"].values) == set([135]) - assert set(new_df["positiveTest_age_0to4"].values) == set([18]) + assert set(new_df["totalTest_age_0_4"].values) == set([135]) + assert set(new_df["positiveTest_age_0_4"].values) == set([18]) def test_hhs(self): df = pd.DataFrame( @@ -178,5 +178,5 @@ def test_hhs(self): assert set(new_df["totalTest_total"].values) == set([150, 200, 950]) assert set(new_df["positiveTest_total"].values) == set([18, 15, 75]) - assert set(new_df["totalTest_age_0to4"].values) == set([30, 20, 85]) - assert set(new_df["positiveTest_age_0to4"].values) == set([3, 3, 12]) + assert set(new_df["totalTest_age_0_4"].values) == set([30, 20, 85]) + assert set(new_df["positiveTest_age_0_4"].values) == set([3, 3, 12]) From 1ee31aed286243ab3495ffc46c36ff6170b2b539 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Fri, 14 Jan 2022 14:13:31 -0500 Subject: [PATCH 10/44] fix a linting error --- quidel_covidtest/delphi_quidel_covidtest/pull.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quidel_covidtest/delphi_quidel_covidtest/pull.py b/quidel_covidtest/delphi_quidel_covidtest/pull.py index 4a074be19..60ff2dd86 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/pull.py +++ b/quidel_covidtest/delphi_quidel_covidtest/pull.py @@ -202,7 +202,7 @@ def preprocess_new_data(start_date, end_date, params, test_mode, logger): df.loc[((df["PatientAge"] >= 50)) & (df["PatientAge"] < 65), "label"] = "age_50_64" df.loc[(df["PatientAge"] >= 65), "label"] = "age_65plus" df.loc[df["PatientAge"] == -1, "label"] = "NA" - + for agegroup in AGE_GROUPS[1:]: if agegroup == "age_0_17": ages = ["age_0_4", "age_5_17"] From 4eee96141f07a595e9515192bbe021a9bd6e4aeb Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Tue, 18 Jan 2022 10:20:56 -0500 Subject: [PATCH 11/44] remove 18-64 age group --- quidel_covidtest/delphi_quidel_covidtest/constants.py | 1 - quidel_covidtest/delphi_quidel_covidtest/pull.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/quidel_covidtest/delphi_quidel_covidtest/constants.py b/quidel_covidtest/delphi_quidel_covidtest/constants.py index f958f023d..8e4d37cb2 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/constants.py +++ b/quidel_covidtest/delphi_quidel_covidtest/constants.py @@ -48,5 +48,4 @@ "age_50_64", "age_65plus", "age_0_17", - "age_18_64", ] diff --git a/quidel_covidtest/delphi_quidel_covidtest/pull.py b/quidel_covidtest/delphi_quidel_covidtest/pull.py index 60ff2dd86..a76938a42 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/pull.py +++ b/quidel_covidtest/delphi_quidel_covidtest/pull.py @@ -206,8 +206,6 @@ def preprocess_new_data(start_date, end_date, params, test_mode, logger): for agegroup in AGE_GROUPS[1:]: if agegroup == "age_0_17": ages = ["age_0_4", "age_5_17"] - elif agegroup == "age_18_64": - ages = ["age_18_49", "age_50_64"] else: ages = [agegroup] # Compute overallPositive From a81050c9e534981b0705de5d5cfae9eca4d105c0 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Tue, 18 Jan 2022 11:41:50 -0500 Subject: [PATCH 12/44] add whitespace and add comments --- quidel_covidtest/delphi_quidel_covidtest/pull.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quidel_covidtest/delphi_quidel_covidtest/pull.py b/quidel_covidtest/delphi_quidel_covidtest/pull.py index a76938a42..d03e13651 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/pull.py +++ b/quidel_covidtest/delphi_quidel_covidtest/pull.py @@ -189,7 +189,7 @@ def preprocess_new_data(start_date, end_date, params, test_mode, logger): ).fillna(0).drop_duplicates() # Compute Summary info for age groups - df["PatientAge"]= df["PatientAge"].fillna(-1) + df["PatientAge"] = df["PatientAge"].fillna(-1) df.loc[df["PatientAge"] == "<1", "PatientAge"] = 0.5 df.loc[df["PatientAge"] == ">85", "PatientAge"] = 100 df["PatientAge"] = df["PatientAge"] .astype(float) @@ -203,7 +203,7 @@ def preprocess_new_data(start_date, end_date, params, test_mode, logger): df.loc[(df["PatientAge"] >= 65), "label"] = "age_65plus" df.loc[df["PatientAge"] == -1, "label"] = "NA" - for agegroup in AGE_GROUPS[1:]: + for agegroup in AGE_GROUPS[1:]: # Exclude total if agegroup == "age_0_17": ages = ["age_0_4", "age_5_17"] else: From dc06d9cf7c58830db811428eaa9c283f333711fd Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Tue, 18 Jan 2022 11:53:21 -0500 Subject: [PATCH 13/44] add tests for ages 0-17 --- quidel_covidtest/tests/test_geo_maps.py | 59 ++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/quidel_covidtest/tests/test_geo_maps.py b/quidel_covidtest/tests/test_geo_maps.py index dc607df3c..83e828f83 100644 --- a/quidel_covidtest/tests/test_geo_maps.py +++ b/quidel_covidtest/tests/test_geo_maps.py @@ -21,10 +21,14 @@ def test_county(self): } ) - for agegroup in AGE_GROUPS[1:]: + for agegroup in AGE_GROUPS[1:-1]: df[f"totalTest_{agegroup}"] = [2, 3, 2, 2, 4, 40, 20, 25] df[f"positiveTest_{agegroup}"] = [1, 1, 1, 1, 1, 1, 3, 8] df[f"numUniqueDevices_{agegroup}"] = [2, 1, 2, 1, 1, 1, 1, 1] + + df[f"totalTest_age_0_17"] = [4, 6, 4, 4, 8, 80, 40, 50] + df[f"positiveTest_age_0_17"] = [2, 2, 2, 2, 2, 2, 6, 16] + df[f"numUniqueDevices_age_0_17"] = [2, 1, 2, 1, 1, 1, 1, 1] new_df, res_key = geo_map("county", df) @@ -37,6 +41,9 @@ def test_county(self): assert set(new_df["totalTest_age_0_4"].values) == set([5, 2, 2, 85, 4]) assert set(new_df["positiveTest_age_0_4"].values) == set([2, 1, 1, 12, 1]) + assert set(new_df["totalTest_age_0_17"].values) == set([10, 4, 4, 170, 8]) + assert set(new_df["positiveTest_age_0_17"].values) == set([4, 2, 2, 24, 2]) + # Test Megacounties new_df["timestamp"] = [datetime.strptime(x, "%Y-%m-%d") for x in new_df["timestamp"]] mega_df = add_megacounties(new_df, True) @@ -47,6 +54,9 @@ def test_county(self): assert set(mega_df["totalTest_age_0_4"].values) == set([5, 2, 2, 85, 4, 4, 9, 4]) assert set(mega_df["positiveTest_age_0_4"].values) == set([2, 1, 1, 12, 1, 4, 1]) + assert set(mega_df["totalTest_age_0_17"].values) == set([10, 4, 4, 170, 8, 8, 18, 8]) + assert set(mega_df["positiveTest_age_0_17"].values) == set([4, 2, 2, 24, 2, 8, 2]) + def test_state(self): @@ -60,10 +70,15 @@ def test_state(self): "numUniqueDevices_total": [2, 1, 1, 1, 1, 1] } ) - for agegroup in AGE_GROUPS[1:]: + for agegroup in AGE_GROUPS[1:-1]: df[f"totalTest_{agegroup}"] = [20, 10, 20, 40, 20, 25] df[f"positiveTest_{agegroup}"] = [2, 1, 3, 1, 3, 8] df[f"numUniqueDevices_{agegroup}"] = [2, 1, 1, 1, 1, 1] + + df[f"totalTest_age_0_17"] = [40, 20, 40, 80, 40, 50] + df[f"positiveTest_age_0_17"] = [4, 2, 6, 2, 6, 16] + df[f"numUniqueDevices_age_0_17"] = [2, 1, 1, 1, 1, 1] + new_df, res_key = geo_map("state", df) @@ -74,6 +89,9 @@ def test_state(self): assert set(new_df["totalTest_age_0_4"].values) == set([30, 85, 20]) assert set(new_df["positiveTest_age_0_4"].values) == set([3, 12, 3]) + + assert set(new_df["totalTest_age_0_17"].values) == set([60, 170, 40]) + assert set(new_df["positiveTest_age_0_17"].values) == set([6, 24, 6]) def test_hrr(self): @@ -87,10 +105,14 @@ def test_hrr(self): "numUniqueDevices_total": [2, 1, 1, 1, 1, 1] } ) - for agegroup in AGE_GROUPS[1:]: + for agegroup in AGE_GROUPS[1:-1]: df[f"totalTest_{agegroup}"] = [20, 10, 20, 40, 20, 25] df[f"positiveTest_{agegroup}"] = [2, 1, 3, 1, 3, 8] df[f"numUniqueDevices_{agegroup}"] = [2, 1, 1, 1, 1, 1] + + df[f"totalTest_age_0_17"] = [40, 20, 40, 80, 40, 50] + df[f"positiveTest_age_0_17"] = [4, 2, 6, 2, 6, 16] + df[f"numUniqueDevices_age_0_17"] = [2, 1, 1, 1, 1, 1] new_df, _ = geo_map("hrr", df) @@ -101,6 +123,9 @@ def test_hrr(self): assert set(new_df["totalTest_age_0_4"].values) == set([25, 20 ,20, 10, 60]) assert set(new_df["positiveTest_age_0_4"].values) == set([8, 2, 3, 1, 4]) + + assert set(new_df["totalTest_age_0_17"].values) == set([50, 40, 40, 20, 120]) + assert set(new_df["positiveTest_age_0_17"].values) == set([16, 4, 6, 2, 8]) def test_msa(self): @@ -114,10 +139,14 @@ def test_msa(self): "numUniqueDevices_total": [2, 1, 1, 1, 1, 1] } ) - for agegroup in AGE_GROUPS[1:]: + for agegroup in AGE_GROUPS[1:-1]: df[f"totalTest_{agegroup}"] = [20, 10, 20, 40, 20, 25] df[f"positiveTest_{agegroup}"] = [2, 1, 3, 1, 3, 8] df[f"numUniqueDevices_{agegroup}"] = [2, 1, 1, 1, 1, 1] + + df[f"totalTest_age_0_17"] = [40, 20, 40, 80, 40, 50] + df[f"positiveTest_age_0_17"] = [4, 2, 6, 2, 6, 16] + df[f"numUniqueDevices_age_0_17"] = [2, 1, 1, 1, 1, 1] new_df, res_key = geo_map("msa", df) @@ -128,6 +157,9 @@ def test_msa(self): assert set(new_df["totalTest_age_0_4"].values) == set([40, 45, 20]) assert set(new_df["positiveTest_age_0_4"].values) == set([1, 11, 2]) + + assert set(new_df["totalTest_age_0_17"].values) == set([80, 90, 40]) + assert set(new_df["positiveTest_age_0_17"].values) == set([2, 22, 4]) def test_nation(self): df = pd.DataFrame( @@ -140,10 +172,14 @@ def test_nation(self): "numUniqueDevices_total": [2, 1, 1, 1, 1, 1] } ) - for agegroup in AGE_GROUPS[1:]: + for agegroup in AGE_GROUPS[1:-1]: df[f"totalTest_{agegroup}"] = [20, 10, 20, 40, 20, 25] df[f"positiveTest_{agegroup}"] = [2, 1, 3, 1, 3, 8] df[f"numUniqueDevices_{agegroup}"] = [2, 1, 1, 1, 1, 1] + + df[f"totalTest_age_0_17"] = [40, 20, 40, 80, 40, 50] + df[f"positiveTest_age_0_17"] = [4, 2, 6, 2, 6, 16] + df[f"numUniqueDevices_age_0_17"] = [2, 1, 1, 1, 1, 1] new_df, res_key = geo_map("nation", df) @@ -154,6 +190,9 @@ def test_nation(self): assert set(new_df["totalTest_age_0_4"].values) == set([135]) assert set(new_df["positiveTest_age_0_4"].values) == set([18]) + + assert set(new_df["totalTest_age_0_17"].values) == set([270]) + assert set(new_df["positiveTest_age_0_17"].values) == set([36]) def test_hhs(self): df = pd.DataFrame( @@ -166,10 +205,14 @@ def test_hhs(self): "numUniqueDevices_total": [2, 1, 1, 1, 1, 1] } ) - for agegroup in AGE_GROUPS[1:]: + for agegroup in AGE_GROUPS[1:-1]: df[f"totalTest_{agegroup}"] = [20, 10, 20, 40, 20, 25] df[f"positiveTest_{agegroup}"] = [2, 1, 3, 1, 3, 8] df[f"numUniqueDevices_{agegroup}"] = [2, 1, 1, 1, 1, 1] + + df[f"totalTest_age_0_17"] = [40, 20, 40, 80, 40, 50] + df[f"positiveTest_age_0_17"] = [4, 2, 6, 2, 6, 16] + df[f"numUniqueDevices_age_0_17"] = [2, 1, 1, 1, 1, 1] new_df, res_key = geo_map("hhs", df) @@ -180,3 +223,7 @@ def test_hhs(self): assert set(new_df["totalTest_age_0_4"].values) == set([30, 20, 85]) assert set(new_df["positiveTest_age_0_4"].values) == set([3, 3, 12]) + + assert set(new_df["totalTest_age_0_17"].values) == set([60, 40, 170]) + assert set(new_df["positiveTest_age_0_17"].values) == set([6, 6, 24]) + From 0c0f9f5143d3af7c26cc1fd73c722bd06ea8e056 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Tue, 18 Jan 2022 11:56:12 -0500 Subject: [PATCH 14/44] small udpates for suggested changes --- quidel_covidtest/delphi_quidel_covidtest/geo_maps.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/quidel_covidtest/delphi_quidel_covidtest/geo_maps.py b/quidel_covidtest/delphi_quidel_covidtest/geo_maps.py index 20ebde1c2..6d802c5e6 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/geo_maps.py +++ b/quidel_covidtest/delphi_quidel_covidtest/geo_maps.py @@ -25,13 +25,13 @@ def geo_map(geo_res, df): # Add population for each zipcode data = GMPR.add_population_column(data, "zip") # zip -> geo_res - data_cols = [] + data_cols = ["population"] for col, agegroup in product(DATA_COLS, AGE_GROUPS): data_cols.append("_".join([col, agegroup])) data = GMPR.replace_geocode( data, from_code="zip", new_code=geo_key, date_col = "timestamp", - data_cols=data_cols+["population"]) + data_cols=data_cols) if geo_res in ["state", "hhs", "nation"]: return data, geo_key # Add parent state @@ -43,7 +43,7 @@ def add_megacounties(data, smooth=False): assert "fips" in data.columns # Make sure the data is at county level # For raw signals, the threshold is MIN_OBS - # For raw signals, the threshold is MIN_OBS/2 + # For smoothed signals, the threshold is MIN_OBS/2 if smooth: threshold_visits = MIN_OBS/2 else: From 1707cfbdebc3ffa53a9a568fa973fcba48ec12e3 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Fri, 21 Jan 2022 12:44:59 -0500 Subject: [PATCH 15/44] add state_id for megacounties --- quidel_covidtest/delphi_quidel_covidtest/geo_maps.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/quidel_covidtest/delphi_quidel_covidtest/geo_maps.py b/quidel_covidtest/delphi_quidel_covidtest/geo_maps.py index 6d802c5e6..9cefc0f9e 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/geo_maps.py +++ b/quidel_covidtest/delphi_quidel_covidtest/geo_maps.py @@ -60,6 +60,8 @@ def add_megacounties(data, smooth=False): pdList.append(megacounties) mega_df = reduce(lambda x, y: pd.merge( x, y, on = ["timestamp", "fips"]), pdList) + mega_df = GMPR.add_geocode(mega_df, from_code="fips", new_code="state_id", + from_col="fips", new_col="state_id") return pd.concat([data, mega_df]) From e1226e19ddfa95542e0f7bdc78c3e81b45672259 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Fri, 21 Jan 2022 12:45:22 -0500 Subject: [PATCH 16/44] add tests for state_id --- quidel_covidtest/tests/test_geo_maps.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/quidel_covidtest/tests/test_geo_maps.py b/quidel_covidtest/tests/test_geo_maps.py index 83e828f83..b1c74af22 100644 --- a/quidel_covidtest/tests/test_geo_maps.py +++ b/quidel_covidtest/tests/test_geo_maps.py @@ -57,6 +57,8 @@ def test_county(self): assert set(mega_df["totalTest_age_0_17"].values) == set([10, 4, 4, 170, 8, 8, 18, 8]) assert set(mega_df["positiveTest_age_0_17"].values) == set([4, 2, 2, 24, 2, 8, 2]) + assert set(mega_df["state_id"].values) == set(["ma", "tx", "wa"]) + def test_state(self): From 562773d6aab7dbda6c7bb8cea268881163348cde Mon Sep 17 00:00:00 2001 From: Dmitry Shemetov Date: Fri, 21 Jan 2022 14:01:56 -0800 Subject: [PATCH 17/44] Add minimal censored counties test and get error? --- quidel_covidtest/tests/test_data/test_data.csv | 4 ++++ quidel_covidtest/tests/test_run.py | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/quidel_covidtest/tests/test_data/test_data.csv b/quidel_covidtest/tests/test_data/test_data.csv index f3bdeadc5..a7c927d8d 100644 --- a/quidel_covidtest/tests/test_data/test_data.csv +++ b/quidel_covidtest/tests/test_data/test_data.csv @@ -1,4 +1,8 @@ SofiaSerNum,TestDate,Facility,City,State,Zip,PatientAge,Result1,Result2,OverallResult,County,FacilityType,Assay,SCO1,SCO2,CLN,CSN,InstrType,StorageDate,ResultId,SarsTestNumber +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, 1,7/18/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, 1,7/18/20,,Lorton,VA,22079,23,negative,,negative,,,,,,,,,8/17/20,, 1,7/18/20,,Lorton,VA,22079,27,negative,,negative,,,,,,,,,8/17/20,, diff --git a/quidel_covidtest/tests/test_run.py b/quidel_covidtest/tests/test_run.py index 89c59a24f..f506aa0ee 100644 --- a/quidel_covidtest/tests/test_run.py +++ b/quidel_covidtest/tests/test_run.py @@ -68,6 +68,18 @@ def test_output_files(self, clean_receiving_dir): ) assert (df.columns.values == ["geo_id", "val", "se", "sample_size"]).all() + # 7/18/20 in test_data/test_data.csv has: + # - zip 24526 -> fips 51019 with 21 positive counts and 3 negative counts + # - zip 22079 -> fips 51059 with many positive and negative counts + # - zip 24527 -> fips 51143 with 150 positive counts and 3 negative counts + # I think that the following output file should then have + # - fips 51059 for the many counts + # - fips 51000 for the censored 24526 counts + # - fips 51143 for the above-threshold 24527 counts + # But instead, 51019 shows up with the same value as 51143. Is this right or am I missing something? + df = pd.read_csv(join("./receiving", "20200718_county_covid_ag_smoothed_pct_positive.csv")) + assert set(df.geo) == set(["51000", "51059", "51143"]) + # test_intermediate_file flag = None for fname in listdir("./cache"): From ef41f6accf9c2811c0c3cdd006a4f3c30a948351 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Fri, 21 Jan 2022 17:50:21 -0500 Subject: [PATCH 18/44] add suggested changes --- quidel_covidtest/delphi_quidel_covidtest/generate_sensor.py | 5 +---- quidel_covidtest/delphi_quidel_covidtest/run.py | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/quidel_covidtest/delphi_quidel_covidtest/generate_sensor.py b/quidel_covidtest/delphi_quidel_covidtest/generate_sensor.py index f43ed3071..5f44a519b 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/generate_sensor.py +++ b/quidel_covidtest/delphi_quidel_covidtest/generate_sensor.py @@ -91,10 +91,7 @@ def generate_sensor_for_parent_geo(state_groups, data, res_key, smooth, res_df = pd.DataFrame(columns=["geo_id", "val", "se", "sample_size"]) if res_key == "fips": # Add rest-of-state report for county level data = add_megacounties(data, smooth) - res_groups = data.groupby(res_key) - loc_list = list(res_groups.groups.keys()) - for loc in loc_list: - res_group = res_groups.get_group(loc) + for loc, res_group in data.groupby(res_key): parent_state = res_group['state_id'].values[0] try: parent_group = state_groups.get_group(parent_state) diff --git a/quidel_covidtest/delphi_quidel_covidtest/run.py b/quidel_covidtest/delphi_quidel_covidtest/run.py index 5823e8e73..fb1a69ac2 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/run.py +++ b/quidel_covidtest/delphi_quidel_covidtest/run.py @@ -133,7 +133,7 @@ def run_module(params: Dict[str, Any]): end_date=export_end_date) if len(dates) > 0: stats.append((max(dates), len(dates))) - + assert geo_res == "state" # Make sure geo_groups is for state level # County/HRR/MSA level for geo_res in PARENT_GEO_RESOLUTIONS: geo_data, res_key = geo_map(geo_res, data) From c81298ba7bb07d357ff29d7ede429e9ba9fdb675 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Sun, 23 Jan 2022 00:24:56 -0500 Subject: [PATCH 19/44] update unit tests based on the current strategy --- quidel_covidtest/tests/test_run.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/quidel_covidtest/tests/test_run.py b/quidel_covidtest/tests/test_run.py index f506aa0ee..5c8938307 100644 --- a/quidel_covidtest/tests/test_run.py +++ b/quidel_covidtest/tests/test_run.py @@ -68,17 +68,8 @@ def test_output_files(self, clean_receiving_dir): ) assert (df.columns.values == ["geo_id", "val", "se", "sample_size"]).all() - # 7/18/20 in test_data/test_data.csv has: - # - zip 24526 -> fips 51019 with 21 positive counts and 3 negative counts - # - zip 22079 -> fips 51059 with many positive and negative counts - # - zip 24527 -> fips 51143 with 150 positive counts and 3 negative counts - # I think that the following output file should then have - # - fips 51059 for the many counts - # - fips 51000 for the censored 24526 counts - # - fips 51143 for the above-threshold 24527 counts - # But instead, 51019 shows up with the same value as 51143. Is this right or am I missing something? df = pd.read_csv(join("./receiving", "20200718_county_covid_ag_smoothed_pct_positive.csv")) - assert set(df.geo) == set(["51000", "51059", "51143"]) + assert set(df.geo_id) == set(["51000", "51059", "51143", "51019"]) # test_intermediate_file flag = None From 7721290b173c4e1e0b4335ef103bdd43ba6a3fce Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Sun, 23 Jan 2022 00:30:27 -0500 Subject: [PATCH 20/44] geo_id should be integers in the unit tests --- quidel_covidtest/tests/test_run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quidel_covidtest/tests/test_run.py b/quidel_covidtest/tests/test_run.py index 5c8938307..85c5b611e 100644 --- a/quidel_covidtest/tests/test_run.py +++ b/quidel_covidtest/tests/test_run.py @@ -69,7 +69,7 @@ def test_output_files(self, clean_receiving_dir): assert (df.columns.values == ["geo_id", "val", "se", "sample_size"]).all() df = pd.read_csv(join("./receiving", "20200718_county_covid_ag_smoothed_pct_positive.csv")) - assert set(df.geo_id) == set(["51000", "51059", "51143", "51019"]) + assert set(df.geo_id) == set([51000, 51059, 51143, 51019]) # test_intermediate_file flag = None From b7f94c98ed4d1fc6e2b605cec96fbe4ce78c93fe Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Tue, 25 Jan 2022 03:06:30 -0500 Subject: [PATCH 21/44] udpate geographical pooling --- .../delphi_quidel_covidtest/data_tools.py | 20 ++++++++++--------- .../delphi_quidel_covidtest/pull.py | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/quidel_covidtest/delphi_quidel_covidtest/data_tools.py b/quidel_covidtest/delphi_quidel_covidtest/data_tools.py index f89a353ed..717a2424f 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/data_tools.py +++ b/quidel_covidtest/delphi_quidel_covidtest/data_tools.py @@ -67,15 +67,14 @@ def _slide_window_sum(arr, k): sarr = np.convolve(temp, np.ones(k, dtype=int), 'valid') return sarr - def _geographical_pooling(tpooled_tests, tpooled_ptests, min_obs): """ Determine how many samples from the parent geography must be borrowed. - If there are no samples available in the parent, the borrow_prop is 0. If - the parent does not have enough samples, we return a borrow_prop of 1, and - the fact that the pooled samples are insufficient are handled in the - statistic fitting step. + If there are no samples available in the parent, the borrow_prop is 0. + If the parent does not have enough samples, we return a borrow_prop of 1. + No more samples borrowed from the parent compared to the number of samples + we currently have. Args: tpooled_tests: np.ndarray[float] @@ -93,10 +92,12 @@ def _geographical_pooling(tpooled_tests, tpooled_ptests, min_obs): """ if (np.any(np.isnan(tpooled_tests)) or np.any(np.isnan(tpooled_ptests))): raise ValueError('[parent] tests should be non-negative ' - 'with no np.nan') + 'with no np.nan') # STEP 1: "TOP UP" USING PARENT LOCATION # Number of observations we need to borrow to "top up" + # Can't borrow more than total no. observations. borrow_tests = np.maximum(min_obs - tpooled_tests, 0) + borrow_tests = np.minimum(borrow_tests, tpooled_tests) # There are many cases (a, b > 0): # Case 1: a / b => no problem # Case 2: a / 0 => np.inf => borrow_prop becomes 1 @@ -108,13 +109,14 @@ def _geographical_pooling(tpooled_tests, tpooled_ptests, min_obs): with np.errstate(divide='ignore', invalid='ignore'): borrow_prop = borrow_tests / tpooled_ptests # If there's nothing to borrow, then ya can't borrow - borrow_prop[np.isnan(borrow_prop)] = 0 - # Can't borrow more than total no. observations. + borrow_prop[(np.isnan(borrow_prop)) + | (tpooled_tests == 0) + | (tpooled_ptests == 0)] = 0 + # Can't borrow more than total no. observations in the parent state # Relies on the fact that np.inf > 1 borrow_prop[borrow_prop > 1] = 1 return borrow_prop - def raw_positive_prop(positives, tests, min_obs): """ Calculate the proportion of positive tests without any temporal smoothing. diff --git a/quidel_covidtest/delphi_quidel_covidtest/pull.py b/quidel_covidtest/delphi_quidel_covidtest/pull.py index d03e13651..ab397ce47 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/pull.py +++ b/quidel_covidtest/delphi_quidel_covidtest/pull.py @@ -346,7 +346,7 @@ def check_export_start_date(export_start_date, export_end_date, export_start_date = datetime(2020, 5, 26) else: export_start_date = datetime.strptime(export_start_date, '%Y-%m-%d') - # Only export data from -45 days to -5 days + # Only export data from -50 days to -5 days if (export_end_date - export_start_date).days > export_day_range: export_start_date = export_end_date - timedelta(days=export_day_range) From 1fdbe49365ab40980125349a928ba6aefcac010a Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Tue, 25 Jan 2022 03:07:07 -0500 Subject: [PATCH 22/44] update unit tests --- .../tests/test_data/test_data.csv | 864 +++++++++--------- quidel_covidtest/tests/test_data_tools.py | 17 +- 2 files changed, 448 insertions(+), 433 deletions(-) diff --git a/quidel_covidtest/tests/test_data/test_data.csv b/quidel_covidtest/tests/test_data/test_data.csv index a7c927d8d..cc4c4ee8b 100644 --- a/quidel_covidtest/tests/test_data/test_data.csv +++ b/quidel_covidtest/tests/test_data/test_data.csv @@ -1,429 +1,435 @@ -SofiaSerNum,TestDate,Facility,City,State,Zip,PatientAge,Result1,Result2,OverallResult,County,FacilityType,Assay,SCO1,SCO2,CLN,CSN,InstrType,StorageDate,ResultId,SarsTestNumber -1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, -1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,23,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,27,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,13,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,68,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,56,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,82,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,6,invalid,,invalid,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,13,positive,,positive,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,82,positive,,positive,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,71,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,53,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,32,positive,,positive,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,4,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,47,positive,,positive,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,47,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,78,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,31,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,85,positive,,positive,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,35,positive,,positive,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,55,positive,,positive,,,,,,,,,8/17/20,, -1,7/18/20,,Lorton,VA,22079,16,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,83,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,39,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,9,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,13,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,77,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,35,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,7,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,76,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,28,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,34,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,13,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,52,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,34,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,61,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,31,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,67,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,13,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,75,positive,,positive,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -2,7/18/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,58,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,29,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,60,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,22,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,15,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,41,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,43,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,81,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,75,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,40,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,82,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,59,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,45,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,25,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,59,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,46,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,84,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,33,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,24,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,17,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,78,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,4,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,70,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,43,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,55,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,9,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,22,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,46,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,66,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,36,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,46,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,70,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,51,negative,,negative,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,5,positive,,positive,,,,,,,,,8/17/20,, -3,7/18/20,,Lorton,VA,22079,22,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,12,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,71,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,39,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,49,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,75,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,79,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,84,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,72,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,10,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,54,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,31,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,67,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,49,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,1,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,78,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,56,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,>85,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,5,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,73,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,36,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,66,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,38,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,11,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,>85,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,42,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,24,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,10,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,74,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,59,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,11,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,77,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,51,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,72,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,>85,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,62,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,31,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,19,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,8,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,30,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,30,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,62,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,82,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,5,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,20,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Santa Rosa Beach,FL,32459,8,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,18,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,34,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,25,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,17,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,16,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,39,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,17,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,20,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,79,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,83,invalid,,invalid,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,27,positive,,positive,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,33,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,55,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,39,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,14,positive,,positive,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,57,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,5,positive,,positive,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,45,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,44,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,83,negative,,negative,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,38,positive,,positive,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,39,positive,,positive,,,,,,,,,8/17/20,, -1,7/19/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,58,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,9,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,48,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,32,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,77,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,26,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,50,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,64,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,40,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,8,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,55,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,11,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,7,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,53,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,38,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,19,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,82,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,22,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,50,positive,,positive,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,45,negative,,negative,,,,,,,,,8/17/20,, -2,7/19/20,,Lorton,VA,22079,52,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,39,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,51,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,73,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,28,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,2,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,35,positive,,positive,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,70,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,12,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,7,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,37,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,80,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,8,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,43,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,3,positive,,positive,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,70,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,57,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,38,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,29,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,1,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,2,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,>85,positive,,positive,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,22,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,40,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,59,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,70,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,25,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,74,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,41,positive,,positive,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,71,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,29,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,54,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,39,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,15,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,48,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,77,positive,,positive,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,12,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,18,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,59,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,38,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,1,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,73,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,52,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,3,positive,,positive,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,30,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,40,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,77,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,56,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,75,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,73,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,2,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,9,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,44,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,70,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,54,positive,,positive,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,14,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,78,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,80,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,56,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,31,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,76,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,84,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,69,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,79,positive,,positive,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,42,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,22,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,72,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,54,negative,,negative,,,,,,,,,8/17/20,, -3,7/19/20,,Baltimore,MD,21229,59,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,63,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,80,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,66,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,23,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,61,positive,,positive,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,46,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,37,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,57,negative,,negative,,,,,,,,,8/17/20,, -3,7/20/20,,Baltimore,MD,21229,70,negative,,negative,,,,,,,,,8/17/20,, -4,7/20/20,,McLean,VA,22101,73,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,<1,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,54,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,62,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,71,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,16,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,51,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,63,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,66,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,24,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,9,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,2,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,44,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,72,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,31,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,59,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,<1,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,25,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,69,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,23,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,44,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,51,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,37,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,1,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,80,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,49,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,45,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,85,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,16,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,16,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,80,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,18,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,65,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,76,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,76,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,77,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,29,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,26,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,36,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,17,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,80,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,61,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,16,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,79,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,1,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,42,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,60,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,62,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,52,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,2,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,53,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,41,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,66,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,72,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,77,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,38,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,77,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,46,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,42,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,42,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,12,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,75,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,82,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,9,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,58,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,80,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,58,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,84,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,67,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,19,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,54,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,68,negative,,negative,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,1,positive,,positive,,,,,,,,,8/17/20,, -5,7/20/20,,Lorton,VA,22079,48,negative,,negative,,,,,,,,,8/17/20,, -5,7/21/20,,Lorton,VA,22079,2,negative,,negative,,,,,,,,,8/17/20,, -5,7/21/20,,Lorton,VA,22079,29,negative,,negative,,,,,,,,,8/17/20,, -6,7/22/20,,Tampa,FL,33625,20,negative,,negative,,,,,,,,,8/17/20,, -6,7/22/20,,Tampa,FL,33625,68,positive,,positive,,,,,,,,,8/17/20,, -6,7/22/20,,Tampa,FL,33625,>85,negative,,negative,,,,,,,,,8/17/20,, -6,7/22/20,,Tampa,FL,33625,46,positive,,positive,,,,,,,,,8/17/20,, -6,7/22/20,,Tampa,FL,33625,19,negative,,negative,,,,,,,,,8/17/20,, -6,7/22/20,,Tampa,FL,33625,26,negative,,negative,,,,,,,,,8/17/20,, -6,7/22/20,,Tampa,FL,33625,56,negative,,negative,,,,,,,,,8/17/20,, -6,7/22/20,,Tampa,FL,33625,53,negative,,negative,,,,,,,,,8/17/20,, -7,7/22/20,,Columbia,SC,29229,>85,negative,,negative,,,,,,,,,8/17/20,, -8,7/22/20,,Lorton,VA,22079,69,negative,,negative,,,,,,,,,8/17/20,, -8,7/22/20,,Lorton,VA,22079,76,negative,,negative,,,,,,,,,8/17/20,, -8,7/22/20,,Lorton,VA,22079,58,negative,,negative,,,,,,,,,8/17/20,, -8,7/22/20,,Lorton,VA,22079,66,negative,,negative,,,,,,,,,8/17/20,, -8,7/22/20,,Lorton,VA,22079,19,negative,,negative,,,,,,,,,8/17/20,, -8,7/22/20,,Lorton,VA,22079,70,negative,,negative,,,,,,,,,8/17/20,, -8,7/22/20,,Lorton,VA,22079,50,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,14,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,38,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,72,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,5,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,17,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,35,positive,,positive,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,85,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,47,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,62,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,74,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,4,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,60,positive,,positive,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,81,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,7,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,>85,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,>85,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,66,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,55,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,82,positive,,positive,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,29,positive,,positive,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,25,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,83,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,5,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,>85,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,>85,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,77,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,58,positive,,positive,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,6,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,36,negative,,negative,,,,,,,,,8/17/20,, -9,7/23/20,,Tampa,FL,33625,24,negative,,negative,,,,,,,,,8/17/20,, +SofiaSerNum,TestDate,Facility,City,State,Zip,PatientAge,Result1,Result2,OverallResult,County,FacilityType,Assay,SCO1,SCO2,CLN,CSN,InstrType,StorageDate,ResultId,SarsTestNumber +2,7/18/20,,Lorton,VA,22079,39,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,9,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,13,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,77,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,35,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,7,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,76,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,28,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,34,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,13,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,52,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,34,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,61,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,31,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,67,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,13,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,75,positive,,positive,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/18/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,58,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,29,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,60,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,22,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,15,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,41,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,43,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,81,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,75,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,40,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,82,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,59,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,45,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,25,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,59,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,46,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,84,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,33,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,24,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,17,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,78,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,4,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,70,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,43,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,55,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,9,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,22,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,46,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,66,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,36,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,46,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,70,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,51,negative,,negative,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,5,positive,,positive,,,,,,,,,8/17/20,, +3,7/18/20,,Lorton,VA,22079,22,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,39,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,51,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,73,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,28,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,2,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,35,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,70,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,12,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,7,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,37,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,80,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,8,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,43,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,3,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,70,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,57,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,38,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,29,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,1,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,2,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,>85,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,22,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,40,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,59,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,70,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,25,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,74,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,41,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,71,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,29,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,54,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,39,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,15,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,48,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,77,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,12,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,18,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,59,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,38,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,1,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,73,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,52,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,3,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,30,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,40,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,77,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,56,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,75,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,73,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,2,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,9,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,44,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,70,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,54,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,14,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,78,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,80,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,56,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,31,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,76,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,84,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,69,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,79,positive,,positive,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,42,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,22,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,72,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,54,negative,,negative,,,,,,,,,8/17/20,, +3,7/19/20,,Baltimore,MD,21229,59,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,18,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,34,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,25,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,17,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,16,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,39,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,17,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,20,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,79,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,83,invalid,,invalid,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,27,positive,,positive,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,33,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,55,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,39,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,14,positive,,positive,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,57,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,5,positive,,positive,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,45,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,44,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,83,negative,,negative,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,38,positive,,positive,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,39,positive,,positive,,,,,,,,,8/17/20,, +1,7/19/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,58,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,9,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,48,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,32,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,77,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,26,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,50,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,64,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,40,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,8,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,55,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,11,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,7,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,53,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,38,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,19,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,82,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,22,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,50,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,45,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Lorton,VA,22079,52,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,12,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,71,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,39,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,49,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,75,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,79,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,84,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,72,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,10,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,54,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,31,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,67,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,49,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,1,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,78,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,56,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,5,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,73,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,36,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,66,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,38,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,11,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,42,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,24,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,10,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,74,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,59,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,11,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,77,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,51,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,72,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,62,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,31,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,19,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,8,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,30,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,30,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,62,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,82,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,5,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,>85,negative,,negative,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,20,positive,,positive,,,,,,,,,8/17/20,, +2,7/19/20,,Santa Rosa Beach,FL,32459,8,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,63,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,80,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,66,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,23,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,61,positive,,positive,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,46,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,37,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,57,negative,,negative,,,,,,,,,8/17/20,, +3,7/20/20,,Baltimore,MD,21229,70,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,<1,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,54,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,62,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,71,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,16,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,51,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,63,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,66,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,24,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,9,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,2,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,44,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,72,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,31,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,59,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,<1,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,25,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,69,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,23,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,44,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,51,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,37,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,1,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,80,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,49,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,45,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,16,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,16,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,80,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,18,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,65,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,76,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,76,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,77,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,29,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,26,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,36,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,21,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,17,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,80,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,61,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,16,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,79,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,1,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,42,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,60,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,62,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,52,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,2,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,53,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,41,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,66,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,72,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,77,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,38,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,77,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,46,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,42,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,42,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,12,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,75,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,82,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,9,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,58,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,80,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,58,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,84,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,74,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,67,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,19,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,>85,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,54,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,68,negative,,negative,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,1,positive,,positive,,,,,,,,,8/17/20,, +5,7/20/20,,Lorton,VA,22079,48,negative,,negative,,,,,,,,,8/17/20,, +4,7/20/20,,McLean,VA,22101,73,negative,,negative,,,,,,,,,8/17/20,, +5,7/21/20,,Lorton,VA,22079,2,negative,,negative,,,,,,,,,8/17/20,, +5,7/21/20,,Lorton,VA,22079,29,negative,,negative,,,,,,,,,8/17/20,, +8,7/22/20,,Lorton,VA,22079,69,negative,,negative,,,,,,,,,8/17/20,, +8,7/22/20,,Lorton,VA,22079,76,negative,,negative,,,,,,,,,8/17/20,, +8,7/22/20,,Lorton,VA,22079,58,negative,,negative,,,,,,,,,8/17/20,, +8,7/22/20,,Lorton,VA,22079,66,negative,,negative,,,,,,,,,8/17/20,, +8,7/22/20,,Lorton,VA,22079,19,negative,,negative,,,,,,,,,8/17/20,, +8,7/22/20,,Lorton,VA,22079,70,negative,,negative,,,,,,,,,8/17/20,, +8,7/22/20,,Lorton,VA,22079,50,negative,,negative,,,,,,,,,8/17/20,, +7,7/22/20,,Columbia,SC,29229,>85,negative,,negative,,,,,,,,,8/17/20,, +6,7/22/20,,Tampa,FL,33625,20,negative,,negative,,,,,,,,,8/17/20,, +6,7/22/20,,Tampa,FL,33625,68,positive,,positive,,,,,,,,,8/17/20,, +6,7/22/20,,Tampa,FL,33625,>85,negative,,negative,,,,,,,,,8/17/20,, +6,7/22/20,,Tampa,FL,33625,46,positive,,positive,,,,,,,,,8/17/20,, +6,7/22/20,,Tampa,FL,33625,19,negative,,negative,,,,,,,,,8/17/20,, +6,7/22/20,,Tampa,FL,33625,26,negative,,negative,,,,,,,,,8/17/20,, +6,7/22/20,,Tampa,FL,33625,56,negative,,negative,,,,,,,,,8/17/20,, +6,7/22/20,,Tampa,FL,33625,53,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,14,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,38,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,72,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,5,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,17,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,35,positive,,positive,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,85,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,47,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,62,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,74,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,4,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,60,positive,,positive,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,81,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,7,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,>85,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,>85,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,66,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,55,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,82,positive,,positive,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,29,positive,,positive,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,25,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,83,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,5,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,>85,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,>85,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,77,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,58,positive,,positive,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,6,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,36,negative,,negative,,,,,,,,,8/17/20,, +9,7/23/20,,Tampa,FL,33625,24,negative,,negative,,,,,,,,,8/17/20,, \ No newline at end of file diff --git a/quidel_covidtest/tests/test_data_tools.py b/quidel_covidtest/tests/test_data_tools.py index cb611b8f5..7125c8eef 100644 --- a/quidel_covidtest/tests/test_data_tools.py +++ b/quidel_covidtest/tests/test_data_tools.py @@ -76,8 +76,8 @@ def test__slide_window_sum(self, k, expected): @pytest.mark.parametrize("min_obs, expected", [ (1, np.array([0, 0, 0, 0])), - (2, np.array([1/2, 0, 0, 0])), - (8, np.array([1, 1, 5/6, 4/8])), + (2, np.array([1/2, 0, 0, 0])), #(2, np.array([1/2, 0, 0, 0])), + (8, np.array([1/2, 2/4, 3/6, 4/8])), #(8, np.array([1, 1, 5/6, 4/8])), ]) def test__geographical_pooling(self, min_obs, expected): tpooled_tests = np.array([1, 2, 3, 4]) @@ -135,10 +135,19 @@ def test_raw_positive_prop(self, min_obs, expected_pos_prop, expected_se, expect np.array([3, 7, 9, 11]), np.array([5, 10, 15, 20]), np.array([(1 + 0.6 + 0.5)/(2 + 1 + 1), 3.5/7, 5.5/11, 7.5/17]), - np.array([np.sqrt(2.1*(4-2.1)/4/4/3), np.sqrt(3.5*(7-3.5)/7/7/6), - np.sqrt(5.5*(11-5.5)/11/11/10), np.sqrt(7.5*(17-7.5)/17/17/16)]), + np.array([np.sqrt(2.1*(4-2.1)/4/4/3), np.sqrt(3.5*(7-3.5)/7/7/6), + np.sqrt(5.5*(11-5.5)/11/11/10), np.sqrt(7.5*(17-7.5)/17/17/16)]), np.array([3, 6, 10, 16]), ), + (5, # parents case, borrow too much + 2, + np.array([3, 7, 9, 11]), + np.array([5, 10, 15, 20]), + np.array([np.nan, 3.5/7, 5.5/11, 7.5/17]), + np.array([np.nan, np.sqrt(3.5*(7-3.5)/7/7/6), + np.sqrt(5.5*(11-5.5)/11/11/10), np.sqrt(7.5*(17-7.5)/17/17/16)]), + np.array([np.nan, 6, 10, 16]), + ), ]) def test_smoothed_positive_prop(self, min_obs, pool_days, parent_positives, parent_tests, expected_prop, expected_se, expected_sample_sz): From 52a4aa6fc029682346ad850babe0896c5eb5d16a Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Tue, 25 Jan 2022 03:08:12 -0500 Subject: [PATCH 23/44] update unit tests in test_run --- quidel_covidtest/tests/test_run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quidel_covidtest/tests/test_run.py b/quidel_covidtest/tests/test_run.py index 85c5b611e..be6150bc5 100644 --- a/quidel_covidtest/tests/test_run.py +++ b/quidel_covidtest/tests/test_run.py @@ -69,7 +69,7 @@ def test_output_files(self, clean_receiving_dir): assert (df.columns.values == ["geo_id", "val", "se", "sample_size"]).all() df = pd.read_csv(join("./receiving", "20200718_county_covid_ag_smoothed_pct_positive.csv")) - assert set(df.geo_id) == set([51000, 51059, 51143, 51019]) + assert set(df.geo_id) == set([51000, 51059]) # test_intermediate_file flag = None From 9f3f6c3709e727cc1b71acff80a99a8efd09ebd2 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Tue, 25 Jan 2022 03:09:31 -0500 Subject: [PATCH 24/44] delete trailing whitespaces --- quidel_covidtest/delphi_quidel_covidtest/data_tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quidel_covidtest/delphi_quidel_covidtest/data_tools.py b/quidel_covidtest/delphi_quidel_covidtest/data_tools.py index 717a2424f..e8958ecfd 100644 --- a/quidel_covidtest/delphi_quidel_covidtest/data_tools.py +++ b/quidel_covidtest/delphi_quidel_covidtest/data_tools.py @@ -71,7 +71,7 @@ def _geographical_pooling(tpooled_tests, tpooled_ptests, min_obs): """ Determine how many samples from the parent geography must be borrowed. - If there are no samples available in the parent, the borrow_prop is 0. + If there are no samples available in the parent, the borrow_prop is 0. If the parent does not have enough samples, we return a borrow_prop of 1. No more samples borrowed from the parent compared to the number of samples we currently have. From 49af72656dfd86857b71db1fddd746b449b9ccb6 Mon Sep 17 00:00:00 2001 From: Dmitry Shemetov Date: Wed, 26 Jan 2022 13:36:17 -0800 Subject: [PATCH 25/44] Add a few tests to double check county censoring --- .../tests/test_data/test_data.csv | 115 ++++++++++++++++-- quidel_covidtest/tests/test_run.py | 8 +- 2 files changed, 114 insertions(+), 9 deletions(-) diff --git a/quidel_covidtest/tests/test_data/test_data.csv b/quidel_covidtest/tests/test_data/test_data.csv index cc4c4ee8b..9f5e907e9 100644 --- a/quidel_covidtest/tests/test_data/test_data.csv +++ b/quidel_covidtest/tests/test_data/test_data.csv @@ -59,6 +59,30 @@ SofiaSerNum,TestDate,Facility,City,State,Zip,PatientAge,Result1,Result2,OverallR 3,7/18/20,,Lorton,VA,22079,51,negative,,negative,,,,,,,,,8/17/20,, 3,7/18/20,,Lorton,VA,22079,5,positive,,positive,,,,,,,,,8/17/20,, 3,7/18/20,,Lorton,VA,22079,22,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24529,21,positive,,positive,,,,,,,,,8/17/20,, 1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, 1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, 1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, @@ -81,22 +105,97 @@ SofiaSerNum,TestDate,Facility,City,State,Zip,PatientAge,Result1,Result2,OverallR 1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, 1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, 1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24526,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, 1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, 1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, 1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, 1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, 1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, 1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, 1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, 1,7/18/20,,TestCity,TestState,24527,3,negative,,negative,,,,,,,,,8/17/20,, -1,7/18/20,,TestCity,TestState,24527,150,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24527,>85,positive,,positive,,,,,,,,,8/17/20,, 3,7/19/20,,Baltimore,MD,21229,>85,negative,,negative,,,,,,,,,8/17/20,, 3,7/19/20,,Baltimore,MD,21229,39,negative,,negative,,,,,,,,,8/17/20,, 3,7/19/20,,Baltimore,MD,21229,51,negative,,negative,,,,,,,,,8/17/20,, diff --git a/quidel_covidtest/tests/test_run.py b/quidel_covidtest/tests/test_run.py index be6150bc5..24dedae65 100644 --- a/quidel_covidtest/tests/test_run.py +++ b/quidel_covidtest/tests/test_run.py @@ -68,8 +68,14 @@ def test_output_files(self, clean_receiving_dir): ) assert (df.columns.values == ["geo_id", "val", "se", "sample_size"]).all() + df = pd.read_csv(join("./receiving", "20200718_county_covid_ag_raw_pct_positive.csv")) + # TODO: should megacounty 51000 be here (it currently is)? + assert set(df.geo_id) == set([51143, 51059, 51000]) + df = pd.read_csv(join("./receiving", "20200718_county_covid_ag_smoothed_pct_positive.csv")) - assert set(df.geo_id) == set([51000, 51059]) + # TODO: should megacounty 51000 be here (it currently isn't)? + assert set(df.geo_id) == set([51019, 51143, 51059]) + assert 1 == 2 # test_intermediate_file flag = None From 3218b1e8f87b38e48fbe853ef3654c9facfb317d Mon Sep 17 00:00:00 2001 From: Dmitry Shemetov Date: Wed, 26 Jan 2022 13:56:46 -0800 Subject: [PATCH 26/44] Remove faux-breakpoint, update test_data, update test_run --- quidel_covidtest/tests/test_data/test_data.csv | 4 ++++ quidel_covidtest/tests/test_run.py | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/quidel_covidtest/tests/test_data/test_data.csv b/quidel_covidtest/tests/test_data/test_data.csv index 9f5e907e9..e93a109d4 100644 --- a/quidel_covidtest/tests/test_data/test_data.csv +++ b/quidel_covidtest/tests/test_data/test_data.csv @@ -59,6 +59,10 @@ SofiaSerNum,TestDate,Facility,City,State,Zip,PatientAge,Result1,Result2,OverallR 3,7/18/20,,Lorton,VA,22079,51,negative,,negative,,,,,,,,,8/17/20,, 3,7/18/20,,Lorton,VA,22079,5,positive,,positive,,,,,,,,,8/17/20,, 3,7/18/20,,Lorton,VA,22079,22,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24534,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24534,21,positive,,positive,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24534,3,negative,,negative,,,,,,,,,8/17/20,, +1,7/18/20,,TestCity,TestState,24534,21,positive,,positive,,,,,,,,,8/17/20,, 1,7/18/20,,TestCity,TestState,24529,3,negative,,negative,,,,,,,,,8/17/20,, 1,7/18/20,,TestCity,TestState,24529,21,positive,,positive,,,,,,,,,8/17/20,, 1,7/18/20,,TestCity,TestState,24529,3,negative,,negative,,,,,,,,,8/17/20,, diff --git a/quidel_covidtest/tests/test_run.py b/quidel_covidtest/tests/test_run.py index 24dedae65..f5b9d9729 100644 --- a/quidel_covidtest/tests/test_run.py +++ b/quidel_covidtest/tests/test_run.py @@ -74,8 +74,7 @@ def test_output_files(self, clean_receiving_dir): df = pd.read_csv(join("./receiving", "20200718_county_covid_ag_smoothed_pct_positive.csv")) # TODO: should megacounty 51000 be here (it currently isn't)? - assert set(df.geo_id) == set([51019, 51143, 51059]) - assert 1 == 2 + assert set(df.geo_id) == set([51000, 51019, 51143, 51059]) # test_intermediate_file flag = None From 5c6d79886ff90cde5e52448eb6d9bf3ce6bbcc45 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Thu, 27 Jan 2022 14:26:46 -0500 Subject: [PATCH 27/44] fix the test in test_run --- quidel_covidtest/tests/test_run.py | 1 - 1 file changed, 1 deletion(-) diff --git a/quidel_covidtest/tests/test_run.py b/quidel_covidtest/tests/test_run.py index f5b9d9729..3fcfa2c1f 100644 --- a/quidel_covidtest/tests/test_run.py +++ b/quidel_covidtest/tests/test_run.py @@ -73,7 +73,6 @@ def test_output_files(self, clean_receiving_dir): assert set(df.geo_id) == set([51143, 51059, 51000]) df = pd.read_csv(join("./receiving", "20200718_county_covid_ag_smoothed_pct_positive.csv")) - # TODO: should megacounty 51000 be here (it currently isn't)? assert set(df.geo_id) == set([51000, 51019, 51143, 51059]) # test_intermediate_file From 3e9232e0605f23bc1033b4e13faad38d56b710e7 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Thu, 27 Jan 2022 14:28:34 -0500 Subject: [PATCH 28/44] remove the question in comments --- quidel_covidtest/tests/test_run.py | 1 - 1 file changed, 1 deletion(-) diff --git a/quidel_covidtest/tests/test_run.py b/quidel_covidtest/tests/test_run.py index 3fcfa2c1f..9d65ebb68 100644 --- a/quidel_covidtest/tests/test_run.py +++ b/quidel_covidtest/tests/test_run.py @@ -69,7 +69,6 @@ def test_output_files(self, clean_receiving_dir): assert (df.columns.values == ["geo_id", "val", "se", "sample_size"]).all() df = pd.read_csv(join("./receiving", "20200718_county_covid_ag_raw_pct_positive.csv")) - # TODO: should megacounty 51000 be here (it currently is)? assert set(df.geo_id) == set([51143, 51059, 51000]) df = pd.read_csv(join("./receiving", "20200718_county_covid_ag_smoothed_pct_positive.csv")) From ab25b356a097c542291ef00a14eefe4f91e6ac99 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Thu, 27 Jan 2022 15:05:31 -0500 Subject: [PATCH 29/44] add tests for values --- quidel_covidtest/tests/test_run.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/quidel_covidtest/tests/test_run.py b/quidel_covidtest/tests/test_run.py index 9d65ebb68..d9e28108a 100644 --- a/quidel_covidtest/tests/test_run.py +++ b/quidel_covidtest/tests/test_run.py @@ -3,8 +3,9 @@ from os.path import join import pandas as pd +import numpy as np -from delphi_utils import read_params, add_prefix +from delphi_utils import add_prefix from delphi_quidel_covidtest.constants import PARENT_GEO_RESOLUTIONS, NONPARENT_GEO_RESOLUTIONS, \ SENSORS from delphi_quidel_covidtest.run import run_module @@ -69,10 +70,32 @@ def test_output_files(self, clean_receiving_dir): assert (df.columns.values == ["geo_id", "val", "se", "sample_size"]).all() df = pd.read_csv(join("./receiving", "20200718_county_covid_ag_raw_pct_positive.csv")) + #ZIP 24534, FIPS 51083 has 4 counts, 2 positives + #ZIP 24529, FIPS 51117 has 24 counts, 12 positives + #ZIP 24526, FIPS 51019 has 49 counts, 26 positives + #MEGAFIPS 51000, should have 4+24+49 = 77 counts, 2+12+26 = 40 positives + #ZIP 24527, FIPS 51143 has 64 counts, 32 positives + #ZIP 22079, FIPS 51059 has 60 counts, 24 positives assert set(df.geo_id) == set([51143, 51059, 51000]) + assert set(df.sample_size) == set([64, 60, 77]) + assert np.allclose(df.val.values, [(40+0.5)/(77+1)*100, (24+0.5)/(60+1)*100, + (32+0.5)/(64+1)*100], equal_nan=True) + df = pd.read_csv(join("./receiving", "20200718_county_covid_ag_smoothed_pct_positive.csv")) assert set(df.geo_id) == set([51000, 51019, 51143, 51059]) + assert set(df.sample_size) == set([50, 50, 64, 60]) + parent_test = 4+24+49+64+60 + parent_pos = 2+12+26+32+24 + #ZIP 24526, FIPS 51019 has 49 counts, 26 positives, borrow 1 pseudo counts from VA + #MEGAFIPS 51000, should have 4+24 = 28 counts, 2+12 = 14 positives, borrow 22 pseudo counts + #ZIP 24527, FIPS 51143 has 64 counts, 32 positives, do not borrow + #ZIP 22079, FIPS 51059 has 60 counts, 24 positives, do not borrow + assert np.allclose(df.val.values, + [(14+parent_pos*22/parent_test+0.5)/(50+1)*100, + (26+parent_pos*1/parent_test+0.5)/(50+1)*100, + (24+0.5)/(60+1)*100, + (32+0.5)/(64+1)*100], equal_nan=True) # test_intermediate_file flag = None From 55f7ee41268ada469ae0f5e802d093100132350a Mon Sep 17 00:00:00 2001 From: rafaelcatoia Date: Wed, 2 Feb 2022 15:10:55 -0500 Subject: [PATCH 30/44] manually added pop size to zipcodes in derive_zip_population_table --- .../data_proc/geomap/geo_data_proc.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/_delphi_utils_python/data_proc/geomap/geo_data_proc.py b/_delphi_utils_python/data_proc/geomap/geo_data_proc.py index 8ca4057e1..c635196bc 100755 --- a/_delphi_utils_python/data_proc/geomap/geo_data_proc.py +++ b/_delphi_utils_python/data_proc/geomap/geo_data_proc.py @@ -181,6 +181,7 @@ def create_jhu_uid_fips_crosswalk(): ] ) + jhu_df = pd.read_csv(JHU_FIPS_URL, dtype={"UID": str, "FIPS": str}).query("Country_Region == 'US'") jhu_df = jhu_df.rename(columns={"UID": "jhu_uid", "FIPS": "fips"}).dropna(subset=["fips"]) @@ -336,6 +337,7 @@ def create_hhs_population_table(): state_pop = pd.read_csv(join(OUTPUT_DIR, STATE_POPULATION_OUT_FILENAME), dtype={"state_code": str, "hhs": int}, usecols=["state_code", "pop"]) state_hhs = pd.read_csv(join(OUTPUT_DIR, STATE_HHS_OUT_FILENAME), dtype=str) hhs_pop = state_pop.merge(state_hhs, on="state_code").groupby("hhs", as_index=False).sum() + hhs_pop.sort_values("hhs").to_csv(join(OUTPUT_DIR, HHS_POPULATION_OUT_FILENAME), index=False) @@ -363,6 +365,24 @@ def derive_zip_population_table(): df = census_pop.merge(fz_df, on="fips", how="left") df["pop"] = df["pop"].multiply(df["weight"], axis=0) df = df.drop(columns=["fips", "weight"]).groupby("zip").sum().dropna().reset_index() + ## filling population NAs for specific zips on zip_pop_missing Issue #0648 + ## cheking if each zip still missing, and concatenating if True + + zip_pop_missing = pd.DataFrame( + { + "zip": ['57756', '57764', '57770', '57772', '57794', '99554', '99563', '99566', + '99573', '99574', '99581', '99585', '99586', '99604', '99620', '99632', + '99650', '99657', '99658', '99662', '99666', '99677', '99686', '99693'], + "pop": [1126, 1923, 5271, 2048, 644, 677, 938, 192, + 1115, 2348, 762, 417, 605, 1093, 577, 813, + 568, 329, 329, 480, 189, 88, 4005, 248] + } + ) + + for x_zip in zip_pop_missing['zip']: + if x_zip not in df['zip']: + df = pd.concat([df, zip_pop_missing[zip_pop_missing['zip'] == x_zip]]) + df["pop"] = df["pop"].astype(int) df.sort_values("zip").to_csv(join(OUTPUT_DIR, ZIP_POPULATION_OUT_FILENAME), index=False) From 7c12efce163546aa74856759a26373457949e7e0 Mon Sep 17 00:00:00 2001 From: rafaelcatoia Date: Wed, 2 Feb 2022 16:21:53 -0500 Subject: [PATCH 31/44] minor alteration: ignore index when concatenating --- _delphi_utils_python/data_proc/geomap/geo_data_proc.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_delphi_utils_python/data_proc/geomap/geo_data_proc.py b/_delphi_utils_python/data_proc/geomap/geo_data_proc.py index c635196bc..88347f2e2 100755 --- a/_delphi_utils_python/data_proc/geomap/geo_data_proc.py +++ b/_delphi_utils_python/data_proc/geomap/geo_data_proc.py @@ -381,7 +381,8 @@ def derive_zip_population_table(): for x_zip in zip_pop_missing['zip']: if x_zip not in df['zip']: - df = pd.concat([df, zip_pop_missing[zip_pop_missing['zip'] == x_zip]]) + df = pd.concat([df, zip_pop_missing[zip_pop_missing['zip'] == x_zip]], + ignore_index=True) df["pop"] = df["pop"].astype(int) df.sort_values("zip").to_csv(join(OUTPUT_DIR, ZIP_POPULATION_OUT_FILENAME), index=False) From 8fbff9320752eff0795d595db22b76a0cc2b0162 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Wed, 2 Feb 2022 16:49:51 -0500 Subject: [PATCH 32/44] add archiver section to quidel params --- quidel_covidtest/params.json.template | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/quidel_covidtest/params.json.template b/quidel_covidtest/params.json.template index a2996b032..797249fcd 100644 --- a/quidel_covidtest/params.json.template +++ b/quidel_covidtest/params.json.template @@ -20,6 +20,15 @@ "wip_signal": [""], "test_mode": false }, + "archive": { + "aws_credentials": { + "aws_access_key_id": "{{ delphi_aws_access_key_id }}", + "aws_secret_access_key": "{{ delphi_aws_secret_access_key }}" + }, + "bucket_name": "delphi-covidcast-indicator-output", + "cache_dir": "./archivediffer_cache", + "indicator_prefix": "quidel" + } "validation": { "common": { "data_source": "quidel", From 963bb5a773de5ce7f70bc89b6f784a81f3903ab6 Mon Sep 17 00:00:00 2001 From: Jingjing Tang Date: Wed, 2 Feb 2022 16:51:37 -0500 Subject: [PATCH 33/44] fix params --- quidel_covidtest/params.json.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quidel_covidtest/params.json.template b/quidel_covidtest/params.json.template index 797249fcd..e96d2ccbc 100644 --- a/quidel_covidtest/params.json.template +++ b/quidel_covidtest/params.json.template @@ -28,7 +28,7 @@ "bucket_name": "delphi-covidcast-indicator-output", "cache_dir": "./archivediffer_cache", "indicator_prefix": "quidel" - } + }, "validation": { "common": { "data_source": "quidel", From ecc66dd32ff1b29cdcdf0a7215a94fc1d0abb3de Mon Sep 17 00:00:00 2001 From: rafaelcatoia Date: Thu, 3 Feb 2022 17:59:01 -0300 Subject: [PATCH 34/44] updetd zip_pop.csv --- .../delphi_utils/data/2019/zip_pop.csv | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/_delphi_utils_python/delphi_utils/data/2019/zip_pop.csv b/_delphi_utils_python/delphi_utils/data/2019/zip_pop.csv index 5c95ac758..ffec76d51 100644 --- a/_delphi_utils_python/delphi_utils/data/2019/zip_pop.csv +++ b/_delphi_utils_python/delphi_utils/data/2019/zip_pop.csv @@ -19549,15 +19549,19 @@ zip,pop 57752,317 57754,4067 57755,119 +57756,1126 57758,219 57759,585 57760,1395 57761,1360 57762,547 57763,266 +57764,1923 57766,224 57767,167 57769,3915 +57770,5271 +57772,2048 57773,145 57775,251 57776,15 @@ -19572,6 +19576,7 @@ zip,pop 57791,213 57792,143 57793,2061 +57794,644 57799,707 58001,54 58002,27 @@ -32756,21 +32761,26 @@ zip,pop 99551,677 99552,373 99553,1092 +99554,677 99555,224 99556,2659 99557,784 99558,79 99559,8248 99561,451 +99563,938 99564,88 99565,76 99566,183 +99566,192 99567,9090 99568,295 99569,64 99571,170 99572,313 +99573,1115 99573,1064 +99574,2348 99574,2242 99575,113 99576,2640 @@ -32778,7 +32788,10 @@ zip,pop 99578,319 99579,106 99580,116 +99581,762 99583,37 +99585,417 +99586,605 99586,577 99587,2220 99588,958 @@ -32787,6 +32800,7 @@ zip,pop 99591,107 99602,166 99603,10427 +99604,1093 99605,223 99606,457 99607,233 @@ -32797,6 +32811,7 @@ zip,pop 99613,372 99614,690 99615,12347 +99620,577 99621,781 99622,346 99624,86 @@ -32806,6 +32821,7 @@ zip,pop 99628,449 99630,206 99631,241 +99632,813 99633,456 99634,382 99636,517 @@ -32820,18 +32836,23 @@ zip,pop 99647,42 99648,110 99649,78 +99650,568 99651,65 99652,4506 99653,155 99654,63494 99655,723 99656,27 +99657,329 +99658,329 99659,422 99660,503 99661,1040 +99662,480 99663,438 99664,5226 99665,77 +99666,189 99667,79 99668,92 99669,15038 @@ -32840,6 +32861,7 @@ zip,pop 99672,3925 99674,1757 99676,1881 +99677,88 99677,84 99678,903 99679,403 @@ -32850,11 +32872,13 @@ zip,pop 99684,725 99685,4438 99686,3824 +99686,4005 99688,3358 99689,579 99690,302 99691,88 99692,159 +99693,248 99693,236 99694,1840 99695,6 From 0a2eeb4a44b9ade527def6950ed7ee30606015c1 Mon Sep 17 00:00:00 2001 From: rafaelcatoia Date: Thu, 3 Feb 2022 18:28:33 -0300 Subject: [PATCH 35/44] changed readme file --- _delphi_utils_python/data_proc/geomap/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/_delphi_utils_python/data_proc/geomap/README.md b/_delphi_utils_python/data_proc/geomap/README.md index 864946cb3..137adadec 100644 --- a/_delphi_utils_python/data_proc/geomap/README.md +++ b/_delphi_utils_python/data_proc/geomap/README.md @@ -17,11 +17,11 @@ You can see consistency checks and diffs with old sources in ./consistency_check We support the following geocodes. -- The ZIP code and the FIPS code are the most granular geocodes we support. - - The [ZIP code](https://en.wikipedia.org/wiki/ZIP_Code) is a US postal code used by the USPS and the [FIPS code](https://en.wikipedia.org/wiki/FIPS_county_code) is an identifier for US counties and other associated territories. The ZIP code is five digit code (with leading zeros). +- The ZIP code and the FIPS code are the most granular geocodes we support. + - The [ZIP code](https://en.wikipedia.org/wiki/ZIP_Code) is a US postal code used by the USPS and the [FIPS code](https://en.wikipedia.org/wiki/FIPS_county_code) is an identifier for US counties and other associated territories. The ZIP code is five digit code (with leading zeros). - The FIPS code is a five digit code (with leading zeros), where the first two digits are a two-digit state code and the last three are a three-digit county code (see this [US Census Bureau page](https://www.census.gov/library/reference/code-lists/ansi.html) for detailed information). -- The Metropolitan Statistical Area (MSA) code refers to regions around cities (these are sometimes referred to as CBSA codes). More information on these can be found at the [US Census Bureau](https://www.census.gov/programs-surveys/metro-micro/about.html). - - We are reserving 10001-10099 for states codes of the form 100XX where XX is the FIPS code for the state (the current smallest CBSA is 10100). In the case that the CBSA codes change then it should be verified that these are not used. +- The Metropolitan Statistical Area (MSA) code refers to regions around cities (these are sometimes referred to as CBSA codes). More information on these can be found at the [US Census Bureau](https://www.cen_sus.gov/programs-surveys/metro-micro/about.html). + - We are reserving 10001-10099 for states codes of the form 100XX where XX is the FIPS code for the state (the current smallest CBSA is 10100). In the case that the CBSA codes change then it should be verified that these are not used. - State codes are a series of equivalent identifiers for US state. They include the state name, the state number (state_id), and the state two-letter abbreviation (state_code). The state number is the state FIPS code. See [here](https://en.wikipedia.org/wiki/List_of_U.S._state_and_territory_abbreviations) for more. - The Hospital Referral Region (HRR) and the Hospital Service Area (HSA). More information [here](https://www.dartmouthatlas.org/covid-19/hrr-mapping/). - The JHU signal contains its own geographic identifier, labeled the UID. Documentation is provided at [their repo](https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data#uid-lookup-table-logic). Its FIPS codes depart in some special cases, so we produce manual changes listed below. @@ -30,7 +30,7 @@ We support the following geocodes. The source files are requested from a government URL when `geo_data_proc.py` is run (see the top of said script for the URLs). Below we describe the locations to find updated versions of the source files, if they are ever needed. -- ZIP -> FIPS (county) population tables available from [US Census](https://www.census.gov/geographies/reference-files/time-series/geo/relationship-files.html#par_textimage_674173622). This file contains the population of the intersections between ZIP and FIPS regions, allowing the creation of a population-weighted transform between the two. +- ZIP -> FIPS (county) population tables available from [US Census](https://www.census.gov/geographies/reference-files/time-series/geo/relationship-files.html#par_textimage_674173622). This file contains the population of the intersections between ZIP and FIPS regions, allowing the creation of a population-weighted transform between the two. 24 ZIPs did not have population number information associated to them, so we filled those values manually using information available in [zipdatamaps website](www.zipdatamaps.com). - ZIP -> HRR -> HSA crosswalk file comes from the 2018 version at the [Dartmouth Atlas Project](https://atlasdata.dartmouth.edu/static/supp_research_data). - FIPS -> MSA crosswalk file comes from the September 2018 version of the delineation files at the [US Census Bureau](https://www.census.gov/geographies/reference-files/time-series/demo/metro-micro/delineation-files.html). - State Code -> State ID -> State Name comes from the ANSI standard at the [US Census](https://www.census.gov/library/reference/code-lists/ansi.html#par_textimage_3). The first two digits of a FIPS codes should match the state code here. @@ -60,6 +60,6 @@ The rest of the crosswalk tables are derived from the mappings above. We provide - MSA tables from March 2020 [here](https://www.census.gov/geographies/reference-files/time-series/demo/metro-micro/delineation-files.html). This file seems to differ in a few fips codes from the source for the 02_20_uszip file which Jingjing constructed. There are at least 10 additional fips in 03_20_msa that are not in the uszip file, and one of the msa codes seems to be incorrect: 49020 (a google search confirms that it is incorrect in uszip and correct in the census data). - MSA tables from 2019 [here](https://apps.bea.gov/regional/docs/msalist.cfm) -## Notes +## Notes - The NAs in the coding currently zero-fills. From b46ebb8c80df97206dcd73cbaa70088ebc0e5d10 Mon Sep 17 00:00:00 2001 From: rafaelcatoia Date: Thu, 3 Feb 2022 20:06:43 -0300 Subject: [PATCH 36/44] typo fixex --- _delphi_utils_python/data_proc/geomap/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_delphi_utils_python/data_proc/geomap/README.md b/_delphi_utils_python/data_proc/geomap/README.md index 137adadec..95059c2ba 100644 --- a/_delphi_utils_python/data_proc/geomap/README.md +++ b/_delphi_utils_python/data_proc/geomap/README.md @@ -18,9 +18,9 @@ You can see consistency checks and diffs with old sources in ./consistency_check We support the following geocodes. - The ZIP code and the FIPS code are the most granular geocodes we support. - - The [ZIP code](https://en.wikipedia.org/wiki/ZIP_Code) is a US postal code used by the USPS and the [FIPS code](https://en.wikipedia.org/wiki/FIPS_county_code) is an identifier for US counties and other associated territories. The ZIP code is five digit code (with leading zeros). + - The [ZIP code](https://en.wikipedia.org/wiki/ZIP_Code) is a US postal code used by the USPS and the [FIPS code](https://en.wikipedia.org/wiki/FIPS_county_code) is an identifier for US counties and other associated territories. The ZIP code is five digit code (with leading zeros). - The FIPS code is a five digit code (with leading zeros), where the first two digits are a two-digit state code and the last three are a three-digit county code (see this [US Census Bureau page](https://www.census.gov/library/reference/code-lists/ansi.html) for detailed information). -- The Metropolitan Statistical Area (MSA) code refers to regions around cities (these are sometimes referred to as CBSA codes). More information on these can be found at the [US Census Bureau](https://www.cen_sus.gov/programs-surveys/metro-micro/about.html). +- The Metropolitan Statistical Area (MSA) code refers to regions around cities (these are sometimes referred to as CBSA codes). More information on these can be found at the [US Census Bureau](https://www.census.gov/programs-surveys/metro-micro/about.html). - We are reserving 10001-10099 for states codes of the form 100XX where XX is the FIPS code for the state (the current smallest CBSA is 10100). In the case that the CBSA codes change then it should be verified that these are not used. - State codes are a series of equivalent identifiers for US state. They include the state name, the state number (state_id), and the state two-letter abbreviation (state_code). The state number is the state FIPS code. See [here](https://en.wikipedia.org/wiki/List_of_U.S._state_and_territory_abbreviations) for more. - The Hospital Referral Region (HRR) and the Hospital Service Area (HSA). More information [here](https://www.dartmouthatlas.org/covid-19/hrr-mapping/). From bd536ce24fc0f766e1c6744ddf7194ff65f194d7 Mon Sep 17 00:00:00 2001 From: Rafael Catoia <36720846+rafaelcatoia@users.noreply.github.com> Date: Fri, 4 Feb 2022 12:52:58 -0300 Subject: [PATCH 37/44] Update _delphi_utils_python/data_proc/geomap/README.md Co-authored-by: Katie Mazaitis --- _delphi_utils_python/data_proc/geomap/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_delphi_utils_python/data_proc/geomap/README.md b/_delphi_utils_python/data_proc/geomap/README.md index 95059c2ba..84fdbefb2 100644 --- a/_delphi_utils_python/data_proc/geomap/README.md +++ b/_delphi_utils_python/data_proc/geomap/README.md @@ -30,7 +30,7 @@ We support the following geocodes. The source files are requested from a government URL when `geo_data_proc.py` is run (see the top of said script for the URLs). Below we describe the locations to find updated versions of the source files, if they are ever needed. -- ZIP -> FIPS (county) population tables available from [US Census](https://www.census.gov/geographies/reference-files/time-series/geo/relationship-files.html#par_textimage_674173622). This file contains the population of the intersections between ZIP and FIPS regions, allowing the creation of a population-weighted transform between the two. 24 ZIPs did not have population number information associated to them, so we filled those values manually using information available in [zipdatamaps website](www.zipdatamaps.com). +- ZIP -> FIPS (county) population tables available from [US Census](https://www.census.gov/geographies/reference-files/time-series/geo/relationship-files.html#par_textimage_674173622). This file contains the population of the intersections between ZIP and FIPS regions, allowing the creation of a population-weighted transform between the two. As of 4 February 2022, this source did not include population information for 24 ZIPs that appear in our indicators. We have added those values manually using information available from the [zipdatamaps website](www.zipdatamaps.com). - ZIP -> HRR -> HSA crosswalk file comes from the 2018 version at the [Dartmouth Atlas Project](https://atlasdata.dartmouth.edu/static/supp_research_data). - FIPS -> MSA crosswalk file comes from the September 2018 version of the delineation files at the [US Census Bureau](https://www.census.gov/geographies/reference-files/time-series/demo/metro-micro/delineation-files.html). - State Code -> State ID -> State Name comes from the ANSI standard at the [US Census](https://www.census.gov/library/reference/code-lists/ansi.html#par_textimage_3). The first two digits of a FIPS codes should match the state code here. From efbb07ebc652c0798cdfa313faa4d11009e612ca Mon Sep 17 00:00:00 2001 From: rafaelcatoia Date: Fri, 4 Feb 2022 13:55:44 -0300 Subject: [PATCH 38/44] added the missing population in a txt file --- .../data_proc/geomap/geo_data_proc.py | 20 ++++++--------- .../data_proc/geomap/zip_pop_filling.txt | 25 +++++++++++++++++++ 2 files changed, 32 insertions(+), 13 deletions(-) create mode 100644 _delphi_utils_python/data_proc/geomap/zip_pop_filling.txt diff --git a/_delphi_utils_python/data_proc/geomap/geo_data_proc.py b/_delphi_utils_python/data_proc/geomap/geo_data_proc.py index 88347f2e2..a9c67c708 100755 --- a/_delphi_utils_python/data_proc/geomap/geo_data_proc.py +++ b/_delphi_utils_python/data_proc/geomap/geo_data_proc.py @@ -32,6 +32,7 @@ FIPS_POPULATION_URL = f"https://www2.census.gov/programs-surveys/popest/datasets/2010-{YEAR}/counties/totals/co-est{YEAR}-alldata.csv" FIPS_PUERTO_RICO_POPULATION_URL = "https://www2.census.gov/geo/docs/maps-data/data/rel/zcta_county_rel_10.txt?" STATE_HHS_FILE = "hhs.txt" +ZIP_POP_MISSING_FILE = "zip_pop_filling.txt" # Out files FIPS_STATE_OUT_FILENAME = "fips_state_table.csv" @@ -365,20 +366,13 @@ def derive_zip_population_table(): df = census_pop.merge(fz_df, on="fips", how="left") df["pop"] = df["pop"].multiply(df["weight"], axis=0) df = df.drop(columns=["fips", "weight"]).groupby("zip").sum().dropna().reset_index() - ## filling population NAs for specific zips on zip_pop_missing Issue #0648 - ## cheking if each zip still missing, and concatenating if True - - zip_pop_missing = pd.DataFrame( - { - "zip": ['57756', '57764', '57770', '57772', '57794', '99554', '99563', '99566', - '99573', '99574', '99581', '99585', '99586', '99604', '99620', '99632', - '99650', '99657', '99658', '99662', '99666', '99677', '99686', '99693'], - "pop": [1126, 1923, 5271, 2048, 644, 677, 938, 192, - 1115, 2348, 762, 417, 605, 1093, 577, 813, - 568, 329, 329, 480, 189, 88, 4005, 248] - } - ) + ## loading populatoin of some zips- #Issue 0648 + zip_pop_missing = pd.read_table( + ZIP_POP_MISSING_FILE,sep=",", + dtype={"zip":str,"pop":np.int32} + ) + ## cheking if each zip still missing, and concatenating if True for x_zip in zip_pop_missing['zip']: if x_zip not in df['zip']: df = pd.concat([df, zip_pop_missing[zip_pop_missing['zip'] == x_zip]], diff --git a/_delphi_utils_python/data_proc/geomap/zip_pop_filling.txt b/_delphi_utils_python/data_proc/geomap/zip_pop_filling.txt new file mode 100644 index 000000000..fef98c92e --- /dev/null +++ b/_delphi_utils_python/data_proc/geomap/zip_pop_filling.txt @@ -0,0 +1,25 @@ +zip,pop +57756,1126 +57764,1923 +57770,5271 +57772,2048 +57794,644 +99554,677 +99563,938 +99566,192 +99573,1115 +99574,2348 +99581,762 +99585,417 +99586,605 +99604,1093 +99620,577 +99632,813 +99650,568 +99657,329 +99658,616 +99662,480 +99666,189 +99677,88 +99686,4005 +99693,248 From 1523879a006d08d99e00d0650e4eab7452c5405d Mon Sep 17 00:00:00 2001 From: rafaelcatoia Date: Fri, 4 Feb 2022 14:07:31 -0300 Subject: [PATCH 39/44] changed txt to csv --- .../data_proc/geomap/geo_data_proc.py | 4 +-- .../data_proc/geomap/zip_pop_filling.csv | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 _delphi_utils_python/data_proc/geomap/zip_pop_filling.csv diff --git a/_delphi_utils_python/data_proc/geomap/geo_data_proc.py b/_delphi_utils_python/data_proc/geomap/geo_data_proc.py index a9c67c708..45e4e4ee3 100755 --- a/_delphi_utils_python/data_proc/geomap/geo_data_proc.py +++ b/_delphi_utils_python/data_proc/geomap/geo_data_proc.py @@ -32,7 +32,7 @@ FIPS_POPULATION_URL = f"https://www2.census.gov/programs-surveys/popest/datasets/2010-{YEAR}/counties/totals/co-est{YEAR}-alldata.csv" FIPS_PUERTO_RICO_POPULATION_URL = "https://www2.census.gov/geo/docs/maps-data/data/rel/zcta_county_rel_10.txt?" STATE_HHS_FILE = "hhs.txt" -ZIP_POP_MISSING_FILE = "zip_pop_filling.txt" +ZIP_POP_MISSING_FILE = "zip_pop_filling.csv" # Out files FIPS_STATE_OUT_FILENAME = "fips_state_table.csv" @@ -368,7 +368,7 @@ def derive_zip_population_table(): df = df.drop(columns=["fips", "weight"]).groupby("zip").sum().dropna().reset_index() ## loading populatoin of some zips- #Issue 0648 - zip_pop_missing = pd.read_table( + zip_pop_missing = pd.read_csv( ZIP_POP_MISSING_FILE,sep=",", dtype={"zip":str,"pop":np.int32} ) diff --git a/_delphi_utils_python/data_proc/geomap/zip_pop_filling.csv b/_delphi_utils_python/data_proc/geomap/zip_pop_filling.csv new file mode 100644 index 000000000..fef98c92e --- /dev/null +++ b/_delphi_utils_python/data_proc/geomap/zip_pop_filling.csv @@ -0,0 +1,25 @@ +zip,pop +57756,1126 +57764,1923 +57770,5271 +57772,2048 +57794,644 +99554,677 +99563,938 +99566,192 +99573,1115 +99574,2348 +99581,762 +99585,417 +99586,605 +99604,1093 +99620,577 +99632,813 +99650,568 +99657,329 +99658,616 +99662,480 +99666,189 +99677,88 +99686,4005 +99693,248 From f473a3c4c99848d75caf5618dadd8527bb2b2acb Mon Sep 17 00:00:00 2001 From: rafaelcatoia Date: Fri, 4 Feb 2022 15:56:15 -0300 Subject: [PATCH 40/44] deleting txt file --- .../data_proc/geomap/zip_pop_filling.txt | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 _delphi_utils_python/data_proc/geomap/zip_pop_filling.txt diff --git a/_delphi_utils_python/data_proc/geomap/zip_pop_filling.txt b/_delphi_utils_python/data_proc/geomap/zip_pop_filling.txt deleted file mode 100644 index fef98c92e..000000000 --- a/_delphi_utils_python/data_proc/geomap/zip_pop_filling.txt +++ /dev/null @@ -1,25 +0,0 @@ -zip,pop -57756,1126 -57764,1923 -57770,5271 -57772,2048 -57794,644 -99554,677 -99563,938 -99566,192 -99573,1115 -99574,2348 -99581,762 -99585,417 -99586,605 -99604,1093 -99620,577 -99632,813 -99650,568 -99657,329 -99658,616 -99662,480 -99666,189 -99677,88 -99686,4005 -99693,248 From 5789cda37f8ae5a1e350563500e87a3a666ed8cf Mon Sep 17 00:00:00 2001 From: rafaelcatoia Date: Fri, 4 Feb 2022 16:01:32 -0300 Subject: [PATCH 41/44] letting only the csv file --- _delphi_utils_python/delphi_utils/data/2019/zip_pop.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_delphi_utils_python/delphi_utils/data/2019/zip_pop.csv b/_delphi_utils_python/delphi_utils/data/2019/zip_pop.csv index ffec76d51..4bb1b1e6c 100644 --- a/_delphi_utils_python/delphi_utils/data/2019/zip_pop.csv +++ b/_delphi_utils_python/delphi_utils/data/2019/zip_pop.csv @@ -32844,7 +32844,7 @@ zip,pop 99655,723 99656,27 99657,329 -99658,329 +99658,616 99659,422 99660,503 99661,1040 From 724046bcaa8fed4efccc80d702b7038f5181a7d2 Mon Sep 17 00:00:00 2001 From: Katie Mazaitis Date: Tue, 8 Feb 2022 11:07:09 -0500 Subject: [PATCH 42/44] [quidel] Activate archivediffer in prod params --- ansible/templates/quidel_covidtest-params-prod.json.j2 | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ansible/templates/quidel_covidtest-params-prod.json.j2 b/ansible/templates/quidel_covidtest-params-prod.json.j2 index 35119ad02..fe605206b 100644 --- a/ansible/templates/quidel_covidtest-params-prod.json.j2 +++ b/ansible/templates/quidel_covidtest-params-prod.json.j2 @@ -48,6 +48,15 @@ ] } }, + "archive": { + "aws_credentials": { + "aws_access_key_id": "{{ delphi_aws_access_key_id }}", + "aws_secret_access_key": "{{ delphi_aws_secret_access_key }}" + }, + "bucket_name": "delphi-covidcast-indicator-output", + "cache_dir": "./archivediffer_cache", + "indicator_prefix": "quidel" + }, "delivery": { "delivery_dir": "/common/covidcast/receiving/quidel" } From c8294f42ee4b332d16732026d2692f01e57adb25 Mon Sep 17 00:00:00 2001 From: Delphi Deploy Bot Date: Tue, 8 Feb 2022 18:32:23 +0000 Subject: [PATCH 43/44] chore: bump delphi_utils to 0.3.1 --- _delphi_utils_python/.bumpversion.cfg | 2 +- _delphi_utils_python/delphi_utils/__init__.py | 2 +- _delphi_utils_python/setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/_delphi_utils_python/.bumpversion.cfg b/_delphi_utils_python/.bumpversion.cfg index 8ce49f20b..988c45f97 100644 --- a/_delphi_utils_python/.bumpversion.cfg +++ b/_delphi_utils_python/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.3.0 +current_version = 0.3.1 commit = True message = chore: bump delphi_utils to {new_version} tag = False diff --git a/_delphi_utils_python/delphi_utils/__init__.py b/_delphi_utils_python/delphi_utils/__init__.py index 898e40e4b..6ea299174 100644 --- a/_delphi_utils_python/delphi_utils/__init__.py +++ b/_delphi_utils_python/delphi_utils/__init__.py @@ -15,4 +15,4 @@ from .nancodes import Nans from .weekday import Weekday -__version__ = "0.3.0" +__version__ = "0.3.1" diff --git a/_delphi_utils_python/setup.py b/_delphi_utils_python/setup.py index 779ef0fd4..cfbafc9f0 100644 --- a/_delphi_utils_python/setup.py +++ b/_delphi_utils_python/setup.py @@ -26,7 +26,7 @@ setup( name="delphi_utils", - version="0.3.0", + version="0.3.1", description="Shared Utility Functions for Indicators", long_description=long_description, long_description_content_type="text/markdown", From 6019bc4bea6959eba96c45f38d73b8c919999cee Mon Sep 17 00:00:00 2001 From: Delphi Deploy Bot Date: Tue, 8 Feb 2022 18:32:23 +0000 Subject: [PATCH 44/44] chore: bump covidcast-indicators to 0.3.2 --- .bumpversion.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 3895e6df1..e208d94af 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.3.1 +current_version = 0.3.2 commit = True message = chore: bump covidcast-indicators to {new_version} tag = False