- Summary: Evaluate approaches to calculate the total drug weight in a batch
- Developed by: Netherlands Forensics Institute, team Evidence Evaluation & Statistics, 2026
- Publication: submitted for publication (DOI-link will be added when available)
- A batch of cardboard banana boxes has been seized. The bottoms of the boxes were impregnated with cocaine.
- The entire batch consists of 1000 boxes, of which 300 have been analysed for cocaine presence.
- From 5 cocaine-containing boxes, the weights of the bottoms have been measured (including cocaine).
- For 10 cardboard bottoms, the cocaine concentrations have been measured using 3 repeats per bottom.
- An estimate is required for the total weight of cocaine in the batch, together with an uncertainty interval.
This repository currently supports the evaluation of five modelling approaches:
- An existing frequentist approach, using weight and drug-presence measurements, based on a tool from ENFSI.
- An existing frequentist approach, using weight and drug-presence measurements, based on a tool from SWGDRUG.
- An existing frequentist approach, using weight and drug-presence measurements, based on Alberink et al. (2010).
- An existing frequentist approach, using weight and concentration measurements, based on Alberink et al. (2016).
- A novel Bayesian approach, using weight, drug-presence and concentration measurements, and using MCMC-simulations.
- Python version: 3.12
- Packages used: listed in
requirements.txt(including version numbers) - Configuration: the
input_configurationsfolder contains all files hat define the simulations:default_case.yaml: default values for all simulation settings and parameterslocal_adjustments.yaml: values in here will override the values of all simulations being done.
An examplelocal_adjustments.yaml-exampleis provided, it can be renamed tolocal_adjustments.yaml.- To reproduce specific simulation results, change the
random_seed:from empty/none to a 'date/time-stamp' number.
This date/time-stamp can be found in the folder name of that specific simulation, for example20260415035613.
There are two ways to run the simulations: via the Python command line, or using a file with a series of OS-commands.
- Start in
main.py - By default a single simulation run is done, based on the values in
default_case.yamlandlocal_adjustments.yaml. - Several optional input arguments are supported:
-no_default_run: Do not run the default simulation defined indefault_case.yaml.-run_single_yaml, in combination with-yaml_fileandpath/to/file.yaml:
Run the simulation specified infile.yaml, located in the folderpath/to.-run_all_yaml_files_in_folder, in combination with-folder_yaml_filesandpath/to/folder:
Run the simulations specified by all yaml-files located in the folderpath/to/folder.-run_method_comparison:
Run the simulations specified by all yaml-files located in the folderinput_configurations/method_comparison.-run_sensitivity_analysis:
Run the simulations specified by all yaml-files located in the folderinput_configurations/sensitivity_analysis.-create_overview_results, in combination with-results_dirandpath/to/folder:
Make an overview table of all simulations results located in the sub-folders of the folderpath/to/folder.
- The four
-run_...arguments should not be combined; use only one of them at a time.- If any of them is used,
-results_diris overwritten with the output folder of that run-argument.
- If any of them is used,
- Some example usages:
- To do the sensitivity analysis including default run and summarising overview:
python main.py -run_sensitivity_analysis -create_overview_results - To do the method comparison without default run and including summarising overview:
python main.py -no_default_run -run_method_comparison -create_overview_results - To make a summarising overview of a selection previously run simulation results:
python main.py -no_default_run -create_overview_results -results_dir results/my_result_selection/
- To do the sensitivity analysis including default run and summarising overview:
- Automatically clearing pytensor cache
- When running a single yaml-file, the 'simulation time per run' slowly increases from the first to the last run.
- This behaviour is caused by the growing size of the pytensor cache, related to the MCMC-calculations.
- By default, this cache is cleared before the start of a simulation (
clear_cache: True). - Clearing the cache is only possible before Python starts its calculation, not during the calculations.
- To automatically run many simulation-yamls while clearing the cache in between, a series of OS-commands can be used.
- Examples files are included for two common types of Operating System (OS):
- Windows:
run_all_yamls.bat-example - Linux:
run_all_yamls.sh-example
- Windows:
- To use such a file, do the following:
- Copy the relevant file, and remove
-examplefrom the file extension - Update some settings in these files, for example:
- Location of the Python interpreter to use
- Location of folder(s) with simulation yaml-files to run
- Execute the
.bator.shfile
- Copy the relevant file, and remove
tests: Folder with several files that contain multiple tests, to verify the implementations of the modelling approaches.
The random nature of the MCMC-calculations may cause the tests intest_baysian.pyto fail, depending on hardware.boundary_methods.py: Functions to calculate the relevant percentiles, based on weights, presences, and concentrations.calculate_percentiles_enfsi: Using ENFSI approach: lower bound, best estimate, and upper bound.calculate_percentile_swgdrug: Using SWGDRUG approach: lower bound.calculate_percentiles_alberink2010: Using approach from Alberink et al. (2010): lower bound, best estimate, and upper boundcalculate_percentiles_alberink2016: Using approach from Alberink et al. (2016): lower bound, best estimate, and upper boundcalculate_percentiles_bayesian: Using novel Bayesian approach: lower bound, best estimate (median), upper bound.
simulation_steps: Functions used to execute distinct parts of a simulation.process_cfg: Process a configuration file (file.yaml) into input variables used for a simulation.run_single_simulation: Do a single simulation run: generate ground truth, sample from it, apply methods.aggregate_simulation_results: Summarise the results of a simulation, by aggregating over its runs.save_aggregated_results: Save the aggregated results as csv-file including rounding, do some MCMC-checks.
utils: Functions to perform various supporting tasks.lower_bound_hyper: Determine lower bound for number of drug-containing units, using a hypergeometric distribution.draw_normal_mcmc_samples: Draw samples from a normal distribution using MCMC-simulations.get_dirs_per_measurement_types: Make lists of sub-folders with results, grouped by measurements types present.create_overview_results: Make an overview table of all simulations results located in a specific folder.