diff --git a/docs/run.md b/docs/run.md index 36906182..d91ab8f0 100644 --- a/docs/run.md +++ b/docs/run.md @@ -4,6 +4,10 @@ The two basic ways to run the simulation are a Python package and command line interface. Both interfaces take simulation parameters as a configuration file and several other user inputs as function arguments or command line arguments. +For a quick start option, use the Jupyter notebook +[run_from_xlsx.ipynb](run_from_xlsx.ipynb) with the provided Excel spreadsheet +template to configure the simulation. + ## Configuration The configuration file contains all parameters needed for a single simulation diff --git a/examples/notebooks/data/scenarios.csv b/examples/notebooks/data/scenarios.csv new file mode 100644 index 00000000..78a6053b --- /dev/null +++ b/examples/notebooks/data/scenarios.csv @@ -0,0 +1,5 @@ +name,inspection/sample_strategy,inspection/hypergeometric/detection_level +hypergeometric 0.01,hypergeometric,0.01 +hypergeometric 0.05,hypergeometric,0.05 +hypergeometric 0.1,hypergeometric,0.1 +proportion 0.02,proportion, diff --git a/examples/notebooks/data/scenarios_config.csv b/examples/notebooks/data/scenarios_long.csv similarity index 100% rename from examples/notebooks/data/scenarios_config.csv rename to examples/notebooks/data/scenarios_long.csv diff --git a/examples/notebooks/data/user_friendly_config.xlsx b/examples/notebooks/data/user_friendly_config.xlsx new file mode 100644 index 00000000..1a6ad998 Binary files /dev/null and b/examples/notebooks/data/user_friendly_config.xlsx differ diff --git a/examples/notebooks/results/user_friendly_config_results.xlsx b/examples/notebooks/results/user_friendly_config_results.xlsx new file mode 100644 index 00000000..0e917143 Binary files /dev/null and b/examples/notebooks/results/user_friendly_config_results.xlsx differ diff --git a/examples/notebooks/run_from_xlsx.ipynb b/examples/notebooks/run_from_xlsx.ipynb index 54a99950..12c10757 100644 --- a/examples/notebooks/run_from_xlsx.ipynb +++ b/examples/notebooks/run_from_xlsx.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -8,7 +9,7 @@ "\n", "## Test example \n", "\n", - "First, we complete the Excel template `data/small_config.xlsx` with the minimal configuration parameter required to run the simulation.\n", + "First, we complete the Excel template `data/user_friendly_config.xlsx` with the configuration parameters required to run the simulation.\n", "\n", "The Excel configuration should include all parameters related to:\n", "1. [consignments](../../docs/consignments.md) (what is imported, from where, in what amounts), \n", @@ -29,14 +30,15 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# Load required functions and packages\n", "\n", "from popsborder.simulation import run_simulation\n", - "from popsborder.inputs import load_configuration\n" + "from popsborder.inputs import load_configuration\n", + "from popsborder.outputs import print_totals_as_text" ] }, { @@ -48,11 +50,11 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ - "xlsx_loc = \"data/small_config.xlsx\"" + "xlsx_loc = \"data/user_friendly_config.xlsx\"" ] }, { @@ -64,11 +66,11 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ - "base_config = load_configuration(xlsx_loc)" + "base_config = load_configuration(xlsx_loc, sheet=None, key_column=\"D\", value_column=\"B\")" ] }, { @@ -82,6 +84,16 @@ "We can include the `pretty` and `verbose` parameters below to visualize the contamination and output directly in the notebook." ] }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "num_simulations=1\n", + "num_consignments=4" + ] + }, { "cell_type": "code", "execution_count": 5, @@ -91,17 +103,17 @@ "name": "stdout", "output_type": "stream", "text": [ - "━━ Consignment ━━ Boxes: 3 ━━ Items: 60 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n", - "🐛 ✿ ✿ 🐛 ✿ 🐛 🐛 🐛 🐛 🐛 ✿ ✿ 🐛 🐛 ✿ ✿ 🐛 🐛 ✿ ✿ | ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ 🐛 ✿ ✿ 🐛 🐛 ✿ ✿ ✿ ✿ ✿ | 🐛 🐛 🐛 ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿\n", - "Inspection worked, found contaminant [TP]\n", - "━━ Consignment ━━ Boxes: 2 ━━ Items: 40 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n", - "🐛 🐛 🐛 ✿ 🐛 🐛 🐛 ✿ 🐛 ✿ 🐛 🐛 ✿ ✿ ✿ ✿ 🐛 ✿ 🐛 🐛 | ✿ 🐛 ✿ 🐛 ✿ ✿ 🐛 🐛 ✿ ✿ ✿ ✿ 🐛 ✿ 🐛 ✿ 🐛 🐛 🐛 🐛\n", - "Inspection worked, found contaminant [TP]\n", - "━━ Consignment ━━ Boxes: 5 ━━ Items: 100 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n", - "✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ 🐛 ✿ 🐛 🐛 ✿ | 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ | ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 | ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ 🐛 ✿ ✿ 🐛 🐛 🐛 ✿ ✿ ✿ ✿ ✿ ✿ | ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ 🐛 ✿ ✿\n", - "Inspection worked, found contaminant [TP]\n", - "━━ Consignment ━━ Boxes: 4 ━━ Items: 80 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n", - "✿ ✿ ✿ 🐛 ✿ 🐛 ✿ 🐛 ✿ 🐛 ✿ ✿ 🐛 🐛 🐛 ✿ ✿ ✿ ✿ ✿ | 🐛 ✿ ✿ ✿ ✿ ✿ 🐛 ✿ 🐛 ✿ ✿ ✿ ✿ 🐛 ✿ ✿ 🐛 ✿ ✿ ✿ | ✿ ✿ ✿ 🐛 🐛 🐛 🐛 🐛 ✿ 🐛 ✿ ✿ 🐛 🐛 ✿ ✿ ✿ 🐛 ✿ ✿ | ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 🐛 🐛 ✿\n", + "━━ Consignment ━━ Boxes: 5 ━━ Items: 250 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n", + "✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ | ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ | ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ | ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ | 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿\n", + "Inspection failed, missed 5 boxes with contaminants [FN]\n", + "━━ Consignment ━━ Boxes: 1 ━━ Items: 50 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n", + "✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿\n", + "Inspection failed, missed 1 boxes with contaminants [FN]\n", + "━━ Consignment ━━ Boxes: 10 ━━ Items: 500 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n", + "✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ | ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ | ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ | ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ | ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ | 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 | ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ | ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ | ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ | ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿\n", + "Inspection failed, missed 10 boxes with contaminants [FN]\n", + "━━ Consignment ━━ Boxes: 7 ━━ Items: 350 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n", + "✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ | ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ | ✿ 🐛 ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ | ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ | ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ | ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ | ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ 🐛 ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ ✿ 🐛 ✿ ✿ ✿ ✿ ✿\n", "Inspection worked, found contaminant [TP]\n", "Missing {missing:.0f}% of contaminated consignments.\n" ] @@ -111,13 +123,72 @@ "result = run_simulation(\n", " config=base_config,\n", " seed=42,\n", - " num_simulations=1,\n", - " num_consignments=4,\n", + " num_simulations=num_simulations,\n", + " num_consignments=num_consignments,\n", " pretty=\"boxes\",\n", " verbose=True\n", " )\n" ] }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "Simulation parameters:\n", + "----------------------------------------------------------\n", + "consignments:\n", + "\t Number consignments simulated: 4\n", + "\t Avg. number of boxes per consignment: 6\n", + "\t Avg. number of items per consignment: 288\n", + "contamination:\n", + "\t unit: item\n", + "\t type: fixed_value\n", + "\t\t contamination rate: 0.05\n", + "\t contaminant arrangement: random\n", + "inspection:\n", + "\t unit: item\n", + "\t sample strategy: proportion\n", + "\t\t value: 0.02\n", + "\t selection strategy: random\n", + "\t tolerance level: 0\n", + "\n", + "\n", + "Simulation results: (averaged across all simulation runs)\n", + "----------------------------------------------------------\n", + "Avg. % contaminated consignments slipped: 75.00%\n", + "Adjusted avg. % contaminated consignments slipped (excluding slipped consignments with contamination rates below tolerance level): 75.00%\n", + "Avg. num. consignments slipped: 3\n", + "Avg. num. slipped consignments within tolerance level: 0\n", + "Avg. num. consignments intercepted: 1\n", + "Total number of slipped contaminants: 39\n", + "Total number of intercepted contaminants: 18\n", + "Contamination rate:\n", + "\tOverall avg: 0.047\n", + "\tSlipped consignments avg.: 0.046\n", + "\tSlipped consignments max.: 0.050\n", + "\tIntercepted consignments avg.: 0.051\n", + "\tIntercepted consignments max.: 0.051\n", + "Avg. number of boxes opened per consignment:\n", + "\t to completion: 4\n", + "\t to detection: 3\n", + "Avg. number of items inspected per consignment:\n", + "\t to completion: 6\n", + "\t to detection: 5\n", + "Avg. % contaminated items unreported if sample ends at detection: 0.00%\n" + ] + } + ], + "source": [ + "print_totals_as_text(num_consignments, base_config, totals=result)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -131,12 +202,11 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ - "from popsborder.outputs import save_simulation_result_to_pandas \n", - "import pandas" + "from popsborder.outputs import save_simulation_result_to_pandas " ] }, { @@ -148,7 +218,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -164,7 +234,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -214,27 +284,27 @@ " \n", " \n", " 0\n", + " 75.0\n", + " 3.0\n", " 0.0\n", - " 0.0\n", - " 0.0\n", - " 4.0\n", + " 1.0\n", " 4.0\n", - " 14.0\n", - " 280.0\n", + " 23.0\n", + " 1150.0\n", " 3.5\n", - " 1.25\n", - " 100.0\n", + " 3.0\n", + " 60.869565\n", " ...\n", - " 53.333333\n", - " 0.345625\n", - " None\n", - " None\n", - " 0.55\n", - " 0.345625\n", - " 0\n", - " 1\n", - " 85.0\n", " 0.0\n", + " 0.047357\n", + " 0.05\n", + " 0.046\n", + " 0.051429\n", + " 0.051429\n", + " 1\n", + " 1\n", + " 18.0\n", + " 39.0\n", " \n", " \n", "\n", @@ -243,33 +313,33 @@ ], "text/plain": [ " missing false_neg missed_within_tolerance intercepted num_inspections \\\n", - "0 0.0 0.0 0.0 4.0 4.0 \n", + "0 75.0 3.0 0.0 1.0 4.0 \n", "\n", " num_boxes num_items avg_boxes_opened_completion \\\n", - "0 14.0 280.0 3.5 \n", + "0 23.0 1150.0 3.5 \n", "\n", " avg_boxes_opened_detection pct_boxes_opened_completion ... \\\n", - "0 1.25 100.0 ... \n", + "0 3.0 60.869565 ... \n", "\n", " pct_contaminant_unreported_if_detection true_contamination_rate \\\n", - "0 53.333333 0.345625 \n", + "0 0.0 0.047357 \n", "\n", " max_missed_contamination_rate avg_missed_contamination_rate \\\n", - "0 None None \n", + "0 0.05 0.046 \n", "\n", " max_intercepted_contamination_rate avg_intercepted_contamination_rate \\\n", - "0 0.55 0.345625 \n", + "0 0.051429 0.051429 \n", "\n", - " false_negative_present true_positive_present \\\n", - "0 0 1 \n", + " false_negative_present true_positive_present \\\n", + "0 1 1 \n", "\n", - " total_intercepted_contaminants total_missed_contaminants \n", - "0 85.0 0.0 \n", + " total_intercepted_contaminants total_missed_contaminants \n", + "0 18.0 39.0 \n", "\n", "[1 rows x 25 columns]" ] }, - "execution_count": 8, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -291,8 +361,251 @@ "metadata": {}, "outputs": [], "source": [ - "results_pd.to_excel('data/small_config_results.xlsx')" + "results_pd.to_excel('results/user_friendly_config_results.xlsx')" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run multiple scenarios\n", + "\n", + "Run the simulation for multiple scenarios at once to compare outcomes." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "from popsborder.scenarios import run_scenarios\n", + "from popsborder.inputs import load_scenario_table\n", + "from popsborder.outputs import save_scenario_result_to_pandas\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load a CSV with the scenarios to run. Each row in the table is a scenario and the columns store the parameters to change for each scenario." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "scenarios_path = \"data/scenarios.csv\"" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "scenario_table=load_scenario_table(scenarios_path)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Each scenario uses a common base configuration file but the parameters in the scenario table are overwritten with the values specified for each scenario." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "num_simulations=10\n", + "num_consignments=100" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running scenario: hypergeometric 0.01\n", + "Running scenario: hypergeometric 0.05\n", + "Running scenario: hypergeometric 0.1\n", + "Running scenario: proportion 0.02\n" + ] + } + ], + "source": [ + "results = run_scenarios(\n", + " config=base_config,\n", + " scenario_table=scenario_table,\n", + " seed=42,\n", + " num_simulations=num_simulations,\n", + " num_consignments=num_consignments,\n", + " detailed=False,\n", + ")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Save scenario results to a pandas dataframe" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "results_df = save_scenario_result_to_pandas(\n", + " results,\n", + " config_columns=[\n", + " \"name\",\n", + " \"contamination/contamination_rate/value\",\n", + " \"contamination/arrangement\",\n", + " \"inspection/selection_strategy\",\n", + " \"inspection/unit\",\n", + " \"inspection/sample_strategy\",\n", + " \"inspection/hypergeometric/detection_level\",\n", + " ],\n", + " result_columns=[\n", + " \"true_contamination_rate\",\n", + " \"max_missed_contamination_rate\",\n", + " \"avg_missed_contamination_rate\",\n", + " \"max_intercepted_contamination_rate\",\n", + " \"avg_intercepted_contamination_rate\",\n", + " \"avg_boxes_opened_completion\",\n", + " \"pct_boxes_opened_completion\",\n", + " \"avg_boxes_opened_detection\",\n", + " \"pct_boxes_opened_detection\",\n", + " \"avg_items_inspected_completion\",\n", + " \"pct_items_inspected_completion\",\n", + " \"avg_items_inspected_detection\",\n", + " \"pct_items_inspected_detection\",\n", + " \"false_neg\",\n", + " \"intercepted\",\n", + " \"total_missed_contaminants\",\n", + " \"total_intercepted_contaminants\",\n", + " \"num_boxes\",\n", + " \"num_items\",\n", + " ],\n", + ")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compute a few additional results metrics" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "results_df['action rate'] = results_df[\"intercepted\"] / num_consignments\n", + "contaminated_consignments = results_df[\"false_neg\"] + results_df[\"intercepted\"]\n", + "results_df[\"interception rate\"] = results_df[\"intercepted\"] / contaminated_consignments\n", + "results_df[\"% missed contaminants\"] = (results_df[\"total_missed_contaminants\"] / (results_df[\"total_missed_contaminants\"] + results_df[\"total_intercepted_contaminants\"])) * 100" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot metrics to compare scenario outcomes" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 0, 'Pct. missed contaminants')" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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CgMuEREREckKAy4RERERyQoDLhERERHJCgMuEREREckKAy4RERERyQoDLhERERHJCgMuEREREckKAy4RERERyQoDLhERERHJCgMuEREREckKAy4RERERyQoDLhERERHJCgMuEREREckKAy4RERERyQoDLhERERHJCgMuEREREckKAy4RERERyQoDLhERERHJCgMuEREREckKAy4RERERyQoDLhERERHJCgMuEREREckKA245ExUVBYVCgQcPHpR1KURERERvBAOujPn7+2PUqFFqbU2bNkVqaiosLCze+PmXLVsGV1dXGBoaolGjRvjzzz9fuk90dDQaNWoEQ0NDVK1aFStWrFDbvnr1ajRr1gwVKlRAhQoVEBAQgL/++utNvQUiIiJ6DzHgviHZ2dlldu6cnJwitxkYGMDOzg4KheKN1rBp0yaMGjUKEydOxOnTp9GsWTO0b98eSUlJRe6TkJCADh06oFmzZjh9+jS++eYbjBgxAlu3bpX6REVF4ZNPPkFkZCRiYmJQpUoVtGnTBsnJyW/0/RAREdH7gwG3BPz9/TFs2DAMGzYMlpaWsLa2xrfffgshhNTHxcUF06ZNw+effw4LCwsMHDgQALB161bUqVMHSqUSLi4umDdvntqxXVxcEBYWhr59+8LU1BQODg5YsmSJWp+kpCR07doVpqamMDc3R69evfDvv/9K20NDQ9GgQQOEh4ejatWqUCqVCAoKQnR0NBYtWgSFQgGFQoEbN24UukShJDXOmDEDwcHBMDMzQ5UqVbBq1apix2z+/Pn4z3/+gwEDBqBWrVpYuHAhnJycsHz58iL3WbFiBapUqYKFCxeiVq1aGDBgAIKDgzF37lypz88//4yhQ4eiQYMGcHd3x+rVq6FSqXDw4MFi6yEiIqLygwG3hNavXw89PT2cOHECixcvxoIFC7BmzRq1Pt9//z3q1q2LuLg4TJo0CXFxcejVqxf69OmDs2fPIjQ0FJMmTcK6des09vPw8MCpU6cQEhKCr776Cvv37wcACCHQrVs33Lt3D9HR0di/fz+uXbuG3r17qx3j6tWr2Lx5M7Zu3Yr4+HgsXrwYPj4+GDhwIFJTU5GamgonJyeN91XSGufNmwcvLy+cPn0aQ4cOxRdffIGLFy8WOlbZ2dmIi4tDmzZt1NrbtGmDY8eOFTnGMTExGvu0bdsWJ0+eLHJWOisr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KlECbd68ORQKBYyNjdVeExERERG9a3iRGZU7vMiMiIjo/fPGLzI7fPgw4uPjtdmViIiIiOiN0irgtmjRAqtXry7tWoiIiIiIXptWAbdSpUowMDAo7VqIiIiIiF6bVrc5aNu2LaKjoyGE4MVm9N6qO3kvdJTGZXb+G7M6ltm5iYiI5EyrGdwZM2bg7t27GDRoEO7du1faNRERERERaU2rGdxPP/0UlpaWCA8Px08//QRXV1fY2tpqzOYqFAocPHiwVAolIiIiIioJrQJuVFSU9O9nz57h4sWLuHjxokY/Ll8gIiIiordNq4CrUqlKuw4iIiIiolKh1RpcIiIiIqJ3FQMuEREREcmKVksU8t26dQuRkZFISUnBs2fPNLYrFApMmjTpdU5BRERERPRKtA64Y8eOxaJFi5CXlye1Fbwvbv6/GXCJiIiI6G3SaonC6tWrMW/ePLRo0QJbtmyBEAJBQUH49ddfMWTIEOjp6eHjjz/GoUOHSrteIiIiIqJiaTWDu2rVKri4uOCPP/6Ajs7zjOzi4oLevXujd+/e6NWrF1q3bo1evXqVarFERERERC+j1QzuxYsX0a5dOyncAkBubq70bz8/P3Ts2BFz5859/QqJiIiIiF6B1ndRsLS0lP5tYmKCu3fvqm2vWbMmzp07p3VhRERERETa0CrgOjo64tatW9LratWq4cSJE2p9/vnnH5iYmLxedUREREREr0irgOvr64vjx49Lr7t27YrTp09jyJAh+P333xESEoI//vgDzZs3L7VCiYiIiIhKQquLzD777DOkpKQgMTERzs7OGDt2LHbt2oVVq1Zh9erVEELAxcUF33//fWnXS0RERERULK0Crr+/P/z9/aXXpqamOH78OP773//i2rVrcHZ2RufOnblEgYiIiIjeutd6kllB+vr6+Pjjj0vrcEREREREWtH6LgpERERERO8irWdwb9++jYiICMTGxuLBgwdqj+zNp1AocPDgwdcqkIiIiIjoVWgVcM+cOYOWLVvi/v37EEIU2U+hUGhdGBERERGRNrRaojBmzBjcu3cPEydOREJCAnJycqBSqTS+CpvVJSIiIiJ6k7SawY2JiUG3bt0wderU0q6HiIiIiOi1aDWDa2BggGrVqpV2LUREREREr02rgNuyZUucPHmytGshIiIiInptWgXc77//HufOncPcuXNLux4iIiIi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SEhAeHg4Ll++rLFt165dcHR0lGZz7e3tsXnz5lItlIiIiIioJEoccFevXo2BAwdCqVSqtV+9ehW9evXC7du3UaVKFbi7u+P+/fvo168fTp8+XeoFExEREREVp8QB98iRI6hfvz6cnZ3V2hctWoSnT5/iyy+/REJCAs6dO4f/+7//Q15eHpYuXVrqBRMRERERFeeVlijUqVNHo33Pnj0wMDDAjBkzpLYePXqgWbNm+PPPP0unSiIiIiKiEipxwL1z5w6cnJzU2h48eIBr167B29sbZmZmatsaNGiA5OTk0qmSiIiIiKiEShxw9fT08ODBA7W2/DW2hd0mzNTU9PUqIyIiIiLSQokDbo0aNXDw4EG1tn379kGhUKBp06Ya/VNSUmBvb//6FRIRERERvYISB9yPPvoIV65cweDBg3HmzBls27YNy5cvh6mpKdq1a6fR/+jRo6hevXqpFktERERE9DIlDrhfffUV6tWrh9WrV6Nhw4bo2bMnMjMz8d1338HExESt78mTJ3H16lW0bt261AsmIiIiIipOiZ9kZmRkhKNHj2LBggU4fvw4rKys0LNnT3Tp0kWj76lTp9C1a9dCtxERERERvUkKIYQo6yKI3qbMzExYWFjAadRm6CiNy6yOG7M6ltm5iYiI3jf5P78zMjJgbm5ebN8SL1EgIiIiInofMOASERERkaww4BIRERGRrDDgEhEREZGsMOASERERkaww4BIRERGRrJT4PrhEcvPPlLYvvc0IERERvX84g0tEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESy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UlISXF1dUblyZaxbtw56em/3LeTk5OCbb77B9evXYWZmhqZNm+Lnn3/WuPMDEREREZWN93aJApG2uESBiIjo/fMqP7/f24vMiIiIiIgKw4BLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREssKAS0RERESywoBLRERERLLCgEtEREREsqJX1gUQvW1CCABAZmZmGVdCREREJZX/czv/53hxGHCp3Ll79y4AwMnJqYwrISIiolf18OFDWFhYFNuHAZfKHSsrKwBAUlLSS/8DKQ8yMzPh5OSEmzdvwtzcvKzLKXMcD3UcD3UcD3Ucj//hWKh7E+MhhMDDhw/h4ODw0r4MuFTu6Og8X3puYWHB/xMqwNzcnONRAMdDHcdDHcdDHcfjfzgW6kp7PEo6McWLzIiIiIhIVhhwiYiIiEhWGHCp3FEqlZg8eTKUSmVZl/JO4Hio43io43io43io43j8D8dCXVmPh0KU5F4LRERERETvCc7gEhEREZGsMOASERERkaww4BIRERGRrDDgEhEREZGsMOBSubNs2TK4urrC0NAQjRo1wp9//lnWJb0Vhw8fRufOneHg4ACFQoEdO3aobRdCIDQ0FA4ODjAyMoK/vz/OnTtXNsW+YTNnzsQHH3wAMzMzVKpUCd26dcOlS5fU+pSn8Vi+fDk8PDykG7L7+Pjgjz/+kLaXp7EozMyZM6FQKDBq1CiprTyNSWhoKBQKhdqXnZ2dtL08jUW+5ORkfPrpp7C2toaxsTEaNGiAuLg4aXt5GhMXFxeN7w+FQoEvv/wSQNmNBQMulSubNm3CqFGjMHHiRJw+fRrNmjVD+/btkZSU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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.barh(results_df[\"name\"], results_df[\"% missed contaminants\"])\n", + "plt.title(\"Missed contaminants\", fontsize=18)\n", + "plt.ylabel(\"Scenario name\", fontsize=14)\n", + "plt.xlabel(\"Pct. missed contaminants\", fontsize=14)" ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 0, 'action rate')" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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tplaSWrUqJH69etne//qq6+qcePGGjRokCSpfPny2rVrl8aOHavXX3/d1q5+/frq37+/rc26des0ceJENWnSRCtWrND27duVkJBgC6hffvmlKleurE2bNunRRx+VdC1UfvnllypVqpTtuK6uripSpIh8fHyy/bkmTJiQqxqfeeYZde3aVZL09ttva+LEiVq9erVCQkIyHfPUqVNKS0uTt7e33XZvb28lJiZmW0tiYmKWfVJTU3Xq1Cn5+vpm6tO/f3/5+fkpPDw82+OOGjVKQ4cOzXY/AAAwF2Zwc+mxxx6zW7caGhqqP//8U2lpabZttWvXtuuze/du1a9f325b/fr1M/ULDQ21axMaGqrdu3fbjuHv7283+1qpUiV5eXnZ2khSQECAXbjNrdzWWLVqVdufLRaLfHx8lJSUlOOxb1znaxjGTdf+ZtUnq+2SNGbMGH311VdauHChChcunO0xBwwYoHPnztlef/31V441AACAexszuPnI3d3d7n1Wge76dbs5yeiXXSi8cfuN586t3Nbo4uKSqb709PQsj/nAAw/Iyckp02xtUlJSphna6/n4+GTZx9nZWSVLlrTbPm7cOI0cOVIrVqywC99ZsVqtslqtObYBAADmwQxuLm3YsCHT++DgYDk5OWXbp1KlSlq7dq3dtvXr16t8+fJ2/bI6dsZX/5UqVdLhw4ftZh137dqlc+fOqWLFijnW7OrqajcLeys15oWrq6tq1aplW0ecYfny5apXr162/UJDQzP1WbZsmWrXrm0XsMeOHavhw4dr6dKlmWbNAQAACLi59Ndff6lPnz76448/9NVXX+nDDz9Uz549c+zTt29frVy5UsOHD9fevXs1a9YsTZ061W6driStW7dOY8aM0d69e/XRRx/pv//9r+3Y4eHhqlq1ql599VVt2bJFv/32myIjI9WwYcObhrvAwEBt3LhRBw8e1KlTp7Kccc1tjXnVp08fzZgxQ9HR0dq9e7d69+6tw4cP680337S1GTBggCIjI23v33zzTR06dEh9+vTR7t27FR0drc8//9yuljFjxujdd99VdHS0AgMDlZiYqMTERF24cOGW6gUAAOZBwM2lyMhIXbp0SXXq1NF//vMfde/eXZ07d86xT82aNTV//nzNnTtXjzzyiN577z0NGzbM7uIt6VrIjIuLU40aNTR8+HCNHz9ezZo1k3Rt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jRs31unTpyVJ33zzjXr27Km+ffvq999/V5cuXdS+fXutWrXKbhyGDx+uyMhIxcfHKyQkRG3atFGXLl00YMAA25PkunXrZmv/008/6bXXXlOPHj20a9cuffrpp5o5c6bef/99SdKmTZskSTExMTp+/LjtvSTt27dP8+fP14IFCxQfH5/l7yUyMlJz587VlClTtHv3bn3yyScqWrRolm0TEhKUmJiopk2b2rZZrVY1bNhQ69evz7KPdG0G9/o+ktSsWbNMff7880+VKVNGZcuW1csvv6wDBw5ke8zLly8rOTnZ7gUAAMzLobsoHD9+XC+//HKObQoXLqyLFy86VFTVqlU1ePBgSVJwcLCmTp2qlStXqkmTJqpXr55txjMqKkrStcDWunVru7Dl7++viRMnymKxqEKFCtqxY4cmTpyoTp06af/+/frqq6905MgRlSlTRpLUr18/LV26VDExMRo5cqSka1/Vf/zxx6pWrZokac+ePVqxYoU2bdqk2rVrS5JmzJih4OBg23lXrVqlHTt2KCkpSVarVZI0btw4LVq0SF9//bU6d+6scePG6fXXX1fXrl0lSX369NGGDRs0btw4Pfnkk7ZjtW/f3hba3377bYWGhmrQoEFq1qyZJKlnz55q3769rf3777+v/v37q127dpKkoKAgDR8+XFFRURo8eLBtltPLyyvTmtUrV67oyy+/zHYmdO/evZo/f76WL1+u8PBw2/Gzk5iYKEny9va22+7t7a1Dhw7l2C+rPhnHk6S6devqiy++UPny5XXixAmNGDFC9erV086dO1WyZMlMxxw1apSGDh2a7TkBAIC5ODSDW7JkyZveNWHPnj3y9fV1qKiqVavavff19bWbJe3YsaNiYmIkSUlJSfrhhx/UoUMHuz6PPfaYLBaL7X1oaKj+/PNPpaWlacuWLTIMQ+XLl1fRokVtrzVr1th95e/q6mpXyx9//CFnZ2fVrFnTtq1cuXIqXry47X1cXJwuXLigkiVL2h07ISHBduzdu3erfv36dvXWr19fu3fvznYcMkJflSpV7Lb9888/thnJuLg4DRs2zO68nTp10vHjx5WSkpJ5oK8TEBCQ49f88fHxcnJyUsOGDXM8zo2u/x1I12a4b9yW1z5PP/20/vWvf6lKlSoKDw/XDz/8IOnarH1WBgwYoHPnztle+XXHDwAAcHdyaAa3QYMG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/+uvvxqFChUyJk+ebBw4cMD49ddfjcqVKxstW7a8w5Xf25YsWWIMHDjQWLBggSHJ+Oabb3JsX5CfrwRcmE6dOnWMN998025bSEiI0b9//yzbR0VFGSEhIXbbunTpYjz22GO3rUYzyuu4Z6VSpUrG0KFD87s003N07F966SXj3XffNQYPHkzAdUBex/3HH380PD09jb///vtOlGdqeR37sWPHGkFBQXbbpkyZYjz44IO3rUazy03ALcjPV5YowFSuXLmiuLg4NW3a1G5706ZNtX79+iz7xMbGZmrfrFkzbd68WVevXr1ttZqJI+N+o/T0dJ0/f14lSpS4HSWalqNjHxMTo/3792vw4MG3u0RTcmTcv/vuO9WuXVtjxoyRn5+fypcvr379+unSpUt3omTTcGTs69WrpyNHjmjJkiUyDEMnTpzQ119/rebNm9+Jku9bBfn56nxbjw7cYadOnVJaWpq8vb3ttnt7eysxMTHLPomJiVm2T01N1alTp+Tr63vb6jULR8b9RuPHj9fFixcVERFxO0o0LUfG/s8//1T//v3166+/ytmZjwFHODLuBw4c0Nq1a1W4cGF98803OnXqlLp27arTp0+zDjcPHBn7evXqafbs2XrppZf0zz//KDU1Vc8995w+/PDDO1HyfasgP1+ZwYUpWSwWu/eGYWTadrP2WW1HzvI67hm++uorDRkyRPPmzVPp0qVvV3mmltuxT0tLU5s2bTR06FCVL1/+TpVnWnn5O5+eni6LxaLZs2erTp06euaZZzRhwgTNnDmTWVwH5GXsd+3apR49eui9995TXFycli5dqoSEBL355pt3otT7WkF9vvJPd5jKAw88ICcnp0z/ik9KSsr0r8gMPj4+WbZ3dnZWyZIlb1utZuLIuGeYN2+e3njjDf33v/9VeHj47SzTlPI69ufPn9fmzZu1detWdevWTdK14GUYhpydnbVs2TI1atTojtR+L3Pk77yvr6/8/Pzk6elp21axYkUZhqEjR44oODj4ttZsFo6M/ahRo1S/fn299dZbkqSqVavK3d1dTzzxhEaMGME3dbdJQX6+MoMLU3F1dVWtWrW0fPlyu+3Lly9XvXr1suwTGhqaqf2yZctUu3Ztubi43LZazcSRcZeuzdy+/vrrmjNnDmvhHJTXsffw8NCOHTsUHx9ve7355puqUKGC4uPjVbdu3TtV+j3Nkb/z9evX17Fjx3ThwgXbtr1796pQoUJ68MEHb2u9ZuLI2KekpKhQIfvI4+TkJOl/M4rIfwX6+XrbL2MD7rCM28d8/vnnxq5du4xevXoZ7u7uxsGDBw3DMIz+/fsbbdu2tbXPuI1J7969jV27dhmff/45twlzQF7Hfc6cOYazs7Px0UcfGcePH7e9zp49W1A/wj0rr2N/I+6i4Ji8jvv58+eNBx980HjxxReNnTt3GmvWrDGCg4ONjh07FtSPcM/K69jHxMQYzs7Oxscff2zs37/fWLt2rVG7dm2jTp06BfUj3JPOnz9vbN261di6dashyZgwYYKxdetW2+3Z7qbPVwIuTOmjjz4yAgICDFdXV6NmzZrGmjVrbPvatWtnNGzY0K796tWrjRo1ahiurq5GYGCgMW3atDtcsTnkZdwbNmxoSMr0ateu3Z0v3ATy+nf+egRcx+V13Hfv3m2Eh4cbbm5uxoMPPmj06dPHSElJucNVm0Nex37KlClGpUqVDDc3N8PX19d49dVXjSNHjtzhqu9tq1atyvH/t++mz1eLYTA3DwAAAPNgDS4AAABMhYALAAAAUyHgAgAAwFQIuAAAADAVAi4AAABMhYALAAAAUyHgAgAAwFQIuACAAhMYGKjAwMCCLgOAyRBwAQC3zeuvvy6LxaKDBw8WdCl33MGDB2WxWPT6668XdCnAfce5oAsAANy/Vq5cWdAlADAhAi4AoMA8/PDDBV0CABNiiQIA3OeuXLmiDz/8UM2aNZO/v7+sVqtKly6tVq1aaevWrdn2++6779SsWTOVLFlShQsXVmBgoNq2bavff/9d0rX1tbNmzZIklS1bVhaLRRaLRWFhYbZjZLcGNyUlRUOGDFFISIgKFy6sEiVKqHnz5lq/fn2mtkOGDJHFYtHq1as1f/581axZU25ubvL19VWPHj106dKlXI3D9UsK9uzZo1atWumBBx6wW2LxzTff6JVXXlG5cuVUpEgReXp66oknntCCBQvsjjVz5kyVLVtWkjRr1izbz55RZwbDMBQdHa369evLw8NDRYoUUe3atRUdHZ2rmgFkjRlcALjPnT59Wr169dITTzyhZ555RsWLF9eBAwf03Xff6ccff9Qvv/yiRx991K5PVFSUxo4dqxIlSqhly5YqXbq0/vrrL61YsUK1atXSI488ol69emnmzJnatm2bevbsKS8vL0m66UVlly9fVuPGjbVhwwbVrFlTvXr1UlJSkubNm6dly5Zp3rx5atWqVaZ+H330kX788Uc9//zzCgsL09KlS/Xhhx/q77//1uzZs3M9Hvv27dNjjz2mypUrq127djp9+rRcXV0lSQMGDJCrq6sef/xx+fr66uTJk/ruu+/04osvasqUKerevbskqXr16urZs6cmT56satWqqWXLlrbjZ/z8hmHotdde05w5c1S+fHm1adNGrq6uWr58ud544w3t2rVL48aNy3XdAK5jAADua//8849x5MiRTNt///13o2jRokZ4eLjd9h9++MGQZFSpUsU4deqU3b6rV68aiYmJtvft2rUzJBkJCQlZnjsgIMAICAiw2zZs2DBDkvHqq68a6enptu3btm0zrFarUbx4cSM5Odm2ffDgwYYkw9PT09izZ49te0pKilG+fHnDYrEYR48evek4JCQkGJIMScagQYOybLN///5M286fP29UqVLF8PT0NC5evJjpeO3atcvyWJ999pkhyXjjjTeMq1ev2rZfvnzZePbZZw1JxubNm29aN4DMWKIAAPc5q9UqPz+/TNsrV66sJ598Ur/88ouuXr1q2/7RRx9JkiZPnqySJUva9XF2dpa3t/ct1TNz5ky5uLho9OjRslgstu1Vq1bV66+/rjNnzujbb7/N1K9nz56qUKGC7b2bm5teeeUVGYahuLi4XJ/fx8dH7777bpb7goKCMm0rWrSoXn/9dZ07d06bNm3K9XmmTp0qd3d3TZ06Vc7O//tC1dXVVe+//74k6auvvsr18QD8D0sUAACKj4/XmDFjtHbtWiUmJtoFWkk6deqUfH19JUm//fabrFarGjZsmO91JCcn68CBA6pYsaIefPDBTPvDwsL06aefKj4+Xq+99prdvpo1a2Zqn3GMs2fP5rqGatWq2ZYk3CgpKUmjR4/Wjz/+qEOHDmVa33vs2LFcnSMlJUU7duxQmTJlNHr06Ez7M8Z/z549ua4bwP8QcAHgPrd+/Xo1atRIktS0aVMFBweraNGislgsWrRokbZt26bLly/b2p89e1Z+fn4qVCj/vwRMTk6WpGxngX18fCRJ586dy7TP09Mz07aMmdG0tLRc15DduU+fPq1HH31Uhw8fVv369RUeHi4vLy85OTkpPj5e3377rd045eTMmTMyDENHjx7V0KFDs2138eLFXNcN4H8IuABwn3v//fd1+fJlrV27VvXr17fbt2HDBm3bts1um5eXlxITE5Wenp7vIdfDw0OSdOLEiSz3Z2zPaHc7XL8s4nqff/65Dh8+rBEjRmjgwIF2+0aPHp3lsonsZNRfq1Ytbd682fFiAWSJNbgAcJ/bv3+/SpQokSncpqSkaMuWLZna16lTR5cvX9aaNWtuemwnJydJuZ9B9fDwUFBQkPbt26ejR49m2p9xzurVq+fqePlp//79kqTnnnsu075ff/0107acfvZixYqpYsWK2r17d56WTwDIHQIuANznAgICdObMGe3cudO2LS0tTf369dPJkycztf/Pf/4j6dpFXadPn7bbl5qaajf7WqJECUnSkSNHcl1Pu3btdPXqVQ0YMECGYdi2//7774qJiZGnp6fdbbfulICAAEnS2rVr7bbPmTNHS5YsydS+ePHislgs2f7sPXr0UEpKijp16pTlUoSEhIT78hHHQH5giQIA3Oe6d++uZcuW6fHHH1dERIQKFy6s1atX6+jRowoLC7N7MIEkPfPMM+rXr5/GjRun4OBgvfDCCypdurSOHj2qlStXql+/furVq5ckqVGjRho3bpy6dOmi1q1by93dXQ899JDatGmTbT1RUVH64Ycf9OWXX2r37t1q3LixTp48qXnz5unq1av64osvVKxYsds4Illr27atPvjgA3Xv3l2rVq1SQECAtm/frhUrVqhVq1ZauHChXfuiRYvq0Ucf1S+//KL27dsrODhYhQoVUps2bfTQQw+pS5cu2rBhg2bNmqV169YpPDxcZcqU0YkTJ7Rnzx5t3LhRc+bMuel9gwFkoYBvUwYAuAt8/fXXRs2aNY0iRYoYDzzwgBEREWHs378/x/vYLliwwHjyyScNT09Pw2q1GoGBgUbbtm2N33//3a7dmDFjjODgYMPFxcWQZDRs2NC2L6v74BqGYVy4cMEYNGiQUb58ecPV1dXw8vIynn76aePXX3/N1DbjPrirVq3KtC8mJsaQZMTExNx0DG5231rDMIz4+HijadOmRvHixY1ixYoZDRs2NFasWJHtef744w/jmWeeMby8vAyLxZJlnfPmzTPCw8ON4sWLGy4uLoafn58RFhZmjB8/3jh58uRN6waQmcUwrvv+BwAAALjHsQYXAAAApkLABQAAgKkQcAEAAGAqBFwAAACYCgEXAAAApkLABQAAgKkQcAEAAGAqBFwAAACYCgEXAAAApkLABQAAgKkQcAEAAGAqBFwAAACYCgEXAAAApvL/rRGMvqmeBSwAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.barh(results_df[\"name\"], results_df[\"action rate\"])\n", + "plt.title(\"Action Rate\", fontsize=18)\n", + "plt.ylabel(\"Scenario name\", fontsize=14)\n", + "plt.xlabel(\"action rate\", fontsize=14)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -300,9 +613,9 @@ "hash": "35a97950b3485d686f65df065bbd4f3ea2db4d126aaaac47be7ba4d8431a0071" }, "kernelspec": { - "display_name": "Python 3.9.7 ('pops_border')", + "display_name": "popsborder", "language": "python", - "name": "python3" + "name": "popsborder" }, "language_info": { "codemirror_mode": { @@ -314,9 +627,8 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.7" - }, - "orig_nbformat": 4 + "version": "3.11.5" + } }, "nbformat": 4, "nbformat_minor": 2 diff --git a/examples/notebooks/scenario_plots.ipynb b/examples/notebooks/scenario_plots.ipynb index 368a0c0c..8feb9220 100644 --- a/examples/notebooks/scenario_plots.ipynb +++ b/examples/notebooks/scenario_plots.ipynb @@ -34,7 +34,7 @@ "from pathlib import Path\n", "datadir = Path(\"data\")\n", "basic_config = load_configuration(datadir / \"base_config.yml\")\n", - "scenario_table = load_scenario_table(datadir / \"scenarios_config.csv\")" + "scenario_table = load_scenario_table(datadir / \"scenarios_long.csv\")" ] }, { diff --git a/examples/notebooks/validation_plots.ipynb b/examples/notebooks/validation_plots.ipynb index 2278bf2e..18ed0e73 100644 --- a/examples/notebooks/validation_plots.ipynb +++ b/examples/notebooks/validation_plots.ipynb @@ -187,7 +187,7 @@ "outputs": [], "source": [ "# Combine dataframes from both tests to view contamination rates\n", - "contaminate_validation_df = contaminate_validation_df_1.append(contaminate_validation_df_2)\n", + "contaminate_validation_df = pd.concat([contaminate_validation_df_1, contaminate_validation_df_2])\n", "contaminate_validation_df.index = range(len(contaminate_validation_df))" ] }, @@ -220,7 +220,7 @@ "beta_expected = pd.Series(0.007)\n", "beta_expected = beta_expected.repeat(repeats=len(contaminate_validation_df_2))\n", "\n", - "expected_rates = fixed_expected.append(beta_expected)\n", + "expected_rates = pd.concat([fixed_expected, beta_expected])\n", "\n", "expected_rates.index = range(len(expected_rates))\n", "simulated_rates = contaminate_validation_df[\"true_contamination_rate\"]\n", diff --git a/popsborder/contamination.py b/popsborder/contamination.py index ef1a056e..3aad66a2 100644 --- a/popsborder/contamination.py +++ b/popsborder/contamination.py @@ -239,7 +239,8 @@ def choose_strata_for_clusters(num_units, cluster_width, num_clusters): # Make sure there are enough strata for the number of clusters needed. if num_strata < num_clusters: raise ValueError( - """Cannot avoid overlapping clusters. Increase contaminated_units_per_cluster + """Cannot avoid overlapping clusters. Increase + contaminated_units_per_cluster or decrease cluster_item_width (if using item contamination_unit)""" ) # If all strata are needed, all strata are selected for clusters diff --git a/popsborder/simulation.py b/popsborder/simulation.py index 3d3fc856..2384f491 100644 --- a/popsborder/simulation.py +++ b/popsborder/simulation.py @@ -169,7 +169,7 @@ def simulation( missing = 100 * float(success_rates.false_negative) / (num_contaminated) false_neg = success_rates.false_negative if verbose: - print("Missing {missing:.0f}% of contaminated consignments.") + print(f"Missing {missing:.0f}% of contaminated consignments.") else: # we didn't miss anything missing = 0