From 94823d675a5e3ae756d4d43b9a1cd2d1ee7badea Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 12 Dec 2023 14:27:34 +0100 Subject: [PATCH 01/65] update deps --- conf/ci_jobs/ukb_from_param_file.config | 2 - main.nf | 71 ++++++++++++++----------- modules/sieve_variance.nf | 26 ++++----- modules/tmle.nf | 49 ++++++++--------- 4 files changed, 80 insertions(+), 68 deletions(-) diff --git a/conf/ci_jobs/ukb_from_param_file.config b/conf/ci_jobs/ukb_from_param_file.config index c4767a16..e54d2d67 100644 --- a/conf/ci_jobs/ukb_from_param_file.config +++ b/conf/ci_jobs/ukb_from_param_file.config @@ -11,8 +11,6 @@ params { NB_PCS = 6 TRAITS_CONFIG = "test/data/ukbconfig_small.yaml" ESTIMATORFILE = "test/data/estimator.jl" - NB_VAR_ESTIMATORS = 0 POSITIVITY_CONSTRAINT = 0.0 - } diff --git a/main.nf b/main.nf index af57b7c9..5099b688 100644 --- a/main.nf +++ b/main.nf @@ -2,38 +2,55 @@ nextflow.enable.dsl = 2 params.DECRYPTED_DATASET = "NO_FILE" -params.PARAMETER_PLAN = "FROM_PARAM_FILE" -params.PARAMETER_FILE = "NO_PARAMETER_FILE" params.CALL_THRESHOLD = 0.9 params.POSITIVITY_CONSTRAINT = 0.01 -params.SAVE_IC = true - params.MAF_THRESHOLD = 0.01 -params.NB_PCS = 6 - -params.GRM_NSPLITS = 100 -params.NB_VAR_ESTIMATORS = 0 -params.MAX_TAU = 0.9 -params.PVAL_THRESHOLD = 0.05 - params.VERBOSITY = 1 -params.OUTDIR = "${launchDir}/results" -params.RESULTS_FILE = "${params.OUTDIR}/summary.csv" -params.TMLE_INPUT_DATASET = "${params.OUTDIR}/tmle_inputs/final.data.arrow" - params.COHORT = "UKBB" params.TRAITS_CONFIG = "NO_UKB_TRAIT_CONFIG" params.WITHDRAWAL_LIST = 'NO_WITHDRAWAL_LIST' + +// Confounding adjustment by PCA +params.NB_PCS = 6 params.QC_FILE = "NO_QC_FILE" params.LD_BLOCKS = "NO_LD_BLOCKS" params.FLASHPCA_EXCLUSION_REGIONS = "data/exclusion_regions_hg19.txt" +// Estimands Generation params.BATCH_SIZE = 400 + +// FROM_PARAM_FILE +params.PARAMETER_PLAN = "FROM_PARAM_FILE" +params.PARAMETER_FILE = "NO_PARAMETER_FILE" + +// FROM_ACTORS params.EXTRA_CONFOUNDERS = 'NO_EXTRA_CONFOUNDER' params.EXTRA_COVARIATES = 'NO_EXTRA_COVARIATE' params.ENVIRONMENTALS = 'NO_EXTRA_TREATMENT' params.ORDERS = "1,2" +// Sieve Variance Plateau +params.SVP = false +params.GRM_NSPLITS = 100 +params.NB_SVP_ESTIMATORS = 100 +params.MAX_SVP_THRESHOLD = 0.9 +params.SVP_ESTIMATOR_KEY = "TMLE" + +// TMLE +params.KEEP_IC = params.SVP == true ? true : false +params.PVAL_THRESHOLD = 0.05 +params.TMLE_SAVE_EVERY = 100 + +// Outputs +params.ARROW_OUTPUT = "dataset.arrow" +params.JSON_OUTPUT = "NO_JSON_OUTPUT" +params.HDF5_OUTPUT = "results.hdf5" + +// Negative Control Default Inputs +params.OUTDIR = "${launchDir}/results" +params.RESULTS_FILE = "${params.OUTDIR}/summary.csv" +params.TMLE_INPUT_DATASET = "${params.OUTDIR}/tmle_inputs/final.data.arrow" + // Permutation Tests Parameters params.MAX_PERMUTATION_TESTS = null params.PVAL_COL = "TMLE_PVALUE" @@ -155,14 +172,13 @@ workflow generateTMLEEstimates { // compute TMLE estimates for continuous targets TMLE( tmle_inputs.traits, - tmle_inputs.parameters.flatten(), + tmle_inputs.estimands.flatten(), estimator_file, ) emit: - tmle_csvs = TMLE.out.tmle_csv - inf_curves = TMLE.out.inf_curve + TMLE.out } @@ -178,15 +194,14 @@ workflow generateSieveEstimates { // Sieve estimation SieveVarianceEstimation(tmle_files.collect(), AggregateGRM.out.grm_ids, AggregateGRM.out.grm_matrix) emit: - csv_file = SieveVarianceEstimation.out.csv_file - hdf5_file = SieveVarianceEstimation.out.hdf5_file + SieveVarianceEstimation.out } workflow negativeControl { - results_file = Channel.value(file("${params.RESULTS_FILE}")) + results_file = Channel.value(file("${params.HDF5_OUTPUT}")) // Permutation Tests - dataset = Channel.value(file("${params.TMLE_INPUT_DATASET}")) + dataset = Channel.value(file("${params.OUTDIR}/${params.ARROW_OUTPUT}")) estimatorfile = Channel.value(file("${params.ESTIMATORFILE}")) sieve_csv = Channel.value(file("NO_SIEVE_FILE")) GeneratePermutationTestsData(dataset, results_file) @@ -221,14 +236,10 @@ workflow { geneticConfounders.out, ) - // generate sieve estimates - if (params.NB_VAR_ESTIMATORS != 0){ - sieve_results = generateSieveEstimates(generateTMLEEstimates.out.inf_curves, generateIIDGenotypes.out) - sieve_csv = sieve_results.csv_file - } - else { - sieve_csv = Channel.value(file("NO_SIEVE_FILE")) + // Generate sieve estimates + if (params.SVP == true){ + sieve_results = generateSieveEstimates(generateTMLEEstimates.out, generateIIDGenotypes.out) } - MergeOutputs(generateTMLEEstimates.out.tmle_csvs.collect(), sieve_csv, "summary.csv") + MergeOutputs(generateTMLEEstimates.out.collect(), "summary.csv") } diff --git a/modules/sieve_variance.nf b/modules/sieve_variance.nf index 92562d62..92928123 100644 --- a/modules/sieve_variance.nf +++ b/modules/sieve_variance.nf @@ -1,5 +1,5 @@ process SieveVarianceEstimation { - container "olivierlabayle/targeted-estimation:0.7" + container "olivierlabayle/targeted-estimation:cv_tmle" publishDir "$params.OUTDIR/hdf5files/sieve", mode: 'symlink', pattern: "*.hdf5" publishDir "$params.OUTDIR/csvs", mode: 'symlink', pattern: "*.csv" @@ -9,36 +9,38 @@ process SieveVarianceEstimation { path GRM_matrix output: - path "sieve_variance.hdf5", emit: hdf5_file - path "sieve_variance.csv", emit: csv_file + path "svp.hdf5" script: """ TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no /TargetedEstimation.jl/scripts/sieve_variance.jl \ - tmle GRM sieve_variance \ - --nb-estimators=$params.NB_VAR_ESTIMATORS --max-tau=$params.MAX_TAU + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no tmle sieve-variance-plateau \ + result \ + --nb-estimators=$params.NB_SVP_ESTIMATORS \ + --max-tau=$params.MAX_SVP_THRESHOLD \ + --estimator_key=$params.SVP_ESTIMATOR_KEY \ + --verbosity=$params.VERBOSITY """ } process MergeOutputs { - container "olivierlabayle/targeted-estimation:0.7" + container "olivierlabayle/targeted-estimation:cv_tmle" publishDir "$params.OUTDIR", mode: 'symlink' input: path tmle_files - path sieve_files val outpath output: path "${outpath}" script: - tmle_prefix = "tmle" - sieve_prefix = sieve_files.getName() == "NO_SIEVE_FILE" ? "" : "--sieve-prefix sieve_variance" + json_output = params.JSON_OUTPUT != "NO_JSON_OUTPUT" ? "--outputs.json.filename=$params.JSON_OUTPUT" : "" """ TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no /TargetedEstimation.jl/scripts/merge_summaries.jl \ - ${tmle_prefix} ${outpath} ${sieve_prefix} + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no tmle make-summary \ + result \ + --outputs.hdf5.filename=${params.HDF5_OUTPUT} \ + ${json_output} """ } \ No newline at end of file diff --git a/modules/tmle.nf b/modules/tmle.nf index 98790dcd..7e60ba5b 100644 --- a/modules/tmle.nf +++ b/modules/tmle.nf @@ -17,7 +17,7 @@ def longest_prefix(files){ } process TMLE { - container "olivierlabayle/targeted-estimation:0.7" + container "olivierlabayle/targeted-estimation:cv_tmle" publishDir "$params.OUTDIR/csvs", mode: 'symlink', pattern: "*.csv" publishDir "$params.OUTDIR/hdf5files/inf_curves", mode: 'symlink', pattern: "*.hdf5" label "bigmem" @@ -25,33 +25,34 @@ process TMLE { input: path data - path parameterfile + path estimandsfile path estimatorfile output: - path "${csvout}", emit: tmle_csv - path "${hdf5out}", optional: true, emit: inf_curve + path "${hdf5out}" script: - basename = "tmle." + parameterfile.getName().take(parameterfile.getName().lastIndexOf('.')) - csvout = basename + ".csv" + basename = "result." + estimandsfile.getName().take(estimandsfile.getName().lastIndexOf('.')) hdf5out = basename + ".hdf5" - hdf5option = params.SAVE_IC == true ? "--hdf5-out=${hdf5out}" : "" + pval_threshold = KEEP_IC == true ? "--outputs.hdf5.pval_threshold=${params.PVAL_THRESHOLD}" : "" + sample_ids = SVP == true ? "--outputs.hdf5.sample_ids=true" : "" """ TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --threads=${task.cpus} --startup-file=no /TargetedEstimation.jl/scripts/tmle.jl \ - $data $parameterfile $csvout \ - --estimator-file=$estimatorfile \ - $hdf5option \ - --chunksize=100 \ - --pval-threshold=${params.PVAL_THRESHOLD} + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --threads=${task.cpus} --startup-file=no tmle tmle \ + $data \ + --estimands=$estimandsfile \ + --estimators=$estimatorfile \ + --outputs.hdf5.filename=$hdf5out \ + $pval_threshold \ + $sample_ids \ + --chunksize=$params.TMLE_SAVE_EVERY \ """ } process TMLEInputsFromParamFile { - container "olivierlabayle/tl-core:0.6" - publishDir "$params.OUTDIR/parameters", mode: 'symlink', pattern: "*.yaml" - publishDir "$params.OUTDIR/tmle_inputs", mode: 'symlink', pattern: "*.arrow" + container "olivierlabayle/tl-core:cvtmle" + publishDir "$params.OUTDIR/estimands", mode: 'symlink', pattern: "*.yaml" + publishDir "$params.OUTDIR", mode: 'symlink', pattern: "*.arrow" label "bigmem" input: @@ -61,12 +62,12 @@ process TMLEInputsFromParamFile { path parameter output: - path "final.data.arrow", emit: traits - path "final.*.yaml", emit: parameters + path "${params.ARROW_OUTPUT}", emit: traits + path "final.*.jls", emit: estimands script: bgen_prefix = longest_prefix(bgenfiles) - batch_size = params.BATCH_SIZE == 0 ? "" : "--batch-size ${params.BATCH_SIZE}" + batch_size = params.BATCH_SIZE == 0 ? "" : "--batch-size ${params.BATCH_SIZE}" """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/tmle_inputs.jl \ @@ -81,9 +82,9 @@ process TMLEInputsFromParamFile { } process TMLEInputsFromActors { - container "olivierlabayle/tl-core:0.6" - publishDir "$params.OUTDIR/parameters", mode: 'symlink', pattern: "*.yaml" - publishDir "$params.OUTDIR/tmle_inputs", mode: 'symlink', pattern: "*.arrow" + container "olivierlabayle/tl-core:cvtmle" + publishDir "$params.OUTDIR/estimands", mode: 'symlink', pattern: "*.yaml" + publishDir "$params.OUTDIR", mode: 'symlink', pattern: "*.arrow" label "bigmem" input: @@ -97,8 +98,8 @@ process TMLEInputsFromActors { path trans_actors output: - path "final.data.arrow", emit: traits - path "final.*.yaml", emit: parameters + path "${params.ARROW_OUTPUT}", emit: traits + path "final.*.jls", emit: estimands script: bgen_prefix = longest_prefix(bgenfiles) From 8e83b4a9f6cee62e3e2ba571727252e363fea6b6 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 12 Dec 2023 14:14:40 +0000 Subject: [PATCH 02/65] start to rename some variables --- conf/ci_jobs/custom_from_actors.config | 4 ++-- conf/ci_jobs/ukb_from_actors.config | 2 +- conf/ci_jobs/ukb_from_param_file.config | 4 ++-- docs/Project.toml | 3 +-- docs/make.jl | 1 - docs/src/negative_control.md | 4 ++-- docs/src/nextflow_params.md | 8 ++++---- docs/src/parameter_specification.md | 6 +++--- docs/src/tmle.md | 1 + main.nf | 24 ++++++++++-------------- test/Project.toml | 2 +- test/ukb_from_param_file.jl | 18 ++++++++++++++++-- test/utils.jl | 11 +---------- 13 files changed, 44 insertions(+), 44 deletions(-) diff --git a/conf/ci_jobs/custom_from_actors.config b/conf/ci_jobs/custom_from_actors.config index a7d8490d..885709a3 100644 --- a/conf/ci_jobs/custom_from_actors.config +++ b/conf/ci_jobs/custom_from_actors.config @@ -1,6 +1,6 @@ params { - PARAMETER_PLAN = "FROM_ACTORS" - PARAMETER_FILE = "test/data/parameters/parameters.yaml" + STUDY_DESIGN = "FROM_ACTORS" + ESTIMANDS_FILE = "test/data/parameters/parameters.yaml" DECRYPTED_DATASET = "test/data/traits.csv" COHORT = "CUSTOM" BED_FILES = "test/data/unphased_bed/ukb_chr{1,2,3}.{bed,bim,fam}" diff --git a/conf/ci_jobs/ukb_from_actors.config b/conf/ci_jobs/ukb_from_actors.config index 8ae9dfab..5f35ff8d 100644 --- a/conf/ci_jobs/ukb_from_actors.config +++ b/conf/ci_jobs/ukb_from_actors.config @@ -1,5 +1,5 @@ params { - PARAMETER_PLAN = "FROM_ACTORS" + STUDY_DESIGN = "FROM_ACTORS" DECRYPTED_DATASET = "test/data/dataset.csv" COHORT = "UKBB" BED_FILES = "test/data/unphased_bed/ukb_chr{1,2,3}.{bed,bim,fam}" diff --git a/conf/ci_jobs/ukb_from_param_file.config b/conf/ci_jobs/ukb_from_param_file.config index e54d2d67..dba889ac 100644 --- a/conf/ci_jobs/ukb_from_param_file.config +++ b/conf/ci_jobs/ukb_from_param_file.config @@ -1,6 +1,6 @@ params { - PARAMETER_PLAN = "FROM_PARAM_FILE" - PARAMETER_FILE = "test/data/parameters/parameters.yaml" + STUDY_DESIGN = "CUSTOM" + ESTIMANDS_FILE = "test/data/parameters/parameters.yaml" DECRYPTED_DATASET = "test/data/dataset.csv" COHORT = "UKBB" BED_FILES = "test/data/unphased_bed/ukb_chr{1,2,3}.{bed,bim,fam}" diff --git a/docs/Project.toml b/docs/Project.toml index 72c3b4b4..9311adea 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,3 +1,2 @@ [deps] -Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -# TarGene = "b5cbcb6f-63f1-4216-956e-b514325a29e1" +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" \ No newline at end of file diff --git a/docs/make.jl b/docs/make.jl index aa1c3013..5769b27d 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,4 +1,3 @@ -# using TarGene using Documenter # DocMeta.setdocmeta!(TarGene, :DocTestSetup, :(using TarGene); recursive=true) diff --git a/docs/src/negative_control.md b/docs/src/negative_control.md index d26dbc47..8b71b1e8 100644 --- a/docs/src/negative_control.md +++ b/docs/src/negative_control.md @@ -24,9 +24,9 @@ The results of those permutation tests will be found in the `$(OUTDIR)/permutati ## Non-functional randomly drawn variants -If you are using the `PARAMETER_PLAN` = `FROM_ACTORS`, it is likely that you have not chosen the genetic variants at random. Mainly trans-acting variants have been defined because of a likely role in a biological mechanism. If this is the case, replacing a trans-actor by a random variant anywhere on the genome is likely to break the interaction. While unlikely, by chance alone (or lack thereof), one could pick a random trans-actor which is also interacting with any of the bQTLs. In order to account for that it is recommended to instead select a certain number of rancom variants, denoted by `N_RANDOM_VARIANTS` (default: 10). Furthermore, we enforce two criteria on each of the randomly chosen random variants: +If you are using the `STUDY_DESIGN` = `FROM_ACTORS`, it is likely that you have not chosen the genetic variants at random. Mainly trans-acting variants have been defined because of a likely role in a biological mechanism. If this is the case, replacing a trans-actor by a random variant anywhere on the genome is likely to break the interaction. While unlikely, by chance alone (or lack thereof), one could pick a random trans-actor which is also interacting with any of the bQTLs. In order to account for that it is recommended to instead select a certain number of rancom variants, denoted by `N_RANDOM_VARIANTS` (default: 10). Furthermore, we enforce two criteria on each of the randomly chosen random variants: - Its minor allele frequency should match that of the original trans-actor up to `MAF_MATCHING_RELTOL` (relative tolerance, default: 0.05). - It shouldn't lie in a known regulatory region. -The result of this part of the pipeline is a parameter file located at `$(OUTDIR)/random_variants_parameters.yaml` directory. To perform the actual tests, you will have to run TarGene again on that parameter file with the `PARAMETER_PLAN` = `FROM_PARAM_FILE` mode. +The result of this part of the pipeline is a parameter file located at `$(OUTDIR)/random_variants_parameters.yaml` directory. To perform the actual tests, you will have to run TarGene again on that parameter file with the `STUDY_DESIGN` = `CUSTOM` mode. diff --git a/docs/src/nextflow_params.md b/docs/src/nextflow_params.md index 1d534ffe..653b4964 100644 --- a/docs/src/nextflow_params.md +++ b/docs/src/nextflow_params.md @@ -23,13 +23,13 @@ Here is a list of all the pipeline parameters: ## [Describing the causal parameters of interest](@ref) -- **`PARAMETER_PLAN`** (required, default: "FROM\_PARAM\_FILE"): One of "FROM\_PARAM\_FILE", "FROM\_ACTORS". +- **`STUDY_DESIGN`** (required, default: "FROM\_PARAM\_FILE"): One of "FROM\_PARAM\_FILE", "FROM\_ACTORS". -If `PARAMETER_PLAN`="FROM\_PARAM\_FILE": +If `STUDY_DESIGN`="FROM\_PARAM\_FILE": -- `PARAMETER_FILE` (required): Path expression to the parameter files. +- `ESTIMANDS_FILE` (required): Path expression to the parameter files. -If `PARAMETER_PLAN`="FROM_ACTORS": +If `STUDY_DESIGN`="FROM_ACTORS": - **`BQTLS` (required)**: A CSV file containing binding quantitative trait loci (bQTLs). If multiple transcription factors (TFs) are included in a single run, you must include a column called `TF`, which specifies the TF associated with each bQTL. - **`TRANS_ACTORS` (required)**: A prefix to CSV files containing quantitative trait loci potentially interacting with the previous bqtls. If multiple transcription factors (TFs) are included in a single run, you must include a column called `TF`, which specifies the TF associated with each transactor. diff --git a/docs/src/parameter_specification.md b/docs/src/parameter_specification.md index 52f001e3..1e2e13e6 100644 --- a/docs/src/parameter_specification.md +++ b/docs/src/parameter_specification.md @@ -47,11 +47,11 @@ Note that variants must be encoded via an explicit genotype string representatio At the moment, there are two main ways one can specify parameters that need to be estimated during a targene-pipeline run. This is done via the `MODE` parameter. -### `PARAMETER_PLAN` = `FROM_PARAM_FILE` +### `STUDY_DESIGN` = `CUSTOM` -This is the most general setting and should match the needs of any project, however it requires some preliminary work. In this setting, one typically provides a set of parameter files as described above. If you are interested in only a few parameters it may be acceptable to write them by hand. Otherwise it is best to generate them using a programming language (for instance using [TMLE.jl](https://targene.github.io/TMLE.jl/stable/api/#TMLE.parameters_to_yaml-Tuple{Any,%20Any})). The path to those parameters is then provided with the `PARAMETER_FILE` nextflow parameter. See the previous section on [Parameter Files](@ref). +This is the most general setting and should match the needs of any project, however it requires some preliminary work. In this setting, one typically provides a set of parameter files as described above. If you are interested in only a few parameters it may be acceptable to write them by hand. Otherwise it is best to generate them using a programming language (for instance using [TMLE.jl](https://targene.github.io/TMLE.jl/stable/api/#TMLE.parameters_to_yaml-Tuple{Any,%20Any})). The path to those parameters is then provided with the `ESTIMANDS_FILE` nextflow parameter. See the previous section on [Parameter Files](@ref). -### `PARAMETER_PLAN` = `FROM_ACTORS` +### `STUDY_DESIGN` = `FROM_ACTORS` In this setting the goal is to infer the interaction effect between multiple variants and potential external factors, interacting together via a specific biological mechanism. Typically, multiple sets of variants are of interest and each set is identified with a specific molecule, contributing to the mechanism. In particular, it is assumed that a set of variants, usually binding quantitative trait loci (bQTLs) play a pivotal role. All interactions of interest are thus defined with respect to that set of genetic variations. Let's Consider the following scenario: we know that a transcription factor binds to molecules `x` and `y` and then differentially binds to specific regions in the genome (`bQTLs`) to regulate downstream genes. We suspect that an alteration of this mechanism is responsible for some diseases. A set of `xQTLs`, associated with the expression of `x` and a set of `yQTLs` associated with the expression of `y` have been identified. Together `xQTLs` and `yQTLs` variants are termed "trans actors". We further suspect that some environmental factors may influence this process. From that scenario, there are many questions that can be asked, for instance : "What is the interaction effects of a bQTL with an environmental factor?". This is a simple pairwise interaction setting and more complex scenarios can be envisaged as described in the following graph. diff --git a/docs/src/tmle.md b/docs/src/tmle.md index d0c24918..220d88dd 100644 --- a/docs/src/tmle.md +++ b/docs/src/tmle.md @@ -6,6 +6,7 @@ TMLE is an adaptive procedure that depends on the specification of learning algo - `p(T|W)`: The propensity score. It is commonly denoted by `G` in the Targeted Learning litterature. The estimator configuration file describes the TMLE specification for the estimation of the parameters defined in the previous section. In order to provide maximum flexibility, this is provided as a plain [Julia](https://julialang.org/) file via the `ESTIMATORFILE` parameter. + ### Description of the file In order to provide maximum flexibility as to the choice of learning algorithms, the estimator file is a plain [Julia](https://julialang.org/) file. This file is optional and omitting it defaults to using generalized linear models. If provided, it must define a [NamedTuple](https://docs.julialang.org/en/v1/base/base/#Core.NamedTuple) called `tmle_spec` containing any of the following fields as follows (default configuration): diff --git a/main.nf b/main.nf index 5099b688..fccb319d 100644 --- a/main.nf +++ b/main.nf @@ -9,6 +9,7 @@ params.VERBOSITY = 1 params.COHORT = "UKBB" params.TRAITS_CONFIG = "NO_UKB_TRAIT_CONFIG" params.WITHDRAWAL_LIST = 'NO_WITHDRAWAL_LIST' +params.OUTDIR = "${launchDir}/results" // Confounding adjustment by PCA params.NB_PCS = 6 @@ -19,9 +20,9 @@ params.FLASHPCA_EXCLUSION_REGIONS = "data/exclusion_regions_hg19.txt" // Estimands Generation params.BATCH_SIZE = 400 -// FROM_PARAM_FILE -params.PARAMETER_PLAN = "FROM_PARAM_FILE" -params.PARAMETER_FILE = "NO_PARAMETER_FILE" +// CUSTOM +params.STUDY_DESIGN = "CUSTOM" +params.ESTIMANDS_FILE = "NO_ESTIMANDS_FILE" // FROM_ACTORS params.EXTRA_CONFOUNDERS = 'NO_EXTRA_CONFOUNDER' @@ -46,11 +47,6 @@ params.ARROW_OUTPUT = "dataset.arrow" params.JSON_OUTPUT = "NO_JSON_OUTPUT" params.HDF5_OUTPUT = "results.hdf5" -// Negative Control Default Inputs -params.OUTDIR = "${launchDir}/results" -params.RESULTS_FILE = "${params.OUTDIR}/summary.csv" -params.TMLE_INPUT_DATASET = "${params.OUTDIR}/tmle_inputs/final.data.arrow" - // Permutation Tests Parameters params.MAX_PERMUTATION_TESTS = null params.PVAL_COL = "TMLE_PVALUE" @@ -142,7 +138,7 @@ workflow generateTMLEEstimates { estimator_file = Channel.value(file("$params.ESTIMATORFILE", checkIfExists: true)) bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() - if (params.PARAMETER_PLAN == "FROM_ACTORS") { + if (params.STUDY_DESIGN == "FROM_ACTORS") { bqtls = Channel.value(file("$params.BQTLS")) trans_actors = Channel.fromPath("$params.TRANS_ACTORS", checkIfExists: true).collect() extra_confounders = Channel.value(file("$params.EXTRA_CONFOUNDERS")) @@ -158,16 +154,16 @@ workflow generateTMLEEstimates { bqtls, trans_actors) } - else if (params.PARAMETER_PLAN == "FROM_PARAM_FILE"){ - parameter_file = Channel.value(file("$params.PARAMETER_FILE")) + else if (params.STUDY_DESIGN == "CUSTOM"){ + estimands_file = Channel.value(file("$params.ESTIMANDS_FILE")) tmle_inputs = TMLEInputsFromParamFile( bgen_files, traits, genetic_confounders, - parameter_file) + estimands_file) } else { - throw new Exception("This PARAMETER_PLAN is not available.") + throw new Exception("This STUDY_DESIGN is not available.") } // compute TMLE estimates for continuous targets TMLE( @@ -213,7 +209,7 @@ workflow negativeControl { MergeOutputs(TMLE.out.tmle_csv.collect(), sieve_csv, "permutation_summary.csv") // Random Variants parameter files generation - if (params.PARAMETER_PLAN == "FROM_ACTORS") { + if (params.STUDY_DESIGN == "FROM_ACTORS") { bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() trans_actors = Channel.fromPath("$params.TRANS_ACTORS", checkIfExists: true).collect() GenerateRandomVariantsTestsData(trans_actors, bgen_files, results_file) diff --git a/test/Project.toml b/test/Project.toml index 429ee6f9..a09c3573 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -8,6 +8,6 @@ YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6" [compat] CSV = "0.10.9" DataFrames = "1.5.0" -TMLE = "0.11" +TMLE = "0.12" YAML = "0.4.8" Arrow = "2.5.0" diff --git a/test/ukb_from_param_file.jl b/test/ukb_from_param_file.jl index fd98853d..d397e086 100644 --- a/test/ukb_from_param_file.jl +++ b/test/ukb_from_param_file.jl @@ -1,7 +1,17 @@ +module TestFromParamFile + +using Test +using CSV +using DataFrames +using YAML +using TMLE +using Arrow +using Serialization + #Β "local" profile assumes singularity is installed -args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] +args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] -include("utils.jl") +include(joinpath(@__DIR__, "test", "utils.jl")) @testset "Test ukb_from_param_files.config" begin cmd = `nextflow run main.nf -c conf/ci_jobs/ukb_from_param_file.config $args` @@ -19,3 +29,7 @@ include("utils.jl") check_fails_are_extremely_rare_traits(output, dataset) test_n_success_more_than_threshold(output, 20) end + +end + +true \ No newline at end of file diff --git a/test/utils.jl b/test/utils.jl index 3a913116..ec28b7ae 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -1,13 +1,3 @@ -using Test -using CSV -using DataFrames -using YAML -using TMLE -using Arrow -using Serialization - -# Move to the project's root -cd(dirname(dirname(@__FILE__))) const SUMMARY_COLUMNS = [ "PARAMETER_TYPE", "TREATMENTS", "CASE", "CONTROL", "TARGET", "CONFOUNDERS", "COVARIATES", @@ -18,6 +8,7 @@ const SUMMARY_COLUMNS = [ const SIEVE_COLUMNS = ["SIEVE_STD", "SIEVE_PVALUE", "SIEVE_LWB", "SIEVE_UPB"] const ADJUTMENT_COL = "TRAIT_ADJUSTED_TMLE_PVALUE" + """ check_fails_are_extremely_rare_traits(output, dataset) From 9be229058c2c111cc6641633848f53fb8b025a23 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 12 Dec 2023 14:19:16 +0000 Subject: [PATCH 03/65] update confounding doc file --- docs/src/confounding_adjustment.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/confounding_adjustment.md b/docs/src/confounding_adjustment.md index f530a22b..d0c1c964 100644 --- a/docs/src/confounding_adjustment.md +++ b/docs/src/confounding_adjustment.md @@ -2,7 +2,7 @@ To account for potential confounding effect due to population stratification, we extract principal components from the genetic data using [flashpca](https://github.com/gabraham/flashpca). We follow the recommended procedure for this tool which implies some preprocessing and filtering. The associated arguments are as follows: -- `LD_BLOCKS` (required): A path to pre-identified linkage desequlibrium blocks around the variants that will be queried for causal effect estimation. Those LD blocks will be removed from the data. -- `FLASHPCA_EXCLUSION_REGIONS` (required): A path to the flashpca special exclusion regions which is provided in [their repository](https://github.com/gabraham/flashpca/blob/master/exclusion_regions_hg19.txt). -- `MAF_THRESHOLD` (optional): Only variants with that minor allele frequency are considered +- `LD_BLOCKS` (optional): A path to pre-identified linkage desequlibrium blocks around the variants that will be queried for causal effect estimation. Those LD blocks will be removed from the data. +- `FLASHPCA_EXCLUSION_REGIONS` (required, default: [data/exclusion_regions_hg19.txt](https://github.com/TARGENE/targene-pipeline/data/exclusion_regions_hg19.txt)): A path to the flashpca special exclusion regions which is provided in [their repository](https://github.com/gabraham/flashpca/blob/master/exclusion_regions_hg19.txt). +- `MAF_THRESHOLD` (optional, default: 0.01): Only variants with that minor allele frequency are used to compute principal components. - `NB_PCS` (optional, default: 6): The number of PCA components to extract. From 92f787e7fa7c5434702942f6d735c7cc1abca6d8 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 12 Dec 2023 14:21:39 +0000 Subject: [PATCH 04/65] up data source doc --- docs/src/data_sources.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/data_sources.md b/docs/src/data_sources.md index 65f51c5a..179261ea 100644 --- a/docs/src/data_sources.md +++ b/docs/src/data_sources.md @@ -1,6 +1,6 @@ # Setting a data source -The following section will describe the data sources that are currently supported by TarGene. +The following section describes the data sources that are currently supported by TarGene. ## Custom Dataset From 22725b307ba30ae4b90b628a213d226352f28551 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 12 Dec 2023 14:23:48 +0000 Subject: [PATCH 05/65] update index doc --- docs/src/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index 25ba182c..950e6ad7 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,6 +1,6 @@ # TarGene -Welcome to TarGene, the software that brings Targeted Learning to population genetic studies! TarGene enables the estimation of various effect sizes including the Average Treatment Effect and the Interaction Average Treatment Effect (epistasis) up to any order. Because we follow the Targeted Learning framework, the final estimates provided by TarGene are covered by mathematical guarantees. The software is delivered as a [Nexflow](https://www.nextflow.io/) pipeline to bring scalability and reproducibility to your research. +Welcome to TarGene, the software that brings Targeted Learning to population genetic studies! TarGene enables the estimation of various effect sizes including the Average Treatment Effect and the Interaction Average Treatment Effect (GxG and GxE) up to any order (GxGxGxEx...!). Because we follow the Targeted Learning framework, the final estimates provided by TarGene are covered by mathematical guarantees. The software is delivered as a [Nexflow](https://www.nextflow.io/) pipeline to bring scalability and reproducibility to your research. Why using TarGene: @@ -11,7 +11,7 @@ Why using TarGene: ## Overview of the pipeline -The pipeline can rougly be decoupled into three steps. The first, aims at pre-processing the data sources to convert them in a table data format that can be wielded by Targeted Maximum Likelihood Estimation (TMLE). The second is the TMLE itself. The third and final step is the Sieve Variance Plateau correction which revises the variance estimate to account for the fact that individuals in the population are not necessarily independent. The following diagram provides a high level interface of the organisation of the pipeline. +The pipeline can roughly be decoupled into three steps. The first, aims at pre-processing the data sources to convert them in a table data format that can be wielded by Targeted Maximum Likelihood Estimation (TMLE). The second is the TMLE itself. The third and final optional step is the Sieve Variance Plateau correction which revises the variance estimate to account for the fact that individuals in the population are not necessarily independent. The following diagram provides a high level interface of the organisation of the pipeline. ```@raw html
@@ -21,7 +21,7 @@ The pipeline can rougly be decoupled into three steps. The first, aims at pre-pr ## Requirements -The pipeline has been tested with: +The pipeline is tested with: - Nextflow: 22.04 - Singularity: 3.8 From d2dab67cd2ed5f97668b94307f029c0638f8f23c Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 12 Dec 2023 14:25:46 +0000 Subject: [PATCH 06/65] more renamings --- conf/ci_jobs/custom_from_actors.config | 2 +- conf/ci_jobs/ukb_from_actors.config | 2 +- docs/src/miscellaneous.md | 2 +- docs/src/nextflow_params.md | 6 +++--- docs/src/sieve_variance.md | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/conf/ci_jobs/custom_from_actors.config b/conf/ci_jobs/custom_from_actors.config index 885709a3..454127ad 100644 --- a/conf/ci_jobs/custom_from_actors.config +++ b/conf/ci_jobs/custom_from_actors.config @@ -8,7 +8,7 @@ params { NB_PCS = 6 TRAITS_CONFIG = "test/data/ukbconfig_small.yaml" ESTIMATORFILE = "test/data/estimator.jl" - NB_VAR_ESTIMATORS = 10 + NB_SVP_ESTIMATORS = 10 PVAL_THRESHOLD = 1 BQTLS = "test/data/actors/bqtls_multiple_TFs.csv" TRANS_ACTORS = "test/data/actors/eqtls_multiple_TFs.csv" diff --git a/conf/ci_jobs/ukb_from_actors.config b/conf/ci_jobs/ukb_from_actors.config index 5f35ff8d..b4666fc6 100644 --- a/conf/ci_jobs/ukb_from_actors.config +++ b/conf/ci_jobs/ukb_from_actors.config @@ -10,7 +10,7 @@ params { NB_PCS = 6 TRAITS_CONFIG = "test/data/ukbconfig_small.yaml" ESTIMATORFILE = "test/data/estimator.jl" - NB_VAR_ESTIMATORS = 10 + NB_SVP_ESTIMATORS = 10 PVAL_THRESHOLD = 1 BQTLS = "test/data/actors/bqtls.csv" TRANS_ACTORS = "test/data/actors/eqtls.csv" diff --git a/docs/src/miscellaneous.md b/docs/src/miscellaneous.md index 5060cef3..ec8a1864 100644 --- a/docs/src/miscellaneous.md +++ b/docs/src/miscellaneous.md @@ -4,5 +4,5 @@ Further Nextflow parameter affecting the behaviour of the pipeline but that does - `CALL_THRESHOLD` (optional, default: 0.9): For putative causal variants (listed in the parameter files described in the [Describing the causal parameters of interest](@ref) section). If an individual's allele's probability is greater than the threshold, then it is called, otherwise it is considered missing. - `BATCH_SIZE` (optional, default: 400): The set of parameters to be estimated is batched and the TMLE processes will run in parallel across batches on your platform. -- `SAVE_IC` (optional, default: true): For all parameters with an p-value below `PVAL_THRESHOLD`, the influence curve is saved. Make sure to keep to `true` if you want to use sieve variance correction, i.e. if `NB_VAR_ESTIMATORS` != 0. +- `SAVE_IC` (optional, default: true): For all parameters with an p-value below `PVAL_THRESHOLD`, the influence curve is saved. Make sure to keep to `true` if you want to use sieve variance correction, i.e. if `NB_SVP_ESTIMATORS` != 0. - `OUTDIR` (optional, default: "results"): Output directory diff --git a/docs/src/nextflow_params.md b/docs/src/nextflow_params.md index 653b4964..fbae798f 100644 --- a/docs/src/nextflow_params.md +++ b/docs/src/nextflow_params.md @@ -42,13 +42,13 @@ If `STUDY_DESIGN`="FROM_ACTORS": - **`ESTIMATORFILE` (required)**: Julia configuration file describing the nuisance parameters learners. - `POSITIVITY_CONSTRAINT` (optional, default: 0.01): Treatment variables rarest configuration should have at least that frequency. -- `SAVE_IC` (optional, default: true): For all parameters with an p-value below `PVAL_THRESHOLD`, the influence curve is saved. Make sure to keep to `true` if you want to use sieve variance correction, i.e. if `NB_VAR_ESTIMATORS` != 0. +- `SAVE_IC` (optional, default: true): For all parameters with an p-value below `PVAL_THRESHOLD`, the influence curve is saved. Make sure to keep to `true` if you want to use sieve variance correction, i.e. if `NB_SVP_ESTIMATORS` != 0. ## [Correcting for population relatedness](@ref) - `GRM_NSPLITS` (optional, default: 100): To fasten GRM computation, it is typically split in batches. -- `NB_VAR_ESTIMATORS` (optional, default: 0): Number of sieve variance estimates per curve. Setting this value to 0 results in skipping sieve variance correction. -- `MAX_TAU` (optional, default: 0.9): Variance estimates are computed for tau ranging from 0 to MAX_TAU +- `NB_SVP_ESTIMATORS` (optional, default: 0): Number of sieve variance estimates per curve. Setting this value to 0 results in skipping sieve variance correction. +- `MAX_SVP_THRESHOLD` (optional, default: 0.9): Variance estimates are computed for tau ranging from 0 to MAX_SVP_THRESHOLD - `PVAL_THRESHOLD` (optional, default: 0.05): To save computation time and disk, only parameters with a p-value below this threshold are considered for sieve variance correction. ## [Tweaking additional behaviour](@ref) diff --git a/docs/src/sieve_variance.md b/docs/src/sieve_variance.md index 13c0a4f3..98ae379c 100644 --- a/docs/src/sieve_variance.md +++ b/docs/src/sieve_variance.md @@ -6,6 +6,6 @@ In brief, the SVP estimator computes a variance estimate for a range of threshol The following arguments can be changed to control the behaviour of the pipeline: - `GRM_NSPLITS` (default: 100): This is a purely computational argument. The GRM is typically very large and splitting enables a good memory/parallelization tradeoff. -- `MAX_TAU` (default: 0.8): Controls the maximum genetic distance considered. -- `NB_VAR_ESTIMATORS` (default: 0): Controls the number of points in the interval [0, `MAX_TAU`]. If 0, the Sieve Variance Plateau method will not be applied. +- `MAX_SVP_THRESHOLD` (default: 0.8): Controls the maximum genetic distance considered. +- `NB_SVP_ESTIMATORS` (default: 0): Controls the number of points in the interval [0, `MAX_SVP_THRESHOLD`]. If 0, the Sieve Variance Plateau method will not be applied. - `PVAL_THRESHOLD` (default: 0.05): Only estimates with a p-value lower than `PVAL_THRESHOLD` will be considered for SVP correction. This is because SVP will only increase the variance of the estimator. From 93fe5bf42c825af988303145a5ab7bd3febfb49e Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 12 Dec 2023 14:31:14 +0000 Subject: [PATCH 07/65] keep renaming stuff --- conf/ci_jobs/custom_from_actors.config | 2 +- conf/ci_jobs/ukb_from_actors.config | 2 +- conf/ci_jobs/ukb_from_param_file.config | 2 +- docs/src/nextflow_params.md | 2 +- docs/src/sieve_variance.md | 2 ++ docs/src/tmle.md | 2 +- main.nf | 6 +++--- modules/tmle.nf | 10 +++++----- 8 files changed, 15 insertions(+), 13 deletions(-) diff --git a/conf/ci_jobs/custom_from_actors.config b/conf/ci_jobs/custom_from_actors.config index 454127ad..20ea8257 100644 --- a/conf/ci_jobs/custom_from_actors.config +++ b/conf/ci_jobs/custom_from_actors.config @@ -7,7 +7,7 @@ params { BGEN_FILES = "test/data/unphased_bgen/ukb_chr{1,2,3}.{bgen,bgen.bgi,sample}" NB_PCS = 6 TRAITS_CONFIG = "test/data/ukbconfig_small.yaml" - ESTIMATORFILE = "test/data/estimator.jl" + ESTIMATOR_FILE = "test/data/estimator.jl" NB_SVP_ESTIMATORS = 10 PVAL_THRESHOLD = 1 BQTLS = "test/data/actors/bqtls_multiple_TFs.csv" diff --git a/conf/ci_jobs/ukb_from_actors.config b/conf/ci_jobs/ukb_from_actors.config index b4666fc6..5d456d71 100644 --- a/conf/ci_jobs/ukb_from_actors.config +++ b/conf/ci_jobs/ukb_from_actors.config @@ -9,7 +9,7 @@ params { WITHDRAWAL_LIST = "test/data/withdrawal_list.txt" NB_PCS = 6 TRAITS_CONFIG = "test/data/ukbconfig_small.yaml" - ESTIMATORFILE = "test/data/estimator.jl" + ESTIMATOR_FILE = "test/data/estimator.jl" NB_SVP_ESTIMATORS = 10 PVAL_THRESHOLD = 1 BQTLS = "test/data/actors/bqtls.csv" diff --git a/conf/ci_jobs/ukb_from_param_file.config b/conf/ci_jobs/ukb_from_param_file.config index dba889ac..a97af087 100644 --- a/conf/ci_jobs/ukb_from_param_file.config +++ b/conf/ci_jobs/ukb_from_param_file.config @@ -10,7 +10,7 @@ params { WITHDRAWAL_LIST = "test/data/withdrawal_list.txt" NB_PCS = 6 TRAITS_CONFIG = "test/data/ukbconfig_small.yaml" - ESTIMATORFILE = "test/data/estimator.jl" + ESTIMATOR_FILE = "test/data/estimator.jl" POSITIVITY_CONSTRAINT = 0.0 } diff --git a/docs/src/nextflow_params.md b/docs/src/nextflow_params.md index fbae798f..d4f2d988 100644 --- a/docs/src/nextflow_params.md +++ b/docs/src/nextflow_params.md @@ -40,7 +40,7 @@ If `STUDY_DESIGN`="FROM_ACTORS": ## [Specifying a Targeted Estimator](@ref) -- **`ESTIMATORFILE` (required)**: Julia configuration file describing the nuisance parameters learners. +- **`ESTIMATOR_FILE` (required)**: Julia configuration file describing the nuisance parameters learners. - `POSITIVITY_CONSTRAINT` (optional, default: 0.01): Treatment variables rarest configuration should have at least that frequency. - `SAVE_IC` (optional, default: true): For all parameters with an p-value below `PVAL_THRESHOLD`, the influence curve is saved. Make sure to keep to `true` if you want to use sieve variance correction, i.e. if `NB_SVP_ESTIMATORS` != 0. diff --git a/docs/src/sieve_variance.md b/docs/src/sieve_variance.md index 98ae379c..95aa068e 100644 --- a/docs/src/sieve_variance.md +++ b/docs/src/sieve_variance.md @@ -5,6 +5,8 @@ In brief, the SVP estimator computes a variance estimate for a range of threshol The following arguments can be changed to control the behaviour of the pipeline: +- `SVP` (default: false): Must be set to true to enable variance adjustement. +- `SVP_ESTIMATOR_KEY` (default: TMLE): The estimator from the `ESTIMATOR_FILE` that will be used for sieve variance plateau adjustment. - `GRM_NSPLITS` (default: 100): This is a purely computational argument. The GRM is typically very large and splitting enables a good memory/parallelization tradeoff. - `MAX_SVP_THRESHOLD` (default: 0.8): Controls the maximum genetic distance considered. - `NB_SVP_ESTIMATORS` (default: 0): Controls the number of points in the interval [0, `MAX_SVP_THRESHOLD`]. If 0, the Sieve Variance Plateau method will not be applied. diff --git a/docs/src/tmle.md b/docs/src/tmle.md index 220d88dd..1a03e5c0 100644 --- a/docs/src/tmle.md +++ b/docs/src/tmle.md @@ -5,7 +5,7 @@ TMLE is an adaptive procedure that depends on the specification of learning algo - `E[Y|T, W, C]`: The mean outcome given the treatment, confounders and extra covariates. It is commonly denoted by `Q` in the Targeted Learning litterature. - `p(T|W)`: The propensity score. It is commonly denoted by `G` in the Targeted Learning litterature. -The estimator configuration file describes the TMLE specification for the estimation of the parameters defined in the previous section. In order to provide maximum flexibility, this is provided as a plain [Julia](https://julialang.org/) file via the `ESTIMATORFILE` parameter. +The estimator configuration file describes the TMLE specification for the estimation of the parameters defined in the previous section. In order to provide maximum flexibility, this is provided as a plain [Julia](https://julialang.org/) file via the `ESTIMATOR_FILE` parameter. ### Description of the file diff --git a/main.nf b/main.nf index fccb319d..2cd52f16 100644 --- a/main.nf +++ b/main.nf @@ -135,7 +135,7 @@ workflow generateTMLEEstimates { genetic_confounders main: - estimator_file = Channel.value(file("$params.ESTIMATORFILE", checkIfExists: true)) + estimator_file = Channel.value(file("$params.ESTIMATOR_FILE", checkIfExists: true)) bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() if (params.STUDY_DESIGN == "FROM_ACTORS") { @@ -198,13 +198,13 @@ workflow negativeControl { // Permutation Tests dataset = Channel.value(file("${params.OUTDIR}/${params.ARROW_OUTPUT}")) - estimatorfile = Channel.value(file("${params.ESTIMATORFILE}")) + estimator_file = Channel.value(file("${params.ESTIMATOR_FILE}")) sieve_csv = Channel.value(file("NO_SIEVE_FILE")) GeneratePermutationTestsData(dataset, results_file) TMLE( GeneratePermutationTestsData.output.dataset, GeneratePermutationTestsData.output.parameters.flatten(), - estimatorfile + estimator_file ) MergeOutputs(TMLE.out.tmle_csv.collect(), sieve_csv, "permutation_summary.csv") diff --git a/modules/tmle.nf b/modules/tmle.nf index 7e60ba5b..5086148f 100644 --- a/modules/tmle.nf +++ b/modules/tmle.nf @@ -25,14 +25,14 @@ process TMLE { input: path data - path estimandsfile - path estimatorfile + path estimands_file + path estimator_file output: path "${hdf5out}" script: - basename = "result." + estimandsfile.getName().take(estimandsfile.getName().lastIndexOf('.')) + basename = "result." + estimands_file.getName().take(estimands_file.getName().lastIndexOf('.')) hdf5out = basename + ".hdf5" pval_threshold = KEEP_IC == true ? "--outputs.hdf5.pval_threshold=${params.PVAL_THRESHOLD}" : "" sample_ids = SVP == true ? "--outputs.hdf5.sample_ids=true" : "" @@ -40,8 +40,8 @@ process TMLE { TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --threads=${task.cpus} --startup-file=no tmle tmle \ $data \ - --estimands=$estimandsfile \ - --estimators=$estimatorfile \ + --estimands=$estimands_file \ + --estimators=$estimator_file \ --outputs.hdf5.filename=$hdf5out \ $pval_threshold \ $sample_ids \ From f2d4690202b1428576b5ccbed85b021c339ae528 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 12 Dec 2023 16:43:59 +0000 Subject: [PATCH 08/65] add more fixes --- docs/make.jl | 2 +- docs/src/sieve_variance.md | 2 +- ...eter_specification.md => study_designs.md} | 115 ++++++++++++------ docs/src/tmle.md | 73 ++++++----- main.nf | 5 +- modules/negative_control.nf | 2 +- modules/sieve_variance.nf | 4 +- modules/tmle.nf | 14 +-- test/data/estimator.jl | 13 +- test/data/parameters/parameters.yaml | 74 +++++++---- test/ukb_from_param_file.jl | 9 +- test/utils.jl | 32 +++++ 12 files changed, 228 insertions(+), 117 deletions(-) rename docs/src/{parameter_specification.md => study_designs.md} (51%) diff --git a/docs/make.jl b/docs/make.jl index 5769b27d..ae67ce92 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -19,7 +19,7 @@ makedocs(; "overview.md", "data_sources.md", "confounding_adjustment.md", - "parameter_specification.md", + "study_designs.md", "tmle.md", "sieve_variance.md", "miscellaneous.md", diff --git a/docs/src/sieve_variance.md b/docs/src/sieve_variance.md index 95aa068e..211e8a20 100644 --- a/docs/src/sieve_variance.md +++ b/docs/src/sieve_variance.md @@ -1,7 +1,7 @@ # Correcting for population relatedness If the i.i.d. (independent and identically distributed) hypothesis is not satisfied, most of the traditional statistical inference theory falls apart. This is typically possible in population genetics where a study may contain related individuals. Here we leverage a non-parametric method called [Sieve Variance Plateau](https://biostats.bepress.com/ucbbiostat/paper322/) (SVP) estimation. The hypothesis is that the dependence between individuals is sufficiently small, so that our targeted estimator will still be asymptotically unbiased, but its variance will be under estimated. -In brief, the SVP estimator computes a variance estimate for a range of thresholds 𝜏, by considering individuals to be genetically independent if their genetic distance exceeds 𝜏. The genetic distance between a pair of individuals (𝑖, 𝑗) equals 1 βˆ’ GRM𝑖,𝑗 , i.e., one minus their genetic relatedness value. As the distance threshold 𝜏 increases, fewer individuals are assumed to be genetically independent. For instance, the estimate corresponding to a distance of 𝜏 = 0 corresponds to the i.i.d. hypothesis, while a distance of 𝜏 = 1 incorporates pairs of individuals who are not genetically correlated. TarGene varies the threshold 𝜏 from 0 to 1 and fits a curve to the corresponding variance estimates. The maximum of this curve is the most conservative estimate of the variance of the target parameter estimator and constitutes our corrected variance estimator. +In brief, the SVP estimator computes a variance estimate for a range of thresholds 𝜏, by considering individuals to be genetically independent if their genetic distance exceeds 𝜏. The genetic distance between a pair of individuals (𝑖, 𝑗) equals 1 βˆ’ GRM𝑖,𝑗 , i.e., one minus their genetic relatedness value. As the distance threshold 𝜏 increases, fewer individuals are assumed to be genetically independent. For instance, the estimate corresponding to a distance of 𝜏 = 0 corresponds to the i.i.d. hypothesis, while a distance of 𝜏 = 1 incorporates pairs of individuals who are not genetically correlated. TarGene varies the threshold 𝜏 from 0 to 1 and fits a curve to the corresponding variance estimates. The maximum of this curve is the most conservative estimate of the variance estimator and constitutes our corrected variance estimator. The following arguments can be changed to control the behaviour of the pipeline: diff --git a/docs/src/parameter_specification.md b/docs/src/study_designs.md similarity index 51% rename from docs/src/parameter_specification.md rename to docs/src/study_designs.md index 1e2e13e6..a0770b21 100644 --- a/docs/src/parameter_specification.md +++ b/docs/src/study_designs.md @@ -1,8 +1,11 @@ -# Describing the causal parameters of interest +# Study Designs -## Parameter Files +A study design describes what are the questions of interest for a given TarGene run. In particular, it answers the two following questions: -In this section, by parameter, we mean a statistical estimand that represents a scientific quantity of interest and will be estimated via TarGene. The complete specification of a parameter requires the description of a causal model which can be represented by the following graph. +- What variants are of interest? +- What are the quantities of interest: Average Treatment Effects, Epistatic Interactions, Gene by Environment Interactions, ...? + +While specifying your estimands, it may be useful to keep the following causal model in mind. ```@raw html
@@ -10,48 +13,82 @@ In this section, by parameter, we mean a statistical estimand that represents a
``` -Parameters are specified by a YAML file containing the list of parameters to be estimated. Each parameter is fully determined by four fields: +The following sections describe the available study designs available with TarGene. -- `type`: The parameter type, one of: - - ATE: Average Treatment Effect - - IATE: Interaction Average Treatment Effect - - CM: Conditional Mean -- `target`: The trait of interest, as specified in the `TRAITS_CONFIG` file in the `phenotypes/name` field. You can also use the wildcard "*" to signify that you want to estimate this parameter accross all traits in the dataset. -- `treatment`: The treatment variables and associated control/case settings (see example below). -- `confounders`: A list of confounding variables. Note that principal components will be added to that list by default and must not be provided here. You can provide an empty list. -- `covariates`: This is optional and correspond to a list of additional covariates for the prediction of the trait. +## `STUDY_DESIGN` = `CUSTOM` -Here is an example parameter file: +This is the most general setting and should match the needs of any project, however it requires some preliminary work. In this setting, one typically provides a file containing a list of the estimands of interest. If you are interested in only a few estimands, it may be acceptable to write them by hand. Otherwise it is best to generate them using a programming language (for instance using [TMLE.jl](https://targene.github.io/TMLE.jl/stable/)). The path to those estimands is then provided with the `ESTIMANDS_FILE` nextflow parameter. Estimands are specified via a YAML file as follows: ```yaml - -Parameters: - - type: IATE - target: "*" - treatment: (RSID_10 = (control = "AA", case = "AC"), Sun_Exposure = (control = 1, case = 0)) - confounders: [Economic_background] - covariates: [Age] - - type: ATE - target: PHENOTYPE_2 - treatment: (RSID_10 = (control = "AA", case = "CC"), RSID_100 = (control = "GC", case = "CC")) - confounders: [] - - type: CM - target: PHENOTYPE_2 - treatment: (RSID_10 = "AA",) - confounders: [] +type: "Configuration" +estimands: + - outcome_extra_covariates: [] + type: "ATE" + treatment_values: + 3:3502414:T:C: + case: "TT" + control: "CT" + 1:238411180:T:C: + case: "TC" + control: "TT" + outcome: ALL + treatment_confounders: + 3:3502414:T:C: [] + 1:238411180:T:C: [] + - outcome_extra_covariates: [] + type: "IATE" + treatment_values: + 3:3502414:T:C: + case: "TT" + control: "CT" + 1:238411180:T:C: + case: "TC" + control: "TT" + outcome: ALL + treatment_confounders: + 3:3502414:T:C: [] + 1:238411180:T:C: [] + - outcome_extra_covariates: [] + type: "CM" + treatment_values: + 3:3502414:T:C: "CT" + 1:238411180:T:C: "TC" + outcome: ALL + treatment_confounders: + 3:3502414:T:C: [] + 1:238411180:T:C: [] + - outcome_extra_covariates: [] + type: "ATE" + treatment_values: + 2:14983:G:A: + case: "GG" + control: "AG" + outcome: ALL + treatment_confounders: + 2:14983:G:A: [] + - outcome_extra_covariates: [] + type: "CM" + treatment_values: + 2:14983:G:A: "AG" + outcome: ALL + treatment_confounders: + 2:14983:G:A: [] ``` -Note that variants must be encoded via an explicit genotype string representation (e.g. "AC"), the order of the alleles in the genotype is not important. - -## Parameter Plans - -At the moment, there are two main ways one can specify parameters that need to be estimated during a targene-pipeline run. This is done via the `MODE` parameter. +For each estimand: -### `STUDY_DESIGN` = `CUSTOM` +- `type`: refers to the type of effect size: + - ATE: Average Treatment Effect + - IATE: Interaction Average Treatment Effect + - CM: Conditional Mean +- `outcome`: The trait of interest. If using the Uk-Biobank datasource it must match the `phenotypes/name` field in the associated `TRAITS_CONFIG` file. You can also use the wildcard "ALL" to specify that you want to estimate this parameter accross all traits in the dataset. +- `treatment_values`: For each treatment variable (genetic-variant / environmental variables), the control/case contrasts. +- `treatment_confounders`: For each treatment variable, a list of confounding variables. If only a single list is provided, then all treatment variables are assumed to share the same confounding variables. Note that principal components will be added to that list automatically and must not be provided here. You can provide an empty list. +- `outcome_extra_covariates`: This is optional and correspond to a list of additional covariates for the prediction of the trait. -This is the most general setting and should match the needs of any project, however it requires some preliminary work. In this setting, one typically provides a set of parameter files as described above. If you are interested in only a few parameters it may be acceptable to write them by hand. Otherwise it is best to generate them using a programming language (for instance using [TMLE.jl](https://targene.github.io/TMLE.jl/stable/api/#TMLE.parameters_to_yaml-Tuple{Any,%20Any})). The path to those parameters is then provided with the `ESTIMANDS_FILE` nextflow parameter. See the previous section on [Parameter Files](@ref). +Note that variants must be encoded via an explicit genotype string representation (e.g. "AC"), the order of the alleles in the genotype is not important. -### `STUDY_DESIGN` = `FROM_ACTORS` +## `STUDY_DESIGN` = `FROM_ACTORS` In this setting the goal is to infer the interaction effect between multiple variants and potential external factors, interacting together via a specific biological mechanism. Typically, multiple sets of variants are of interest and each set is identified with a specific molecule, contributing to the mechanism. In particular, it is assumed that a set of variants, usually binding quantitative trait loci (bQTLs) play a pivotal role. All interactions of interest are thus defined with respect to that set of genetic variations. Let's Consider the following scenario: we know that a transcription factor binds to molecules `x` and `y` and then differentially binds to specific regions in the genome (`bQTLs`) to regulate downstream genes. We suspect that an alteration of this mechanism is responsible for some diseases. A set of `xQTLs`, associated with the expression of `x` and a set of `yQTLs` associated with the expression of `y` have been identified. Together `xQTLs` and `yQTLs` variants are termed "trans actors". We further suspect that some environmental factors may influence this process. From that scenario, there are many questions that can be asked, for instance : "What is the interaction effects of a bQTL with an environmental factor?". This is a simple pairwise interaction setting and more complex scenarios can be envisaged as described in the following graph. @@ -69,9 +106,9 @@ Let us now turn to the pipeline specification for this parameter plan: - `EXTRA_COVARIATES`: A path to a `.txt` file containing a list of extra covariate variables with no header and one variable per line. Each variable should be available from the trait dataset. - `EXTRA_CONFOUNDERS`: A path to a `.txt` file containing a list of extra confounding variables with no header and one variable per line. Each variable should be available from the trait dataset. - `ORDERS`: A comma separated string that specifies the various interaction orders of interest. All combinations satisfying the positivity constraint will be generated. The order 1 corresponds to the Average Treatment Effect (ATE) for `bQTLs`, any higher order corresponds to the Interaction Average Treatment Effect (IATE) for the various actors. For example, in the previous scenario, assume we provided `ORDERS`=`1,2`. This would generate parameter files for the estimation of all: - - ATEs parameters for all bQTLs - - IATEs parameters for all (bQTLs, xQTLs), (bQTLs, yQTLs), (bQTLs, Envs) pairs. + - ATEs estimands for all bQTLs + - IATEs estimands for all (bQTLs, xQTLs), (bQTLs, yQTLs), (bQTLs, Envs) pairs. ## Parallelization -Depending on the available resources, you can achieve further speed by batching the parameters to be estimated. The batch size can be controled via `BATCH_SIZE`(default: 400). +Depending on the available resources, you can achieve further speed by batching the estimands. The batch size can be controled via `BATCH_SIZE`(default: 400). diff --git a/docs/src/tmle.md b/docs/src/tmle.md index 1a03e5c0..f88e0510 100644 --- a/docs/src/tmle.md +++ b/docs/src/tmle.md @@ -1,46 +1,55 @@ # Specifying a Targeted Estimator -TMLE is an adaptive procedure that depends on the specification of learning algorithms for the estimation of the nuisance parameters (see [TMLE.jl](https://targene.github.io/TMLE.jl/stable/) for a description of the assumed setting). In our case, there are two nuisance parameters for which we need to specify learning algorithms: +TarGene is a flexible procedure that does not impose any constraint on the functional form of the relationship between genetic variants, environmental variables and traits. In practice, we rely on [MLJ](https://alan-turing-institute.github.io/MLJ.jl/dev/) to provide machine learning algorithms. In population genetics studies, there are two learning algorithms we need to specify: -- `E[Y|T, W, C]`: The mean outcome given the treatment, confounders and extra covariates. It is commonly denoted by `Q` in the Targeted Learning litterature. -- `p(T|W)`: The propensity score. It is commonly denoted by `G` in the Targeted Learning litterature. +- `E[Y|T, W, C]`: The mean outcome given the treatment, confounders and extra covariates. It is commonly denoted by `Q` in the Targeted Learning litterature. In reality, we will need one specification for continuous outcomes and one specification for binary outcomes. +- `p(T|W)`: The propensity score, which enables the targeting step of the estimation procedure. It is commonly denoted by `G` in the Targeted Learning litterature. -The estimator configuration file describes the TMLE specification for the estimation of the parameters defined in the previous section. In order to provide maximum flexibility, this is provided as a plain [Julia](https://julialang.org/) file via the `ESTIMATOR_FILE` parameter. +There are two main ways to define targeted estimators, from a predefined configuration or from a custom file. -### Description of the file +## Predefined estimators -In order to provide maximum flexibility as to the choice of learning algorithms, the estimator file is a plain [Julia](https://julialang.org/) file. This file is optional and omitting it defaults to using generalized linear models. If provided, it must define a [NamedTuple](https://docs.julialang.org/en/v1/base/base/#Core.NamedTuple) called `tmle_spec` containing any of the following fields as follows (default configuration): +A set of predefined estimators is readily available and can be accessed by using the configuration's name as the `ESTIMATOR_FILE` parameter. For instance, we provide the following: -```julia +- G-superlearning-Q-glm +- G-superlearning-Q-glmnet +- glm-with-interactions-for-Q +- glm +- glmnet-with-interactions-for-Q +- glmnet +- superlearning-with-interactions-for-Q +- superlearning +- tuned-xgboost -tmle_spec = ( - Q_continuous = LinearRegressor(), - Q_binary = LogisticClassifier(lambda=0.), - G = LogisticClassifier(lambda=0.), - threshold = 1e-8, - cache = false, - weighted_fluctuation = false -) -``` +all using TMLE as the final statistical inference method. While these should cover most use cases, it may be useful to define a custom estimation strategy. This can be achieved by writing a small [Julia](https://julialang.org/) file. + +## Custom estimators from a file -where: +Writin a [Julia](https://julialang.org/) estimators file is the most flexible way to define an estimation strategy for your study. -- `Q_continuous`: is a MLJ model used for the estimation of `E[Y|T, W, C]` when the outcome `Y` is continuous. -- `Q_binary`: is a MLJ model used for the estimation of `E[Y|T, W, C]` when the outcome `Y` is binary. -- `G`: is a MLJ model used for the estimation of `p(T|W)`. -- `threshold`: is the minimum value the propensity score `G` is allowed to take. -- `cache`: controls caching of data by [MLJ machines](https://alan-turing-institute.github.io/MLJ.jl/dev/machines/). Setting it to `true` may result in faster runtime but higher memory usage. -- `weighted_fluctuation`: controls whether the fluctuation for `Q` is a weighted glm or not. If some of the treatment values are rare it may lead to more robust estimation. +This file should simply define an `ESTIMATORS` [NamedTuple](https://docs.julialang.org/en/v1/base/base/#Core.NamedTuple) variable listing estimators to be used for inference. For example, the following: -Typically, `Q_continuous`, `Q_binary` and `G` will be adjusted and other fields can be left unspecified. +```julia +default_models = TMLE.default_models( + #Β For the estimation of E[Y|W, T]: continuous outcome + Q_continuous = LinearRegressor(), + #Β For the estimation of E[Y|W, T]: binary target + Q_binary = LogisticClassifier(lambda=0.), + #Β For the estimation of p(T| W) + G = LogisticClassifier(lambda=0.) +) + +ESTIMATORS = ( + TMLE_weighted = TMLEE(models=default_models, weighted=true), + TMLE_unweighted = TMLEE(models=default_models, weighted=false), + OSE = OSE(models=default_models) +) +``` -### Ready to use estimator files +defines three estimators: a weighted fluctuation `TMLE` (Targeted Maximum Likelihood Estimator), an unweighted fluctuation `TMLE` and a `OSE` (One Step Estimator). All estimators will learn the nuisance functions `Q` and `G` with the provided defaults: -We recognize not everyone will be familiar with [Julia](https://julialang.org/). We thus provide a set of ready to use estimator files that can be simplified or extended as needed: +- `Q_continuous`: A MLJ model used for the estimation of `E[Y|T, W, C]` when the outcome `Y` is continuous. +- `Q_binary`: A MLJ model used for the estimation of `E[Y|T, W, C]` when the outcome `Y` is binary. +- `G`: A MLJ model used for the estimation of `p(T|W)`. -- Super Learning: [with](./estimators/superlearning-with-interactions-for-Q.jl) and [without](./estimators/superlearning.jl) interaction terms in the GLM models for Q. -- Super Learning for G and GLMNet for Q: [here](./estimators/G-superlearning-Q-glmnet.jl). -- Super Learning for G and GLM for Q: [here](./estimators/G-superlearning-Q-glm.jl). -- GLMNet: [with](./estimators/glmnet-with-interactions-for-Q.jl) and [without](./estimators/glmnet.jl) interaction terms in the GLM models for Q. -- GLM: [with](./estimators/glm-with-interactions-for-Q.jl) and [without](./estimators/glm.jl) interaction terms in the GLM models for Q. -- XGBoost: [with tuning](./estimators/tuned-xgboost.jl). +For full details, visit the [TMLE.jl documentation](https://targene.github.io/TMLE.jl/stable/). diff --git a/main.nf b/main.nf index 2cd52f16..f8e51e6f 100644 --- a/main.nf +++ b/main.nf @@ -199,14 +199,13 @@ workflow negativeControl { // Permutation Tests dataset = Channel.value(file("${params.OUTDIR}/${params.ARROW_OUTPUT}")) estimator_file = Channel.value(file("${params.ESTIMATOR_FILE}")) - sieve_csv = Channel.value(file("NO_SIEVE_FILE")) GeneratePermutationTestsData(dataset, results_file) TMLE( GeneratePermutationTestsData.output.dataset, - GeneratePermutationTestsData.output.parameters.flatten(), + GeneratePermutationTestsData.output.estimands.flatten(), estimator_file ) - MergeOutputs(TMLE.out.tmle_csv.collect(), sieve_csv, "permutation_summary.csv") + MergeOutputs(TMLE.out.tmle_csv.collect(), "permutation_summary.csv") // Random Variants parameter files generation if (params.STUDY_DESIGN == "FROM_ACTORS") { diff --git a/modules/negative_control.nf b/modules/negative_control.nf index 3f49329e..95bdf3b8 100644 --- a/modules/negative_control.nf +++ b/modules/negative_control.nf @@ -27,7 +27,7 @@ process GeneratePermutationTestsData { output: path "permutation_dataset.arrow", emit: dataset - path "*.yaml", emit: parameters + path "*.yaml", emit: estimands script: limit = params.MAX_PERMUTATION_TESTS == null ? "" : "--limit=${params.MAX_PERMUTATION_TESTS}" diff --git a/modules/sieve_variance.nf b/modules/sieve_variance.nf index 92928123..8261be30 100644 --- a/modules/sieve_variance.nf +++ b/modules/sieve_variance.nf @@ -14,7 +14,7 @@ process SieveVarianceEstimation { script: """ TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no tmle sieve-variance-plateau \ + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no /opt/bin/tmle sieve-variance-plateau \ result \ --nb-estimators=$params.NB_SVP_ESTIMATORS \ --max-tau=$params.MAX_SVP_THRESHOLD \ @@ -38,7 +38,7 @@ process MergeOutputs { json_output = params.JSON_OUTPUT != "NO_JSON_OUTPUT" ? "--outputs.json.filename=$params.JSON_OUTPUT" : "" """ TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no tmle make-summary \ + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no /opt/bin/tmle make-summary \ result \ --outputs.hdf5.filename=${params.HDF5_OUTPUT} \ ${json_output} diff --git a/modules/tmle.nf b/modules/tmle.nf index 5086148f..28eb7b35 100644 --- a/modules/tmle.nf +++ b/modules/tmle.nf @@ -34,11 +34,11 @@ process TMLE { script: basename = "result." + estimands_file.getName().take(estimands_file.getName().lastIndexOf('.')) hdf5out = basename + ".hdf5" - pval_threshold = KEEP_IC == true ? "--outputs.hdf5.pval_threshold=${params.PVAL_THRESHOLD}" : "" - sample_ids = SVP == true ? "--outputs.hdf5.sample_ids=true" : "" + pval_threshold = params.KEEP_IC == true ? "--outputs.hdf5.pval_threshold=${params.PVAL_THRESHOLD}" : "" + sample_ids = params.SVP == true ? "--outputs.hdf5.sample_ids=true" : "" """ TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --threads=${task.cpus} --startup-file=no tmle tmle \ + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --threads=${task.cpus} --startup-file=no /opt/bin/tmle tmle \ $data \ --estimands=$estimands_file \ --estimators=$estimator_file \ @@ -52,7 +52,7 @@ process TMLE { process TMLEInputsFromParamFile { container "olivierlabayle/tl-core:cvtmle" publishDir "$params.OUTDIR/estimands", mode: 'symlink', pattern: "*.yaml" - publishDir "$params.OUTDIR", mode: 'symlink', pattern: "*.arrow" + publishDir "$params.OUTDIR", mode: 'symlink', pattern: "*.arrow", saveAs: { filename -> "${params.ARROW_OUTPUT}" } label "bigmem" input: @@ -62,7 +62,7 @@ process TMLEInputsFromParamFile { path parameter output: - path "${params.ARROW_OUTPUT}", emit: traits + path "final.data.arrow", emit: traits path "final.*.jls", emit: estimands script: @@ -84,7 +84,7 @@ process TMLEInputsFromParamFile { process TMLEInputsFromActors { container "olivierlabayle/tl-core:cvtmle" publishDir "$params.OUTDIR/estimands", mode: 'symlink', pattern: "*.yaml" - publishDir "$params.OUTDIR", mode: 'symlink', pattern: "*.arrow" + publishDir "$params.OUTDIR", mode: 'symlink', pattern: "*.arrow", saveAs: { filename -> "${params.ARROW_OUTPUT}" } label "bigmem" input: @@ -98,7 +98,7 @@ process TMLEInputsFromActors { path trans_actors output: - path "${params.ARROW_OUTPUT}", emit: traits + path "final.data.arrow", emit: traits path "final.*.jls", emit: estimands script: diff --git a/test/data/estimator.jl b/test/data/estimator.jl index 13f34cef..0981c602 100644 --- a/test/data/estimator.jl +++ b/test/data/estimator.jl @@ -1,12 +1,13 @@ -tmle_spec = ( - #Β Controls caching of data by MLJ machines: turning to `true` may result in faster execution but higher memory usage - cache = false, - # Propensity score threshold - threshold = 1e-8, - #Β For the estimation of E[Y|W, T]: continuous target +default_models = TMLE.default_models( + #Β For the estimation of E[Y|W, T]: continuous outcome Q_continuous = LinearRegressor(), #Β For the estimation of E[Y|W, T]: binary target Q_binary = LogisticClassifier(lambda=0.), #Β For the estimation of p(T| W) G = LogisticClassifier(lambda=0.) +) + +ESTIMATORS = ( + TMLE = TMLEE(models=default_models, weighted=true), + OSE = OSE(models=default_models) ) \ No newline at end of file diff --git a/test/data/parameters/parameters.yaml b/test/data/parameters/parameters.yaml index c662a2ba..3f896b14 100644 --- a/test/data/parameters/parameters.yaml +++ b/test/data/parameters/parameters.yaml @@ -1,21 +1,53 @@ -Parameters: - - type: ATE - target: "*" - treatment: (var"1:238411180:T:C" = (control = "TT", case = "TC"), var"3:3502414:T:C" = (control = "CT", case = "TT")) - confounders: [] - - type: IATE - target: "*" - treatment: (var"1:238411180:T:C" = (control = "TT", case = "TC"), var"3:3502414:T:C" = (control = "CT", case = "TT")) - confounders: [] - - type: CM - target: "*" - treatment: (var"1:238411180:T:C" = "TC", var"3:3502414:T:C" = "CT") - confounders: [] - - type: ATE - target: "*" - treatment: (var"2:14983:G:A" = (control = "AG", case = "GG"),) - confounders: [] - - type: CM - target: "*" - treatment: (var"2:14983:G:A" = "AG",) - confounders: [] +type: "Configuration" +estimands: + - outcome_extra_covariates: [] + type: "ATE" + treatment_values: + 3:3502414:T:C: + case: "TT" + control: "CT" + 1:238411180:T:C: + case: "TC" + control: "TT" + outcome: ALL + treatment_confounders: + 3:3502414:T:C: [] + 1:238411180:T:C: [] + - outcome_extra_covariates: [] + type: "IATE" + treatment_values: + 3:3502414:T:C: + case: "TT" + control: "CT" + 1:238411180:T:C: + case: "TC" + control: "TT" + outcome: ALL + treatment_confounders: + 3:3502414:T:C: [] + 1:238411180:T:C: [] + - outcome_extra_covariates: [] + type: "CM" + treatment_values: + 3:3502414:T:C: "CT" + 1:238411180:T:C: "TC" + outcome: ALL + treatment_confounders: + 3:3502414:T:C: [] + 1:238411180:T:C: [] + - outcome_extra_covariates: [] + type: "ATE" + treatment_values: + 2:14983:G:A: + case: "GG" + control: "AG" + outcome: ALL + treatment_confounders: + 2:14983:G:A: [] + - outcome_extra_covariates: [] + type: "CM" + treatment_values: + 2:14983:G:A: "AG" + outcome: ALL + treatment_confounders: + 2:14983:G:A: [] diff --git a/test/ukb_from_param_file.jl b/test/ukb_from_param_file.jl index d397e086..022da954 100644 --- a/test/ukb_from_param_file.jl +++ b/test/ukb_from_param_file.jl @@ -7,6 +7,7 @@ using YAML using TMLE using Arrow using Serialization +using JLD2 #Β "local" profile assumes singularity is installed args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] @@ -20,14 +21,14 @@ include(joinpath(@__DIR__, "test", "utils.jl")) r = run(cmd) @test r.exitcode == 0 - output = CSV.read(joinpath("results", "summary.csv"), DataFrame) - dataset = DataFrame(Arrow.Table(joinpath("results", "tmle_inputs", "final.data.arrow"))) + results = jldopen(joinpath("results", "results.hdf5")) + dataset = DataFrame(Arrow.Table(joinpath("results", "dataset.arrow"))) @test names(output) == vcat(SUMMARY_COLUMNS, ADJUTMENT_COL) # 2 bQTLs and 1 trans-actor @test Set(unique(output.TREATMENTS)) == Set(["1:238411180:T:C_&_3:3502414:T:C", "2:14983:G:A"]) - check_fails_are_extremely_rare_traits(output, dataset) - test_n_success_more_than_threshold(output, 20) + check_fails_are_extremely_rare_traits(results, dataset) + test_n_success_more_than_threshold(results, 20) end end diff --git a/test/utils.jl b/test/utils.jl index ec28b7ae..05967b28 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -38,3 +38,35 @@ function test_n_success_more_than_threshold(output, threshold) n_succeses_per_treatment = DataFrames.combine(groupby(successes, :TREATMENTS), nrow) @test all(x > threshold for x in n_succeses_per_treatment.nrow) end + + +function write_custom_configuration() + config = Configuration(estimands=[ + ATE( + outcome = "ALL", + treatment_values = NamedTuple{(Symbol("1:238411180:T:C"), Symbol("3:3502414:T:C"))}([(control = "TT", case = "TC"), (control = "CT", case = "TT")]), + treatment_confounders = [] + ), + IATE( + outcome = "ALL", + treatment_values = NamedTuple{(Symbol("1:238411180:T:C"), Symbol("3:3502414:T:C"))}([(control = "TT", case = "TC"), (control = "CT", case = "TT")]), + treatment_confounders = [] + ), + CM( + outcome = "ALL", + treatment_values = NamedTuple{(Symbol("1:238411180:T:C"), Symbol("3:3502414:T:C"))}(["TC", "CT"]), + treatment_confounders = [] + ), + ATE( + outcome = "ALL", + treatment_values = NamedTuple{(Symbol("2:14983:G:A"),)}([(control = "AG", case = "GG")]), + treatment_confounders = [] + ), + CM( + outcome = "ALL", + treatment_values = NamedTuple{(Symbol("2:14983:G:A"),)}(["AG"]), + treatment_confounders = [] + ) + ]) + TMLE.write_yaml(joinpath("test", "data", "parameters", "parameters.yaml"), config) +end \ No newline at end of file From d346550f2135ad37c21fb4610e178ce082ba2aa3 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Wed, 13 Dec 2023 11:47:13 +0000 Subject: [PATCH 09/65] update config and some publish dir --- conf/ci.config | 4 ++-- conf/docker.config | 7 +++++++ conf/eddie.config | 6 ++---- conf/local.config | 5 +---- conf/singularity.config | 6 ++++++ modules/tmle.nf | 7 +++---- nextflow.config | 7 ++++++- 7 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 conf/docker.config create mode 100644 conf/singularity.config diff --git a/conf/ci.config b/conf/ci.config index 3fc18f75..048385ad 100644 --- a/conf/ci.config +++ b/conf/ci.config @@ -1,9 +1,9 @@ docker { - enabled = true - fixOwnership = true runOptions = '-u $(id -u):$(id -g)' } +includeConfig 'docker.config' + process { memory = '4G' diff --git a/conf/docker.config b/conf/docker.config new file mode 100644 index 00000000..91634e65 --- /dev/null +++ b/conf/docker.config @@ -0,0 +1,7 @@ +docker { + enabled = true + pullTimeout = '1h' + envWhitelist = 'TMPDIR' + fixOwnership = true +} + diff --git a/conf/eddie.config b/conf/eddie.config index 6db26c1f..0810c24e 100644 --- a/conf/eddie.config +++ b/conf/eddie.config @@ -53,9 +53,7 @@ env { } singularity { - // Correctly set the temporary directory environment variables and isolate PIDs - envWhitelist = "SINGULARITY_TMPDIR,TMPDIR" runOptions = '-p -B "$TMPDIR"' - enabled = true - autoMounts = true } + +includeConfig 'singularity.config' diff --git a/conf/local.config b/conf/local.config index a14a782e..5f58826c 100644 --- a/conf/local.config +++ b/conf/local.config @@ -9,9 +9,6 @@ env { } singularity { - // Correctly set the temporary directory environment variables and isolate PIDs - envWhitelist = "SINGULARITY_TMPDIR,TMPDIR" runOptions = '-p -B "$TMPDIR"' - enabled = true - autoMounts = true } +includeConfig 'singularity.config' diff --git a/conf/singularity.config b/conf/singularity.config new file mode 100644 index 00000000..268b4a84 --- /dev/null +++ b/conf/singularity.config @@ -0,0 +1,6 @@ +singularity { + enabled = true + autoMounts = true + pullTimeout = '1h' + envWhitelist = 'SINGULARITY_TMPDIR,TMPDIR' +} diff --git a/modules/tmle.nf b/modules/tmle.nf index 28eb7b35..289c30d3 100644 --- a/modules/tmle.nf +++ b/modules/tmle.nf @@ -18,8 +18,7 @@ def longest_prefix(files){ process TMLE { container "olivierlabayle/targeted-estimation:cv_tmle" - publishDir "$params.OUTDIR/csvs", mode: 'symlink', pattern: "*.csv" - publishDir "$params.OUTDIR/hdf5files/inf_curves", mode: 'symlink', pattern: "*.hdf5" + publishDir "$params.OUTDIR/tmle_outputs/", mode: 'symlink', pattern: "*.hdf5" label "bigmem" label "multithreaded" @@ -51,7 +50,7 @@ process TMLE { process TMLEInputsFromParamFile { container "olivierlabayle/tl-core:cvtmle" - publishDir "$params.OUTDIR/estimands", mode: 'symlink', pattern: "*.yaml" + publishDir "$params.OUTDIR/estimands", mode: 'symlink', pattern: "*.jls" publishDir "$params.OUTDIR", mode: 'symlink', pattern: "*.arrow", saveAs: { filename -> "${params.ARROW_OUTPUT}" } label "bigmem" @@ -83,7 +82,7 @@ process TMLEInputsFromParamFile { process TMLEInputsFromActors { container "olivierlabayle/tl-core:cvtmle" - publishDir "$params.OUTDIR/estimands", mode: 'symlink', pattern: "*.yaml" + publishDir "$params.OUTDIR/estimands", mode: 'symlink', pattern: "*.jls" publishDir "$params.OUTDIR", mode: 'symlink', pattern: "*.arrow", saveAs: { filename -> "${params.ARROW_OUTPUT}" } label "bigmem" diff --git a/nextflow.config b/nextflow.config index e81d91e8..8b95168d 100644 --- a/nextflow.config +++ b/nextflow.config @@ -19,7 +19,6 @@ process { withLabel: multithreaded { cpus = 10 } - } profiles { @@ -32,4 +31,10 @@ profiles { local { includeConfig 'conf/local.config' } + docker { + includeConfig 'conf/docker.config' + } + singularity { + includeConfig 'conf/singularity.config' + } } From 39b97d66f5b5f8b5696047557b4107710dcc9c61 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Wed, 13 Dec 2023 13:33:53 +0000 Subject: [PATCH 10/65] fix one test --- .gitignore | 1 - main.nf | 6 +- modules/sieve_variance.nf | 12 +- modules/tmle.nf | 2 +- test/Manifest.toml | 1787 +++++++++++++++++++++++++++++++++++ test/Project.toml | 5 +- test/ukb_from_param_file.jl | 30 +- test/utils.jl | 37 +- 8 files changed, 1832 insertions(+), 48 deletions(-) create mode 100644 test/Manifest.toml diff --git a/.gitignore b/.gitignore index 61ef683b..b1f6488a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,5 +13,4 @@ test/sandbox.jl docs/Manifest.toml *.DS_Store trace.txt* -test/Manifest.toml trace.txt diff --git a/main.nf b/main.nf index f8e51e6f..6b624e03 100644 --- a/main.nf +++ b/main.nf @@ -46,6 +46,8 @@ params.TMLE_SAVE_EVERY = 100 params.ARROW_OUTPUT = "dataset.arrow" params.JSON_OUTPUT = "NO_JSON_OUTPUT" params.HDF5_OUTPUT = "results.hdf5" +params.PERMUTATION_HDF5_OUTPUT = "permutation_results.hdf5" +params.PERMUTATION_JSON_OUTPUT = "NO_JSON_OUTPUT" // Permutation Tests Parameters params.MAX_PERMUTATION_TESTS = null @@ -205,7 +207,7 @@ workflow negativeControl { GeneratePermutationTestsData.output.estimands.flatten(), estimator_file ) - MergeOutputs(TMLE.out.tmle_csv.collect(), "permutation_summary.csv") + MergeOutputs(TMLE.out.collect(), params.PERMUTATION_HDF5_OUTPUT, params.PERMUTATION_JSON_OUTPUT) // Random Variants parameter files generation if (params.STUDY_DESIGN == "FROM_ACTORS") { @@ -236,5 +238,5 @@ workflow { sieve_results = generateSieveEstimates(generateTMLEEstimates.out, generateIIDGenotypes.out) } - MergeOutputs(generateTMLEEstimates.out.collect(), "summary.csv") + MergeOutputs(generateTMLEEstimates.out.collect(), params.HDF5_OUTPUT, params.JSON_OUTPUT) } diff --git a/modules/sieve_variance.nf b/modules/sieve_variance.nf index 8261be30..24178a69 100644 --- a/modules/sieve_variance.nf +++ b/modules/sieve_variance.nf @@ -15,7 +15,7 @@ process SieveVarianceEstimation { """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no /opt/bin/tmle sieve-variance-plateau \ - result \ + tmle_result \ --nb-estimators=$params.NB_SVP_ESTIMATORS \ --max-tau=$params.MAX_SVP_THRESHOLD \ --estimator_key=$params.SVP_ESTIMATOR_KEY \ @@ -29,17 +29,19 @@ process MergeOutputs { input: path tmle_files - val outpath + val hdf5_output + val json_output output: - path "${outpath}" + path "${hdf5_output}" + path "${json_output}", optional: true script: - json_output = params.JSON_OUTPUT != "NO_JSON_OUTPUT" ? "--outputs.json.filename=$params.JSON_OUTPUT" : "" + json_output = json_output != "NO_JSON_OUTPUT" ? "--outputs.json.filename=${json_output}" : "" """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no /opt/bin/tmle make-summary \ - result \ + tmle_result \ --outputs.hdf5.filename=${params.HDF5_OUTPUT} \ ${json_output} """ diff --git a/modules/tmle.nf b/modules/tmle.nf index 289c30d3..1d88c15d 100644 --- a/modules/tmle.nf +++ b/modules/tmle.nf @@ -31,7 +31,7 @@ process TMLE { path "${hdf5out}" script: - basename = "result." + estimands_file.getName().take(estimands_file.getName().lastIndexOf('.')) + basename = "tmle_result." + estimands_file.getName().take(estimands_file.getName().lastIndexOf('.')) hdf5out = basename + ".hdf5" pval_threshold = params.KEEP_IC == true ? "--outputs.hdf5.pval_threshold=${params.PVAL_THRESHOLD}" : "" sample_ids = params.SVP == true ? "--outputs.hdf5.sample_ids=true" : "" diff --git a/test/Manifest.toml b/test/Manifest.toml new file mode 100644 index 00000000..0c686562 --- /dev/null +++ b/test/Manifest.toml @@ -0,0 +1,1787 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.9.0" +manifest_format = "2.0" +project_hash = "75349bcfa7b99363b0d380bd8da5df342d556b10" + +[[deps.ARFFFiles]] +deps = ["CategoricalArrays", "Dates", "Parsers", "Tables"] +git-tree-sha1 = "e8c8e0a2be6eb4f56b1672e46004463033daa409" +uuid = "da404889-ca92-49ff-9e8b-0aa6b4d38dc8" +version = "1.4.1" + +[[deps.AbstractDifferentiation]] +deps = ["ExprTools", "LinearAlgebra", "Requires"] +git-tree-sha1 = "6a5e61dc899ab116035c18ead4ec890269f3c478" +uuid = "c29ec348-61ec-40c8-8164-b8c60e9d9f3d" +version = "0.6.0" + + [deps.AbstractDifferentiation.extensions] + AbstractDifferentiationChainRulesCoreExt = "ChainRulesCore" + AbstractDifferentiationFiniteDifferencesExt = "FiniteDifferences" + AbstractDifferentiationForwardDiffExt = ["DiffResults", "ForwardDiff"] + AbstractDifferentiationReverseDiffExt = ["DiffResults", "ReverseDiff"] + AbstractDifferentiationTrackerExt = "Tracker" + AbstractDifferentiationZygoteExt = "Zygote" + + [deps.AbstractDifferentiation.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + DiffResults = "163ba53b-c6d8-5494-b064-1a9d43ac40c5" + FiniteDifferences = "26cc04aa-876d-5657-8c51-4c34ba976000" + ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" + ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" + Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" + Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" + +[[deps.AbstractFFTs]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "d92ad398961a3ed262d8bf04a1a2b8340f915fef" +uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c" +version = "1.5.0" +weakdeps = ["ChainRulesCore", "Test"] + + [deps.AbstractFFTs.extensions] + AbstractFFTsChainRulesCoreExt = "ChainRulesCore" + AbstractFFTsTestExt = "Test" + +[[deps.AbstractTrees]] +git-tree-sha1 = "faa260e4cb5aba097a73fab382dd4b5819d8ec8c" +uuid = "1520ce14-60c1-5f80-bbc7-55ef81b5835c" +version = "0.4.4" + +[[deps.Adapt]] +deps = ["LinearAlgebra", "Requires"] +git-tree-sha1 = "cde29ddf7e5726c9fb511f340244ea3481267608" +uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" +version = "3.7.2" +weakdeps = ["StaticArrays"] + + [deps.Adapt.extensions] + AdaptStaticArraysExt = "StaticArrays" + +[[deps.ArgCheck]] +git-tree-sha1 = "a3a402a35a2f7e0b87828ccabbd5ebfbebe356b4" +uuid = "dce04be8-c92d-5529-be00-80e4d2c0e197" +version = "2.3.0" + +[[deps.ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" +version = "1.1.1" + +[[deps.ArnoldiMethod]] +deps = ["LinearAlgebra", "Random", "StaticArrays"] +git-tree-sha1 = "62e51b39331de8911e4a7ff6f5aaf38a5f4cc0ae" +uuid = "ec485272-7323-5ecc-a04f-4719b315124d" +version = "0.2.0" + +[[deps.ArrayInterface]] +deps = ["Adapt", "LinearAlgebra", "Requires", "SparseArrays", "SuiteSparse"] +git-tree-sha1 = "247efbccf92448be332d154d6ca56b9fcdd93c31" +uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" +version = "7.6.1" + + [deps.ArrayInterface.extensions] + ArrayInterfaceBandedMatricesExt = "BandedMatrices" + ArrayInterfaceBlockBandedMatricesExt = "BlockBandedMatrices" + ArrayInterfaceCUDAExt = "CUDA" + ArrayInterfaceGPUArraysCoreExt = "GPUArraysCore" + ArrayInterfaceStaticArraysCoreExt = "StaticArraysCore" + ArrayInterfaceTrackerExt = "Tracker" + + [deps.ArrayInterface.weakdeps] + BandedMatrices = "aae01518-5342-5314-be14-df237901396f" + BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527" + StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" + Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" + +[[deps.Arrow]] +deps = ["ArrowTypes", "BitIntegers", "CodecLz4", "CodecZstd", "ConcurrentUtilities", "DataAPI", "Dates", "EnumX", "LoggingExtras", "Mmap", "PooledArrays", "SentinelArrays", "Tables", "TimeZones", "TranscodingStreams", "UUIDs"] +git-tree-sha1 = "cd893c29839c524ca2c5944b8e05f26e299df105" +uuid = "69666777-d1a9-59fb-9406-91d4454c9d45" +version = "2.7.0" + +[[deps.ArrowTypes]] +deps = ["Sockets", "UUIDs"] +git-tree-sha1 = "404265cd8128a2515a81d5eae16de90fdef05101" +uuid = "31f734f8-188a-4ce0-8406-c8a06bd891cd" +version = "2.3.0" + +[[deps.Artifacts]] +uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" + +[[deps.Atomix]] +deps = ["UnsafeAtomics"] +git-tree-sha1 = "c06a868224ecba914baa6942988e2f2aade419be" +uuid = "a9b6321e-bd34-4604-b9c9-b65b8de01458" +version = "0.1.0" + +[[deps.BSON]] +git-tree-sha1 = "2208958832d6e1b59e49f53697483a84ca8d664e" +uuid = "fbb218c0-5317-5bc6-957e-2ee96dd4b1f0" +version = "0.3.7" + +[[deps.BangBang]] +deps = ["Compat", "ConstructionBase", "InitialValues", "LinearAlgebra", "Requires", "Setfield", "Tables"] +git-tree-sha1 = "e28912ce94077686443433c2800104b061a827ed" +uuid = "198e06fe-97b7-11e9-32a5-e1d131e6ad66" +version = "0.3.39" + + [deps.BangBang.extensions] + BangBangChainRulesCoreExt = "ChainRulesCore" + BangBangDataFramesExt = "DataFrames" + BangBangStaticArraysExt = "StaticArrays" + BangBangStructArraysExt = "StructArrays" + BangBangTypedTablesExt = "TypedTables" + + [deps.BangBang.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" + TypedTables = "9d95f2ec-7b3d-5a63-8d20-e2491e220bb9" + +[[deps.Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" + +[[deps.Baselet]] +git-tree-sha1 = "aebf55e6d7795e02ca500a689d326ac979aaf89e" +uuid = "9718e550-a3fa-408a-8086-8db961cd8217" +version = "0.1.1" + +[[deps.BitFlags]] +git-tree-sha1 = "2dc09997850d68179b69dafb58ae806167a32b1b" +uuid = "d1d4a3ce-64b1-5f1a-9ba4-7e7e69966f35" +version = "0.1.8" + +[[deps.BitIntegers]] +deps = ["Random"] +git-tree-sha1 = "a55462dfddabc34bc97d3a7403a2ca2802179ae6" +uuid = "c3b6d118-76ef-56ca-8cc7-ebb389d030a1" +version = "0.3.1" + +[[deps.CEnum]] +git-tree-sha1 = "389ad5c84de1ae7cf0e28e381131c98ea87d54fc" +uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82" +version = "0.5.0" + +[[deps.CSV]] +deps = ["CodecZlib", "Dates", "FilePathsBase", "InlineStrings", "Mmap", "Parsers", "PooledArrays", "PrecompileTools", "SentinelArrays", "Tables", "Unicode", "WeakRefStrings", "WorkerUtilities"] +git-tree-sha1 = "44dbf560808d49041989b8a96cae4cffbeb7966a" +uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" +version = "0.10.11" + +[[deps.CUDA_Driver_jll]] +deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "Pkg"] +git-tree-sha1 = "1e42ef1bdb45487ff28de16182c0df4920181dc3" +uuid = "4ee394cb-3365-5eb0-8335-949819d2adfc" +version = "0.7.0+0" + +[[deps.CUDA_Runtime_jll]] +deps = ["Artifacts", "CUDA_Driver_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"] +git-tree-sha1 = "9704e50c9158cf8896c2776b8dbc5edd136caf80" +uuid = "76a88914-d11a-5bdc-97e0-2f5a05c973a2" +version = "0.10.1+0" + +[[deps.Calculus]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "f641eb0a4f00c343bbc32346e1217b86f3ce9dad" +uuid = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9" +version = "0.5.1" + +[[deps.CategoricalArrays]] +deps = ["DataAPI", "Future", "Missings", "Printf", "Requires", "Statistics", "Unicode"] +git-tree-sha1 = "1568b28f91293458345dabba6a5ea3f183250a61" +uuid = "324d7699-5711-5eae-9e2f-1d82baa6b597" +version = "0.10.8" +weakdeps = ["JSON", "RecipesBase", "SentinelArrays", "StructTypes"] + + [deps.CategoricalArrays.extensions] + CategoricalArraysJSONExt = "JSON" + CategoricalArraysRecipesBaseExt = "RecipesBase" + CategoricalArraysSentinelArraysExt = "SentinelArrays" + CategoricalArraysStructTypesExt = "StructTypes" + +[[deps.CategoricalDistributions]] +deps = ["CategoricalArrays", "Distributions", "Missings", "OrderedCollections", "Random", "ScientificTypes"] +git-tree-sha1 = "3124343a1b0c9a2f5fdc1d9bcc633ba11735a4c4" +uuid = "af321ab8-2d2e-40a6-b165-3d674595d28e" +version = "0.1.13" + + [deps.CategoricalDistributions.extensions] + UnivariateFiniteDisplayExt = "UnicodePlots" + + [deps.CategoricalDistributions.weakdeps] + UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228" + +[[deps.ChainRules]] +deps = ["Adapt", "ChainRulesCore", "Compat", "Distributed", "GPUArraysCore", "IrrationalConstants", "LinearAlgebra", "Random", "RealDot", "SparseArrays", "SparseInverseSubset", "Statistics", "StructArrays", "SuiteSparse"] +git-tree-sha1 = "006cc7170be3e0fa02ccac6d4164a1eee1fc8c27" +uuid = "082447d4-558c-5d27-93f4-14fc19e9eca2" +version = "1.58.0" + +[[deps.ChainRulesCore]] +deps = ["Compat", "LinearAlgebra"] +git-tree-sha1 = "e0af648f0692ec1691b5d094b8724ba1346281cf" +uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" +version = "1.18.0" +weakdeps = ["SparseArrays"] + + [deps.ChainRulesCore.extensions] + ChainRulesCoreSparseArraysExt = "SparseArrays" + +[[deps.CodecLz4]] +deps = ["Lz4_jll", "TranscodingStreams"] +git-tree-sha1 = "8bf4f9e2ee52b5e217451a7cd9171fcd4e16ae23" +uuid = "5ba52731-8f18-5e0d-9241-30f10d1ec561" +version = "0.4.1" + +[[deps.CodecZlib]] +deps = ["TranscodingStreams", "Zlib_jll"] +git-tree-sha1 = "cd67fc487743b2f0fd4380d4cbd3a24660d0eec8" +uuid = "944b1d66-785c-5afd-91f1-9de20f533193" +version = "0.7.3" + +[[deps.CodecZstd]] +deps = ["TranscodingStreams", "Zstd_jll"] +git-tree-sha1 = "f69e46bf7b307d15a896b57d5b3321c01cd64923" +uuid = "6b39b394-51ab-5f42-8807-6242bab2b4c2" +version = "0.8.1" + +[[deps.ColorTypes]] +deps = ["FixedPointNumbers", "Random"] +git-tree-sha1 = "eb7f0f8307f71fac7c606984ea5fb2817275d6e4" +uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" +version = "0.11.4" + +[[deps.Combinatorics]] +git-tree-sha1 = "08c8b6831dc00bfea825826be0bc8336fc369860" +uuid = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" +version = "1.0.2" + +[[deps.CommonSolve]] +git-tree-sha1 = "0eee5eb66b1cf62cd6ad1b460238e60e4b09400c" +uuid = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2" +version = "0.2.4" + +[[deps.CommonSubexpressions]] +deps = ["MacroTools", "Test"] +git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7" +uuid = "bbf7d656-a473-5ed7-a52c-81e309532950" +version = "0.3.0" + +[[deps.Comonicon]] +deps = ["Configurations", "ExproniconLite", "Libdl", "Logging", "Markdown", "OrderedCollections", "PackageCompiler", "Pkg", "Scratch", "TOML", "UUIDs"] +git-tree-sha1 = "552667002fdd5602ca72e0aeac8bd099daa0e040" +uuid = "863f3e99-da2a-4334-8734-de3dacbe5542" +version = "1.0.6" + +[[deps.Compat]] +deps = ["UUIDs"] +git-tree-sha1 = "886826d76ea9e72b35fcd000e535588f7b60f21d" +uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" +version = "4.10.1" +weakdeps = ["Dates", "LinearAlgebra"] + + [deps.Compat.extensions] + CompatLinearAlgebraExt = "LinearAlgebra" + +[[deps.CompilerSupportLibraries_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" +version = "1.0.2+0" + +[[deps.CompositionsBase]] +git-tree-sha1 = "802bb88cd69dfd1509f6670416bd4434015693ad" +uuid = "a33af91c-f02d-484b-be07-31d278c5ca2b" +version = "0.1.2" + + [deps.CompositionsBase.extensions] + CompositionsBaseInverseFunctionsExt = "InverseFunctions" + + [deps.CompositionsBase.weakdeps] + InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" + +[[deps.ComputationalResources]] +git-tree-sha1 = "52cb3ec90e8a8bea0e62e275ba577ad0f74821f7" +uuid = "ed09eef8-17a6-5b46-8889-db040fac31e3" +version = "0.3.2" + +[[deps.ConcurrentUtilities]] +deps = ["Serialization", "Sockets"] +git-tree-sha1 = "8cfa272e8bdedfa88b6aefbbca7c19f1befac519" +uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb" +version = "2.3.0" + +[[deps.Configurations]] +deps = ["ExproniconLite", "OrderedCollections", "TOML"] +git-tree-sha1 = "4358750bb58a3caefd5f37a4a0c5bfdbbf075252" +uuid = "5218b696-f38b-4ac9-8b61-a12ec717816d" +version = "0.17.6" + +[[deps.ConstructionBase]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "c53fc348ca4d40d7b371e71fd52251839080cbc9" +uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9" +version = "1.5.4" + + [deps.ConstructionBase.extensions] + ConstructionBaseIntervalSetsExt = "IntervalSets" + ConstructionBaseStaticArraysExt = "StaticArrays" + + [deps.ConstructionBase.weakdeps] + IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + +[[deps.ContextVariablesX]] +deps = ["Compat", "Logging", "UUIDs"] +git-tree-sha1 = "25cc3803f1030ab855e383129dcd3dc294e322cc" +uuid = "6add18c4-b38d-439d-96f6-d6bc489c04c5" +version = "0.1.3" + +[[deps.Crayons]] +git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15" +uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f" +version = "4.1.1" + +[[deps.DataAPI]] +git-tree-sha1 = "8da84edb865b0b5b0100c0666a9bc9a0b71c553c" +uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" +version = "1.15.0" + +[[deps.DataFrames]] +deps = ["Compat", "DataAPI", "DataStructures", "Future", "InlineStrings", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrecompileTools", "PrettyTables", "Printf", "REPL", "Random", "Reexport", "SentinelArrays", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"] +git-tree-sha1 = "04c738083f29f86e62c8afc341f0967d8717bdb8" +uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +version = "1.6.1" + +[[deps.DataStructures]] +deps = ["Compat", "InteractiveUtils", "OrderedCollections"] +git-tree-sha1 = "3dbd312d370723b6bb43ba9d02fc36abade4518d" +uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" +version = "0.18.15" + +[[deps.DataValueInterfaces]] +git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" +uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464" +version = "1.0.0" + +[[deps.Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" + +[[deps.DefineSingletons]] +git-tree-sha1 = "0fba8b706d0178b4dc7fd44a96a92382c9065c2c" +uuid = "244e2a9f-e319-4986-a169-4d1fe445cd52" +version = "0.1.2" + +[[deps.DelimitedFiles]] +deps = ["Mmap"] +git-tree-sha1 = "9e2f36d3c96a820c678f2f1f1782582fcf685bae" +uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab" +version = "1.9.1" + +[[deps.DiffResults]] +deps = ["StaticArraysCore"] +git-tree-sha1 = "782dd5f4561f5d267313f23853baaaa4c52ea621" +uuid = "163ba53b-c6d8-5494-b064-1a9d43ac40c5" +version = "1.1.0" + +[[deps.DiffRules]] +deps = ["IrrationalConstants", "LogExpFunctions", "NaNMath", "Random", "SpecialFunctions"] +git-tree-sha1 = "23163d55f885173722d1e4cf0f6110cdbaf7e272" +uuid = "b552c78f-8df3-52c6-915a-8e097449b14b" +version = "1.15.1" + +[[deps.Distances]] +deps = ["LinearAlgebra", "Statistics", "StatsAPI"] +git-tree-sha1 = "66c4c81f259586e8f002eacebc177e1fb06363b0" +uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7" +version = "0.10.11" +weakdeps = ["ChainRulesCore", "SparseArrays"] + + [deps.Distances.extensions] + DistancesChainRulesCoreExt = "ChainRulesCore" + DistancesSparseArraysExt = "SparseArrays" + +[[deps.Distributed]] +deps = ["Random", "Serialization", "Sockets"] +uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" + +[[deps.Distributions]] +deps = ["FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns"] +git-tree-sha1 = "9242eec9b7e2e14f9952e8ea1c7e31a50501d587" +uuid = "31c24e10-a181-5473-b8eb-7969acd0382f" +version = "0.25.104" + + [deps.Distributions.extensions] + DistributionsChainRulesCoreExt = "ChainRulesCore" + DistributionsDensityInterfaceExt = "DensityInterface" + DistributionsTestExt = "Test" + + [deps.Distributions.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + DensityInterface = "b429d917-457f-4dbc-8f4c-0cc954292b1d" + Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.DocStringExtensions]] +deps = ["LibGit2"] +git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d" +uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" +version = "0.9.3" + +[[deps.Downloads]] +deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +version = "1.6.0" + +[[deps.DualNumbers]] +deps = ["Calculus", "NaNMath", "SpecialFunctions"] +git-tree-sha1 = "5837a837389fccf076445fce071c8ddaea35a566" +uuid = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74" +version = "0.6.8" + +[[deps.EarCut_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "e3290f2d49e661fbd94046d7e3726ffcb2d41053" +uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5" +version = "2.2.4+0" + +[[deps.EarlyStopping]] +deps = ["Dates", "Statistics"] +git-tree-sha1 = "98fdf08b707aaf69f524a6cd0a67858cefe0cfb6" +uuid = "792122b4-ca99-40de-a6bc-6742525f08b6" +version = "0.3.0" + +[[deps.EnumX]] +git-tree-sha1 = "bdb1942cd4c45e3c678fd11569d5cccd80976237" +uuid = "4e289a0a-7415-4d19-859d-a7e5c4648b56" +version = "1.0.4" + +[[deps.EvoTrees]] +deps = ["BSON", "CategoricalArrays", "Distributions", "MLJModelInterface", "NetworkLayout", "Random", "RecipesBase", "Statistics", "StatsBase", "Tables"] +git-tree-sha1 = "f08d64339d7259b0c69a00a1e321dc6da79672ea" +uuid = "f6006082-12f8-11e9-0c9c-0d5d367ab1e5" +version = "0.16.5" + + [deps.EvoTrees.extensions] + EvoTreesCUDAExt = "CUDA" + + [deps.EvoTrees.weakdeps] + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + +[[deps.ExceptionUnwrapping]] +deps = ["Test"] +git-tree-sha1 = "e90caa41f5a86296e014e148ee061bd6c3edec96" +uuid = "460bff9d-24e4-43bc-9d9f-a8973cb893f4" +version = "0.1.9" + +[[deps.ExprTools]] +git-tree-sha1 = "27415f162e6028e81c72b82ef756bf321213b6ec" +uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04" +version = "0.1.10" + +[[deps.ExproniconLite]] +git-tree-sha1 = "fbc390c2f896031db5484bc152a7e805ecdfb01f" +uuid = "55351af7-c7e9-48d6-89ff-24e801d99491" +version = "0.10.5" + +[[deps.Extents]] +git-tree-sha1 = "2140cd04483da90b2da7f99b2add0750504fc39c" +uuid = "411431e0-e8b7-467b-b5e0-f676ba4f2910" +version = "0.1.2" + +[[deps.FLoops]] +deps = ["BangBang", "Compat", "FLoopsBase", "InitialValues", "JuliaVariables", "MLStyle", "Serialization", "Setfield", "Transducers"] +git-tree-sha1 = "ffb97765602e3cbe59a0589d237bf07f245a8576" +uuid = "cc61a311-1640-44b5-9fba-1b764f453329" +version = "0.2.1" + +[[deps.FLoopsBase]] +deps = ["ContextVariablesX"] +git-tree-sha1 = "656f7a6859be8673bf1f35da5670246b923964f7" +uuid = "b9860ae5-e623-471e-878b-f6a53c775ea6" +version = "0.1.1" + +[[deps.FileIO]] +deps = ["Pkg", "Requires", "UUIDs"] +git-tree-sha1 = "299dc33549f68299137e51e6d49a13b5b1da9673" +uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" +version = "1.16.1" + +[[deps.FilePathsBase]] +deps = ["Compat", "Dates", "Mmap", "Printf", "Test", "UUIDs"] +git-tree-sha1 = "9f00e42f8d99fdde64d40c8ea5d14269a2e2c1aa" +uuid = "48062228-2e41-5def-b9a4-89aafe57970f" +version = "0.9.21" + +[[deps.FileWatching]] +uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" + +[[deps.FillArrays]] +deps = ["LinearAlgebra", "Random"] +git-tree-sha1 = "5b93957f6dcd33fc343044af3d48c215be2562f1" +uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" +version = "1.9.3" +weakdeps = ["PDMats", "SparseArrays", "Statistics"] + + [deps.FillArrays.extensions] + FillArraysPDMatsExt = "PDMats" + FillArraysSparseArraysExt = "SparseArrays" + FillArraysStatisticsExt = "Statistics" + +[[deps.FiniteDiff]] +deps = ["ArrayInterface", "LinearAlgebra", "Requires", "Setfield", "SparseArrays"] +git-tree-sha1 = "c6e4a1fbe73b31a3dea94b1da449503b8830c306" +uuid = "6a86dc24-6348-571c-b903-95158fe2bd41" +version = "2.21.1" + + [deps.FiniteDiff.extensions] + FiniteDiffBandedMatricesExt = "BandedMatrices" + FiniteDiffBlockBandedMatricesExt = "BlockBandedMatrices" + FiniteDiffStaticArraysExt = "StaticArrays" + + [deps.FiniteDiff.weakdeps] + BandedMatrices = "aae01518-5342-5314-be14-df237901396f" + BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + +[[deps.FixedPointNumbers]] +deps = ["Statistics"] +git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc" +uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" +version = "0.8.4" + +[[deps.ForwardDiff]] +deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "LogExpFunctions", "NaNMath", "Preferences", "Printf", "Random", "SpecialFunctions"] +git-tree-sha1 = "cf0fe81336da9fb90944683b8c41984b08793dad" +uuid = "f6369f11-7733-5829-9624-2563aa707210" +version = "0.10.36" +weakdeps = ["StaticArrays"] + + [deps.ForwardDiff.extensions] + ForwardDiffStaticArraysExt = "StaticArrays" + +[[deps.Future]] +deps = ["Random"] +uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820" + +[[deps.GLM]] +deps = ["Distributions", "LinearAlgebra", "Printf", "Reexport", "SparseArrays", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns", "StatsModels"] +git-tree-sha1 = "273bd1cd30768a2fddfa3fd63bbc746ed7249e5f" +uuid = "38e38edf-8417-5370-95a0-9cbb8c7f171a" +version = "1.9.0" + +[[deps.GLMNet]] +deps = ["DataFrames", "Distributed", "Distributions", "Printf", "Random", "SparseArrays", "StatsBase", "glmnet_jll"] +git-tree-sha1 = "7ea4e2bbb84183fe52a488d05e16c152b2387b95" +uuid = "8d5ece8b-de18-5317-b113-243142960cc6" +version = "0.7.2" + +[[deps.GPUArrays]] +deps = ["Adapt", "GPUArraysCore", "LLVM", "LinearAlgebra", "Printf", "Random", "Reexport", "Serialization", "Statistics"] +git-tree-sha1 = "85d7fb51afb3def5dcb85ad31c3707795c8bccc1" +uuid = "0c68f7d7-f131-5f86-a1c3-88cf8149b2d7" +version = "9.1.0" + +[[deps.GPUArraysCore]] +deps = ["Adapt"] +git-tree-sha1 = "2d6ca471a6c7b536127afccfa7564b5b39227fe0" +uuid = "46192b85-c4d5-4398-a991-12ede77f4527" +version = "0.1.5" + +[[deps.GeoInterface]] +deps = ["Extents"] +git-tree-sha1 = "d53480c0793b13341c40199190f92c611aa2e93c" +uuid = "cf35fbd7-0cd7-5166-be24-54bfbe79505f" +version = "1.3.2" + +[[deps.GeometryBasics]] +deps = ["EarCut_jll", "Extents", "GeoInterface", "IterTools", "LinearAlgebra", "StaticArrays", "StructArrays", "Tables"] +git-tree-sha1 = "424a5a6ce7c5d97cca7bcc4eac551b97294c54af" +uuid = "5c1252a2-5f33-56bf-86c9-59e7332b4326" +version = "0.4.9" + +[[deps.Glob]] +git-tree-sha1 = "97285bbd5230dd766e9ef6749b80fc617126d496" +uuid = "c27321d9-0574-5035-807b-f59d2c89b15c" +version = "1.3.1" + +[[deps.Graphs]] +deps = ["ArnoldiMethod", "Compat", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"] +git-tree-sha1 = "899050ace26649433ef1af25bc17a815b3db52b7" +uuid = "86223c79-3864-5bf0-83f7-82e725a168b6" +version = "1.9.0" + +[[deps.HDF5]] +deps = ["Compat", "HDF5_jll", "Libdl", "MPIPreferences", "Mmap", "Preferences", "Printf", "Random", "Requires", "UUIDs"] +git-tree-sha1 = "26407bd1c60129062cec9da63dc7d08251544d53" +uuid = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" +version = "0.17.1" + + [deps.HDF5.extensions] + MPIExt = "MPI" + + [deps.HDF5.weakdeps] + MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" + +[[deps.HDF5_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "LLVMOpenMP_jll", "LazyArtifacts", "LibCURL_jll", "Libdl", "MPICH_jll", "MPIPreferences", "MPItrampoline_jll", "MicrosoftMPI_jll", "OpenMPI_jll", "OpenSSL_jll", "TOML", "Zlib_jll", "libaec_jll"] +git-tree-sha1 = "38c8874692d48d5440d5752d6c74b0c6b0b60739" +uuid = "0234f1f7-429e-5d53-9886-15a909be8d59" +version = "1.14.2+1" + +[[deps.HTTP]] +deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "ExceptionUnwrapping", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"] +git-tree-sha1 = "abbbb9ec3afd783a7cbd82ef01dcd088ea051398" +uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3" +version = "1.10.1" + +[[deps.Hwloc_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "ca0f6bf568b4bfc807e7537f081c81e35ceca114" +uuid = "e33a78d0-f292-5ffc-b300-72abe9b543c8" +version = "2.10.0+0" + +[[deps.HypergeometricFunctions]] +deps = ["DualNumbers", "LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"] +git-tree-sha1 = "f218fe3736ddf977e0e772bc9a586b2383da2685" +uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a" +version = "0.3.23" + +[[deps.HypothesisTests]] +deps = ["Combinatorics", "Distributions", "LinearAlgebra", "Printf", "Random", "Rmath", "Roots", "Statistics", "StatsAPI", "StatsBase"] +git-tree-sha1 = "4b5d5ba51f5f473737ed9de6d8a7aa190ad8c72f" +uuid = "09f84164-cd44-5f33-b23f-e6b0d136a0d5" +version = "0.11.0" + +[[deps.IRTools]] +deps = ["InteractiveUtils", "MacroTools", "Test"] +git-tree-sha1 = "8aa91235360659ca7560db43a7d57541120aa31d" +uuid = "7869d1d1-7146-5819-86e3-90919afe41df" +version = "0.4.11" + +[[deps.Inflate]] +git-tree-sha1 = "ea8031dea4aff6bd41f1df8f2fdfb25b33626381" +uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9" +version = "0.1.4" + +[[deps.InitialValues]] +git-tree-sha1 = "4da0f88e9a39111c2fa3add390ab15f3a44f3ca3" +uuid = "22cec73e-a1b8-11e9-2c92-598750a2cf9c" +version = "0.3.1" + +[[deps.InlineStrings]] +deps = ["Parsers"] +git-tree-sha1 = "9cc2baf75c6d09f9da536ddf58eb2f29dedaf461" +uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48" +version = "1.4.0" + +[[deps.IntelOpenMP_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "ad37c091f7d7daf900963171600d7c1c5c3ede32" +uuid = "1d5cc7b8-4909-519e-a0f8-d0f5ad9712d0" +version = "2023.2.0+0" + +[[deps.InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" + +[[deps.InvertedIndices]] +git-tree-sha1 = "0dc7b50b8d436461be01300fd8cd45aa0274b038" +uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f" +version = "1.3.0" + +[[deps.IrrationalConstants]] +git-tree-sha1 = "630b497eafcc20001bba38a4651b327dcfc491d2" +uuid = "92d709cd-6900-40b7-9082-c6be49f344b6" +version = "0.2.2" + +[[deps.IterTools]] +git-tree-sha1 = "4ced6667f9974fc5c5943fa5e2ef1ca43ea9e450" +uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e" +version = "1.8.0" + +[[deps.IterationControl]] +deps = ["EarlyStopping", "InteractiveUtils"] +git-tree-sha1 = "d7df9a6fdd82a8cfdfe93a94fcce35515be634da" +uuid = "b3c1a2ee-3fec-4384-bf48-272ea71de57c" +version = "0.5.3" + +[[deps.IterativeSolvers]] +deps = ["LinearAlgebra", "Printf", "Random", "RecipesBase", "SparseArrays"] +git-tree-sha1 = "b435d190ef8369cf4d79cc9dd5fba88ba0165307" +uuid = "42fd0dbc-a981-5370-80f2-aaf504508153" +version = "0.9.3" + +[[deps.IteratorInterfaceExtensions]] +git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" +uuid = "82899510-4779-5014-852e-03e436cf321d" +version = "1.0.0" + +[[deps.JLD2]] +deps = ["FileIO", "MacroTools", "Mmap", "OrderedCollections", "Pkg", "PrecompileTools", "Printf", "Reexport", "Requires", "TranscodingStreams", "UUIDs"] +git-tree-sha1 = "9bbb5130d3b4fa52846546bca4791ecbdfb52730" +uuid = "033835bb-8acc-5ee8-8aae-3f567f8a3819" +version = "0.4.38" + +[[deps.JLLWrappers]] +deps = ["Artifacts", "Preferences"] +git-tree-sha1 = "7e5d6779a1e09a36db2a7b6cff50942a0a7d0fca" +uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" +version = "1.5.0" + +[[deps.JSON]] +deps = ["Dates", "Mmap", "Parsers", "Unicode"] +git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a" +uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +version = "0.21.4" + +[[deps.JSON3]] +deps = ["Dates", "Mmap", "Parsers", "PrecompileTools", "StructTypes", "UUIDs"] +git-tree-sha1 = "95220473901735a0f4df9d1ca5b171b568b2daa3" +uuid = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" +version = "1.13.2" + +[[deps.JuliaVariables]] +deps = ["MLStyle", "NameResolution"] +git-tree-sha1 = "49fb3cb53362ddadb4415e9b73926d6b40709e70" +uuid = "b14d175d-62b4-44ba-8fb7-3064adc8c3ec" +version = "0.2.4" + +[[deps.KernelAbstractions]] +deps = ["Adapt", "Atomix", "InteractiveUtils", "LinearAlgebra", "MacroTools", "PrecompileTools", "Requires", "SparseArrays", "StaticArrays", "UUIDs", "UnsafeAtomics", "UnsafeAtomicsLLVM"] +git-tree-sha1 = "81de11f7b02465435aab0ed7e935965bfcb3072b" +uuid = "63c18a36-062a-441e-b654-da1e3ab1ce7c" +version = "0.9.14" + + [deps.KernelAbstractions.extensions] + EnzymeExt = "EnzymeCore" + + [deps.KernelAbstractions.weakdeps] + EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" + +[[deps.LLVM]] +deps = ["CEnum", "LLVMExtra_jll", "Libdl", "Preferences", "Printf", "Requires", "Unicode"] +git-tree-sha1 = "0678579657515e88b6632a3a482d39adcbb80445" +uuid = "929cbde3-209d-540e-8aea-75f648917ca0" +version = "6.4.1" + + [deps.LLVM.extensions] + BFloat16sExt = "BFloat16s" + + [deps.LLVM.weakdeps] + BFloat16s = "ab4f0b2a-ad5b-11e8-123f-65d77653426b" + +[[deps.LLVMExtra_jll]] +deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"] +git-tree-sha1 = "98eaee04d96d973e79c25d49167668c5c8fb50e2" +uuid = "dad2f222-ce93-54a1-a47d-0025e8a3acab" +version = "0.0.27+1" + +[[deps.LLVMOpenMP_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "f689897ccbe049adb19a065c495e75f372ecd42b" +uuid = "1d63c593-3942-5779-bab2-d838dc0a180e" +version = "15.0.4+0" + +[[deps.LaTeXStrings]] +git-tree-sha1 = "50901ebc375ed41dbf8058da26f9de442febbbec" +uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" +version = "1.3.1" + +[[deps.LatinHypercubeSampling]] +deps = ["Random", "StableRNGs", "StatsBase", "Test"] +git-tree-sha1 = "825289d43c753c7f1bf9bed334c253e9913997f8" +uuid = "a5e1c1ea-c99a-51d3-a14d-a9a37257b02d" +version = "1.9.0" + +[[deps.LazyArtifacts]] +deps = ["Artifacts", "Pkg"] +uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3" + +[[deps.LearnAPI]] +deps = ["InteractiveUtils", "Statistics"] +git-tree-sha1 = "ec695822c1faaaa64cee32d0b21505e1977b4809" +uuid = "92ad9a40-7767-427a-9ee6-6e577f1266cb" +version = "0.1.0" + +[[deps.LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" +version = "0.6.3" + +[[deps.LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" +version = "7.84.0+0" + +[[deps.LibGit2]] +deps = ["Base64", "NetworkOptions", "Printf", "SHA"] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" + +[[deps.LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" +version = "1.10.2+0" + +[[deps.Libdl]] +uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" + +[[deps.Libiconv_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "f9557a255370125b405568f9767d6d195822a175" +uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" +version = "1.17.0+0" + +[[deps.LineSearches]] +deps = ["LinearAlgebra", "NLSolversBase", "NaNMath", "Parameters", "Printf"] +git-tree-sha1 = "7bbea35cec17305fc70a0e5b4641477dc0789d9d" +uuid = "d3d80556-e9d4-5f37-9878-2ab0fcc64255" +version = "7.2.0" + +[[deps.LinearAlgebra]] +deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] +uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + +[[deps.LinearMaps]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "9df2ab050ffefe870a09c7b6afdb0cde381703f2" +uuid = "7a12625a-238d-50fd-b39a-03d52299707e" +version = "3.11.1" +weakdeps = ["ChainRulesCore", "SparseArrays", "Statistics"] + + [deps.LinearMaps.extensions] + LinearMapsChainRulesCoreExt = "ChainRulesCore" + LinearMapsSparseArraysExt = "SparseArrays" + LinearMapsStatisticsExt = "Statistics" + +[[deps.LogExpFunctions]] +deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"] +git-tree-sha1 = "7d6dd4e9212aebaeed356de34ccf262a3cd415aa" +uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" +version = "0.3.26" + + [deps.LogExpFunctions.extensions] + LogExpFunctionsChainRulesCoreExt = "ChainRulesCore" + LogExpFunctionsChangesOfVariablesExt = "ChangesOfVariables" + LogExpFunctionsInverseFunctionsExt = "InverseFunctions" + + [deps.LogExpFunctions.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + ChangesOfVariables = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0" + InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" + +[[deps.Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" + +[[deps.LoggingExtras]] +deps = ["Dates", "Logging"] +git-tree-sha1 = "c1dd6d7978c12545b4179fb6153b9250c96b0075" +uuid = "e6f89c97-d47a-5376-807f-9c37f3926c36" +version = "1.0.3" + +[[deps.Lz4_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "6c26c5e8a4203d43b5497be3ec5d4e0c3cde240a" +uuid = "5ced341a-0733-55b8-9ab6-a4889d929147" +version = "1.9.4+0" + +[[deps.MKL]] +deps = ["Artifacts", "Libdl", "LinearAlgebra", "MKL_jll"] +git-tree-sha1 = "100521a1d2181cb39036ee1a6955d6b9686bb363" +uuid = "33e6dc65-8f57-5167-99aa-e5a354878fb2" +version = "0.6.1" + +[[deps.MKL_jll]] +deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "Pkg"] +git-tree-sha1 = "eb006abbd7041c28e0d16260e50a24f8f9104913" +uuid = "856f044c-d86e-5d09-b602-aeab76dc8ba7" +version = "2023.2.0+0" + +[[deps.MLFlowClient]] +deps = ["Dates", "FilePathsBase", "HTTP", "JSON", "ShowCases", "URIs", "UUIDs"] +git-tree-sha1 = "32cee10a6527476bef0c6484ff4c60c2cead5d3e" +uuid = "64a0f543-368b-4a9a-827a-e71edb2a0b83" +version = "0.4.4" + +[[deps.MLJ]] +deps = ["CategoricalArrays", "ComputationalResources", "Distributed", "Distributions", "LinearAlgebra", "MLJBalancing", "MLJBase", "MLJEnsembles", "MLJFlow", "MLJIteration", "MLJModels", "MLJTuning", "OpenML", "Pkg", "ProgressMeter", "Random", "Reexport", "ScientificTypes", "StatisticalMeasures", "Statistics", "StatsBase", "Tables"] +git-tree-sha1 = "981196c41a23cbc1befbad190558b1f0ebb97910" +uuid = "add582a8-e3ab-11e8-2d5e-e98b27df1bc7" +version = "0.20.2" + +[[deps.MLJBalancing]] +deps = ["MLJBase", "MLJModelInterface", "MLUtils", "OrderedCollections", "Random", "StatsBase"] +git-tree-sha1 = "e4be85602f010291f49b6a6464ccde1708ce5d62" +uuid = "45f359ea-796d-4f51-95a5-deb1a414c586" +version = "0.1.3" + +[[deps.MLJBase]] +deps = ["CategoricalArrays", "CategoricalDistributions", "ComputationalResources", "Dates", "DelimitedFiles", "Distributed", "Distributions", "InteractiveUtils", "InvertedIndices", "LearnAPI", "LinearAlgebra", "MLJModelInterface", "Missings", "OrderedCollections", "Parameters", "PrettyTables", "ProgressMeter", "Random", "Reexport", "ScientificTypes", "Serialization", "StatisticalMeasuresBase", "StatisticalTraits", "Statistics", "StatsBase", "Tables"] +git-tree-sha1 = "6d433d34a1764324cf37a1ddc47dcc42ec05340f" +uuid = "a7f614a8-145f-11e9-1d2a-a57a1082229d" +version = "1.0.1" +weakdeps = ["StatisticalMeasures"] + + [deps.MLJBase.extensions] + DefaultMeasuresExt = "StatisticalMeasures" + +[[deps.MLJEnsembles]] +deps = ["CategoricalArrays", "CategoricalDistributions", "ComputationalResources", "Distributed", "Distributions", "MLJModelInterface", "ProgressMeter", "Random", "ScientificTypesBase", "StatisticalMeasuresBase", "StatsBase"] +git-tree-sha1 = "94403b2c8f692011df6731913376e0e37f6c0fe9" +uuid = "50ed68f4-41fd-4504-931a-ed422449fee0" +version = "0.4.0" + +[[deps.MLJFlow]] +deps = ["MLFlowClient", "MLJBase", "MLJModelInterface"] +git-tree-sha1 = "89d0e7a7e08359476482f20b2d8ff12080d171ee" +uuid = "7b7b8358-b45c-48ea-a8ef-7ca328ad328f" +version = "0.3.0" + +[[deps.MLJGLMInterface]] +deps = ["Distributions", "GLM", "MLJModelInterface", "StatsModels", "Tables"] +git-tree-sha1 = "06aba1c96b19f31744f7e97d96fcf66b79739e05" +uuid = "caf8df21-4939-456d-ac9c-5fefbfb04c0c" +version = "0.3.5" + +[[deps.MLJIteration]] +deps = ["IterationControl", "MLJBase", "Random", "Serialization"] +git-tree-sha1 = "991e10d4c8da49d534e312e8a4fbe56b7ac6f70c" +uuid = "614be32b-d00c-4edb-bd02-1eb411ab5e55" +version = "0.6.0" + +[[deps.MLJLinearModels]] +deps = ["DocStringExtensions", "IterativeSolvers", "LinearAlgebra", "LinearMaps", "MLJModelInterface", "Optim", "Parameters"] +git-tree-sha1 = "7f517fd840ca433a8fae673edb31678ff55d969c" +uuid = "6ee0df7b-362f-4a72-a706-9e79364fb692" +version = "0.10.0" + +[[deps.MLJModelInterface]] +deps = ["Random", "ScientificTypesBase", "StatisticalTraits"] +git-tree-sha1 = "381d99f0af76d98f50bd5512dcf96a99c13f8223" +uuid = "e80e1ace-859a-464e-9ed9-23947d8ae3ea" +version = "1.9.3" + +[[deps.MLJModels]] +deps = ["CategoricalArrays", "CategoricalDistributions", "Combinatorics", "Dates", "Distances", "Distributions", "InteractiveUtils", "LinearAlgebra", "MLJModelInterface", "Markdown", "OrderedCollections", "Parameters", "Pkg", "PrettyPrinting", "REPL", "Random", "RelocatableFolders", "ScientificTypes", "StatisticalTraits", "Statistics", "StatsBase", "Tables"] +git-tree-sha1 = "10d221910fc3f3eedad567178ddbca3cc0f776a3" +uuid = "d491faf4-2d78-11e9-2867-c94bc002c0b7" +version = "0.16.12" + +[[deps.MLJTuning]] +deps = ["ComputationalResources", "Distributed", "Distributions", "LatinHypercubeSampling", "MLJBase", "ProgressMeter", "Random", "RecipesBase", "StatisticalMeasuresBase"] +git-tree-sha1 = "44dc126646a15018d7829f020d121b85b4def9bc" +uuid = "03970b2e-30c4-11ea-3135-d1576263f10f" +version = "0.8.0" + +[[deps.MLJXGBoostInterface]] +deps = ["MLJModelInterface", "SparseArrays", "Tables", "XGBoost"] +git-tree-sha1 = "988c399a352f0b49bc1345c509d8a4800cb468c5" +uuid = "54119dfa-1dab-4055-a167-80440f4f7a91" +version = "0.3.10" + +[[deps.MLStyle]] +git-tree-sha1 = "bc38dff0548128765760c79eb7388a4b37fae2c8" +uuid = "d8e11817-5142-5d16-987a-aa16d5891078" +version = "0.4.17" + +[[deps.MLUtils]] +deps = ["ChainRulesCore", "Compat", "DataAPI", "DelimitedFiles", "FLoops", "NNlib", "Random", "ShowCases", "SimpleTraits", "Statistics", "StatsBase", "Tables", "Transducers"] +git-tree-sha1 = "3504cdb8c2bc05bde4d4b09a81b01df88fcbbba0" +uuid = "f1d291b0-491e-4a28-83b9-f70985020b54" +version = "0.4.3" + +[[deps.MPICH_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML"] +git-tree-sha1 = "2ee75365ca243c1a39d467e35ffd3d4d32eef11e" +uuid = "7cb0a576-ebde-5e09-9194-50597f1243b4" +version = "4.1.2+1" + +[[deps.MPIPreferences]] +deps = ["Libdl", "Preferences"] +git-tree-sha1 = "8f6af051b9e8ec597fa09d8885ed79fd582f33c9" +uuid = "3da0fdf6-3ccc-4f1b-acd9-58baa6c99267" +version = "0.1.10" + +[[deps.MPItrampoline_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML"] +git-tree-sha1 = "6979eccb6a9edbbb62681e158443e79ecc0d056a" +uuid = "f1f71cc9-e9ae-5b93-9b94-4fe0e1ad3748" +version = "5.3.1+0" + +[[deps.MacroTools]] +deps = ["Markdown", "Random"] +git-tree-sha1 = "9ee1618cbf5240e6d4e0371d6f24065083f60c48" +uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" +version = "0.5.11" + +[[deps.Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" + +[[deps.MbedTLS]] +deps = ["Dates", "MbedTLS_jll", "MozillaCACerts_jll", "NetworkOptions", "Random", "Sockets"] +git-tree-sha1 = "c067a280ddc25f196b5e7df3877c6b226d390aaf" +uuid = "739be429-bea8-5141-9913-cc70e7f3736d" +version = "1.1.9" + +[[deps.MbedTLS_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" +version = "2.28.2+0" + +[[deps.MetaGraphsNext]] +deps = ["Graphs", "JLD2", "SimpleTraits"] +git-tree-sha1 = "a385fe5aa1384647e55c0c8773457b71e9b08518" +uuid = "fa8bd995-216d-47f1-8a91-f3b68fbeb377" +version = "0.7.0" + +[[deps.MicroCollections]] +deps = ["BangBang", "InitialValues", "Setfield"] +git-tree-sha1 = "629afd7d10dbc6935ec59b32daeb33bc4460a42e" +uuid = "128add7d-3638-4c79-886c-908ea0c25c34" +version = "0.1.4" + +[[deps.MicrosoftMPI_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "b01beb91d20b0d1312a9471a36017b5b339d26de" +uuid = "9237b28f-5490-5468-be7b-bb81f5f5e6cf" +version = "10.1.4+1" + +[[deps.Missings]] +deps = ["DataAPI"] +git-tree-sha1 = "f66bdc5de519e8f8ae43bdc598782d35a25b1272" +uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28" +version = "1.1.0" + +[[deps.Mmap]] +uuid = "a63ad114-7e13-5084-954f-fe012c677804" + +[[deps.Mocking]] +deps = ["Compat", "ExprTools"] +git-tree-sha1 = "4cc0c5a83933648b615c36c2b956d94fda70641e" +uuid = "78c3b35d-d492-501b-9361-3d52fe80e533" +version = "0.7.7" + +[[deps.MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" +version = "2022.10.11" + +[[deps.MultipleTesting]] +deps = ["Distributions", "SpecialFunctions", "StatsBase"] +git-tree-sha1 = "1e98f8f732e7035c4333135b75605b74f3462b9b" +uuid = "f8716d33-7c4a-5097-896f-ce0ecbd3ef6b" +version = "0.6.0" + +[[deps.NLSolversBase]] +deps = ["DiffResults", "Distributed", "FiniteDiff", "ForwardDiff"] +git-tree-sha1 = "a0b464d183da839699f4c79e7606d9d186ec172c" +uuid = "d41bc354-129a-5804-8e4c-c37616107c6c" +version = "7.8.3" + +[[deps.NNlib]] +deps = ["Adapt", "Atomix", "ChainRulesCore", "GPUArraysCore", "KernelAbstractions", "LinearAlgebra", "Pkg", "Random", "Requires", "Statistics"] +git-tree-sha1 = "ac86d2944bf7a670ac8bf0f7ec099b5898abcc09" +uuid = "872c559c-99b0-510c-b3b7-b6c96a88d5cd" +version = "0.9.8" + + [deps.NNlib.extensions] + NNlibAMDGPUExt = "AMDGPU" + NNlibCUDACUDNNExt = ["CUDA", "cuDNN"] + NNlibCUDAExt = "CUDA" + NNlibEnzymeCoreExt = "EnzymeCore" + + [deps.NNlib.weakdeps] + AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" + cuDNN = "02a925ec-e4fe-4b08-9a7e-0d78e3d38ccd" + +[[deps.NaNMath]] +deps = ["OpenLibm_jll"] +git-tree-sha1 = "0877504529a3e5c3343c6f8b4c0381e57e4387e4" +uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" +version = "1.0.2" + +[[deps.NameResolution]] +deps = ["PrettyPrint"] +git-tree-sha1 = "1a0fa0e9613f46c9b8c11eee38ebb4f590013c5e" +uuid = "71a1bf82-56d0-4bbc-8a3c-48b961074391" +version = "0.1.5" + +[[deps.NetworkLayout]] +deps = ["GeometryBasics", "LinearAlgebra", "Random", "Requires", "StaticArrays"] +git-tree-sha1 = "91bb2fedff8e43793650e7a677ccda6e6e6e166b" +uuid = "46757867-2c16-5918-afeb-47bfcb05e46a" +version = "0.4.6" +weakdeps = ["Graphs"] + + [deps.NetworkLayout.extensions] + NetworkLayoutGraphsExt = "Graphs" + +[[deps.NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" +version = "1.2.0" + +[[deps.OpenBLAS_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] +uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" +version = "0.3.21+4" + +[[deps.OpenLibm_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "05823500-19ac-5b8b-9628-191a04bc5112" +version = "0.8.1+0" + +[[deps.OpenML]] +deps = ["ARFFFiles", "HTTP", "JSON", "Markdown", "Pkg", "Scratch"] +git-tree-sha1 = "6efb039ae888699d5a74fb593f6f3e10c7193e33" +uuid = "8b6db2d4-7670-4922-a472-f9537c81ab66" +version = "0.3.1" + +[[deps.OpenMPI_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Hwloc_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "PMIx_jll", "TOML", "Zlib_jll", "libevent_jll", "prrte_jll"] +git-tree-sha1 = "694458ae803b684f09c07f90459cb79655fb377d" +uuid = "fe0851c0-eecd-5654-98d4-656369965a5c" +version = "5.0.0+0" + +[[deps.OpenSSL]] +deps = ["BitFlags", "Dates", "MozillaCACerts_jll", "OpenSSL_jll", "Sockets"] +git-tree-sha1 = "51901a49222b09e3743c65b8847687ae5fc78eb2" +uuid = "4d8831e6-92b7-49fb-bdf8-b643e874388c" +version = "1.4.1" + +[[deps.OpenSSL_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "cc6e1927ac521b659af340e0ca45828a3ffc748f" +uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" +version = "3.0.12+0" + +[[deps.OpenSpecFun_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1" +uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" +version = "0.5.5+0" + +[[deps.Optim]] +deps = ["Compat", "FillArrays", "ForwardDiff", "LineSearches", "LinearAlgebra", "NLSolversBase", "NaNMath", "Parameters", "PositiveFactorizations", "Printf", "SparseArrays", "StatsBase"] +git-tree-sha1 = "01f85d9269b13fedc61e63cc72ee2213565f7a72" +uuid = "429524aa-4258-5aef-a3af-852621145aeb" +version = "1.7.8" + +[[deps.OrderedCollections]] +git-tree-sha1 = "dfdf5519f235516220579f949664f1bf44e741c5" +uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" +version = "1.6.3" + +[[deps.PDMats]] +deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"] +git-tree-sha1 = "949347156c25054de2db3b166c52ac4728cbad65" +uuid = "90014a1f-27ba-587c-ab20-58faa44d9150" +version = "0.11.31" + +[[deps.PMIx_jll]] +deps = ["Artifacts", "Hwloc_jll", "JLLWrappers", "Libdl", "Zlib_jll", "libevent_jll"] +git-tree-sha1 = "8b3b19351fa24791f94d7ae85faf845ca1362541" +uuid = "32165bc3-0280-59bc-8c0b-c33b6203efab" +version = "4.2.7+0" + +[[deps.PackageCompiler]] +deps = ["Artifacts", "Glob", "LazyArtifacts", "Libdl", "Pkg", "Printf", "RelocatableFolders", "TOML", "UUIDs", "p7zip_jll"] +git-tree-sha1 = "f9392ab72832f4315220a853747ff3dba758c9d1" +uuid = "9b87118b-4619-50d2-8e1e-99f35a4d4d9d" +version = "2.1.15" + +[[deps.Parameters]] +deps = ["OrderedCollections", "UnPack"] +git-tree-sha1 = "34c0e9ad262e5f7fc75b10a9952ca7692cfc5fbe" +uuid = "d96e819e-fc66-5662-9728-84c9c7592b0a" +version = "0.12.3" + +[[deps.Parsers]] +deps = ["Dates", "PrecompileTools", "UUIDs"] +git-tree-sha1 = "a935806434c9d4c506ba941871b327b96d41f2bf" +uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" +version = "2.8.0" + +[[deps.Pkg]] +deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] +uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +version = "1.9.0" + +[[deps.PooledArrays]] +deps = ["DataAPI", "Future"] +git-tree-sha1 = "36d8b4b899628fb92c2749eb488d884a926614d3" +uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720" +version = "1.4.3" + +[[deps.PositiveFactorizations]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "17275485f373e6673f7e7f97051f703ed5b15b20" +uuid = "85a6dd25-e78a-55b7-8502-1745935b8125" +version = "0.2.4" + +[[deps.PrecompileTools]] +deps = ["Preferences"] +git-tree-sha1 = "03b4c25b43cb84cee5c90aa9b5ea0a78fd848d2f" +uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +version = "1.2.0" + +[[deps.Preferences]] +deps = ["TOML"] +git-tree-sha1 = "00805cd429dcb4870060ff49ef443486c262e38e" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.4.1" + +[[deps.PrettyPrint]] +git-tree-sha1 = "632eb4abab3449ab30c5e1afaa874f0b98b586e4" +uuid = "8162dcfd-2161-5ef2-ae6c-7681170c5f98" +version = "0.2.0" + +[[deps.PrettyPrinting]] +git-tree-sha1 = "22a601b04a154ca38867b991d5017469dc75f2db" +uuid = "54e16d92-306c-5ea0-a30b-337be88ac337" +version = "0.4.1" + +[[deps.PrettyTables]] +deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "Reexport", "StringManipulation", "Tables"] +git-tree-sha1 = "88b895d13d53b5577fd53379d913b9ab9ac82660" +uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d" +version = "2.3.1" + +[[deps.Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" + +[[deps.ProgressMeter]] +deps = ["Distributed", "Printf"] +git-tree-sha1 = "00099623ffee15972c16111bcf84c58a0051257c" +uuid = "92933f4c-e287-5a05-a399-4b506db050ca" +version = "1.9.0" + +[[deps.QuadGK]] +deps = ["DataStructures", "LinearAlgebra"] +git-tree-sha1 = "9ebcd48c498668c7fa0e97a9cae873fbee7bfee1" +uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc" +version = "2.9.1" + +[[deps.REPL]] +deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] +uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" + +[[deps.Random]] +deps = ["SHA", "Serialization"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" + +[[deps.RealDot]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "9f0a1b71baaf7650f4fa8a1d168c7fb6ee41f0c9" +uuid = "c1ae055f-0cd5-4b69-90a6-9a35b1a98df9" +version = "0.1.0" + +[[deps.RecipesBase]] +deps = ["PrecompileTools"] +git-tree-sha1 = "5c3d09cc4f31f5fc6af001c250bf1278733100ff" +uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" +version = "1.3.4" + +[[deps.Reexport]] +git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" +uuid = "189a3867-3050-52da-a836-e630ba90ab69" +version = "1.2.2" + +[[deps.RelocatableFolders]] +deps = ["SHA", "Scratch"] +git-tree-sha1 = "ffdaf70d81cf6ff22c2b6e733c900c3321cab864" +uuid = "05181044-ff0b-4ac5-8273-598c1e38db00" +version = "1.0.1" + +[[deps.Requires]] +deps = ["UUIDs"] +git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7" +uuid = "ae029012-a4dd-5104-9daa-d747884805df" +version = "1.3.0" + +[[deps.Rmath]] +deps = ["Random", "Rmath_jll"] +git-tree-sha1 = "f65dcb5fa46aee0cf9ed6274ccbd597adc49aa7b" +uuid = "79098fc4-a85e-5d69-aa6a-4863f24498fa" +version = "0.7.1" + +[[deps.Rmath_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "6ed52fdd3382cf21947b15e8870ac0ddbff736da" +uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f" +version = "0.4.0+0" + +[[deps.Roots]] +deps = ["ChainRulesCore", "CommonSolve", "Printf", "Setfield"] +git-tree-sha1 = "0f1d92463a020321983d04c110f476c274bafe2e" +uuid = "f2b01f46-fcfa-551c-844a-d8ac1e96c665" +version = "2.0.22" + + [deps.Roots.extensions] + RootsForwardDiffExt = "ForwardDiff" + RootsIntervalRootFindingExt = "IntervalRootFinding" + RootsSymPyExt = "SymPy" + RootsSymPyPythonCallExt = "SymPyPythonCall" + + [deps.Roots.weakdeps] + ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" + IntervalRootFinding = "d2bf35a9-74e0-55ec-b149-d360ff49b807" + SymPy = "24249f21-da20-56a4-8eb1-6a02cf4ae2e6" + SymPyPythonCall = "bc8888f7-b21e-4b7c-a06a-5d9c9496438c" + +[[deps.SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" +version = "0.7.0" + +[[deps.ScientificTypes]] +deps = ["CategoricalArrays", "ColorTypes", "Dates", "Distributions", "PrettyTables", "Reexport", "ScientificTypesBase", "StatisticalTraits", "Tables"] +git-tree-sha1 = "75ccd10ca65b939dab03b812994e571bf1e3e1da" +uuid = "321657f4-b219-11e9-178b-2701a2544e81" +version = "3.0.2" + +[[deps.ScientificTypesBase]] +git-tree-sha1 = "a8e18eb383b5ecf1b5e6fc237eb39255044fd92b" +uuid = "30f210dd-8aff-4c5f-94ba-8e64358c1161" +version = "3.0.0" + +[[deps.Scratch]] +deps = ["Dates"] +git-tree-sha1 = "3bac05bc7e74a75fd9cba4295cde4045d9fe2386" +uuid = "6c6a2e73-6563-6170-7368-637461726353" +version = "1.2.1" + +[[deps.SentinelArrays]] +deps = ["Dates", "Random"] +git-tree-sha1 = "0e7508ff27ba32f26cd459474ca2ede1bc10991f" +uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c" +version = "1.4.1" + +[[deps.Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" + +[[deps.Setfield]] +deps = ["ConstructionBase", "Future", "MacroTools", "StaticArraysCore"] +git-tree-sha1 = "e2cc6d8c88613c05e1defb55170bf5ff211fbeac" +uuid = "efcf1570-3423-57d1-acb7-fd33fddbac46" +version = "1.1.1" + +[[deps.SharedArrays]] +deps = ["Distributed", "Mmap", "Random", "Serialization"] +uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" + +[[deps.ShiftedArrays]] +git-tree-sha1 = "503688b59397b3307443af35cd953a13e8005c16" +uuid = "1277b4bf-5013-50f5-be3d-901d8477a67a" +version = "2.0.0" + +[[deps.ShowCases]] +git-tree-sha1 = "7f534ad62ab2bd48591bdeac81994ea8c445e4a5" +uuid = "605ecd9f-84a6-4c9e-81e2-4798472b76a3" +version = "0.1.0" + +[[deps.SimpleBufferStream]] +git-tree-sha1 = "874e8867b33a00e784c8a7e4b60afe9e037b74e1" +uuid = "777ac1f9-54b0-4bf8-805c-2214025038e7" +version = "1.1.0" + +[[deps.SimpleTraits]] +deps = ["InteractiveUtils", "MacroTools"] +git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231" +uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" +version = "0.9.4" + +[[deps.Sockets]] +uuid = "6462fe0b-24de-5631-8697-dd941f90decc" + +[[deps.SortingAlgorithms]] +deps = ["DataStructures"] +git-tree-sha1 = "5165dfb9fd131cf0c6957a3a7605dede376e7b63" +uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c" +version = "1.2.0" + +[[deps.SparseArrays]] +deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"] +uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + +[[deps.SparseInverseSubset]] +deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"] +git-tree-sha1 = "91402087fd5d13b2d97e3ef29bbdf9d7859e678a" +uuid = "dc90abb0-5640-4711-901d-7e5b23a2fada" +version = "0.1.1" + +[[deps.SparseMatricesCSR]] +deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"] +git-tree-sha1 = "38677ca58e80b5cad2382e5a1848f93b054ad28d" +uuid = "a0a7dd2c-ebf4-11e9-1f05-cf50bc540ca1" +version = "0.6.7" + +[[deps.SpecialFunctions]] +deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] +git-tree-sha1 = "e2cfc4012a19088254b3950b85c3c1d8882d864d" +uuid = "276daf66-3868-5448-9aa4-cd146d93841b" +version = "2.3.1" +weakdeps = ["ChainRulesCore"] + + [deps.SpecialFunctions.extensions] + SpecialFunctionsChainRulesCoreExt = "ChainRulesCore" + +[[deps.SplittablesBase]] +deps = ["Setfield", "Test"] +git-tree-sha1 = "e08a62abc517eb79667d0a29dc08a3b589516bb5" +uuid = "171d559e-b47b-412a-8079-5efa626c420e" +version = "0.1.15" + +[[deps.StableRNGs]] +deps = ["Random", "Test"] +git-tree-sha1 = "ddc1a7b85e760b5285b50b882fa91e40c603be47" +uuid = "860ef19b-820b-49d6-a774-d7a799459cd3" +version = "1.0.1" + +[[deps.StaticArrays]] +deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"] +git-tree-sha1 = "5ef59aea6f18c25168842bded46b16662141ab87" +uuid = "90137ffa-7385-5640-81b9-e52037218182" +version = "1.7.0" +weakdeps = ["Statistics"] + + [deps.StaticArrays.extensions] + StaticArraysStatisticsExt = "Statistics" + +[[deps.StaticArraysCore]] +git-tree-sha1 = "36b3d696ce6366023a0ea192b4cd442268995a0d" +uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" +version = "1.4.2" + +[[deps.StatisticalMeasures]] +deps = ["CategoricalArrays", "CategoricalDistributions", "Distributions", "LearnAPI", "LinearAlgebra", "MacroTools", "OrderedCollections", "PrecompileTools", "ScientificTypesBase", "StatisticalMeasuresBase", "Statistics", "StatsBase"] +git-tree-sha1 = "b58c7cc3d7de6c0d75d8437b81481af924970123" +uuid = "a19d573c-0a75-4610-95b3-7071388c7541" +version = "0.1.3" + + [deps.StatisticalMeasures.extensions] + LossFunctionsExt = "LossFunctions" + ScientificTypesExt = "ScientificTypes" + + [deps.StatisticalMeasures.weakdeps] + LossFunctions = "30fc2ffe-d236-52d8-8643-a9d8f7c094a7" + ScientificTypes = "321657f4-b219-11e9-178b-2701a2544e81" + +[[deps.StatisticalMeasuresBase]] +deps = ["CategoricalArrays", "InteractiveUtils", "MLUtils", "MacroTools", "OrderedCollections", "PrecompileTools", "ScientificTypesBase", "Statistics"] +git-tree-sha1 = "17dfb22e2e4ccc9cd59b487dce52883e0151b4d3" +uuid = "c062fc1d-0d66-479b-b6ac-8b44719de4cc" +version = "0.1.1" + +[[deps.StatisticalTraits]] +deps = ["ScientificTypesBase"] +git-tree-sha1 = "30b9236691858e13f167ce829490a68e1a597782" +uuid = "64bff920-2084-43da-a3e6-9bb72801c0c9" +version = "3.2.0" + +[[deps.Statistics]] +deps = ["LinearAlgebra", "SparseArrays"] +uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +version = "1.9.0" + +[[deps.StatsAPI]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "1ff449ad350c9c4cbc756624d6f8a8c3ef56d3ed" +uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0" +version = "1.7.0" + +[[deps.StatsBase]] +deps = ["DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"] +git-tree-sha1 = "1d77abd07f617c4868c33d4f5b9e1dbb2643c9cf" +uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" +version = "0.34.2" + +[[deps.StatsFuns]] +deps = ["HypergeometricFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"] +git-tree-sha1 = "f625d686d5a88bcd2b15cd81f18f98186fdc0c9a" +uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c" +version = "1.3.0" + + [deps.StatsFuns.extensions] + StatsFunsChainRulesCoreExt = "ChainRulesCore" + StatsFunsInverseFunctionsExt = "InverseFunctions" + + [deps.StatsFuns.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" + +[[deps.StatsModels]] +deps = ["DataAPI", "DataStructures", "LinearAlgebra", "Printf", "REPL", "ShiftedArrays", "SparseArrays", "StatsAPI", "StatsBase", "StatsFuns", "Tables"] +git-tree-sha1 = "5cf6c4583533ee38639f73b880f35fc85f2941e0" +uuid = "3eaba693-59b7-5ba5-a881-562e759f1c8d" +version = "0.7.3" + +[[deps.StringEncodings]] +deps = ["Libiconv_jll"] +git-tree-sha1 = "b765e46ba27ecf6b44faf70df40c57aa3a547dcb" +uuid = "69024149-9ee7-55f6-a4c4-859efe599b68" +version = "0.3.7" + +[[deps.StringManipulation]] +deps = ["PrecompileTools"] +git-tree-sha1 = "a04cabe79c5f01f4d723cc6704070ada0b9d46d5" +uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e" +version = "0.3.4" + +[[deps.StructArrays]] +deps = ["Adapt", "ConstructionBase", "DataAPI", "GPUArraysCore", "StaticArraysCore", "Tables"] +git-tree-sha1 = "0a3db38e4cce3c54fe7a71f831cd7b6194a54213" +uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" +version = "0.6.16" + +[[deps.StructTypes]] +deps = ["Dates", "UUIDs"] +git-tree-sha1 = "ca4bccb03acf9faaf4137a9abc1881ed1841aa70" +uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4" +version = "1.10.0" + +[[deps.SuiteSparse]] +deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"] +uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" + +[[deps.SuiteSparse_jll]] +deps = ["Artifacts", "Libdl", "Pkg", "libblastrampoline_jll"] +uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" +version = "5.10.1+6" + +[[deps.TMLE]] +deps = ["AbstractDifferentiation", "CategoricalArrays", "Combinatorics", "Distributions", "GLM", "Graphs", "HypothesisTests", "LogExpFunctions", "MLJBase", "MLJGLMInterface", "MLJModels", "MetaGraphsNext", "Missings", "PrecompileTools", "PrettyTables", "Random", "Statistics", "TableOperations", "Tables", "Zygote"] +git-tree-sha1 = "e66fe5f9cfdfb69f8fb8f870a89b5ce151789ae9" +uuid = "8afdd2fb-6e73-43df-8b62-b1650cd9c8cf" +version = "0.12.1" +weakdeps = ["JSON", "YAML"] + + [deps.TMLE.extensions] + JSONExt = "JSON" + YAMLExt = "YAML" + +[[deps.TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +version = "1.0.3" + +[[deps.TZJData]] +deps = ["Artifacts"] +git-tree-sha1 = "d39314cdbaf5b90a047db33858626f8d1cc973e1" +uuid = "dc5dba14-91b3-4cab-a142-028a31da12f7" +version = "1.0.0+2023c" + +[[deps.TableOperations]] +deps = ["SentinelArrays", "Tables", "Test"] +git-tree-sha1 = "e383c87cf2a1dc41fa30c093b2a19877c83e1bc1" +uuid = "ab02a1b2-a7df-11e8-156e-fb1833f50b87" +version = "1.2.0" + +[[deps.TableTraits]] +deps = ["IteratorInterfaceExtensions"] +git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39" +uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" +version = "1.0.1" + +[[deps.Tables]] +deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "OrderedCollections", "TableTraits"] +git-tree-sha1 = "cb76cf677714c095e535e3501ac7954732aeea2d" +uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +version = "1.11.1" + +[[deps.Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" +version = "1.10.0" + +[[deps.TargetedEstimation]] +deps = ["Arrow", "CSV", "CategoricalArrays", "Combinatorics", "Comonicon", "Configurations", "DataFrames", "EvoTrees", "GLMNet", "HDF5", "JLD2", "JSON", "MKL", "MLJ", "MLJBase", "MLJLinearModels", "MLJModelInterface", "MLJModels", "MLJXGBoostInterface", "Mmap", "MultipleTesting", "Optim", "Random", "Serialization", "TMLE", "Tables", "YAML"] +git-tree-sha1 = "41196d46d57e39591e6d6c354ae446c3d336e62b" +repo-rev = "cv_tmle" +repo-url = "https://github.com/TARGENE/TargetedEstimation.jl.git" +uuid = "2573d147-4098-46ba-9db2-8608d210ccac" +version = "0.7.4" + +[[deps.Test]] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] +uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.TimeZones]] +deps = ["Artifacts", "Dates", "Downloads", "InlineStrings", "LazyArtifacts", "Mocking", "Printf", "Scratch", "TZJData", "Unicode", "p7zip_jll"] +git-tree-sha1 = "89e64d61ef3cd9e80f7fc12b7d13db2d75a23c03" +uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53" +version = "1.13.0" +weakdeps = ["RecipesBase"] + + [deps.TimeZones.extensions] + TimeZonesRecipesBaseExt = "RecipesBase" + +[[deps.TranscodingStreams]] +git-tree-sha1 = "1fbeaaca45801b4ba17c251dd8603ef24801dd84" +uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" +version = "0.10.2" +weakdeps = ["Random", "Test"] + + [deps.TranscodingStreams.extensions] + TestExt = ["Test", "Random"] + +[[deps.Transducers]] +deps = ["Adapt", "ArgCheck", "BangBang", "Baselet", "CompositionsBase", "ConstructionBase", "DefineSingletons", "Distributed", "InitialValues", "Logging", "Markdown", "MicroCollections", "Requires", "Setfield", "SplittablesBase", "Tables"] +git-tree-sha1 = "e579d3c991938fecbb225699e8f611fa3fbf2141" +uuid = "28d57a85-8fef-5791-bfe6-a80928e7c999" +version = "0.4.79" + + [deps.Transducers.extensions] + TransducersBlockArraysExt = "BlockArrays" + TransducersDataFramesExt = "DataFrames" + TransducersLazyArraysExt = "LazyArrays" + TransducersOnlineStatsBaseExt = "OnlineStatsBase" + TransducersReferenceablesExt = "Referenceables" + + [deps.Transducers.weakdeps] + BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e" + DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" + LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02" + OnlineStatsBase = "925886fa-5bf2-5e8e-b522-a9147a512338" + Referenceables = "42d2dcc6-99eb-4e98-b66c-637b7d73030e" + +[[deps.URIs]] +git-tree-sha1 = "67db6cc7b3821e19ebe75791a9dd19c9b1188f2b" +uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" +version = "1.5.1" + +[[deps.UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" + +[[deps.UnPack]] +git-tree-sha1 = "387c1f73762231e86e0c9c5443ce3b4a0a9a0c2b" +uuid = "3a884ed6-31ef-47d7-9d2a-63182c4928ed" +version = "1.0.2" + +[[deps.Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" + +[[deps.UnsafeAtomics]] +git-tree-sha1 = "6331ac3440856ea1988316b46045303bef658278" +uuid = "013be700-e6cd-48c3-b4a1-df204f14c38f" +version = "0.2.1" + +[[deps.UnsafeAtomicsLLVM]] +deps = ["LLVM", "UnsafeAtomics"] +git-tree-sha1 = "323e3d0acf5e78a56dfae7bd8928c989b4f3083e" +uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249" +version = "0.1.3" + +[[deps.WeakRefStrings]] +deps = ["DataAPI", "InlineStrings", "Parsers"] +git-tree-sha1 = "b1be2855ed9ed8eac54e5caff2afcdb442d52c23" +uuid = "ea10d353-3f73-51f8-a26c-33c1cb351aa5" +version = "1.4.2" + +[[deps.WorkerUtilities]] +git-tree-sha1 = "cd1659ba0d57b71a464a29e64dbc67cfe83d54e7" +uuid = "76eceee3-57b5-4d4a-8e66-0e911cebbf60" +version = "1.6.1" + +[[deps.XGBoost]] +deps = ["AbstractTrees", "CEnum", "JSON3", "LinearAlgebra", "OrderedCollections", "SparseArrays", "SparseMatricesCSR", "Statistics", "Tables", "XGBoost_jll"] +git-tree-sha1 = "bacb62e07d104630094c8dac2fd070f5d4b9b305" +uuid = "009559a3-9522-5dbb-924b-0b6ed2b22bb9" +version = "2.5.1" + + [deps.XGBoost.extensions] + XGBoostCUDAExt = "CUDA" + XGBoostTermExt = "Term" + + [deps.XGBoost.weakdeps] + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + Term = "22787eb5-b846-44ae-b979-8e399b8463ab" + +[[deps.XGBoost_jll]] +deps = ["Artifacts", "CUDA_Runtime_jll", "CompilerSupportLibraries_jll", "JLLWrappers", "LLVMOpenMP_jll", "LazyArtifacts", "Libdl", "TOML"] +git-tree-sha1 = "1c0aa2390a7ebb28a3d6c214f64e57a24091fbd7" +uuid = "a5c6f535-4255-5ca2-a466-0e519f119c46" +version = "2.0.1+0" + +[[deps.YAML]] +deps = ["Base64", "Dates", "Printf", "StringEncodings"] +git-tree-sha1 = "e6330e4b731a6af7959673621e91645eb1356884" +uuid = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6" +version = "0.4.9" + +[[deps.Zlib_jll]] +deps = ["Libdl"] +uuid = "83775a58-1f1d-513f-b197-d71354ab007a" +version = "1.2.13+0" + +[[deps.Zstd_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "49ce682769cd5de6c72dcf1b94ed7790cd08974c" +uuid = "3161d3a3-bdf6-5164-811a-617609db77b4" +version = "1.5.5+0" + +[[deps.Zygote]] +deps = ["AbstractFFTs", "ChainRules", "ChainRulesCore", "DiffRules", "Distributed", "FillArrays", "ForwardDiff", "GPUArrays", "GPUArraysCore", "IRTools", "InteractiveUtils", "LinearAlgebra", "LogExpFunctions", "MacroTools", "NaNMath", "PrecompileTools", "Random", "Requires", "SparseArrays", "SpecialFunctions", "Statistics", "ZygoteRules"] +git-tree-sha1 = "5ded212acd815612df112bb895ef3910c5a03f57" +uuid = "e88e6eb3-aa80-5325-afca-941959d7151f" +version = "0.6.67" + + [deps.Zygote.extensions] + ZygoteColorsExt = "Colors" + ZygoteDistancesExt = "Distances" + ZygoteTrackerExt = "Tracker" + + [deps.Zygote.weakdeps] + Colors = "5ae59095-9a9b-59fe-a467-6f913c188581" + Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7" + Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" + +[[deps.ZygoteRules]] +deps = ["ChainRulesCore", "MacroTools"] +git-tree-sha1 = "9d749cd449fb448aeca4feee9a2f4186dbb5d184" +uuid = "700de1a5-db45-46bc-99cf-38207098b444" +version = "0.2.4" + +[[deps.glmnet_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "31adae3b983b579a1fbd7cfd43a4bc0d224c2f5a" +uuid = "78c6b45d-5eaf-5d68-bcfb-a5a2cb06c27f" +version = "2.0.13+0" + +[[deps.libaec_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "eddd19a8dea6b139ea97bdc8a0e2667d4b661720" +uuid = "477f73a3-ac25-53e9-8cc3-50b2fa2566f0" +version = "1.0.6+1" + +[[deps.libblastrampoline_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" +version = "5.7.0+0" + +[[deps.libevent_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "OpenSSL_jll"] +git-tree-sha1 = "f04ec6d9a186115fb38f858f05c0c4e1b7fc9dcb" +uuid = "1080aeaf-3a6a-583e-a51c-c537b09f60ec" +version = "2.1.13+1" + +[[deps.nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" +version = "1.48.0+0" + +[[deps.p7zip_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" +version = "17.4.0+0" + +[[deps.prrte_jll]] +deps = ["Artifacts", "Hwloc_jll", "JLLWrappers", "Libdl", "PMIx_jll", "libevent_jll"] +git-tree-sha1 = "5adb2d7a18a30280feb66cad6f1a1dfdca2dc7b0" +uuid = "eb928a42-fffd-568d-ab9c-3f5d54fc65b9" +version = "3.0.2+0" diff --git a/test/Project.toml b/test/Project.toml index a09c3573..5b19b406 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -2,12 +2,15 @@ Arrow = "69666777-d1a9-59fb-9406-91d4454c9d45" CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" TMLE = "8afdd2fb-6e73-43df-8b62-b1650cd9c8cf" +TargetedEstimation = "2573d147-4098-46ba-9db2-8608d210ccac" YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6" [compat] +Arrow = "2.5.0" CSV = "0.10.9" DataFrames = "1.5.0" TMLE = "0.12" YAML = "0.4.8" -Arrow = "2.5.0" +JLD2 = "0.4.38" diff --git a/test/ukb_from_param_file.jl b/test/ukb_from_param_file.jl index 022da954..59b0078f 100644 --- a/test/ukb_from_param_file.jl +++ b/test/ukb_from_param_file.jl @@ -21,14 +21,30 @@ include(joinpath(@__DIR__, "test", "utils.jl")) r = run(cmd) @test r.exitcode == 0 - results = jldopen(joinpath("results", "results.hdf5")) + result_file = jldopen(joinpath("results", "results.hdf5")) + results = vcat(results["Batch_1"], result_file["Batch_2"]) dataset = DataFrame(Arrow.Table(joinpath("results", "dataset.arrow"))) - @test names(output) == vcat(SUMMARY_COLUMNS, ADJUTMENT_COL) - # 2 bQTLs and 1 trans-actor - @test Set(unique(output.TREATMENTS)) == Set(["1:238411180:T:C_&_3:3502414:T:C", "2:14983:G:A"]) - - check_fails_are_extremely_rare_traits(results, dataset) - test_n_success_more_than_threshold(results, 20) + + failed_results = (TMLE = [], OSE = []) + for result ∈ results + @test keys(result) == (:TMLE, :OSE) + @test result.TMLE isa Union{TMLE.TMLEstimate, TargetedEstimation.FailedEstimate} + @test result.OSE isa Union{TMLE.OSEstimate, TargetedEstimation.FailedEstimate} + if result.TMLE isa TargetedEstimation.FailedEstimate + push!(failed_results.TMLE, result.TMLE) + end + if result.OSE isa TargetedEstimation.FailedEstimate + push!(failed_results.OSE, result.OSE) + end + end + # All fails are due to fluctuation failure due non positive definite matrix + # This does not affect the OSE + @test isempty(failed_results.OSE) + # Less than 1/3 affected: this is still quite significant + @test length(failed_results.TMLE) / length(results) < 1/3 + @test all(startswith(x.msg, "Could not fluctuate") for x ∈ failed_results.TMLE) + + check_fails_are_extremely_rare_traits(failed_results.TMLE, dataset; ncases=3) end end diff --git a/test/utils.jl b/test/utils.jl index 05967b28..738532f1 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -1,44 +1,19 @@ -const SUMMARY_COLUMNS = [ - "PARAMETER_TYPE", "TREATMENTS", "CASE", "CONTROL", "TARGET", "CONFOUNDERS", "COVARIATES", - "INITIAL_ESTIMATE", "TMLE_ESTIMATE", "TMLE_STD", "TMLE_PVALUE", "TMLE_LWB", "TMLE_UPB", - "ONESTEP_ESTIMATE", "ONESTEP_STD", "ONESTEP_PVALUE", "ONESTEP_LWB", "ONESTEP_UPB", "LOG" -] - -const SIEVE_COLUMNS = ["SIEVE_STD", "SIEVE_PVALUE", "SIEVE_LWB", "SIEVE_UPB"] - -const ADJUTMENT_COL = "TRAIT_ADJUSTED_TMLE_PVALUE" - """ check_fails_are_extremely_rare_traits(output, dataset) The failures are due to traits with only very few cases (<=3) which is due to the fact that the dataset is quite degenerate. """ -function check_fails_are_extremely_rare_traits(output, dataset) - groups = groupby(output, :TREATMENTS) - for (treatment, group) in pairs(groups) - treatment = treatment.TREATMENTS - fails = filter(x -> x.LOG !== missing, group) - for target in unique(fails.TARGET) - @test eltype(dataset[!, target]) == Bool - nomissing = dropmissing(dataset, Symbol.([target, split(treatment, "_&_")...])) - @test sum(nomissing[!, target]) <= 3 - end +function check_fails_are_extremely_rare_traits(results, dataset; ncases=3) + for result ∈ results + Ξ¨ = result.estimand + @test eltype(dataset[!, Ξ¨.outcome]) == Bool + nomissing = dropmissing(dataset, Symbol.([Ξ¨.outcome, keys(Ξ¨.treatment_values)...])) + @test sum(nomissing[!, Ξ¨.outcome]) <= ncases end end -""" - -This is more of a non-regression test where we check that at least a certain amount of -estimates are a success. -""" -function test_n_success_more_than_threshold(output, threshold) - successes = filter(x -> x.LOG === missing, output) - n_succeses_per_treatment = DataFrames.combine(groupby(successes, :TREATMENTS), nrow) - @test all(x > threshold for x in n_succeses_per_treatment.nrow) -end - function write_custom_configuration() config = Configuration(estimands=[ From 3c54634920e9e04d978ee9bfc743359012d56461 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Wed, 13 Dec 2023 17:10:55 +0000 Subject: [PATCH 11/65] fix second test --- conf/ci_jobs/custom_from_actors.config | 9 +--- conf/ci_jobs/ukb_from_actors.config | 3 -- modules/sieve_variance.nf | 7 ++- test/custom_from_actors.jl | 63 +++++++++++++++++++------- test/ukb_from_actors.jl | 2 +- test/ukb_from_param_file.jl | 18 ++------ test/utils.jl | 15 ++++++ 7 files changed, 69 insertions(+), 48 deletions(-) diff --git a/conf/ci_jobs/custom_from_actors.config b/conf/ci_jobs/custom_from_actors.config index 20ea8257..575e9f2d 100644 --- a/conf/ci_jobs/custom_from_actors.config +++ b/conf/ci_jobs/custom_from_actors.config @@ -1,22 +1,15 @@ params { STUDY_DESIGN = "FROM_ACTORS" - ESTIMANDS_FILE = "test/data/parameters/parameters.yaml" DECRYPTED_DATASET = "test/data/traits.csv" COHORT = "CUSTOM" BED_FILES = "test/data/unphased_bed/ukb_chr{1,2,3}.{bed,bim,fam}" BGEN_FILES = "test/data/unphased_bgen/ukb_chr{1,2,3}.{bgen,bgen.bgi,sample}" - NB_PCS = 6 TRAITS_CONFIG = "test/data/ukbconfig_small.yaml" ESTIMATOR_FILE = "test/data/estimator.jl" + SVP = true NB_SVP_ESTIMATORS = 10 PVAL_THRESHOLD = 1 BQTLS = "test/data/actors/bqtls_multiple_TFs.csv" TRANS_ACTORS = "test/data/actors/eqtls_multiple_TFs.csv" - ORDERS = "1,2" - POSITIVITY_CONSTRAINT = 0.01 GRM_NSPLITS = 10 - BATCH_SIZE = 400 - MAX_PERMUTATION_TESTS = 100 - MAF_MATCHING_RELTOL = 0.9 - } diff --git a/conf/ci_jobs/ukb_from_actors.config b/conf/ci_jobs/ukb_from_actors.config index 5d456d71..ebea1030 100644 --- a/conf/ci_jobs/ukb_from_actors.config +++ b/conf/ci_jobs/ukb_from_actors.config @@ -7,17 +7,14 @@ params { QC_FILE = "test/data/qc_file.csv" LD_BLOCKS = "test/data/ld_blocks.txt" WITHDRAWAL_LIST = "test/data/withdrawal_list.txt" - NB_PCS = 6 TRAITS_CONFIG = "test/data/ukbconfig_small.yaml" ESTIMATOR_FILE = "test/data/estimator.jl" NB_SVP_ESTIMATORS = 10 PVAL_THRESHOLD = 1 BQTLS = "test/data/actors/bqtls.csv" TRANS_ACTORS = "test/data/actors/eqtls.csv" - ORDERS = "1,2" POSITIVITY_CONSTRAINT = 0.01 GRM_NSPLITS = 10 - BATCH_SIZE = 400 MAX_PERMUTATION_TESTS = 100 MAF_MATCHING_RELTOL = 0.9 N_RANDOM_VARIANTS = 5 diff --git a/modules/sieve_variance.nf b/modules/sieve_variance.nf index 24178a69..2c30506c 100644 --- a/modules/sieve_variance.nf +++ b/modules/sieve_variance.nf @@ -1,7 +1,6 @@ process SieveVarianceEstimation { container "olivierlabayle/targeted-estimation:cv_tmle" - publishDir "$params.OUTDIR/hdf5files/sieve", mode: 'symlink', pattern: "*.hdf5" - publishDir "$params.OUTDIR/csvs", mode: 'symlink', pattern: "*.csv" + publishDir "$params.OUTDIR", mode: 'symlink' input: path tmle_files @@ -16,9 +15,9 @@ process SieveVarianceEstimation { TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no /opt/bin/tmle sieve-variance-plateau \ tmle_result \ - --nb-estimators=$params.NB_SVP_ESTIMATORS \ + --n-estimators=$params.NB_SVP_ESTIMATORS \ --max-tau=$params.MAX_SVP_THRESHOLD \ - --estimator_key=$params.SVP_ESTIMATOR_KEY \ + --estimator-key=$params.SVP_ESTIMATOR_KEY \ --verbosity=$params.VERBOSITY """ } diff --git a/test/custom_from_actors.jl b/test/custom_from_actors.jl index 668c23b9..b94e04fa 100644 --- a/test/custom_from_actors.jl +++ b/test/custom_from_actors.jl @@ -1,7 +1,18 @@ +module TestCustomDatasetFromActors + +using Test +using JLD2 +using Arrow +using DataFrames +using TMLE +using CSV +using TargetedEstimation +using Serialization + #Β "local" profile assumes singularity is installed args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] -include("utils.jl") +include(joinpath(@__DIR__, "test", "utils.jl")) @testset "Test custom_from_actors.config" begin cmd = `nextflow run main.nf -c conf/ci_jobs/custom_from_actors.config $args` @@ -9,29 +20,47 @@ include("utils.jl") r = run(cmd) @test r.exitcode == 0 - - output = CSV.read(joinpath("results", "summary.csv"), DataFrame) - dataset = DataFrame(Arrow.Table(joinpath("results", "tmle_inputs", "final.data.arrow"))) - bQTLs = Symbol.(CSV.read(joinpath("test", "data", "actors", "bqtls.csv"), DataFrame).ID) - @test names(output) == vcat(SUMMARY_COLUMNS, SIEVE_COLUMNS, ADJUTMENT_COL) - # 2 bQTLs and 1 trans-actor - @test Set(unique(output.TREATMENTS)) == Set(["1:238411180:T:C", "3:3502414:T:C", "1:238411180:T:C_&_2:14983:G:A", "3:3502414:T:C_&_2:14983:G:A"]) - - test_n_success_more_than_threshold(output, 20) + # Sieve Variance Plateau File + svp = jldopen(joinpath("results", "svp.hdf5")) + @test haskey(svp, "taus") + @test haskey(svp, "variances") + @test length(svp["results"]) > 200 + @test all(x.TMLE isa TMLE.TMLEstimate for x in svp["results"]) + + # Results + results_file = jldopen(joinpath("results", "results.hdf5")) + results = vcat((results_file[key] for key in keys(results_file))...) + @test length(results) > 300 + failed_results = retrieve_failed_results(results; expected_keys=(:TMLE, :OSE, :SAMPLE_IDS)) + # All fails are due to fluctuation failure due non positive definite matrix + # This does not affect the OSE + @test isempty(failed_results.OSE) + # Less than 1/3 affected: this is still quite significant + @test length(failed_results.TMLE) / length(results) < 1/3 + @test all(startswith(x.msg, "Could not fluctuate") for x ∈ failed_results.TMLE) + + dataset = Arrow.Table(joinpath("results", "dataset.arrow")) |> DataFrame + + check_fails_are_extremely_rare_traits(failed_results.TMLE, dataset; ncases=7) # Here we test that the process generateIIDGenotypes has been run once for each chromosome - n_chr_files = filter(x -> startswith(x, "LDpruned.filtered.ukb_chr"), readdir(joinpath("results","ld_pruned_chromosomes"))) # There should be 4 files for each chromosome + n_chr_files = filter(x -> startswith(x, "LDpruned.filtered.ukb_chr"), readdir(joinpath("results", "ld_pruned_chromosomes"))) @test length(n_chr_files) == 4*3 ##Β Checking parameter files correspond to either bQTL only or bQTL/eQTL - parameters_tf1 = parameters_from_yaml(joinpath("results", "parameters", "final.TF1.param_1.yaml")) - parameters_tf2 = parameters_from_yaml(joinpath("results", "parameters", "final.TF2.param_1.yaml")) - @test size(parameters_tf1, 1) == 296 - @test size(parameters_tf2, 1) == 148 - for Ξ¨ in vcat(parameters_tf1, parameters_tf2) - @test keys(Ξ¨.treatment)[1] ∈ bQTLs + bQTLs = Symbol.(CSV.read(joinpath("test", "data", "actors", "bqtls.csv"), DataFrame).ID) + + estimands_tf1 = deserialize(joinpath("results", "estimands", "final.TF1.estimands_1.jls")) + estimands_tf2 = deserialize(joinpath("results", "estimands", "final.TF2.estimands_1.jls")) + @test size(estimands_tf1.estimands, 1) == 296 + @test size(estimands_tf2.estimands, 1) == 148 + for Ξ¨ in vcat(estimands_tf1.estimands, estimands_tf2.estimands) + @test length(intersect(keys(Ξ¨.treatment_values), bQTLs)) == 1 end +end end + +true \ No newline at end of file diff --git a/test/ukb_from_actors.jl b/test/ukb_from_actors.jl index c12ad0ae..19573791 100644 --- a/test/ukb_from_actors.jl +++ b/test/ukb_from_actors.jl @@ -1,7 +1,7 @@ #Β "local" profile assumes singularity is installed args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] -include("utils.jl") +include(joinpath(@__DIR__, "test", "utils.jl")) @testset "Test ukb_from_actors.config" begin cmd = `nextflow run main.nf -c conf/ci_jobs/ukb_from_actors.config $args` diff --git a/test/ukb_from_param_file.jl b/test/ukb_from_param_file.jl index 59b0078f..bd25ebba 100644 --- a/test/ukb_from_param_file.jl +++ b/test/ukb_from_param_file.jl @@ -1,13 +1,11 @@ module TestFromParamFile using Test -using CSV using DataFrames -using YAML using TMLE using Arrow -using Serialization using JLD2 +using TargetedEstimation #Β "local" profile assumes singularity is installed args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] @@ -25,18 +23,8 @@ include(joinpath(@__DIR__, "test", "utils.jl")) results = vcat(results["Batch_1"], result_file["Batch_2"]) dataset = DataFrame(Arrow.Table(joinpath("results", "dataset.arrow"))) - failed_results = (TMLE = [], OSE = []) - for result ∈ results - @test keys(result) == (:TMLE, :OSE) - @test result.TMLE isa Union{TMLE.TMLEstimate, TargetedEstimation.FailedEstimate} - @test result.OSE isa Union{TMLE.OSEstimate, TargetedEstimation.FailedEstimate} - if result.TMLE isa TargetedEstimation.FailedEstimate - push!(failed_results.TMLE, result.TMLE) - end - if result.OSE isa TargetedEstimation.FailedEstimate - push!(failed_results.OSE, result.OSE) - end - end + failed_results = retrieve_failed_results(results) + # All fails are due to fluctuation failure due non positive definite matrix # This does not affect the OSE @test isempty(failed_results.OSE) diff --git a/test/utils.jl b/test/utils.jl index 738532f1..ac64ca63 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -14,6 +14,21 @@ function check_fails_are_extremely_rare_traits(results, dataset; ncases=3) end end +function retrieve_failed_results(results; expected_keys=(:TMLE, :OSE)) + failed_results = (TMLE = [], OSE = []) + for result ∈ results + @test keys(result) == expected_keys + @test result.TMLE isa Union{TMLE.TMLEstimate, TargetedEstimation.FailedEstimate} + @test result.OSE isa Union{TMLE.OSEstimate, TargetedEstimation.FailedEstimate} + if result.TMLE isa TargetedEstimation.FailedEstimate + push!(failed_results.TMLE, result.TMLE) + end + if result.OSE isa TargetedEstimation.FailedEstimate + push!(failed_results.OSE, result.OSE) + end + end + return failed_results +end function write_custom_configuration() config = Configuration(estimands=[ From 412e4f3f83435c0397fb863140925af163880189 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Wed, 13 Dec 2023 17:19:22 +0000 Subject: [PATCH 12/65] fix include --- conf/ci_jobs/ukb_from_actors.config | 1 - test/custom_from_actors.jl | 2 +- test/ukb_from_actors.jl | 2 +- test/ukb_from_param_file.jl | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/conf/ci_jobs/ukb_from_actors.config b/conf/ci_jobs/ukb_from_actors.config index ebea1030..5e700719 100644 --- a/conf/ci_jobs/ukb_from_actors.config +++ b/conf/ci_jobs/ukb_from_actors.config @@ -9,7 +9,6 @@ params { WITHDRAWAL_LIST = "test/data/withdrawal_list.txt" TRAITS_CONFIG = "test/data/ukbconfig_small.yaml" ESTIMATOR_FILE = "test/data/estimator.jl" - NB_SVP_ESTIMATORS = 10 PVAL_THRESHOLD = 1 BQTLS = "test/data/actors/bqtls.csv" TRANS_ACTORS = "test/data/actors/eqtls.csv" diff --git a/test/custom_from_actors.jl b/test/custom_from_actors.jl index b94e04fa..25934787 100644 --- a/test/custom_from_actors.jl +++ b/test/custom_from_actors.jl @@ -12,7 +12,7 @@ using Serialization #Β "local" profile assumes singularity is installed args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] -include(joinpath(@__DIR__, "test", "utils.jl")) +include("utils.jl") @testset "Test custom_from_actors.config" begin cmd = `nextflow run main.nf -c conf/ci_jobs/custom_from_actors.config $args` diff --git a/test/ukb_from_actors.jl b/test/ukb_from_actors.jl index 19573791..c12ad0ae 100644 --- a/test/ukb_from_actors.jl +++ b/test/ukb_from_actors.jl @@ -1,7 +1,7 @@ #Β "local" profile assumes singularity is installed args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] -include(joinpath(@__DIR__, "test", "utils.jl")) +include("utils.jl") @testset "Test ukb_from_actors.config" begin cmd = `nextflow run main.nf -c conf/ci_jobs/ukb_from_actors.config $args` diff --git a/test/ukb_from_param_file.jl b/test/ukb_from_param_file.jl index bd25ebba..8b13ead1 100644 --- a/test/ukb_from_param_file.jl +++ b/test/ukb_from_param_file.jl @@ -10,7 +10,7 @@ using TargetedEstimation #Β "local" profile assumes singularity is installed args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] -include(joinpath(@__DIR__, "test", "utils.jl")) +include("utils.jl") @testset "Test ukb_from_param_files.config" begin cmd = `nextflow run main.nf -c conf/ci_jobs/ukb_from_param_file.config $args` From 838b2acfc832444bec384e583d4ae340520f58e9 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Wed, 13 Dec 2023 18:03:05 +0000 Subject: [PATCH 13/65] try update CI script --- .github/workflows/CI.yml | 3 +++ test/ukb_from_actors.jl | 18 +++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 0f642bb5..f410be24 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -19,6 +19,9 @@ jobs: - "ukb_from_param_file.jl" - "custom_from_actors.jl" steps: + - run: | + sudo apt-get update + sudo apt-get install procps - uses: actions/checkout@v2 - uses: julia-actions/setup-julia@v1 with: diff --git a/test/ukb_from_actors.jl b/test/ukb_from_actors.jl index c12ad0ae..46638bae 100644 --- a/test/ukb_from_actors.jl +++ b/test/ukb_from_actors.jl @@ -11,9 +11,21 @@ include("utils.jl") @test r.exitcode == 0 ##Β Checking main output - output = CSV.read(joinpath("results", "summary.csv"), DataFrame) - dataset = DataFrame(Arrow.Table(joinpath("results", "tmle_inputs", "final.data.arrow"))) - bQTLs = Symbol.(CSV.read(joinpath("test", "data", "actors", "bqtls.csv"), DataFrame).ID) + # Results + results_file = jldopen(joinpath("results", "results.hdf5")) + results = vcat((results_file[key] for key in keys(results_file))...) + @test length(results) > 300 + failed_results = retrieve_failed_results(results; expected_keys=(:TMLE, :OSE, :SAMPLE_IDS)) + # All fails are due to fluctuation failure due non positive definite matrix + # This does not affect the OSE + @test isempty(failed_results.OSE) + # Less than 1/3 affected: this is still quite significant + @test length(failed_results.TMLE) / length(results) < 1/3 + @test all(startswith(x.msg, "Could not fluctuate") for x ∈ failed_results.TMLE) + + dataset = Arrow.Table(joinpath("results", "dataset.arrow")) |> DataFrame + + check_fails_are_extremely_rare_traits(failed_results.TMLE, dataset; ncases=3) @test names(output) == vcat(SUMMARY_COLUMNS, SIEVE_COLUMNS, ADJUTMENT_COL) # 2 bQTLs and 1 trans-actor From b0a933957c32036e154592f2ea3aeb19ec9891fd Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Thu, 14 Dec 2023 07:49:33 +0000 Subject: [PATCH 14/65] up doc and remove procps from ci --- .github/workflows/CI.yml | 3 --- docs/src/miscellaneous.md | 2 +- docs/src/nextflow_params.md | 4 ++-- docs/src/overview.md | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index f410be24..0f642bb5 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -19,9 +19,6 @@ jobs: - "ukb_from_param_file.jl" - "custom_from_actors.jl" steps: - - run: | - sudo apt-get update - sudo apt-get install procps - uses: actions/checkout@v2 - uses: julia-actions/setup-julia@v1 with: diff --git a/docs/src/miscellaneous.md b/docs/src/miscellaneous.md index ec8a1864..a8668018 100644 --- a/docs/src/miscellaneous.md +++ b/docs/src/miscellaneous.md @@ -2,7 +2,7 @@ Further Nextflow parameter affecting the behaviour of the pipeline but that does not fit in any previously described category is listed here: -- `CALL_THRESHOLD` (optional, default: 0.9): For putative causal variants (listed in the parameter files described in the [Describing the causal parameters of interest](@ref) section). If an individual's allele's probability is greater than the threshold, then it is called, otherwise it is considered missing. +- `CALL_THRESHOLD` (optional, default: 0.9): For putative causal variants (listed in the parameter files described in the [Study Designs](@ref) section). If an individual's allele's probability is greater than the threshold, then it is called, otherwise it is considered missing. - `BATCH_SIZE` (optional, default: 400): The set of parameters to be estimated is batched and the TMLE processes will run in parallel across batches on your platform. - `SAVE_IC` (optional, default: true): For all parameters with an p-value below `PVAL_THRESHOLD`, the influence curve is saved. Make sure to keep to `true` if you want to use sieve variance correction, i.e. if `NB_SVP_ESTIMATORS` != 0. - `OUTDIR` (optional, default: "results"): Output directory diff --git a/docs/src/nextflow_params.md b/docs/src/nextflow_params.md index d4f2d988..ac6fe550 100644 --- a/docs/src/nextflow_params.md +++ b/docs/src/nextflow_params.md @@ -21,7 +21,7 @@ Here is a list of all the pipeline parameters: - `MAF_THRESHOLD` (optional): Only variants with that minor allele frequency are considered - `NB_PCS` (optional, default: 6): The number of PCA components to extract. -## [Describing the causal parameters of interest](@ref) +## [Study Designs](@ref) - **`STUDY_DESIGN`** (required, default: "FROM\_PARAM\_FILE"): One of "FROM\_PARAM\_FILE", "FROM\_ACTORS". @@ -53,7 +53,7 @@ If `STUDY_DESIGN`="FROM_ACTORS": ## [Tweaking additional behaviour](@ref) -- `CALL_THRESHOLD` (optional, default: 0.9): For putative causal variants (listed in the parameter files described in the [Describing the causal parameters of interest](@ref) section). If a individual's allele's probability is greater than the threshold, then it is called, otherwise it is considered missing. +- `CALL_THRESHOLD` (optional, default: 0.9): For putative causal variants (listed in the parameter files described in the [Study Designs](@ref) section). If a individual's allele's probability is greater than the threshold, then it is called, otherwise it is considered missing. - `BATCH_SIZE` (optional, default: 400): The set of parameters to be estimated is batched and the TMLE processes will run in parallel across batches on your platform. - `OUTDIR` (optional, default: "results"): Output directory - `RNG` (optional, default: 123): General random seed used where appropriate. diff --git a/docs/src/overview.md b/docs/src/overview.md index 7a296092..9d8009ad 100644 --- a/docs/src/overview.md +++ b/docs/src/overview.md @@ -15,7 +15,7 @@ All arguments are optional but encouraged. Here `-r vX` describes the version to 2. You need to provide the configuration details associated with your project, this is usually done in a `nextflow.config` file living at the root of your project's directory. The configuration parameters are described in the following sections: - [Setting a data source](@ref) - [Adjusting for confounders](@ref) - - [Describing the causal parameters of interest](@ref) + - [Study Designs](@ref) - [Specifying a Targeted Estimator](@ref) - [Correcting for population relatedness](@ref) - [Tweaking additional behaviour](@ref) From 5587c21362891983c02aac9cd0604b19d9499b78 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Thu, 14 Dec 2023 08:28:20 +0000 Subject: [PATCH 15/65] up testfile --- conf/ci_jobs/ukb_from_actors.config | 1 + modules/sieve_variance.nf | 7 ++++--- test/ukb_from_param_file.jl | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/conf/ci_jobs/ukb_from_actors.config b/conf/ci_jobs/ukb_from_actors.config index 5e700719..56d57916 100644 --- a/conf/ci_jobs/ukb_from_actors.config +++ b/conf/ci_jobs/ukb_from_actors.config @@ -9,6 +9,7 @@ params { WITHDRAWAL_LIST = "test/data/withdrawal_list.txt" TRAITS_CONFIG = "test/data/ukbconfig_small.yaml" ESTIMATOR_FILE = "test/data/estimator.jl" + JSON_OUTPUT = "results.json" PVAL_THRESHOLD = 1 BQTLS = "test/data/actors/bqtls.csv" TRANS_ACTORS = "test/data/actors/eqtls.csv" diff --git a/modules/sieve_variance.nf b/modules/sieve_variance.nf index 2c30506c..81a5ddee 100644 --- a/modules/sieve_variance.nf +++ b/modules/sieve_variance.nf @@ -25,7 +25,8 @@ process SieveVarianceEstimation { process MergeOutputs { container "olivierlabayle/targeted-estimation:cv_tmle" publishDir "$params.OUTDIR", mode: 'symlink' - + label "bigmem" + input: path tmle_files val hdf5_output @@ -36,12 +37,12 @@ process MergeOutputs { path "${json_output}", optional: true script: - json_output = json_output != "NO_JSON_OUTPUT" ? "--outputs.json.filename=${json_output}" : "" + json_option = json_output !== "NO_JSON_OUTPUT" ? "--outputs.json.filename=${json_output}" : "" """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no /opt/bin/tmle make-summary \ tmle_result \ --outputs.hdf5.filename=${params.HDF5_OUTPUT} \ - ${json_output} + ${json_option} """ } \ No newline at end of file diff --git a/test/ukb_from_param_file.jl b/test/ukb_from_param_file.jl index 8b13ead1..a5c67e89 100644 --- a/test/ukb_from_param_file.jl +++ b/test/ukb_from_param_file.jl @@ -20,7 +20,7 @@ include("utils.jl") @test r.exitcode == 0 result_file = jldopen(joinpath("results", "results.hdf5")) - results = vcat(results["Batch_1"], result_file["Batch_2"]) + results = vcat(result_file["Batch_1"], result_file["Batch_2"]) dataset = DataFrame(Arrow.Table(joinpath("results", "dataset.arrow"))) failed_results = retrieve_failed_results(results) From f2f2b857965aa2c91089fb3b757ff6aa5285532b Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Thu, 14 Dec 2023 14:35:41 +0000 Subject: [PATCH 16/65] fix last test --- main.nf | 3 +- modules/negative_control.nf | 15 ++++---- modules/sieve_variance.nf | 2 +- test/ukb_from_actors.jl | 73 ++++++++++++++++++++----------------- 4 files changed, 49 insertions(+), 44 deletions(-) diff --git a/main.nf b/main.nf index 6b624e03..1ea6192b 100644 --- a/main.nf +++ b/main.nf @@ -51,7 +51,6 @@ params.PERMUTATION_JSON_OUTPUT = "NO_JSON_OUTPUT" // Permutation Tests Parameters params.MAX_PERMUTATION_TESTS = null -params.PVAL_COL = "TMLE_PVALUE" params.PERMUTATION_ORDERS = "1" params.RNG = 123 params.MAF_MATCHING_RELTOL = 0.05 @@ -196,7 +195,7 @@ workflow generateSieveEstimates { } workflow negativeControl { - results_file = Channel.value(file("${params.HDF5_OUTPUT}")) + results_file = Channel.value(file("${params.OUTDIR}/${params.HDF5_OUTPUT}")) // Permutation Tests dataset = Channel.value(file("${params.OUTDIR}/${params.ARROW_OUTPUT}")) diff --git a/modules/negative_control.nf b/modules/negative_control.nf index 95bdf3b8..c3aabfae 100644 --- a/modules/negative_control.nf +++ b/modules/negative_control.nf @@ -17,8 +17,9 @@ def longest_prefix(files){ } process GeneratePermutationTestsData { - container "olivierlabayle/negative-controls:0.2" - publishDir "${params.OUTDIR}/permutation_data", mode: 'symlink' + container "olivierlabayle/negative-controls:cvtmle" + publishDir "${params.OUTDIR}/permutation_tests", mode: 'symlink', pattern: '*.arrow' + publishDir "${params.OUTDIR}/permutation_tests/estimands", mode: 'symlink', pattern: '*.jls' label "bigmem" input: @@ -27,7 +28,7 @@ process GeneratePermutationTestsData { output: path "permutation_dataset.arrow", emit: dataset - path "*.yaml", emit: estimands + path "*.jls", emit: estimands script: limit = params.MAX_PERMUTATION_TESTS == null ? "" : "--limit=${params.MAX_PERMUTATION_TESTS}" @@ -36,7 +37,6 @@ process GeneratePermutationTestsData { JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/NegativeControl --startup-file=no /NegativeControl/bin/generate_permutation_data.jl \ ${dataset} ${results} \ ${limit} \ - --pval-col=${params.PVAL_COL} \ --pval-threshold=${params.PVAL_THRESHOLD} \ --orders=${params.PERMUTATION_ORDERS} \ --chunksize=${params.BATCH_SIZE} \ @@ -46,7 +46,7 @@ process GeneratePermutationTestsData { } process GenerateRandomVariantsTestsData { - container "olivierlabayle/negative-controls:0.2" + container "olivierlabayle/negative-controls:cvtmle" publishDir "${params.OUTDIR}", mode: 'symlink' label "bigmem" @@ -56,7 +56,7 @@ process GenerateRandomVariantsTestsData { path results output: - path "random_variants_parameters.yaml" + path "random_variants_estimands.jls" script: trans_actors_prefix = longest_prefix(trans_actors) @@ -65,10 +65,9 @@ process GenerateRandomVariantsTestsData { TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/NegativeControl --startup-file=no /NegativeControl/bin/generate_random_variant_parameters.jl \ ${trans_actors_prefix} ${results} ${bgen_prefix} \ - --out=random_variants_parameters.yaml \ + --out=random_variants_estimands.jls \ --p=${params.N_RANDOM_VARIANTS} \ --reltol=${params.MAF_MATCHING_RELTOL} \ - --pval-col=${params.PVAL_COL} \ --pval-threshold=${params.PVAL_THRESHOLD} \ --rng=${params.RNG} \ --verbosity=${params.VERBOSITY} diff --git a/modules/sieve_variance.nf b/modules/sieve_variance.nf index 81a5ddee..64f83a1f 100644 --- a/modules/sieve_variance.nf +++ b/modules/sieve_variance.nf @@ -42,7 +42,7 @@ process MergeOutputs { TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no /opt/bin/tmle make-summary \ tmle_result \ - --outputs.hdf5.filename=${params.HDF5_OUTPUT} \ + --outputs.hdf5.filename=${hdf5_output} \ ${json_option} """ } \ No newline at end of file diff --git a/test/ukb_from_actors.jl b/test/ukb_from_actors.jl index 46638bae..1e139cf5 100644 --- a/test/ukb_from_actors.jl +++ b/test/ukb_from_actors.jl @@ -1,3 +1,14 @@ +module Test UKBFromActors + +using Test +using JLD2 +using Arrow +using DataFrames +using TMLE +using CSV +using TargetedEstimation +using Serialization + #Β "local" profile assumes singularity is installed args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] @@ -12,41 +23,33 @@ include("utils.jl") ##Β Checking main output # Results - results_file = jldopen(joinpath("results", "results.hdf5")) - results = vcat((results_file[key] for key in keys(results_file))...) - @test length(results) > 300 - failed_results = retrieve_failed_results(results; expected_keys=(:TMLE, :OSE, :SAMPLE_IDS)) + hdf5_results_file = jldopen(joinpath("results", "results.hdf5")) + results_from_hdf5 = vcat((hdf5_results_file[key] for key in keys(hdf5_results_file))...) + results_from_json = TMLE.read_json(joinpath("results", "results.json")) + @test length(results_from_json) == length(results_from_hdf5) > 300 + + failed_results = retrieve_failed_results(results_from_hdf5; expected_keys=(:TMLE, :OSE)) # All fails are due to fluctuation failure due non positive definite matrix # This does not affect the OSE @test isempty(failed_results.OSE) # Less than 1/3 affected: this is still quite significant - @test length(failed_results.TMLE) / length(results) < 1/3 + @test length(failed_results.TMLE) / length(results_from_hdf5) < 1/3 @test all(startswith(x.msg, "Could not fluctuate") for x ∈ failed_results.TMLE) dataset = Arrow.Table(joinpath("results", "dataset.arrow")) |> DataFrame check_fails_are_extremely_rare_traits(failed_results.TMLE, dataset; ncases=3) - @test names(output) == vcat(SUMMARY_COLUMNS, SIEVE_COLUMNS, ADJUTMENT_COL) - # 2 bQTLs and 1 trans-actor - @test Set(unique(output.TREATMENTS)) == Set(["1:238411180:T:C", "3:3502414:T:C", "1:238411180:T:C_&_2:14983:G:A", "3:3502414:T:C_&_2:14983:G:A"]) - - check_fails_are_extremely_rare_traits(output, dataset) - test_n_success_more_than_threshold(output, 20) - ##Β Checking parameter files correspond to either bQTL only or bQTL/eQTL - parameters_1 = parameters_from_yaml(joinpath("results", "parameters", "final.param_1.yaml")) - @test size(parameters_1, 1) == 400 - for Ξ¨ in parameters_1 - @test keys(Ξ¨.treatment)[1] ∈ bQTLs - end + bQTLs = Symbol.(CSV.read(joinpath("test", "data", "actors", "bqtls.csv"), DataFrame).ID) - parameters_2 = parameters_from_yaml(joinpath("results", "parameters", "final.param_2.yaml")) - @test size(parameters_2, 1) == 44 - for Ξ¨ in parameters_2 - @test keys(Ξ¨.treatment)[1] ∈ bQTLs + config_1 = deserialize(joinpath("results", "estimands", "final.estimands_1.jls")) + @test length(config_1.estimands) == 400 + config_2 = deserialize(joinpath("results", "estimands", "final.estimands_2.jls")) + @test 0 < length(config_2.estimands) <= 400 + for Ξ¨ in vcat(config_1.estimands, config_2.estimands) + @test length(intersect(keys(Ξ¨.treatment_values), bQTLs)) == 1 end - end @testset "Test negative controls" begin @@ -57,7 +60,7 @@ end @test r.exitcode == 0 # Check permutation test - data = DataFrame(Arrow.Table(joinpath("results", "permutation_data", "permutation_dataset.arrow"))) + data = Arrow.Table(joinpath("results", "permutation_tests", "permutation_dataset.arrow")) |> DataFrame n_permuted_cols = 0 for colname in names(data) @@ -67,16 +70,20 @@ end end @test n_permuted_cols > 20 - parameters = parameters_from_yaml(joinpath("results", "permutation_data", "permutation_param_1.yaml")) - @test size(parameters, 1) == 100 - @test all(Ξ¨ isa IATE for Ξ¨ in parameters) + permutation_config = deserialize(joinpath("results", "permutation_tests", "estimands", "permutation_estimands_1.jls")) + @test length(permutation_config.estimands) == 100 + @test Set(typeof(Ξ¨) for Ξ¨ in permutation_config.estimands) == Set([TMLE.StatisticalATE, TMLE.StatisticalIATE]) - results = CSV.read(joinpath("results", "permutation_summary.csv"), DataFrame) - @test size(results) == (100, 20) - @test length(collect(skipmissing(results.TMLE_PVALUE))) > 20 + results = jldopen(joinpath("results", "permutation_results.hdf5"))["Batch_1"] + @test length(results) == 100 + failed_results = retrieve_failed_results(results; expected_keys=(:TMLE, :OSE)) + @test failed_results == (TMLE=[], OSE=[]) # Check random variants data - parameters = parameters_from_yaml(joinpath("results", "random_variants_parameters.yaml")) - @test size(parameters, 1) > 200 - @test all(Ξ¨ isa IATE for Ξ¨ in parameters) -end \ No newline at end of file + random_config = deserialize(joinpath("results", "random_variants_estimands.jls")) + @test length(random_config.estimands) > 200 + @test Set(typeof(Ξ¨) for Ξ¨ in random_config.estimands) == Set([TMLE.StatisticalATE, TMLE.StatisticalIATE]) +end + +end +true \ No newline at end of file From 4f1a6deaa8ebbb44f2652bae99957889f8a5bed8 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Thu, 14 Dec 2023 14:43:14 +0000 Subject: [PATCH 17/65] fix typo --- test/ukb_from_actors.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ukb_from_actors.jl b/test/ukb_from_actors.jl index 1e139cf5..18de9b17 100644 --- a/test/ukb_from_actors.jl +++ b/test/ukb_from_actors.jl @@ -1,4 +1,4 @@ -module Test UKBFromActors +module TestUKBFromActors using Test using JLD2 From 78ad0a2ad2a45f0d9ea46034ff627056bd1bd76b Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Fri, 15 Dec 2023 12:42:31 +0000 Subject: [PATCH 18/65] start pipeline refactor --- conf/ci_jobs/custom_from_actors.config | 2 +- conf/ci_jobs/ukb_from_actors.config | 6 +- conf/ci_jobs/ukb_from_param_file.config | 6 +- conf/eddie.config | 2 +- main.nf | 265 +++++++--------------- modules/confounders.nf | 12 + modules/estimation.nf | 100 ++++++++ modules/{tmle.nf => estimation_inputs.nf} | 95 ++++---- modules/genotypes.nf | 20 +- modules/grm.nf | 34 --- modules/negative_control.nf | 50 ++-- modules/pca.nf | 11 + modules/sieve_variance.nf | 48 ---- modules/svp.nf | 89 ++++++++ modules/{ukb_traits.nf => traits.nf} | 27 +++ modules/utils.nf | 17 ++ test/custom_from_actors.jl | 2 +- 17 files changed, 437 insertions(+), 349 deletions(-) create mode 100644 modules/estimation.nf rename modules/{tmle.nf => estimation_inputs.nf} (62%) delete mode 100644 modules/grm.nf create mode 100644 modules/pca.nf delete mode 100644 modules/sieve_variance.nf create mode 100644 modules/svp.nf rename modules/{ukb_traits.nf => traits.nf} (68%) create mode 100644 modules/utils.nf diff --git a/conf/ci_jobs/custom_from_actors.config b/conf/ci_jobs/custom_from_actors.config index 575e9f2d..1cecb8c3 100644 --- a/conf/ci_jobs/custom_from_actors.config +++ b/conf/ci_jobs/custom_from_actors.config @@ -1,6 +1,6 @@ params { STUDY_DESIGN = "FROM_ACTORS" - DECRYPTED_DATASET = "test/data/traits.csv" + TRAITS_DATASET = "test/data/traits.csv" COHORT = "CUSTOM" BED_FILES = "test/data/unphased_bed/ukb_chr{1,2,3}.{bed,bim,fam}" BGEN_FILES = "test/data/unphased_bgen/ukb_chr{1,2,3}.{bgen,bgen.bgi,sample}" diff --git a/conf/ci_jobs/ukb_from_actors.config b/conf/ci_jobs/ukb_from_actors.config index 56d57916..1e8b9b1a 100644 --- a/conf/ci_jobs/ukb_from_actors.config +++ b/conf/ci_jobs/ukb_from_actors.config @@ -1,13 +1,13 @@ params { STUDY_DESIGN = "FROM_ACTORS" - DECRYPTED_DATASET = "test/data/dataset.csv" + TRAITS_DATASET = "test/data/dataset.csv" COHORT = "UKBB" BED_FILES = "test/data/unphased_bed/ukb_chr{1,2,3}.{bed,bim,fam}" BGEN_FILES = "test/data/unphased_bgen/ukb_chr{1,2,3}.{bgen,bgen.bgi,sample}" QC_FILE = "test/data/qc_file.csv" LD_BLOCKS = "test/data/ld_blocks.txt" - WITHDRAWAL_LIST = "test/data/withdrawal_list.txt" - TRAITS_CONFIG = "test/data/ukbconfig_small.yaml" + UKB_WITHDRAWAL_LIST = "test/data/withdrawal_list.txt" + UKB_CONFIG = "test/data/ukbconfig_small.yaml" ESTIMATOR_FILE = "test/data/estimator.jl" JSON_OUTPUT = "results.json" PVAL_THRESHOLD = 1 diff --git a/conf/ci_jobs/ukb_from_param_file.config b/conf/ci_jobs/ukb_from_param_file.config index a97af087..e162bd94 100644 --- a/conf/ci_jobs/ukb_from_param_file.config +++ b/conf/ci_jobs/ukb_from_param_file.config @@ -1,15 +1,15 @@ params { STUDY_DESIGN = "CUSTOM" ESTIMANDS_FILE = "test/data/parameters/parameters.yaml" - DECRYPTED_DATASET = "test/data/dataset.csv" + TRAITS_DATASET = "test/data/dataset.csv" COHORT = "UKBB" BED_FILES = "test/data/unphased_bed/ukb_chr{1,2,3}.{bed,bim,fam}" BGEN_FILES = "test/data/unphased_bgen/ukb_chr{1,2,3}.{bgen,bgen.bgi,sample}" QC_FILE = "test/data/qc_file.csv" LD_BLOCKS = "test/data/ld_blocks.txt" - WITHDRAWAL_LIST = "test/data/withdrawal_list.txt" + UKB_WITHDRAWAL_LIST = "test/data/withdrawal_list.txt" NB_PCS = 6 - TRAITS_CONFIG = "test/data/ukbconfig_small.yaml" + UKB_CONFIG = "test/data/ukbconfig_small.yaml" ESTIMATOR_FILE = "test/data/estimator.jl" POSITIVITY_CONSTRAINT = 0.0 diff --git a/conf/eddie.config b/conf/eddie.config index 0810c24e..d0207a7b 100644 --- a/conf/eddie.config +++ b/conf/eddie.config @@ -34,7 +34,7 @@ process { export SINGULARITY_TMPDIR="\$TMPDIR" """ - withName: SieveVarianceEstimation { + withName: SVP { cpus = 30 memory = '2000G' clusterOptions = { task.memory ? "-l mem_free=20G,h_vmem=${task.memory.bytes/task.cpus}" : null } diff --git a/main.nf b/main.nf index 1ea6192b..d4ba9319 100644 --- a/main.nf +++ b/main.nf @@ -1,14 +1,15 @@ #!/usr/bin/env nextflow nextflow.enable.dsl = 2 -params.DECRYPTED_DATASET = "NO_FILE" +params.VERBOSITY = 0 +params.TRAITS_DATASET = "NO_TRAITS_DATASET" +params.UKB_ENCODING_FILE = "NO_UKB_ENCODING_FILE" params.CALL_THRESHOLD = 0.9 params.POSITIVITY_CONSTRAINT = 0.01 params.MAF_THRESHOLD = 0.01 -params.VERBOSITY = 1 params.COHORT = "UKBB" -params.TRAITS_CONFIG = "NO_UKB_TRAIT_CONFIG" -params.WITHDRAWAL_LIST = 'NO_WITHDRAWAL_LIST' +params.UKB_CONFIG = "NO_UKB_TRAIT_CONFIG" +params.UKB_WITHDRAWAL_LIST = 'NO_WITHDRAWAL_LIST' params.OUTDIR = "${launchDir}/results" // Confounding adjustment by PCA @@ -41,201 +42,101 @@ params.SVP_ESTIMATOR_KEY = "TMLE" params.KEEP_IC = params.SVP == true ? true : false params.PVAL_THRESHOLD = 0.05 params.TMLE_SAVE_EVERY = 100 +params.AGGREGATED_DATASET = "results/dataset.arrow" +params.ESTIMATOR_FILE = "glmnet" // Outputs params.ARROW_OUTPUT = "dataset.arrow" params.JSON_OUTPUT = "NO_JSON_OUTPUT" params.HDF5_OUTPUT = "results.hdf5" -params.PERMUTATION_HDF5_OUTPUT = "permutation_results.hdf5" -params.PERMUTATION_JSON_OUTPUT = "NO_JSON_OUTPUT" - -// Permutation Tests Parameters -params.MAX_PERMUTATION_TESTS = null -params.PERMUTATION_ORDERS = "1" -params.RNG = 123 -params.MAF_MATCHING_RELTOL = 0.05 -params.N_RANDOM_VARIANTS = 10 - +include { EstimationInputs } from './modules/estimation_inputs.nf' include { IIDGenotypes } from './modules/genotypes.nf' -include { FlashPCA; AdaptFlashPCA } from './modules/confounders.nf' -include { UKBFieldsList; UKBConv; TraitsFromUKB } from './modules/ukb_traits.nf' -include { TMLE; TMLEInputsFromParamFile; TMLEInputsFromActors } from './modules/tmle.nf' -include { GRMPart; AggregateGRM } from './modules/grm.nf' -include { SieveVarianceEstimation ; MergeOutputs } from './modules/sieve_variance.nf' -include { GeneratePermutationTestsData; GenerateRandomVariantsTestsData } from './modules/negative_control.nf' - -workflow extractTraits { - traits_config = Channel.value(file("$params.TRAITS_CONFIG")) - withdrawal_list = Channel.value(file("$params.WITHDRAWAL_LIST")) - if (params.DECRYPTED_DATASET == "NO_FILE") { - encrypted_dataset = Channel.value(file("$params.ENCRYPTED_DATASET")) - encoding_file = Channel.value(file("$params.ENCODING_FILE")) - UKBFieldsList(traits_config) - decrypted_dataset = UKBConv(UKBFieldsList.out, encrypted_dataset, encoding_file) - } - else { - decrypted_dataset = Channel.value(file("$params.DECRYPTED_DATASET")) - } - - if (params.COHORT == "UKBB") { - extracted_traits = TraitsFromUKB(decrypted_dataset, traits_config, withdrawal_list) - } - else { - extracted_traits = decrypted_dataset - } - - emit: - extracted_traits -} - -workflow generateIIDGenotypes { - take: - traits - - main: - qc_file = Channel.value(file("$params.QC_FILE")) - flashpca_excl_reg = Channel.value(file("$params.FLASHPCA_EXCLUSION_REGIONS")) - ld_blocks = Channel.value(file("$params.LD_BLOCKS")) - bed_files_ch = Channel.fromFilePairs("$params.BED_FILES", size: 3, checkIfExists: true){ file -> file.baseName } - - IIDGenotypes(flashpca_excl_reg, ld_blocks, bed_files_ch, qc_file, traits) - - emit: - IIDGenotypes.out -} - -workflow geneticConfounders { - take: - iid_genotypes - - main: - FlashPCA(iid_genotypes) - AdaptFlashPCA(FlashPCA.out) - - emit: - AdaptFlashPCA.out - -} - -workflow runPCA { - // Extract traits - extractTraits() - - // Generate IID Genotypes - generateIIDGenotypes(extractTraits.out) - - // Genetic confounders up to NB_PCS - geneticConfounders(generateIIDGenotypes.out) +include { GeneticConfounders } from './modules/confounders.nf' +include { ExtractTraits } from './modules/traits.nf' +include { EstimationWorkflow } from './modules/estimation.nf' +include { SVPWorkflow } from './modules/svp.nf' -} - -workflow generateTMLEEstimates { - take: - traits - genetic_confounders - - main: - estimator_file = Channel.value(file("$params.ESTIMATOR_FILE", checkIfExists: true)) - bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() - - if (params.STUDY_DESIGN == "FROM_ACTORS") { - bqtls = Channel.value(file("$params.BQTLS")) - trans_actors = Channel.fromPath("$params.TRANS_ACTORS", checkIfExists: true).collect() - extra_confounders = Channel.value(file("$params.EXTRA_CONFOUNDERS")) - extra_treatments = Channel.value(file("$params.ENVIRONMENTALS")) - extra_covariates = Channel.value(file("$params.EXTRA_COVARIATES")) - tmle_inputs = TMLEInputsFromActors( - bgen_files, - traits, - genetic_confounders, - extra_confounders, - extra_treatments, - extra_covariates, - bqtls, - trans_actors) - } - else if (params.STUDY_DESIGN == "CUSTOM"){ - estimands_file = Channel.value(file("$params.ESTIMANDS_FILE")) - tmle_inputs = TMLEInputsFromParamFile( - bgen_files, - traits, - genetic_confounders, - estimands_file) - } - else { - throw new Exception("This STUDY_DESIGN is not available.") - } - // compute TMLE estimates for continuous targets - TMLE( - tmle_inputs.traits, - tmle_inputs.estimands.flatten(), - estimator_file, - ) - - - emit: - TMLE.out -} - - -workflow generateSieveEstimates { - take: - tmle_files - iid_genotypes +workflow { + // Define Parameters + verbosity = params.VERBOSITY + + cohort = params.COHORT + ukb_encoding_file = params.UKB_ENCODING_FILE + ukb_config = Channel.value(file("$params.UKB_CONFIG")) + ukb_withdrawal_list = Channel.value(file("$params.UKB_WITHDRAWAL_LIST")) + traits_dataset = Channel.value(file("$params.TRAITS_DATASET")) + + maf_threshold = params.MAF_THRESHOLD + qc_file = Channel.value(file("$params.QC_FILE")) + flashpca_excl_reg = Channel.value(file("$params.FLASHPCA_EXCLUSION_REGIONS")) + ld_blocks = Channel.value(file("$params.LD_BLOCKS")) + bed_files = Channel.fromFilePairs("$params.BED_FILES", size: 3, checkIfExists: true){ file -> file.baseName } - main: - grm_parts = Channel.from( 1..params.GRM_NSPLITS ) - GRMPart(iid_genotypes.collect(), params.GRM_NSPLITS, grm_parts) - AggregateGRM(GRMPart.out.collect()) - // Sieve estimation - SieveVarianceEstimation(tmle_files.collect(), AggregateGRM.out.grm_ids, AggregateGRM.out.grm_matrix) - emit: - SieveVarianceEstimation.out -} - -workflow negativeControl { - results_file = Channel.value(file("${params.OUTDIR}/${params.HDF5_OUTPUT}")) - - // Permutation Tests - dataset = Channel.value(file("${params.OUTDIR}/${params.ARROW_OUTPUT}")) - estimator_file = Channel.value(file("${params.ESTIMATOR_FILE}")) - GeneratePermutationTestsData(dataset, results_file) - TMLE( - GeneratePermutationTestsData.output.dataset, - GeneratePermutationTestsData.output.estimands.flatten(), - estimator_file + estimator_config = Channel.value(file("${params.ESTIMATOR_FILE}")) + keep_ic = params.KEEP_IC + pval_threshold = params.PVAL_THRESHOLD + save_every = params.TMLE_SAVE_EVERY + hdf5_output = "${params.HDF5_OUTPUT}" + json_output = "${params.JSON_OUTPUT}" + + do_svp = params.SVP + n_svp_estimators = params.NB_SVP_ESTIMATORS + max_svp_threshold = params.MAX_SVP_THRESHOLD + svp_estimator_key = params.SVP_ESTIMATOR_KEY + grm_n_splits = params.GRM_NSPLITS + + // Extract Traits + ExtractTraits( + traits_dataset, + cohort, + ukb_config, + ukb_withdrawal_list, + ukb_encoding_file, ) - MergeOutputs(TMLE.out.collect(), params.PERMUTATION_HDF5_OUTPUT, params.PERMUTATION_JSON_OUTPUT) - // Random Variants parameter files generation - if (params.STUDY_DESIGN == "FROM_ACTORS") { - bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() - trans_actors = Channel.fromPath("$params.TRANS_ACTORS", checkIfExists: true).collect() - GenerateRandomVariantsTestsData(trans_actors, bgen_files, results_file) - } -} - -workflow { - // Extract traits for UKBB - extractTraits() - - // Generate IID Genotypes - generateIIDGenotypes(extractTraits.out) + // IID Genotypes + IIDGenotypes( + flashpca_excl_reg, + ld_blocks, + bed_files, + qc_file, + ExtractTraits.out, + maf_threshold + ) // Genetic confounders - geneticConfounders(generateIIDGenotypes.out) + GeneticConfounders(IIDGenotypes.out) + + // generate main dataset and estimand configuration files + EstimationInputs( + ExtractTraits.out, + GeneticConfounders.out + ) // generate estimates - generateTMLEEstimates( - extractTraits.out, - geneticConfounders.out, + EstimationWorkflow( + EstimationInputs.out.aggregated_dataset, + EstimationInputs.out.estimands.flatten(), + estimator_config, + keep_ic, + do_svp, + pval_threshold, + save_every, + hdf5_output, + json_output ) // Generate sieve estimates - if (params.SVP == true){ - sieve_results = generateSieveEstimates(generateTMLEEstimates.out, generateIIDGenotypes.out) + if (do_svp == true){ + sieve_results = SVPWorkflow( + EstimationWorkflow.out.hdf5_result, + IIDGenotypes.out, + n_svp_estimators, + max_svp_threshold, + svp_estimator_key, + grm_n_splits, + verbosity + ) } - - MergeOutputs(generateTMLEEstimates.out.collect(), params.HDF5_OUTPUT, params.JSON_OUTPUT) } diff --git a/modules/confounders.nf b/modules/confounders.nf index 685be94d..b1e13bcb 100644 --- a/modules/confounders.nf +++ b/modules/confounders.nf @@ -30,3 +30,15 @@ process AdaptFlashPCA { JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/prepare_confounders.jl --input $flashpca_out --output pcs.csv adapt """ } + +workflow GeneticConfounders { + take: + iid_genotypes + + main: + FlashPCA(iid_genotypes) + AdaptFlashPCA(FlashPCA.out) + + emit: + AdaptFlashPCA.out +} \ No newline at end of file diff --git a/modules/estimation.nf b/modules/estimation.nf new file mode 100644 index 00000000..4cd17ae6 --- /dev/null +++ b/modules/estimation.nf @@ -0,0 +1,100 @@ +#!/usr/bin/env nextflow +nextflow.enable.dsl = 2 + +process MergeOutputs { + container "olivierlabayle/targeted-estimation:cv_tmle" + publishDir "$params.OUTDIR", mode: 'symlink' + label "bigmem" + + input: + path tmle_files + val hdf5_output + val json_output + + output: + path "${hdf5_output}", emit: hdf5_file + path "${json_output}", optional: true, emit:json_file + + script: + json_option = json_output != "NO_JSON_OUTPUT" ? "--outputs.json.filename=${json_output}" : "" + """ + TEMPD=\$(mktemp -d) + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no /opt/bin/tmle make-summary \ + tmle_result \ + --outputs.hdf5.filename=${hdf5_output} \ + ${json_option} + """ +} + +process TMLE { + container "olivierlabayle/targeted-estimation:cv_tmle" + publishDir "$params.OUTDIR/tmle_outputs/", mode: 'symlink', pattern: "*.hdf5" + label "bigmem" + label "multithreaded" + + input: + path data + path estimands_file + path estimator_file + val keep_ic + val do_svp + val pval_threshold + val save_every + + output: + path "${hdf5out}" + + script: + basename = "tmle_result." + estimands_file.getName().take(estimands_file.getName().lastIndexOf('.')) + hdf5out = basename + ".hdf5" + pval_threshold = keep_ic == true ? "--outputs.hdf5.pval_threshold=${pval_threshold}" : "" + sample_ids = do_svp == true ? "--outputs.hdf5.sample_ids=true" : "" + """ + TEMPD=\$(mktemp -d) + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --threads=${task.cpus} --startup-file=no /opt/bin/tmle tmle \ + $data \ + --estimands=$estimands_file \ + --estimators=$estimator_file \ + --outputs.hdf5.filename=$hdf5out \ + $pval_threshold \ + $sample_ids \ + --chunksize=$save_every \ + """ +} + +workflow EstimationWorkflow { + take: + dataset + estimands_configs + estimators_config + keep_ic + do_svp + pval_threshold + save_every + hdf5_output + json_output + + main: + TMLE( + dataset, + estimands_configs, + estimators_config, + keep_ic, + do_svp, + pval_threshold, + save_every + ) + MergeOutputs(TMLE.out.collect(), hdf5_output, json_output) + + emit: + hdf5_result = MergeOutputs.out.hdf5_file +} + +// workflow { +// dataset = Channel.value(file("${params.AGGREGATED_DATASET}")) +// estimands_configs = Channel.value(file("${params.ESTIMAND_CONFIG_FILES}")) +// estimators_config = Channel.value(file("${params.ESTIMATOR_FILE}", checkIfExists: false)) +// hdf5_output = "${params.HDF5_OUTPUT}" +// json_output = "${params.JSON_OUTPUT}" +// EstimationWorkflow(dataset, estimands_configs, estimators_config, hdf5_output, json_output) +// } \ No newline at end of file diff --git a/modules/tmle.nf b/modules/estimation_inputs.nf similarity index 62% rename from modules/tmle.nf rename to modules/estimation_inputs.nf index 1d88c15d..c99d2e7b 100644 --- a/modules/tmle.nf +++ b/modules/estimation_inputs.nf @@ -1,52 +1,4 @@ -def longest_prefix(files){ - // Only one file, strangely it is not passed as a list - if (files instanceof Collection == false) { - return files.getName() - } - // More than one file - index = 0 - while(true){ - current_prefix = files[0].getName()[0..index] - for (file in files){ - if(file.getName()[0..index] != current_prefix){ - return current_prefix[0..-2] - } - } - index++ - } -} - -process TMLE { - container "olivierlabayle/targeted-estimation:cv_tmle" - publishDir "$params.OUTDIR/tmle_outputs/", mode: 'symlink', pattern: "*.hdf5" - label "bigmem" - label "multithreaded" - - input: - path data - path estimands_file - path estimator_file - - output: - path "${hdf5out}" - - script: - basename = "tmle_result." + estimands_file.getName().take(estimands_file.getName().lastIndexOf('.')) - hdf5out = basename + ".hdf5" - pval_threshold = params.KEEP_IC == true ? "--outputs.hdf5.pval_threshold=${params.PVAL_THRESHOLD}" : "" - sample_ids = params.SVP == true ? "--outputs.hdf5.sample_ids=true" : "" - """ - TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --threads=${task.cpus} --startup-file=no /opt/bin/tmle tmle \ - $data \ - --estimands=$estimands_file \ - --estimators=$estimator_file \ - --outputs.hdf5.filename=$hdf5out \ - $pval_threshold \ - $sample_ids \ - --chunksize=$params.TMLE_SAVE_EVERY \ - """ -} +include { longest_prefix } from './utils.nf' process TMLEInputsFromParamFile { container "olivierlabayle/tl-core:cvtmle" @@ -61,7 +13,7 @@ process TMLEInputsFromParamFile { path parameter output: - path "final.data.arrow", emit: traits + path "final.data.arrow", emit: dataset path "final.*.jls", emit: estimands script: @@ -97,7 +49,7 @@ process TMLEInputsFromActors { path trans_actors output: - path "final.data.arrow", emit: traits + path "final.data.arrow", emit: dataset path "final.*.jls", emit: estimands script: @@ -119,3 +71,44 @@ process TMLEInputsFromActors { from-actors $bqtls $trans_actors_prefix $extra_confounders $extra_treatments $extra_covariates --orders ${params.ORDERS} """ } + +workflow EstimationInputs { + take: + traits + genetic_confounders + + main: + bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() + + if (params.STUDY_DESIGN == "FROM_ACTORS") { + bqtls = Channel.value(file("$params.BQTLS")) + trans_actors = Channel.fromPath("$params.TRANS_ACTORS", checkIfExists: true).collect() + extra_confounders = Channel.value(file("$params.EXTRA_CONFOUNDERS")) + extra_treatments = Channel.value(file("$params.ENVIRONMENTALS")) + extra_covariates = Channel.value(file("$params.EXTRA_COVARIATES")) + tmle_inputs = TMLEInputsFromActors( + bgen_files, + traits, + genetic_confounders, + extra_confounders, + extra_treatments, + extra_covariates, + bqtls, + trans_actors) + } + else if (params.STUDY_DESIGN == "CUSTOM"){ + estimands_file = Channel.value(file("$params.ESTIMANDS_FILE")) + tmle_inputs = TMLEInputsFromParamFile( + bgen_files, + traits, + genetic_confounders, + estimands_file) + } + else { + throw new Exception("This STUDY_DESIGN is not available.") + } + + emit: + aggregated_dataset = tmle_inputs.dataset + estimands = tmle_inputs.estimands +} \ No newline at end of file diff --git a/modules/genotypes.nf b/modules/genotypes.nf index 266134ed..f226c3f2 100644 --- a/modules/genotypes.nf +++ b/modules/genotypes.nf @@ -8,19 +8,20 @@ process filterBED{ path qcfile path ld_blocks path traits + val maf_threshold output: path "filtered.*", emit: filtered_bedfiles script: prefix = bedfiles[0].toString().minus('.bed') - qc_file = params.QC_FILE !== 'NO_QC_FILE' ? "--qcfile $qcfile" : '' - ld_blocks = params.LD_BLOCKS !== 'NO_LD_BLOCKS' ? "--ld-blocks $ld_blocks" : '' - + qc_file = qcfile.getName() != 'NO_QC_FILE' ? "--qcfile $qcfile" : '' + ld_blocks = ld_blocks.getName() != 'NO_LD_BLOCKS' ? "--ld-blocks $ld_blocks" : '' + println(ld_blocks) """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/prepare_confounders.jl \ - --input $prefix --output filtered.$prefix $qc_file --maf-threshold $params.MAF_THRESHOLD \ + --input $prefix --output filtered.$prefix $qc_file --maf-threshold $maf_threshold \ $ld_blocks --traits $traits filter """ } @@ -61,7 +62,9 @@ process mergeBEDS{ script: """ TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/prepare_confounders.jl --input LDpruned. --output ukbb_merged merge + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/prepare_confounders.jl \ + --input LDpruned. \ + --output ukbb_merged merge """ } @@ -88,14 +91,15 @@ workflow IIDGenotypes{ ld_blocks bed_files qc_file - sample_ids + traits + maf_threshold main: - filtered_bedfiles = filterBED(bed_files, qc_file, ld_blocks, sample_ids) + filtered_bedfiles = filterBED(bed_files, qc_file, ld_blocks, traits, maf_threshold) ld_pruned = thinByLD(flashpca_excl_reg, filtered_bedfiles) mergeBEDS(ld_pruned.collect()) SampleQCFilter(mergeBEDS.out.collect()) emit: SampleQCFilter.out -} +} \ No newline at end of file diff --git a/modules/grm.nf b/modules/grm.nf deleted file mode 100644 index 148b7a11..00000000 --- a/modules/grm.nf +++ /dev/null @@ -1,34 +0,0 @@ -process GRMPart { - container "olivierlabayle/tl-core:0.6" - label "bigmem" - label "multithreaded" - - input: - path bedfiles - val nparts - val part_id - - output: - path "GRM*.grm.*" - - script: - base = bedfiles.first().getName().split("\\.")[0] - "gcta64 --bfile $base --make-grm-part $nparts $part_id --thread-num ${task.cpus} --out GRM" -} - -process AggregateGRM { - publishDir "$params.OUTDIR/GRM", mode: 'symlink' - - input: - path grm_files - - output: - path "GRM.id", emit: grm_ids - path "GRM.bin", emit: grm_matrix - - script: - """ - cat *.grm.id > GRM.id - cat *.grm.bin > GRM.bin - """ -} diff --git a/modules/negative_control.nf b/modules/negative_control.nf index c3aabfae..cb0afe81 100644 --- a/modules/negative_control.nf +++ b/modules/negative_control.nf @@ -1,20 +1,14 @@ -def longest_prefix(files){ - // Only one file, strangely it is not passed as a list - if (files instanceof Collection == false) { - return files.getName() - } - // More than one file - index = 0 - while(true){ - current_prefix = files[0].getName()[0..index] - for (file in files){ - if(file.getName()[0..index] != current_prefix){ - return current_prefix[0..-2] - } - } - index++ - } -} +params.PERMUTATION_HDF5_OUTPUT = "permutation_results.hdf5" +params.PERMUTATION_JSON_OUTPUT = "NO_JSON_OUTPUT" + +// Permutation Tests Parameters +params.MAX_PERMUTATION_TESTS = null +params.PERMUTATION_ORDERS = "1" +params.RNG = 123 +params.MAF_MATCHING_RELTOL = 0.05 +params.N_RANDOM_VARIANTS = 10 + +include { longest_prefix } from './utils.nf' process GeneratePermutationTestsData { container "olivierlabayle/negative-controls:cvtmle" @@ -72,4 +66,26 @@ process GenerateRandomVariantsTestsData { --rng=${params.RNG} \ --verbosity=${params.VERBOSITY} """ +} + +workflow NegativeControl { + results_file = Channel.value(file("${params.OUTDIR}/${params.HDF5_OUTPUT}")) + + // Permutation Tests + dataset = Channel.value(file("${params.OUTDIR}/${params.ARROW_OUTPUT}")) + estimator_file = Channel.value(file("${params.ESTIMATOR_FILE}")) + GeneratePermutationTestsData(dataset, results_file) + TMLE( + GeneratePermutationTestsData.output.dataset, + GeneratePermutationTestsData.output.estimands.flatten(), + estimator_file + ) + MergeOutputs(TMLE.out.collect(), params.PERMUTATION_HDF5_OUTPUT, params.PERMUTATION_JSON_OUTPUT) + + // Random Variants parameter files generation + if (params.STUDY_DESIGN == "FROM_ACTORS") { + bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() + trans_actors = Channel.fromPath("$params.TRANS_ACTORS", checkIfExists: true).collect() + GenerateRandomVariantsTestsData(trans_actors, bgen_files, results_file) + } } \ No newline at end of file diff --git a/modules/pca.nf b/modules/pca.nf new file mode 100644 index 00000000..09a2bcc7 --- /dev/null +++ b/modules/pca.nf @@ -0,0 +1,11 @@ +workflow PCA { + // Extract traits + extractTraits() + + // Generate IID Genotypes + IIDGenotypes(extractTraits.out) + + // Genetic confounders up to NB_PCS + geneticConfounders(IIDGenotypes.out) + +} \ No newline at end of file diff --git a/modules/sieve_variance.nf b/modules/sieve_variance.nf deleted file mode 100644 index 64f83a1f..00000000 --- a/modules/sieve_variance.nf +++ /dev/null @@ -1,48 +0,0 @@ -process SieveVarianceEstimation { - container "olivierlabayle/targeted-estimation:cv_tmle" - publishDir "$params.OUTDIR", mode: 'symlink' - - input: - path tmle_files - path GRM_ids - path GRM_matrix - - output: - path "svp.hdf5" - - script: - """ - TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no /opt/bin/tmle sieve-variance-plateau \ - tmle_result \ - --n-estimators=$params.NB_SVP_ESTIMATORS \ - --max-tau=$params.MAX_SVP_THRESHOLD \ - --estimator-key=$params.SVP_ESTIMATOR_KEY \ - --verbosity=$params.VERBOSITY - """ -} - -process MergeOutputs { - container "olivierlabayle/targeted-estimation:cv_tmle" - publishDir "$params.OUTDIR", mode: 'symlink' - label "bigmem" - - input: - path tmle_files - val hdf5_output - val json_output - - output: - path "${hdf5_output}" - path "${json_output}", optional: true - - script: - json_option = json_output !== "NO_JSON_OUTPUT" ? "--outputs.json.filename=${json_output}" : "" - """ - TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no /opt/bin/tmle make-summary \ - tmle_result \ - --outputs.hdf5.filename=${hdf5_output} \ - ${json_option} - """ -} \ No newline at end of file diff --git a/modules/svp.nf b/modules/svp.nf new file mode 100644 index 00000000..c4ee3174 --- /dev/null +++ b/modules/svp.nf @@ -0,0 +1,89 @@ +process GRMPart { + container "olivierlabayle/tl-core:0.6" + label "bigmem" + label "multithreaded" + + input: + path bedfiles + val nparts + val part_id + + output: + path "GRM*.grm.*" + + script: + base = bedfiles.first().getName().split("\\.")[0] + "gcta64 --bfile $base --make-grm-part $nparts $part_id --thread-num ${task.cpus} --out GRM" +} + +process AggregateGRM { + publishDir "$params.OUTDIR/GRM", mode: 'symlink' + + input: + path grm_files + + output: + path "GRM.id", emit: grm_ids + path "GRM.bin", emit: grm_matrix + + script: + """ + cat *.grm.id > GRM.id + cat *.grm.bin > GRM.bin + """ +} + +process SVP { + container "olivierlabayle/targeted-estimation:cv_tmle" + publishDir "$params.OUTDIR", mode: 'symlink' + + input: + path tmle_files + path GRM_ids + path GRM_matrix + val n_estimators + val max_tau + val estimator_key + val verbosity + + output: + path "svp.hdf5" + + script: + """ + TEMPD=\$(mktemp -d) + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no /opt/bin/tmle sieve-variance-plateau \ + tmle_result \ + --n-estimators=$n_estimators \ + --max-tau=$max_tau \ + --estimator-key=$estimator_key \ + --verbosity=$verbosity + """ +} + + +workflow SVPWorkflow { + take: + hdf5_result + iid_genotypes + n_svp_estimators + max_svp_threshold + svp_estimator_key + grm_n_splits + verbosity + + main: + grm_parts = Channel.from( 1..grm_n_splits ) + GRMPart(iid_genotypes.collect(), grm_n_splits, grm_parts) + AggregateGRM(GRMPart.out.collect()) + // Sieve estimation + SVP( + hdf5_result.collect(), + AggregateGRM.out.grm_ids, + AggregateGRM.out.grm_matrix, + n_svp_estimators, + max_svp_threshold, + svp_estimator_key, + verbosity + ) +} \ No newline at end of file diff --git a/modules/ukb_traits.nf b/modules/traits.nf similarity index 68% rename from modules/ukb_traits.nf rename to modules/traits.nf index aa6a2b23..67b5d753 100644 --- a/modules/ukb_traits.nf +++ b/modules/traits.nf @@ -53,3 +53,30 @@ process TraitsFromUKB { $dataset $traits_config $withdrawal_list """ } + +workflow ExtractTraits { + take: + traits_dataset + cohort + ukb_config + ukb_withdrawal_list + ukb_encoding_file + + main: + if (cohort == "UKBB") { + if (ukb_encoding_file != "NO_UKB_ENCODING_FILE") { + UKBFieldsList(ukb_config) + decrypted_dataset = UKBConv(UKBFieldsList.out, traits_dataset, ukb_encoding_file) + } + else { + decrypted_dataset = traits_dataset + } + extracted_traits = TraitsFromUKB(decrypted_dataset, ukb_config, ukb_withdrawal_list) + } + else { + extracted_traits = traits_dataset + } + + emit: + extracted_traits +} \ No newline at end of file diff --git a/modules/utils.nf b/modules/utils.nf new file mode 100644 index 00000000..6b9ff9e8 --- /dev/null +++ b/modules/utils.nf @@ -0,0 +1,17 @@ +def longest_prefix(files){ + // Only one file, strangely it is not passed as a list + if (files instanceof Collection == false) { + return files.getName() + } + // More than one file + index = 0 + while(true){ + current_prefix = files[0].getName()[0..index] + for (file in files){ + if(file.getName()[0..index] != current_prefix){ + return current_prefix[0..-2] + } + } + index++ + } +} \ No newline at end of file diff --git a/test/custom_from_actors.jl b/test/custom_from_actors.jl index 25934787..c0a386b9 100644 --- a/test/custom_from_actors.jl +++ b/test/custom_from_actors.jl @@ -44,7 +44,7 @@ include("utils.jl") check_fails_are_extremely_rare_traits(failed_results.TMLE, dataset; ncases=7) - # Here we test that the process generateIIDGenotypes has been run once for each chromosome + # Here we test that the process IIDGenotypes has been run once for each chromosome # There should be 4 files for each chromosome n_chr_files = filter(x -> startswith(x, "LDpruned.filtered.ukb_chr"), readdir(joinpath("results", "ld_pruned_chromosomes"))) @test length(n_chr_files) == 4*3 From fe2ba248496b60c1dfa17ca0e513238b8f8c228a Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Fri, 15 Dec 2023 14:39:15 +0000 Subject: [PATCH 19/65] more refactoring and add some assets --- data/NO_EXTRA_CONFOUNDER | 0 data/NO_EXTRA_COVARIATE | 0 data/NO_EXTRA_TREATMENT | 0 data/NO_LD_BLOCKS | 0 data/NO_QC_FILE | 0 data/NO_UKB_ENCODING_FILE | 0 data/NO_WITHDRAWAL_LIST | 0 data/ukbconfig.yaml | 17280 +++++++++++++++++++++++++++++++++ main.nf | 55 +- modules/estimation_inputs.nf | 55 +- modules/svp.nf | 5 +- test/custom_from_actors.jl | 2 +- 12 files changed, 17359 insertions(+), 38 deletions(-) create mode 100644 data/NO_EXTRA_CONFOUNDER create mode 100644 data/NO_EXTRA_COVARIATE create mode 100644 data/NO_EXTRA_TREATMENT create mode 100644 data/NO_LD_BLOCKS create mode 100644 data/NO_QC_FILE create mode 100644 data/NO_UKB_ENCODING_FILE create mode 100644 data/NO_WITHDRAWAL_LIST create mode 100644 data/ukbconfig.yaml diff --git a/data/NO_EXTRA_CONFOUNDER b/data/NO_EXTRA_CONFOUNDER new file mode 100644 index 00000000..e69de29b diff --git a/data/NO_EXTRA_COVARIATE b/data/NO_EXTRA_COVARIATE new file mode 100644 index 00000000..e69de29b diff --git a/data/NO_EXTRA_TREATMENT b/data/NO_EXTRA_TREATMENT new file mode 100644 index 00000000..e69de29b diff --git a/data/NO_LD_BLOCKS b/data/NO_LD_BLOCKS new file mode 100644 index 00000000..e69de29b diff --git a/data/NO_QC_FILE b/data/NO_QC_FILE new file mode 100644 index 00000000..e69de29b diff --git a/data/NO_UKB_ENCODING_FILE b/data/NO_UKB_ENCODING_FILE new file mode 100644 index 00000000..e69de29b diff --git a/data/NO_WITHDRAWAL_LIST b/data/NO_WITHDRAWAL_LIST new file mode 100644 index 00000000..e69de29b diff --git a/data/ukbconfig.yaml b/data/ukbconfig.yaml new file mode 100644 index 00000000..ac145b59 --- /dev/null +++ b/data/ukbconfig.yaml @@ -0,0 +1,17280 @@ +traits: + - fields: + - "41202" + - "41204" + phenotypes: + - name: "J40-J47 Chronic lower respiratory diseases" + codings: + - "J40" + - "J41" + - "J410" + - "J411" + - "J418" + - "J42" + - "J43" + - "J430" + - "J431" + - "J432" + - "J438" + - "J439" + - "J44" + - "J440" + - "J441" + - "J448" + - "J449" + - "J45" + - "J450" + - "J451" + - "J458" + - "J459" + - "J46" + - "J47" + - name: "G25 Other extrapyramidal and movement disorders" + codings: + - "G254" + - "G255" + - "G256" + - "G258" + - "G259" + - "G250" + - "G251" + - "G252" + - "G253" + - name: "G20 Parkinson's disease" + codings: + - "G20" + - name: "L72 Follicular cysts of skin and subcutaneous tissue" + codings: + - "L720" + - "L721" + - "L722" + - "L728" + - "L729" + - name: "J34 Other disorders of nose and nasal sinuses" + codings: + - "J341" + - "J342" + - "J343" + - "J348" + - "J340" + - name: "H15-H22 Disorders of sclera, cornea, iris and ciliary body" + codings: + - "H15" + - "H150" + - "H151" + - "H158" + - "H159" + - "H16" + - "H160" + - "H161" + - "H162" + - "H163" + - "H164" + - "H168" + - "H169" + - "H17" + - "H170" + - "H171" + - "H178" + - "H179" + - "H18" + - "H180" + - "H181" + - "H182" + - "H183" + - "H184" + - "H185" + - "H186" + - "H187" + - "H188" + - "H189" + - "H19" + - "H190" + - "H191" + - "H192" + - "H193" + - "H198" + - "H20" + - "H200" + - "H201" + - "H202" + - "H208" + - "H209" + - "H21" + - "H210" + - "H211" + - "H212" + - "H213" + - "H214" + - "H215" + - "H218" + - "H219" + - "H22" + - "H220" + - "H221" + - "H228" + - name: "O26 Maternal care for other conditions predominantly related to pregnancy" + codings: + - "O264" + - "O265" + - "O266" + - "O267" + - "O268" + - "O269" + - "O260" + - "O261" + - "O262" + - "O263" + - name: "O20 Haemorrhage in early pregnancy" + codings: + - "O200" + - "O208" + - "O209" + - name: "O94-O99 Other obstetric conditions, not elsewhere classified" + codings: + - "O94" + - "O95" + - "O96" + - "O960" + - "O961" + - "O969" + - "O97" + - "O970" + - "O971" + - "O979" + - "O98" + - "O980" + - "O981" + - "O982" + - "O983" + - "O984" + - "O985" + - "O986" + - "O987" + - "O988" + - "O989" + - "O99" + - "O990" + - "O991" + - "O992" + - "O993" + - "O994" + - "O995" + - "O996" + - "O997" + - "O998" + - name: "O20-O29 Other maternal disorders predominantly related to pregnancy" + codings: + - "O20" + - "O200" + - "O208" + - "O209" + - "O21" + - "O210" + - "O211" + - "O212" + - "O218" + - "O219" + - "O22" + - "O220" + - "O221" + - "O222" + - "O223" + - "O224" + - "O225" + - "O228" + - "O229" + - "O23" + - "O230" + - "O231" + - "O232" + - "O233" + - "O234" + - "O235" + - "O239" + - "O24" + - "O240" + - "O241" + - "O242" + - "O243" + - "O244" + - "O249" + - "O25" + - "O26" + - "O260" + - "O261" + - "O262" + - "O263" + - "O264" + - "O265" + - "O266" + - "O267" + - "O268" + - "O269" + - "O28" + - "O280" + - "O281" + - "O282" + - "O283" + - "O284" + - "O285" + - "O288" + - "O289" + - "O29" + - "O290" + - "O291" + - "O292" + - "O293" + - "O294" + - "O295" + - "O296" + - "O298" + - "O299" + - name: "A30-A49 Other bacterial diseases" + codings: + - "A418" + - "A419" + - "A42" + - "A420" + - "A421" + - "A422" + - "A427" + - "A428" + - "A429" + - "A43" + - "A430" + - "A431" + - "A438" + - "A439" + - "A44" + - "A440" + - "A441" + - "A448" + - "A449" + - "A46" + - "A48" + - "A480" + - "A481" + - "A482" + - "A483" + - "A484" + - "A488" + - "A49" + - "A490" + - "A491" + - "A492" + - "A493" + - "A498" + - "A499" + - "A30" + - "A300" + - "A301" + - "A302" + - "A303" + - "A304" + - "A305" + - "A308" + - "A309" + - "A31" + - "A310" + - "A311" + - "A318" + - "A319" + - "A32" + - "A320" + - "A321" + - "A327" + - "A328" + - "A329" + - "A33" + - "A34" + - "A35" + - "A36" + - "A360" + - "A361" + - "A362" + - "A363" + - "A368" + - "A369" + - "A37" + - "A370" + - "A371" + - "A378" + - "A379" + - "A38" + - "A39" + - "A390" + - "A391" + - "A392" + - "A393" + - "A394" + - "A395" + - "A398" + - "A399" + - "A40" + - "A400" + - "A401" + - "A402" + - "A403" + - "A408" + - "A409" + - "A41" + - "A410" + - "A411" + - "A412" + - "A413" + - "A414" + - "A415" + - name: "K44 Diaphragmatic hernia" + codings: + - "K440" + - "K441" + - "K449" + - name: "K40 Inguinal hernia" + codings: + - "K400" + - "K401" + - "K402" + - "K403" + - "K404" + - "K409" + - name: "K41 Femoral hernia" + codings: + - "K410" + - "K411" + - "K412" + - "K413" + - "K414" + - "K419" + - name: "K42 Umbilical hernia" + codings: + - "K420" + - "K421" + - "K429" + - name: "K43 Ventral hernia" + codings: + - "K437" + - "K439" + - "K430" + - "K431" + - "K432" + - "K433" + - "K434" + - "K435" + - "K436" + - name: "G51 Facial nerve disorders" + codings: + - "G510" + - "G511" + - "G512" + - "G513" + - "G514" + - "G518" + - "G519" + - name: "G57 Mononeuropathies of lower limb" + codings: + - "G570" + - "G571" + - "G572" + - "G573" + - "G574" + - "G575" + - "G576" + - "G578" + - "G579" + - name: "G56 Mononeuropathies of upper limb" + codings: + - "G560" + - "G561" + - "G562" + - "G563" + - "G564" + - "G568" + - "G569" + - name: "G55 Nerve root and plexus compressions in diseases classified elsewhere" + codings: + - "G550" + - "G551" + - "G552" + - "G553" + - "G558" + - name: "E66 Obesity" + codings: + - "E660" + - "E661" + - "E662" + - "E668" + - "E669" + - name: "M05-M14 Inflammatory polyarthropathies" + codings: + - "M0750" + - "M0751" + - "M0752" + - "M0753" + - "M0754" + - "M0755" + - "M0756" + - "M0757" + - "M0758" + - "M0759" + - "M076" + - "M0760" + - "M0761" + - "M0762" + - "M0763" + - "M0764" + - "M0765" + - "M0766" + - "M0767" + - "M0768" + - "M0769" + - "M08" + - "M080" + - "M0800" + - "M0801" + - "M0802" + - "M0803" + - "M0804" + - "M0805" + - "M0806" + - "M0807" + - "M0808" + - "M0809" + - "M081" + - "M0810" + - "M0811" + - "M0812" + - "M0813" + - "M0814" + - "M0815" + - "M0816" + - "M0817" + - "M0818" + - "M0819" + - "M082" + - "M0820" + - "M0821" + - "M0822" + - "M0823" + - "M0824" + - "M0825" + - "M0826" + - "M0827" + - "M0828" + - "M0829" + - "M083" + - "M0830" + - "M0831" + - "M0832" + - "M0833" + - "M0834" + - "M0835" + - "M0836" + - "M0837" + - "M0838" + - "M0839" + - "M084" + - "M0840" + - "M0841" + - "M0842" + - "M0843" + - "M0844" + - "M0845" + - "M0846" + - "M0847" + - "M0848" + - "M0849" + - "M088" + - "M0880" + - "M0881" + - "M0882" + - "M0883" + - "M0884" + - "M0885" + - "M0886" + - "M0887" + - "M0888" + - "M0889" + - "M089" + - "M0890" + - "M0891" + - "M0892" + - "M0893" + - "M0894" + - "M0895" + - "M0896" + - "M0897" + - "M0898" + - "M0899" + - "M09" + - "M090" + - "M0900" + - "M0901" + - "M0902" + - "M0903" + - "M0904" + - "M0905" + - "M0906" + - "M0907" + - "M0908" + - "M0909" + - "M091" + - "M0910" + - "M0911" + - "M0912" + - "M0913" + - "M0914" + - "M0915" + - "M0916" + - "M0917" + - "M0918" + - "M0919" + - "M092" + - "M0920" + - "M0921" + - "M0922" + - "M0923" + - "M0924" + - "M0925" + - "M0926" + - "M0927" + - "M0928" + - "M0929" + - "M098" + - "M0980" + - "M0981" + - "M0982" + - "M0983" + - "M0984" + - "M0985" + - "M0986" + - "M0987" + - "M0988" + - "M0989" + - "M10" + - "M100" + - "M1000" + - "M1001" + - "M1002" + - "M1003" + - "M1004" + - "M1005" + - "M1006" + - "M1007" + - "M1008" + - "M1009" + - "M101" + - "M1010" + - "M1011" + - "M1012" + - "M1013" + - "M1014" + - "M1015" + - "M1016" + - "M1017" + - "M1018" + - "M1019" + - "M102" + - "M1020" + - "M1021" + - "M1022" + - "M1023" + - "M1024" + - "M1025" + - "M1026" + - "M1027" + - "M1028" + - "M1029" + - "M103" + - "M1030" + - "M1031" + - "M1032" + - "M1033" + - "M1034" + - "M1035" + - "M1036" + - "M1037" + - "M1038" + - "M1039" + - "M104" + - "M1040" + - "M1041" + - "M1042" + - "M1043" + - "M1044" + - "M1045" + - "M1046" + - "M1047" + - "M1048" + - "M1049" + - "M109" + - "M1090" + - "M1091" + - "M1092" + - "M1093" + - "M1094" + - "M1095" + - "M1096" + - "M1097" + - "M1098" + - "M1099" + - "M11" + - "M110" + - "M1100" + - "M1101" + - "M1102" + - "M1103" + - "M1104" + - "M1105" + - "M1106" + - "M1107" + - "M1108" + - "M1109" + - "M111" + - "M1110" + - "M1111" + - "M1112" + - "M1113" + - "M1114" + - "M1115" + - "M1116" + - "M1117" + - "M1118" + - "M1119" + - "M112" + - "M1120" + - "M1121" + - "M1122" + - "M1123" + - "M1124" + - "M1125" + - "M1126" + - "M1127" + - "M1128" + - "M1129" + - "M118" + - "M1180" + - "M1181" + - "M1182" + - "M1183" + - "M1184" + - "M1185" + - "M1186" + - "M1187" + - "M1188" + - "M1189" + - "M119" + - "M1190" + - "M1191" + - "M1192" + - "M1193" + - "M1194" + - "M1195" + - "M1196" + - "M1197" + - "M1198" + - "M1199" + - "M12" + - "M120" + - "M1200" + - "M1201" + - "M1202" + - "M1203" + - "M1204" + - "M1205" + - "M1206" + - "M1207" + - "M1208" + - "M1209" + - "M121" + - "M1210" + - "M1211" + - "M1212" + - "M1213" + - "M1214" + - "M1215" + - "M1216" + - "M1217" + - "M1218" + - "M1219" + - "M122" + - "M1220" + - "M1221" + - "M1222" + - "M1223" + - "M1224" + - "M1225" + - "M1226" + - "M1227" + - "M1228" + - "M1229" + - "M123" + - "M1230" + - "M1231" + - "M1232" + - "M1233" + - "M1234" + - "M1235" + - "M1236" + - "M1237" + - "M1238" + - "M1239" + - "M124" + - "M1240" + - "M1241" + - "M1242" + - "M1243" + - "M1244" + - "M1245" + - "M1246" + - "M1247" + - "M1248" + - "M1249" + - "M125" + - "M1250" + - "M1251" + - "M1252" + - "M1253" + - "M1254" + - "M1255" + - "M1256" + - "M1257" + - "M1258" + - "M1259" + - "M128" + - "M1280" + - "M1281" + - "M1282" + - "M1283" + - "M1284" + - "M1285" + - "M1286" + - "M1287" + - "M1288" + - "M1289" + - "M13" + - "M130" + - "M1300" + - "M1301" + - "M1302" + - "M1303" + - "M1304" + - "M1305" + - "M1306" + - "M1307" + - "M1308" + - "M1309" + - "M131" + - "M1310" + - "M1311" + - "M1312" + - "M1313" + - "M1314" + - "M1315" + - "M1316" + - "M1317" + - "M1318" + - "M1319" + - "M138" + - "M1380" + - "M1381" + - "M1382" + - "M1383" + - "M1384" + - "M1385" + - "M1386" + - "M1387" + - "M1388" + - "M1389" + - "M139" + - "M1390" + - "M1391" + - "M1392" + - "M1393" + - "M1394" + - "M1395" + - "M1396" + - "M1397" + - "M1398" + - "M1399" + - "M14" + - "M140" + - "M141" + - "M142" + - "M143" + - "M144" + - "M145" + - "M146" + - "M148" + - "M05" + - "M050" + - "M0500" + - "M0501" + - "M0502" + - "M0503" + - "M0504" + - "M0505" + - "M0506" + - "M0507" + - "M0508" + - "M0509" + - "M051" + - "M0510" + - "M0511" + - "M0512" + - "M0513" + - "M0514" + - "M0515" + - "M0516" + - "M0517" + - "M0518" + - "M0519" + - "M052" + - "M0520" + - "M0521" + - "M0522" + - "M0523" + - "M0524" + - "M0525" + - "M0526" + - "M0527" + - "M0528" + - "M0529" + - "M053" + - "M0530" + - "M0531" + - "M0532" + - "M0533" + - "M0534" + - "M0535" + - "M0536" + - "M0537" + - "M0538" + - "M0539" + - "M058" + - "M0580" + - "M0581" + - "M0582" + - "M0583" + - "M0584" + - "M0585" + - "M0586" + - "M0587" + - "M0588" + - "M0589" + - "M059" + - "M0590" + - "M0591" + - "M0592" + - "M0593" + - "M0594" + - "M0595" + - "M0596" + - "M0597" + - "M0598" + - "M0599" + - "M06" + - "M060" + - "M0600" + - "M0601" + - "M0602" + - "M0603" + - "M0604" + - "M0605" + - "M0606" + - "M0607" + - "M0608" + - "M0609" + - "M061" + - "M0610" + - "M0611" + - "M0612" + - "M0613" + - "M0614" + - "M0615" + - "M0616" + - "M0617" + - "M0618" + - "M0619" + - "M062" + - "M0620" + - "M0621" + - "M0622" + - "M0623" + - "M0624" + - "M0625" + - "M0626" + - "M0627" + - "M0628" + - "M0629" + - "M063" + - "M0630" + - "M0631" + - "M0632" + - "M0633" + - "M0634" + - "M0635" + - "M0636" + - "M0637" + - "M0638" + - "M0639" + - "M064" + - "M0640" + - "M0641" + - "M0642" + - "M0643" + - "M0644" + - "M0645" + - "M0646" + - "M0647" + - "M0648" + - "M0649" + - "M068" + - "M0680" + - "M0681" + - "M0682" + - "M0683" + - "M0684" + - "M0685" + - "M0686" + - "M0687" + - "M0688" + - "M0689" + - "M069" + - "M0690" + - "M0691" + - "M0692" + - "M0693" + - "M0694" + - "M0695" + - "M0696" + - "M0697" + - "M0698" + - "M0699" + - "M07" + - "M070" + - "M0700" + - "M0701" + - "M0702" + - "M0703" + - "M0704" + - "M0705" + - "M0706" + - "M0707" + - "M0708" + - "M0709" + - "M071" + - "M0710" + - "M0711" + - "M0712" + - "M0713" + - "M0714" + - "M0715" + - "M0716" + - "M0717" + - "M0718" + - "M0719" + - "M072" + - "M0720" + - "M0721" + - "M0722" + - "M0723" + - "M0724" + - "M0725" + - "M0726" + - "M0727" + - "M0728" + - "M0729" + - "M073" + - "M0730" + - "M0731" + - "M0732" + - "M0733" + - "M0734" + - "M0735" + - "M0736" + - "M0737" + - "M0738" + - "M0739" + - "M074" + - "M0740" + - "M0741" + - "M0742" + - "M0743" + - "M0744" + - "M0745" + - "M0746" + - "M0747" + - "M0748" + - "M0749" + - "M075" + - name: "G40-G47 Episodic and paroxysmal disorders" + codings: + - "G444" + - "G448" + - "G45" + - "G450" + - "G451" + - "G452" + - "G453" + - "G454" + - "G458" + - "G459" + - "G46" + - "G460" + - "G461" + - "G462" + - "G463" + - "G464" + - "G465" + - "G466" + - "G467" + - "G468" + - "G47" + - "G470" + - "G471" + - "G472" + - "G473" + - "G474" + - "G478" + - "G479" + - "G40" + - "G400" + - "G401" + - "G402" + - "G403" + - "G404" + - "G405" + - "G406" + - "G407" + - "G408" + - "G409" + - "G41" + - "G410" + - "G411" + - "G412" + - "G418" + - "G419" + - "G43" + - "G430" + - "G431" + - "G432" + - "G433" + - "G438" + - "G439" + - "G44" + - "G440" + - "G441" + - "G442" + - "G443" + - name: "G00-G09 Inflammatory diseases of the central nervous system" + codings: + - "G05" + - "G050" + - "G051" + - "G052" + - "G058" + - "G06" + - "G060" + - "G061" + - "G062" + - "G07" + - "G08" + - "G09" + - "G00" + - "G000" + - "G001" + - "G002" + - "G003" + - "G008" + - "G009" + - "G01" + - "G02" + - "G020" + - "G021" + - "G028" + - "G03" + - "G030" + - "G031" + - "G032" + - "G038" + - "G039" + - "G04" + - "G040" + - "G041" + - "G042" + - "G048" + - "G049" + - name: "J22 Unspecified acute lower respiratory infection" + codings: + - "J22" + - name: "O10-O16 Oedema, proteinuria and hypertensive disorders in pregnancy, childbirth and the puerperium" + codings: + - "O10" + - "O100" + - "O101" + - "O102" + - "O103" + - "O104" + - "O109" + - "O11" + - "O12" + - "O120" + - "O121" + - "O122" + - "O13" + - "O14" + - "O140" + - "O141" + - "O142" + - "O149" + - "O15" + - "O150" + - "O151" + - "O152" + - "O159" + - "O16" + - name: "D73 Diseases of spleen" + codings: + - "D730" + - "D731" + - "D732" + - "D733" + - "D734" + - "D735" + - "D738" + - "D739" + - name: "D70 Agranulocytosis" + codings: + - "D70" + - name: "B25-B34 Other viral diseases" + codings: + - "B25" + - "B250" + - "B251" + - "B252" + - "B258" + - "B259" + - "B26" + - "B260" + - "B261" + - "B262" + - "B263" + - "B268" + - "B269" + - "B27" + - "B270" + - "B271" + - "B278" + - "B279" + - "B30" + - "B300" + - "B301" + - "B302" + - "B303" + - "B308" + - "B309" + - "B33" + - "B330" + - "B331" + - "B332" + - "B333" + - "B334" + - "B338" + - "B34" + - "B340" + - "B341" + - "B342" + - "B343" + - "B344" + - "B348" + - "B349" + - name: "D75 Other diseases of blood and blood-forming organs" + codings: + - "D751" + - "D752" + - "D758" + - "D759" + - "D750" + - name: "N92 Excessive, frequent and irregular menstruation" + codings: + - "N926" + - "N920" + - "N921" + - "N922" + - "N923" + - "N924" + - "N925" + - name: "N93 Other abnormal uterine and vaginal bleeding" + codings: + - "N930" + - "N938" + - "N939" + - name: "N90 Other noninflammatory disorders of vulva and perineum" + codings: + - "N900" + - "N901" + - "N902" + - "N903" + - "N904" + - "N905" + - "N906" + - "N907" + - "N908" + - "N909" + - name: "N97 Female infertility" + codings: + - "N970" + - "N971" + - "N972" + - "N973" + - "N974" + - "N978" + - "N979" + - name: "N94 Pain and other conditions associated with female genital organs and menstrual cycle" + codings: + - "N940" + - "N941" + - "N942" + - "N943" + - "N944" + - "N945" + - "N946" + - "N948" + - "N949" + - name: "N95 Menopausal and other perimenopausal disorders" + codings: + - "N950" + - "N951" + - "N952" + - "N953" + - "N958" + - "N959" + - name: "F05 Delirium, not induced by alcohol and other psychoactive substances" + codings: + - "F050" + - "F051" + - "F058" + - "F059" + - name: "D51 Vitamin B12 deficiency anaemia" + codings: + - "D518" + - "D519" + - "D510" + - "D511" + - "D512" + - "D513" + - name: "L20-L30 Dermatitis and eczema" + codings: + - "L249" + - "L25" + - "L250" + - "L251" + - "L252" + - "L253" + - "L254" + - "L255" + - "L258" + - "L259" + - "L26" + - "L27" + - "L270" + - "L271" + - "L272" + - "L278" + - "L279" + - "L28" + - "L280" + - "L281" + - "L282" + - "L29" + - "L290" + - "L291" + - "L292" + - "L293" + - "L298" + - "L299" + - "L30" + - "L300" + - "L301" + - "L302" + - "L303" + - "L304" + - "L305" + - "L308" + - "L309" + - "L20" + - "L200" + - "L208" + - "L209" + - "L21" + - "L210" + - "L211" + - "L218" + - "L219" + - "L22" + - "L23" + - "L230" + - "L231" + - "L232" + - "L233" + - "L234" + - "L235" + - "L236" + - "L237" + - "L238" + - "L239" + - "L24" + - "L240" + - "L241" + - "L242" + - "L243" + - "L244" + - "L245" + - "L246" + - "L247" + - "L248" + - name: "M70-M79 Other soft tissue disorders" + codings: + - "M70" + - "M700" + - "M7000" + - "M7001" + - "M7002" + - "M7003" + - "M7004" + - "M7005" + - "M7006" + - "M7007" + - "M7008" + - "M7009" + - "M701" + - "M7010" + - "M7011" + - "M7012" + - "M7013" + - "M7014" + - "M7015" + - "M7016" + - "M7017" + - "M7018" + - "M7019" + - "M702" + - "M7020" + - "M7021" + - "M7022" + - "M7023" + - "M7024" + - "M7025" + - "M7026" + - "M7027" + - "M7028" + - "M7029" + - "M703" + - "M7030" + - "M7031" + - "M7032" + - "M7033" + - "M7034" + - "M7035" + - "M7036" + - "M7037" + - "M7038" + - "M7039" + - "M704" + - "M7040" + - "M7041" + - "M7042" + - "M7043" + - "M7044" + - "M7045" + - "M7046" + - "M7047" + - "M7048" + - "M7049" + - "M705" + - "M7050" + - "M7051" + - "M7052" + - "M7053" + - "M7054" + - "M7055" + - "M7056" + - "M7057" + - "M7058" + - "M7059" + - "M706" + - "M7060" + - "M7061" + - "M7062" + - "M7063" + - "M7064" + - "M7065" + - "M7066" + - "M7067" + - "M7068" + - "M7069" + - "M707" + - "M7070" + - "M7071" + - "M7072" + - "M7073" + - "M7074" + - "M7075" + - "M7076" + - "M7077" + - "M7078" + - "M7079" + - "M708" + - "M7080" + - "M7081" + - "M7082" + - "M7083" + - "M7084" + - "M7085" + - "M7086" + - "M7087" + - "M7088" + - "M7089" + - "M709" + - "M7090" + - "M7091" + - "M7092" + - "M7093" + - "M7094" + - "M7095" + - "M7096" + - "M7097" + - "M7098" + - "M7099" + - "M71" + - "M710" + - "M7100" + - "M7101" + - "M7102" + - "M7103" + - "M7104" + - "M7105" + - "M7106" + - "M7107" + - "M7108" + - "M7109" + - "M711" + - "M7110" + - "M7111" + - "M7112" + - "M7113" + - "M7114" + - "M7115" + - "M7116" + - "M7117" + - "M7118" + - "M7119" + - "M712" + - "M7120" + - "M7121" + - "M7122" + - "M7123" + - "M7124" + - "M7125" + - "M7126" + - "M7127" + - "M7128" + - "M7129" + - "M713" + - "M7130" + - "M7131" + - "M7132" + - "M7133" + - "M7134" + - "M7135" + - "M7136" + - "M7137" + - "M7138" + - "M7139" + - "M714" + - "M7140" + - "M7141" + - "M7142" + - "M7143" + - "M7144" + - "M7145" + - "M7146" + - "M7147" + - "M7148" + - "M7149" + - "M715" + - "M7150" + - "M7151" + - "M7152" + - "M7153" + - "M7154" + - "M7155" + - "M7156" + - "M7157" + - "M7158" + - "M7159" + - "M718" + - "M7180" + - "M7181" + - "M7182" + - "M7183" + - "M7184" + - "M7185" + - "M7186" + - "M7187" + - "M7188" + - "M7189" + - "M719" + - "M7190" + - "M7191" + - "M7192" + - "M7193" + - "M7194" + - "M7195" + - "M7196" + - "M7197" + - "M7198" + - "M7199" + - "M72" + - "M720" + - "M7200" + - "M7201" + - "M7202" + - "M7203" + - "M7204" + - "M7205" + - "M7206" + - "M7207" + - "M7208" + - "M7209" + - "M721" + - "M7210" + - "M7211" + - "M7212" + - "M7213" + - "M7214" + - "M7215" + - "M7216" + - "M7217" + - "M7218" + - "M7219" + - "M722" + - "M7220" + - "M7221" + - "M7222" + - "M7223" + - "M7224" + - "M7225" + - "M7226" + - "M7227" + - "M7228" + - "M7229" + - "M723" + - "M7230" + - "M7231" + - "M7232" + - "M7233" + - "M7234" + - "M7235" + - "M7236" + - "M7237" + - "M7238" + - "M7239" + - "M724" + - "M7240" + - "M7241" + - "M7242" + - "M7243" + - "M7244" + - "M7245" + - "M7246" + - "M7247" + - "M7248" + - "M7249" + - "M725" + - "M7250" + - "M7251" + - "M7252" + - "M7253" + - "M7254" + - "M7255" + - "M7256" + - "M7257" + - "M7258" + - "M7259" + - "M726" + - "M7260" + - "M7261" + - "M7262" + - "M7263" + - "M7264" + - "M7265" + - "M7266" + - "M7267" + - "M7268" + - "M7269" + - "M728" + - "M7280" + - "M7281" + - "M7282" + - "M7283" + - "M7284" + - "M7285" + - "M7286" + - "M7287" + - "M7288" + - "M7289" + - "M729" + - "M7290" + - "M7291" + - "M7292" + - "M7293" + - "M7294" + - "M7295" + - "M7296" + - "M7297" + - "M7298" + - "M7299" + - "M73" + - "M730" + - "M7300" + - "M7301" + - "M7302" + - "M7303" + - "M7304" + - "M7305" + - "M7306" + - "M7307" + - "M7308" + - "M7309" + - "M731" + - "M7310" + - "M7311" + - "M7312" + - "M7313" + - "M7314" + - "M7315" + - "M7316" + - "M7317" + - "M7318" + - "M7319" + - "M738" + - "M7380" + - "M7381" + - "M7382" + - "M7383" + - "M7384" + - "M7385" + - "M7386" + - "M7387" + - "M7388" + - "M7389" + - "M75" + - "M750" + - "M751" + - "M752" + - "M753" + - "M754" + - "M755" + - "M758" + - "M7581" + - "M759" + - "M76" + - "M760" + - "M7600" + - "M7601" + - "M7602" + - "M7603" + - "M7604" + - "M7605" + - "M7606" + - "M7607" + - "M7608" + - "M7609" + - "M761" + - "M7610" + - "M7611" + - "M7612" + - "M7613" + - "M7614" + - "M7615" + - "M7616" + - "M7617" + - "M7618" + - "M7619" + - "M762" + - "M7620" + - "M7621" + - "M7622" + - "M7623" + - "M7624" + - "M7625" + - "M7626" + - "M7627" + - "M7628" + - "M7629" + - "M763" + - "M7630" + - "M7631" + - "M7632" + - "M7633" + - "M7634" + - "M7635" + - "M7636" + - "M7637" + - "M7638" + - "M7639" + - "M764" + - "M7640" + - "M7641" + - "M7642" + - "M7643" + - "M7644" + - "M7645" + - "M7646" + - "M7647" + - "M7648" + - "M7649" + - "M765" + - "M7650" + - "M7651" + - "M7652" + - "M7653" + - "M7654" + - "M7655" + - "M7656" + - "M7657" + - "M7658" + - "M7659" + - "M766" + - "M7660" + - "M7661" + - "M7662" + - "M7663" + - "M7664" + - "M7665" + - "M7666" + - "M7667" + - "M7668" + - "M7669" + - "M767" + - "M7670" + - "M7671" + - "M7672" + - "M7673" + - "M7674" + - "M7675" + - "M7676" + - "M7677" + - "M7678" + - "M7679" + - "M768" + - "M7680" + - "M7681" + - "M7682" + - "M7683" + - "M7684" + - "M7685" + - "M7686" + - "M7687" + - "M7688" + - "M7689" + - "M769" + - "M7690" + - "M7691" + - "M7692" + - "M7693" + - "M7694" + - "M7695" + - "M7696" + - "M7697" + - "M7698" + - "M7699" + - "M77" + - "M770" + - "M7700" + - "M7701" + - "M7702" + - "M7703" + - "M7704" + - "M7705" + - "M7706" + - "M7707" + - "M7708" + - "M7709" + - "M771" + - "M7710" + - "M7711" + - "M7712" + - "M7713" + - "M7714" + - "M7715" + - "M7716" + - "M7717" + - "M7718" + - "M7719" + - "M772" + - "M7720" + - "M7721" + - "M7722" + - "M7723" + - "M7724" + - "M7725" + - "M7726" + - "M7727" + - "M7728" + - "M7729" + - "M773" + - "M7730" + - "M7731" + - "M7732" + - "M7733" + - "M7734" + - "M7735" + - "M7736" + - "M7737" + - "M7738" + - "M7739" + - "M774" + - "M7740" + - "M7741" + - "M7742" + - "M7743" + - "M7744" + - "M7745" + - "M7746" + - "M7747" + - "M7748" + - "M7749" + - "M775" + - "M7750" + - "M7751" + - "M7752" + - "M7753" + - "M7754" + - "M7755" + - "M7756" + - "M7757" + - "M7758" + - "M7759" + - "M778" + - "M7780" + - "M7781" + - "M7782" + - "M7783" + - "M7784" + - "M7785" + - "M7786" + - "M7787" + - "M7788" + - "M7789" + - "M779" + - "M7790" + - "M7791" + - "M7792" + - "M7793" + - "M7794" + - "M7795" + - "M7796" + - "M7797" + - "M7798" + - "M7799" + - "M79" + - "M790" + - "M7900" + - "M7901" + - "M7902" + - "M7903" + - "M7904" + - "M7905" + - "M7906" + - "M7907" + - "M7908" + - "M7909" + - "M791" + - "M7910" + - "M7911" + - "M7912" + - "M7913" + - "M7914" + - "M7915" + - "M7916" + - "M7917" + - "M7918" + - "M7919" + - "M792" + - "M7920" + - "M7921" + - "M7922" + - "M7923" + - "M7924" + - "M7925" + - "M7926" + - "M7927" + - "M7928" + - "M7929" + - "M793" + - "M7930" + - "M7931" + - "M7932" + - "M7933" + - "M7934" + - "M7935" + - "M7936" + - "M7937" + - "M7938" + - "M7939" + - "M794" + - "M7940" + - "M7941" + - "M7942" + - "M7943" + - "M7944" + - "M7945" + - "M7946" + - "M7947" + - "M7948" + - "M7949" + - "M795" + - "M7950" + - "M7951" + - "M7952" + - "M7953" + - "M7954" + - "M7955" + - "M7956" + - "M7957" + - "M7958" + - "M7959" + - "M796" + - "M7960" + - "M7961" + - "M7962" + - "M7963" + - "M7964" + - "M7965" + - "M7966" + - "M7967" + - "M7968" + - "M7969" + - "M797" + - "M7970" + - "M7971" + - "M7972" + - "M7973" + - "M7974" + - "M7975" + - "M7976" + - "M7977" + - "M7978" + - "M7979" + - "M798" + - "M7980" + - "M7981" + - "M7982" + - "M7983" + - "M7984" + - "M7985" + - "M7986" + - "M7987" + - "M7988" + - "M7989" + - "M799" + - "M7990" + - "M7991" + - "M7992" + - "M7993" + - "M7994" + - "M7995" + - "M7996" + - "M7997" + - "M7998" + - "M7999" + - name: "I51 Complications and ill-defined descriptions of heart disease" + codings: + - "I514" + - "I515" + - "I516" + - "I517" + - "I518" + - "I519" + - "I510" + - "I511" + - "I512" + - "I513" + - name: "I50 Heart failure" + codings: + - "I500" + - "I501" + - "I509" + - name: "N03 Chronic nephritic syndrome" + codings: + - "N030" + - "N031" + - "N032" + - "N033" + - "N034" + - "N035" + - "N036" + - "N037" + - "N038" + - "N039" + - name: "N02 Recurrent and persistent haematuria" + codings: + - "N020" + - "N021" + - "N022" + - "N023" + - "N024" + - "N025" + - "N026" + - "N027" + - "N028" + - "N029" + - name: "H18 Other disorders of cornea" + codings: + - "H180" + - "H181" + - "H182" + - "H183" + - "H184" + - "H185" + - "H186" + - "H187" + - "H188" + - "H189" + - name: "M24 Other specific joint derangements" + codings: + - "M240" + - "M2400" + - "M2401" + - "M2402" + - "M2403" + - "M2404" + - "M2405" + - "M2406" + - "M2407" + - "M2408" + - "M2409" + - "M241" + - "M2410" + - "M2411" + - "M2412" + - "M2413" + - "M2414" + - "M2415" + - "M2416" + - "M2417" + - "M2418" + - "M2419" + - "M242" + - "M2420" + - "M2421" + - "M2422" + - "M2423" + - "M2424" + - "M2425" + - "M2426" + - "M2427" + - "M2428" + - "M2429" + - "M243" + - "M2430" + - "M2431" + - "M2432" + - "M2433" + - "M2434" + - "M2435" + - "M2436" + - "M2437" + - "M2438" + - "M2439" + - "M244" + - "M2440" + - "M2441" + - "M2442" + - "M2443" + - "M2444" + - "M2445" + - "M2446" + - "M2447" + - "M2448" + - "M2449" + - "M245" + - "M2450" + - "M2451" + - "M2452" + - "M2453" + - "M2454" + - "M2455" + - "M2456" + - "M2457" + - "M2458" + - "M2459" + - "M246" + - "M2460" + - "M2461" + - "M2462" + - "M2463" + - "M2464" + - "M2465" + - "M2466" + - "M2467" + - "M2468" + - "M2469" + - "M247" + - "M2470" + - "M2471" + - "M2472" + - "M2473" + - "M2474" + - "M2475" + - "M2476" + - "M2477" + - "M2478" + - "M2479" + - "M248" + - "M2480" + - "M2481" + - "M2482" + - "M2483" + - "M2484" + - "M2485" + - "M2486" + - "M2487" + - "M2488" + - "M2489" + - "M249" + - "M2490" + - "M2491" + - "M2492" + - "M2493" + - "M2494" + - "M2495" + - "M2496" + - "M2497" + - "M2498" + - "M2499" + - name: "H11 Other disorders of conjunctiva" + codings: + - "H110" + - "H111" + - "H112" + - "H113" + - "H114" + - "H118" + - "H119" + - name: "M20 Acquired deformities of fingers and toes" + codings: + - "M200" + - "M201" + - "M202" + - "M203" + - "M204" + - "M205" + - "M206" + - name: "M21 Other acquired deformities of limbs" + codings: + - "M2110" + - "M2111" + - "M2112" + - "M2113" + - "M2114" + - "M2115" + - "M2116" + - "M2117" + - "M2118" + - "M2119" + - "M212" + - "M2120" + - "M2121" + - "M2122" + - "M2123" + - "M2124" + - "M2125" + - "M2126" + - "M2127" + - "M2128" + - "M2129" + - "M213" + - "M2130" + - "M2131" + - "M2132" + - "M2133" + - "M2134" + - "M2135" + - "M2136" + - "M2137" + - "M2138" + - "M2139" + - "M214" + - "M2140" + - "M2141" + - "M2142" + - "M2143" + - "M2144" + - "M2145" + - "M2146" + - "M2147" + - "M2148" + - "M2149" + - "M215" + - "M2150" + - "M2151" + - "M2152" + - "M2153" + - "M2154" + - "M2155" + - "M2156" + - "M2157" + - "M2158" + - "M2159" + - "M216" + - "M2160" + - "M2161" + - "M2162" + - "M2163" + - "M2164" + - "M2165" + - "M2166" + - "M2167" + - "M2168" + - "M2169" + - "M217" + - "M2170" + - "M2171" + - "M2172" + - "M2173" + - "M2174" + - "M2175" + - "M2176" + - "M2177" + - "M2178" + - "M2179" + - "M218" + - "M2180" + - "M2181" + - "M2182" + - "M2183" + - "M2184" + - "M2185" + - "M2186" + - "M2187" + - "M2188" + - "M2189" + - "M219" + - "M2190" + - "M2191" + - "M2192" + - "M2193" + - "M2194" + - "M2195" + - "M2196" + - "M2197" + - "M2198" + - "M2199" + - "M210" + - "M2100" + - "M2101" + - "M2102" + - "M2103" + - "M2104" + - "M2105" + - "M2106" + - "M2107" + - "M2108" + - "M2109" + - "M211" + - name: "M22 Disorders of patella" + codings: + - "M220" + - "M221" + - "M2210" + - "M222" + - "M223" + - "M224" + - "M228" + - "M229" + - name: "M23 Internal derangement of knee" + codings: + - "M230" + - "M2300" + - "M2301" + - "M2302" + - "M2303" + - "M2304" + - "M2305" + - "M2306" + - "M2307" + - "M2309" + - "M231" + - "M2310" + - "M2311" + - "M2312" + - "M2313" + - "M2314" + - "M2315" + - "M2316" + - "M2317" + - "M2319" + - "M232" + - "M2320" + - "M2321" + - "M2322" + - "M2323" + - "M2324" + - "M2325" + - "M2326" + - "M2327" + - "M2329" + - "M233" + - "M2330" + - "M2331" + - "M2332" + - "M2333" + - "M2334" + - "M2335" + - "M2336" + - "M2337" + - "M2339" + - "M234" + - "M2340" + - "M2341" + - "M2342" + - "M2343" + - "M2344" + - "M2345" + - "M2346" + - "M2347" + - "M2349" + - "M235" + - "M2350" + - "M2351" + - "M2352" + - "M2353" + - "M2354" + - "M2355" + - "M2356" + - "M2357" + - "M2359" + - "M236" + - "M2360" + - "M2361" + - "M2362" + - "M2363" + - "M2364" + - "M2365" + - "M2366" + - "M2367" + - "M2369" + - "M238" + - "M2380" + - "M2381" + - "M2382" + - "M2383" + - "M2384" + - "M2385" + - "M2386" + - "M2387" + - "M2389" + - "M239" + - "M2390" + - "M2391" + - "M2392" + - "M2393" + - "M2394" + - "M2395" + - "M2396" + - "M2397" + - "M2399" + - name: "D65-D69 Coagulation defects, purpura and other haemorrhagic conditions" + codings: + - "D65" + - "D66" + - "D67" + - "D68" + - "D680" + - "D681" + - "D682" + - "D683" + - "D684" + - "D685" + - "D686" + - "D688" + - "D689" + - "D69" + - "D690" + - "D691" + - "D692" + - "D693" + - "D694" + - "D695" + - "D696" + - "D698" + - "D699" + - name: "D86 Sarcoidosis" + codings: + - "D860" + - "D861" + - "D862" + - "D863" + - "D868" + - "D869" + - name: "O60-O75 Complications of labour and delivery" + codings: + - "O60" + - "O600" + - "O601" + - "O602" + - "O603" + - "O61" + - "O610" + - "O611" + - "O618" + - "O619" + - "O62" + - "O620" + - "O621" + - "O622" + - "O623" + - "O624" + - "O628" + - "O629" + - "O63" + - "O630" + - "O631" + - "O632" + - "O639" + - "O64" + - "O640" + - "O641" + - "O642" + - "O643" + - "O644" + - "O645" + - "O648" + - "O649" + - "O65" + - "O650" + - "O651" + - "O652" + - "O653" + - "O654" + - "O655" + - "O658" + - "O659" + - "O66" + - "O660" + - "O661" + - "O662" + - "O663" + - "O664" + - "O665" + - "O668" + - "O669" + - "O67" + - "O670" + - "O678" + - "O679" + - "O68" + - "O680" + - "O681" + - "O682" + - "O683" + - "O688" + - "O689" + - "O69" + - "O690" + - "O691" + - "O692" + - "O693" + - "O694" + - "O695" + - "O698" + - "O699" + - "O70" + - "O700" + - "O701" + - "O702" + - "O703" + - "O709" + - "O71" + - "O710" + - "O711" + - "O712" + - "O713" + - "O714" + - "O715" + - "O716" + - "O717" + - "O718" + - "O719" + - "O72" + - "O720" + - "O721" + - "O722" + - "O723" + - "O73" + - "O730" + - "O731" + - "O74" + - "O740" + - "O741" + - "O742" + - "O743" + - "O744" + - "O745" + - "O746" + - "O747" + - "O748" + - "O749" + - "O75" + - "O750" + - "O751" + - "O752" + - "O753" + - "O754" + - "O755" + - "O756" + - "O757" + - "O758" + - "O759" + - name: "E50-E64 Other nutritional deficiencies" + codings: + - "E640" + - "E641" + - "E642" + - "E643" + - "E648" + - "E649" + - "E50" + - "E500" + - "E501" + - "E502" + - "E503" + - "E504" + - "E505" + - "E506" + - "E507" + - "E508" + - "E509" + - "E51" + - "E511" + - "E512" + - "E518" + - "E519" + - "E52" + - "E53" + - "E530" + - "E531" + - "E538" + - "E539" + - "E54" + - "E55" + - "E550" + - "E559" + - "E56" + - "E560" + - "E561" + - "E568" + - "E569" + - "E58" + - "E59" + - "E60" + - "E61" + - "E610" + - "E611" + - "E612" + - "E613" + - "E614" + - "E615" + - "E616" + - "E617" + - "E618" + - "E619" + - "E63" + - "E630" + - "E631" + - "E638" + - "E639" + - "E64" + - name: "J95-J99 Other diseases of the respiratory system" + codings: + - "J95" + - "J950" + - "J951" + - "J952" + - "J953" + - "J954" + - "J955" + - "J958" + - "J959" + - "J96" + - "J960" + - "J9600" + - "J9601" + - "J9609" + - "J961" + - "J9610" + - "J9611" + - "J9619" + - "J969" + - "J9690" + - "J9691" + - "J9699" + - "J98" + - "J980" + - "J981" + - "J982" + - "J983" + - "J984" + - "J985" + - "J986" + - "J988" + - "J989" + - "J99" + - "J990" + - "J991" + - "J998" + - name: "K90-K93 Other diseases of the digestive system" + codings: + - "K90" + - "K900" + - "K901" + - "K902" + - "K903" + - "K904" + - "K908" + - "K909" + - "K91" + - "K910" + - "K911" + - "K912" + - "K913" + - "K914" + - "K915" + - "K918" + - "K919" + - "K92" + - "K920" + - "K921" + - "K922" + - "K928" + - "K929" + - "K93" + - "K930" + - "K931" + - "K938" + - name: "E05 Thyrotoxicosis [hyperthyroidism]" + codings: + - "E050" + - "E051" + - "E052" + - "E053" + - "E054" + - "E055" + - "E058" + - "E059" + - name: "K35 Acute appendicitis" + codings: + - "K350" + - "K351" + - "K352" + - "K353" + - "K358" + - "K359" + - name: "B98 Other specified infectious agents as the cause of diseases classified to other chapters" + codings: + - "B980" + - "B981" + - name: "B96 Other bacterial agents as the cause of diseases classified to other chapters" + codings: + - "B960" + - "B961" + - "B962" + - "B963" + - "B964" + - "B965" + - "B966" + - "B967" + - "B968" + - name: "B97 Viral agents as the cause of diseases classified to other chapters" + codings: + - "B970" + - "B971" + - "B972" + - "B973" + - "B974" + - "B975" + - "B976" + - "B977" + - "B978" + - name: "B95 Streptococcus and staphylococcus as the cause of diseases classified to other chapters" + codings: + - "B950" + - "B951" + - "B952" + - "B953" + - "B954" + - "B955" + - "B956" + - "B957" + - "B958" + - name: "L00-L08 Infections of the skin and subcutaneous tissue" + codings: + - "L00" + - "L01" + - "L010" + - "L011" + - "L02" + - "L020" + - "L021" + - "L022" + - "L023" + - "L024" + - "L028" + - "L029" + - "L03" + - "L030" + - "L031" + - "L032" + - "L033" + - "L038" + - "L039" + - "L04" + - "L040" + - "L041" + - "L042" + - "L043" + - "L048" + - "L049" + - "L05" + - "L050" + - "L059" + - "L08" + - "L080" + - "L081" + - "L088" + - "L089" + - name: "K20-K31 Diseases of oesophagus, stomach and duodenum" + codings: + - "K20" + - "K21" + - "K210" + - "K219" + - "K22" + - "K220" + - "K221" + - "K222" + - "K223" + - "K224" + - "K225" + - "K226" + - "K227" + - "K228" + - "K229" + - "K23" + - "K230" + - "K231" + - "K238" + - "K25" + - "K250" + - "K251" + - "K252" + - "K253" + - "K254" + - "K255" + - "K256" + - "K257" + - "K259" + - "K26" + - "K260" + - "K261" + - "K262" + - "K263" + - "K264" + - "K265" + - "K266" + - "K267" + - "K269" + - "K27" + - "K270" + - "K271" + - "K272" + - "K273" + - "K274" + - "K275" + - "K276" + - "K277" + - "K279" + - "K28" + - "K280" + - "K281" + - "K282" + - "K283" + - "K284" + - "K285" + - "K286" + - "K287" + - "K289" + - "K29" + - "K290" + - "K291" + - "K292" + - "K293" + - "K294" + - "K295" + - "K296" + - "K297" + - "K298" + - "K299" + - "K30" + - "K31" + - "K310" + - "K311" + - "K312" + - "K313" + - "K314" + - "K315" + - "K316" + - "K317" + - "K318" + - "K319" + - name: "F10 Mental and behavioural disorders due to use of alcohol" + codings: + - "F100" + - "F101" + - "F102" + - "F103" + - "F104" + - "F105" + - "F106" + - "F107" + - "F108" + - "F109" + - name: "I69 Sequelae of cerebrovascular disease" + codings: + - "I690" + - "I691" + - "I692" + - "I693" + - "I694" + - "I698" + - name: "N30-N39 Other diseases of urinary system" + codings: + - "N33" + - "N330" + - "N338" + - "N34" + - "N340" + - "N341" + - "N342" + - "N343" + - "N35" + - "N350" + - "N351" + - "N358" + - "N359" + - "N36" + - "N360" + - "N361" + - "N362" + - "N363" + - "N368" + - "N369" + - "N37" + - "N370" + - "N378" + - "N39" + - "N390" + - "N391" + - "N392" + - "N393" + - "N394" + - "N398" + - "N399" + - "N30" + - "N300" + - "N301" + - "N302" + - "N303" + - "N304" + - "N308" + - "N309" + - "N31" + - "N310" + - "N311" + - "N312" + - "N318" + - "N319" + - "N32" + - "N320" + - "N321" + - "N322" + - "N323" + - "N324" + - "N328" + - "N329" + - name: "H25-H28 Disorders of lens" + codings: + - "H281" + - "H282" + - "H288" + - "H25" + - "H250" + - "H251" + - "H252" + - "H258" + - "H259" + - "H26" + - "H260" + - "H261" + - "H262" + - "H263" + - "H264" + - "H268" + - "H269" + - "H27" + - "H270" + - "H271" + - "H278" + - "H279" + - "H28" + - "H280" + - name: "I74 Arterial embolism and thrombosis" + codings: + - "I742" + - "I743" + - "I744" + - "I745" + - "I748" + - "I749" + - "I740" + - "I741" + - name: "I72 Other aneurysm" + codings: + - "I720" + - "I721" + - "I722" + - "I723" + - "I724" + - "I725" + - "I726" + - "I728" + - "I729" + - name: "L43 Lichen planus" + codings: + - "L430" + - "L431" + - "L432" + - "L433" + - "L438" + - "L439" + - name: "E27 Other disorders of adrenal gland" + codings: + - "E270" + - "E271" + - "E272" + - "E273" + - "E274" + - "E275" + - "E278" + - "E279" + - name: "A00-A09 Intestinal infectious diseases" + codings: + - "A00" + - "A000" + - "A001" + - "A009" + - "A01" + - "A010" + - "A011" + - "A012" + - "A013" + - "A014" + - "A02" + - "A020" + - "A021" + - "A022" + - "A028" + - "A029" + - "A03" + - "A030" + - "A031" + - "A032" + - "A033" + - "A038" + - "A039" + - "A04" + - "A040" + - "A041" + - "A042" + - "A043" + - "A044" + - "A045" + - "A046" + - "A047" + - "A048" + - "A049" + - "A05" + - "A050" + - "A051" + - "A052" + - "A053" + - "A054" + - "A058" + - "A059" + - "A06" + - "A060" + - "A061" + - "A062" + - "A063" + - "A064" + - "A065" + - "A066" + - "A067" + - "A068" + - "A069" + - "A07" + - "A070" + - "A071" + - "A072" + - "A073" + - "A078" + - "A079" + - "A08" + - "A080" + - "A081" + - "A082" + - "A083" + - "A084" + - "A085" + - "A09" + - "A090" + - "A099" + - name: "E21 Hyperparathyroidism and other disorders of parathyroid gland" + codings: + - "E210" + - "E211" + - "E212" + - "E213" + - "E214" + - "E215" + - name: "O80 Single spontaneous delivery" + codings: + - "O800" + - "O801" + - "O808" + - "O809" + - name: "O82 Single delivery by Caesarean section" + codings: + - "O828" + - "O829" + - "O820" + - "O821" + - "O822" + - name: "H49-H52 Disorders of ocular muscles, binocular movement, accommodation and refraction" + codings: + - "H527" + - "H49" + - "H490" + - "H491" + - "H492" + - "H493" + - "H494" + - "H498" + - "H499" + - "H50" + - "H500" + - "H501" + - "H502" + - "H503" + - "H504" + - "H505" + - "H506" + - "H508" + - "H509" + - "H51" + - "H510" + - "H511" + - "H512" + - "H518" + - "H519" + - "H52" + - "H520" + - "H521" + - "H522" + - "H523" + - "H524" + - "H525" + - "H526" + - name: "G20-G26 Extrapyramidal and movement disorders" + codings: + - "G20" + - "G21" + - "G210" + - "G211" + - "G212" + - "G213" + - "G214" + - "G218" + - "G219" + - "G22" + - "G23" + - "G230" + - "G231" + - "G232" + - "G233" + - "G238" + - "G239" + - "G24" + - "G240" + - "G241" + - "G242" + - "G243" + - "G244" + - "G245" + - "G248" + - "G249" + - "G25" + - "G250" + - "G251" + - "G252" + - "G253" + - "G254" + - "G255" + - "G256" + - "G258" + - "G259" + - "G26" + - name: "O16 Unspecified maternal hypertension" + codings: + - "O16" + - name: "M91-M94 Chondropathies" + codings: + - "M91" + - "M910" + - "M9100" + - "M9101" + - "M9102" + - "M9103" + - "M9104" + - "M9105" + - "M9106" + - "M9107" + - "M9108" + - "M9109" + - "M911" + - "M9110" + - "M9111" + - "M9112" + - "M9113" + - "M9114" + - "M9115" + - "M9116" + - "M9117" + - "M9118" + - "M9119" + - "M912" + - "M9120" + - "M9121" + - "M9122" + - "M9123" + - "M9124" + - "M9125" + - "M9126" + - "M9127" + - "M9128" + - "M9129" + - "M913" + - "M9130" + - "M9131" + - "M9132" + - "M9133" + - "M9134" + - "M9135" + - "M9136" + - "M9137" + - "M9138" + - "M9139" + - "M918" + - "M9180" + - "M9181" + - "M9182" + - "M9183" + - "M9184" + - "M9185" + - "M9186" + - "M9187" + - "M9188" + - "M9189" + - "M919" + - "M9190" + - "M9191" + - "M9192" + - "M9193" + - "M9194" + - "M9195" + - "M9196" + - "M9197" + - "M9198" + - "M9199" + - "M92" + - "M920" + - "M921" + - "M9210" + - "M922" + - "M923" + - "M924" + - "M925" + - "M9250" + - "M9251" + - "M926" + - "M927" + - "M928" + - "M929" + - "M93" + - "M930" + - "M931" + - "M932" + - "M9326" + - "M938" + - "M9386" + - "M939" + - "M94" + - "M940" + - "M9400" + - "M9401" + - "M9402" + - "M9403" + - "M9404" + - "M9405" + - "M9406" + - "M9407" + - "M9408" + - "M9409" + - "M941" + - "M9410" + - "M9411" + - "M9412" + - "M9413" + - "M9414" + - "M9415" + - "M9416" + - "M9417" + - "M9418" + - "M9419" + - "M942" + - "M9420" + - "M9421" + - "M9422" + - "M9423" + - "M9424" + - "M9425" + - "M9426" + - "M9427" + - "M9428" + - "M9429" + - "M943" + - "M9430" + - "M9431" + - "M9432" + - "M9433" + - "M9434" + - "M9435" + - "M9436" + - "M9437" + - "M9438" + - "M9439" + - "M948" + - "M9480" + - "M9481" + - "M9482" + - "M9483" + - "M9484" + - "M9485" + - "M9486" + - "M9487" + - "M9488" + - "M9489" + - "M949" + - "M9490" + - "M9491" + - "M9492" + - "M9493" + - "M9494" + - "M9495" + - "M9496" + - "M9497" + - "M9498" + - "M9499" + - name: "D50-D53 Nutritional anaemias" + codings: + - "D50" + - "D500" + - "D501" + - "D508" + - "D509" + - "D51" + - "D510" + - "D511" + - "D512" + - "D513" + - "D518" + - "D519" + - "D52" + - "D520" + - "D521" + - "D528" + - "D529" + - "D53" + - "D530" + - "D531" + - "D532" + - "D538" + - "D539" + - name: "K00-K14 Diseases of oral cavity, salivary glands and jaws" + codings: + - "K00" + - "K000" + - "K001" + - "K002" + - "K003" + - "K004" + - "K005" + - "K006" + - "K007" + - "K008" + - "K009" + - "K01" + - "K010" + - "K011" + - "K02" + - "K020" + - "K021" + - "K022" + - "K023" + - "K024" + - "K025" + - "K028" + - "K029" + - "K03" + - "K030" + - "K031" + - "K032" + - "K033" + - "K034" + - "K035" + - "K036" + - "K037" + - "K038" + - "K039" + - "K04" + - "K040" + - "K041" + - "K042" + - "K043" + - "K044" + - "K045" + - "K046" + - "K047" + - "K048" + - "K049" + - "K05" + - "K050" + - "K051" + - "K052" + - "K0522" + - "K053" + - "K054" + - "K055" + - "K056" + - "K06" + - "K060" + - "K061" + - "K062" + - "K068" + - "K069" + - "K07" + - "K070" + - "K071" + - "K072" + - "K073" + - "K074" + - "K075" + - "K076" + - "K078" + - "K079" + - "K08" + - "K080" + - "K081" + - "K082" + - "K083" + - "K088" + - "K089" + - "K09" + - "K090" + - "K091" + - "K092" + - "K098" + - "K099" + - "K10" + - "K100" + - "K101" + - "K102" + - "K103" + - "K108" + - "K109" + - "K11" + - "K110" + - "K111" + - "K112" + - "K113" + - "K114" + - "K115" + - "K116" + - "K117" + - "K118" + - "K119" + - "K12" + - "K120" + - "K121" + - "K122" + - "K123" + - "K13" + - "K130" + - "K131" + - "K132" + - "K1329" + - "K133" + - "K134" + - "K135" + - "K136" + - "K137" + - "K14" + - "K140" + - "K141" + - "K142" + - "K143" + - "K144" + - "K145" + - "K146" + - "K148" + - "K149" + - name: "L30 Other dermatitis" + codings: + - "L303" + - "L304" + - "L305" + - "L308" + - "L309" + - "L300" + - "L301" + - "L302" + - name: "M60-M63 Disorders of muscles" + codings: + - "M60" + - "M600" + - "M6000" + - "M6001" + - "M6002" + - "M6003" + - "M6004" + - "M6005" + - "M6006" + - "M6007" + - "M6008" + - "M6009" + - "M601" + - "M6010" + - "M6011" + - "M6012" + - "M6013" + - "M6014" + - "M6015" + - "M6016" + - "M6017" + - "M6018" + - "M6019" + - "M602" + - "M6020" + - "M6021" + - "M6022" + - "M6023" + - "M6024" + - "M6025" + - "M6026" + - "M6027" + - "M6028" + - "M6029" + - "M608" + - "M6080" + - "M6081" + - "M6082" + - "M6083" + - "M6084" + - "M6085" + - "M6086" + - "M6087" + - "M6088" + - "M6089" + - "M609" + - "M6090" + - "M6091" + - "M6092" + - "M6093" + - "M6094" + - "M6095" + - "M6096" + - "M6097" + - "M6098" + - "M6099" + - "M61" + - "M610" + - "M6100" + - "M6101" + - "M6102" + - "M6103" + - "M6104" + - "M6105" + - "M6106" + - "M6107" + - "M6108" + - "M6109" + - "M611" + - "M6110" + - "M6111" + - "M6112" + - "M6113" + - "M6114" + - "M6115" + - "M6116" + - "M6117" + - "M6118" + - "M6119" + - "M612" + - "M6120" + - "M6121" + - "M6122" + - "M6123" + - "M6124" + - "M6125" + - "M6126" + - "M6127" + - "M6128" + - "M6129" + - "M613" + - "M6130" + - "M6131" + - "M6132" + - "M6133" + - "M6134" + - "M6135" + - "M6136" + - "M6137" + - "M6138" + - "M6139" + - "M614" + - "M6140" + - "M6141" + - "M6142" + - "M6143" + - "M6144" + - "M6145" + - "M6146" + - "M6147" + - "M6148" + - "M6149" + - "M615" + - "M6150" + - "M6151" + - "M6152" + - "M6153" + - "M6154" + - "M6155" + - "M6156" + - "M6157" + - "M6158" + - "M6159" + - "M619" + - "M6190" + - "M6191" + - "M6192" + - "M6193" + - "M6194" + - "M6195" + - "M6196" + - "M6197" + - "M6198" + - "M6199" + - "M62" + - "M620" + - "M6200" + - "M6201" + - "M6202" + - "M6203" + - "M6204" + - "M6205" + - "M6206" + - "M6207" + - "M6208" + - "M6209" + - "M621" + - "M6210" + - "M6211" + - "M6212" + - "M6213" + - "M6214" + - "M6215" + - "M6216" + - "M6217" + - "M6218" + - "M6219" + - "M622" + - "M6220" + - "M6221" + - "M6222" + - "M6223" + - "M6224" + - "M6225" + - "M6226" + - "M6227" + - "M6228" + - "M6229" + - "M623" + - "M6230" + - "M6231" + - "M6232" + - "M6233" + - "M6234" + - "M6235" + - "M6236" + - "M6237" + - "M6238" + - "M6239" + - "M624" + - "M6240" + - "M6241" + - "M6242" + - "M6243" + - "M6244" + - "M6245" + - "M6246" + - "M6247" + - "M6248" + - "M6249" + - "M625" + - "M6250" + - "M6251" + - "M6252" + - "M6253" + - "M6254" + - "M6255" + - "M6256" + - "M6257" + - "M6258" + - "M6259" + - "M626" + - "M6260" + - "M6261" + - "M6262" + - "M6263" + - "M6264" + - "M6265" + - "M6266" + - "M6267" + - "M6268" + - "M6269" + - "M628" + - "M6280" + - "M6281" + - "M6282" + - "M6283" + - "M6284" + - "M6285" + - "M6286" + - "M6287" + - "M6288" + - "M6289" + - "M629" + - "M6290" + - "M6291" + - "M6292" + - "M6293" + - "M6294" + - "M6295" + - "M6296" + - "M6297" + - "M6298" + - "M6299" + - "M63" + - "M630" + - "M631" + - "M632" + - "M633" + - "M638" + - name: "F41 Other anxiety disorders" + codings: + - "F411" + - "F412" + - "F413" + - "F418" + - "F419" + - "F410" + - name: "F40 Phobic anxiety disorders" + codings: + - "F400" + - "F401" + - "F402" + - "F408" + - "F409" + - name: "F43 Reaction to severe stress, and adjustment disorders" + codings: + - "F439" + - "F430" + - "F431" + - "F432" + - "F438" + - name: "K31 Other diseases of stomach and duodenum" + codings: + - "K310" + - "K311" + - "K312" + - "K313" + - "K314" + - "K315" + - "K316" + - "K317" + - "K318" + - "K319" + - name: "K30 Dyspepsia" + codings: + - "K30" + - name: "M48 Other spondylopathies" + codings: + - "M480" + - "M4800" + - "M4801" + - "M4802" + - "M4803" + - "M4804" + - "M4805" + - "M4806" + - "M4807" + - "M4808" + - "M4809" + - "M481" + - "M4810" + - "M4811" + - "M4812" + - "M4813" + - "M4814" + - "M4815" + - "M4816" + - "M4817" + - "M4818" + - "M4819" + - "M482" + - "M4820" + - "M4821" + - "M4822" + - "M4823" + - "M4824" + - "M4825" + - "M4826" + - "M4827" + - "M4828" + - "M4829" + - "M483" + - "M4830" + - "M4831" + - "M4832" + - "M4833" + - "M4834" + - "M4835" + - "M4836" + - "M4837" + - "M4838" + - "M4839" + - "M484" + - "M4840" + - "M4841" + - "M4842" + - "M4843" + - "M4844" + - "M4845" + - "M4846" + - "M4847" + - "M4848" + - "M4849" + - "M485" + - "M4850" + - "M4851" + - "M4852" + - "M4853" + - "M4854" + - "M4855" + - "M4856" + - "M4857" + - "M4858" + - "M4859" + - "M488" + - "M4880" + - "M4881" + - "M4882" + - "M4883" + - "M4884" + - "M4885" + - "M4886" + - "M4887" + - "M4888" + - "M4889" + - "M489" + - "M4890" + - "M4891" + - "M4892" + - "M4893" + - "M4894" + - "M4895" + - "M4896" + - "M4897" + - "M4898" + - "M4899" + - name: "N48 Other disorders of penis" + codings: + - "N485" + - "N486" + - "N488" + - "N489" + - "N480" + - "N481" + - "N482" + - "N483" + - "N484" + - name: "N41 Inflammatory diseases of prostate" + codings: + - "N410" + - "N411" + - "N412" + - "N413" + - "N418" + - "N419" + - name: "N40 Hyperplasia of prostate" + codings: + - "N40" + - name: "N43 Hydrocele and spermatocele" + codings: + - "N431" + - "N432" + - "N433" + - "N434" + - "N430" + - name: "N42 Other disorders of prostate" + codings: + - "N420" + - "N421" + - "N422" + - "N423" + - "N428" + - "N429" + - name: "N45 Orchitis and epididymitis" + codings: + - "N450" + - "N459" + - name: "N47 Redundant prepuce, phimosis and paraphimosis" + codings: + - "N47" + - name: "K80 Cholelithiasis" + codings: + - "K805" + - "K808" + - "K800" + - "K801" + - "K802" + - "K803" + - "K8036" + - "K804" + - name: "B95-B98 Bacterial, viral and other infectious agents" + codings: + - "B95" + - "B950" + - "B951" + - "B952" + - "B953" + - "B954" + - "B955" + - "B956" + - "B957" + - "B958" + - "B96" + - "B960" + - "B961" + - "B962" + - "B963" + - "B964" + - "B965" + - "B966" + - "B967" + - "B968" + - "B97" + - "B970" + - "B971" + - "B972" + - "B973" + - "B974" + - "B975" + - "B976" + - "B977" + - "B978" + - "B98" + - "B980" + - "B981" + - name: "K82 Other diseases of gallbladder" + codings: + - "K820" + - "K821" + - "K822" + - "K823" + - "K824" + - "K828" + - "K829" + - name: "K83 Other diseases of biliary tract" + codings: + - "K830" + - "K831" + - "K832" + - "K833" + - "K834" + - "K835" + - "K838" + - "K839" + - name: "K85 Acute pancreatitis" + codings: + - "K850" + - "K851" + - "K852" + - "K853" + - "K858" + - "K859" + - name: "K86 Other diseases of pancreas" + codings: + - "K860" + - "K861" + - "K862" + - "K863" + - "K868" + - "K869" + - name: "K76 Other diseases of liver" + codings: + - "K760" + - "K761" + - "K762" + - "K763" + - "K764" + - "K765" + - "K766" + - "K767" + - "K768" + - "K769" + - name: "A08 Viral and other specified intestinal infections" + codings: + - "A085" + - "A080" + - "A081" + - "A082" + - "A083" + - "A084" + - name: "A09 Diarrhoea and gastro-enteritis of presumed infectious origin" + codings: + - "A090" + - "A099" + - name: "J20-J22 Other acute lower respiratory infections" + codings: + - "J20" + - "J200" + - "J201" + - "J202" + - "J203" + - "J204" + - "J205" + - "J206" + - "J207" + - "J208" + - "J209" + - "J21" + - "J210" + - "J211" + - "J218" + - "J219" + - "J22" + - name: "A04 Other bacterial intestinal infections" + codings: + - "A040" + - "A041" + - "A042" + - "A043" + - "A044" + - "A045" + - "A046" + - "A047" + - "A048" + - "A049" + - name: "I08 Multiple valve diseases" + codings: + - "I080" + - "I081" + - "I082" + - "I083" + - "I088" + - "I089" + - name: "K65-K67 Diseases of peritoneum" + codings: + - "K65" + - "K650" + - "K658" + - "K659" + - "K66" + - "K660" + - "K661" + - "K668" + - "K669" + - "K67" + - "K670" + - "K671" + - "K672" + - "K673" + - "K678" + - name: "K55-K64 Other diseases of intestines" + codings: + - "K631" + - "K632" + - "K633" + - "K634" + - "K635" + - "K638" + - "K639" + - "K64" + - "K640" + - "K641" + - "K642" + - "K643" + - "K644" + - "K645" + - "K648" + - "K649" + - "K55" + - "K550" + - "K551" + - "K552" + - "K558" + - "K559" + - "K56" + - "K560" + - "K561" + - "K562" + - "K563" + - "K564" + - "K565" + - "K566" + - "K567" + - "K57" + - "K570" + - "K571" + - "K572" + - "K573" + - "K574" + - "K575" + - "K578" + - "K579" + - "K58" + - "K580" + - "K589" + - "K59" + - "K590" + - "K591" + - "K592" + - "K593" + - "K594" + - "K598" + - "K599" + - "K60" + - "K600" + - "K601" + - "K602" + - "K603" + - "K604" + - "K605" + - "K61" + - "K610" + - "K611" + - "K612" + - "K613" + - "K614" + - "K62" + - "K620" + - "K621" + - "K622" + - "K623" + - "K624" + - "K625" + - "K626" + - "K627" + - "K628" + - "K629" + - "K63" + - "K630" + - name: "M51 Other intervertebral disk disorders" + codings: + - "M510" + - "M511" + - "M5116" + - "M5119" + - "M512" + - "M513" + - "M5137" + - "M514" + - "M518" + - "M519" + - name: "M50 Cervical disk disorders" + codings: + - "M501" + - "M502" + - "M503" + - "M508" + - "M509" + - "M500" + - name: "M53 Other dorsopathies, not elsewhere classified" + codings: + - "M5382" + - "M5383" + - "M5384" + - "M5385" + - "M5386" + - "M5387" + - "M5388" + - "M5389" + - "M539" + - "M5390" + - "M5391" + - "M5392" + - "M5393" + - "M5394" + - "M5395" + - "M5396" + - "M5397" + - "M5398" + - "M5399" + - "M530" + - "M5300" + - "M5301" + - "M5302" + - "M5303" + - "M5304" + - "M5305" + - "M5306" + - "M5307" + - "M5308" + - "M5309" + - "M531" + - "M5310" + - "M5311" + - "M5312" + - "M5313" + - "M5314" + - "M5315" + - "M5316" + - "M5317" + - "M5318" + - "M5319" + - "M532" + - "M5320" + - "M5321" + - "M5322" + - "M5323" + - "M5324" + - "M5325" + - "M5326" + - "M5327" + - "M5328" + - "M5329" + - "M533" + - "M5330" + - "M5331" + - "M5332" + - "M5333" + - "M5334" + - "M5335" + - "M5336" + - "M5337" + - "M5338" + - "M5339" + - "M538" + - "M5380" + - "M5381" + - name: "H55-H59 Other disorders of eye and adnexa" + codings: + - "H59" + - "H590" + - "H598" + - "H599" + - "H55" + - "H57" + - "H570" + - "H571" + - "H578" + - "H579" + - "H58" + - "H580" + - "H581" + - "H588" + - "H589" + - name: "M07 Psoriatic and enteropathic arthropathies" + codings: + - "M0750" + - "M0751" + - "M0752" + - "M0753" + - "M0754" + - "M0755" + - "M0756" + - "M0757" + - "M0758" + - "M0759" + - "M076" + - "M0760" + - "M0761" + - "M0762" + - "M0763" + - "M0764" + - "M0765" + - "M0766" + - "M0767" + - "M0768" + - "M0769" + - "M070" + - "M0700" + - "M0701" + - "M0702" + - "M0703" + - "M0704" + - "M0705" + - "M0706" + - "M0707" + - "M0708" + - "M0709" + - "M071" + - "M0710" + - "M0711" + - "M0712" + - "M0713" + - "M0714" + - "M0715" + - "M0716" + - "M0717" + - "M0718" + - "M0719" + - "M072" + - "M0720" + - "M0721" + - "M0722" + - "M0723" + - "M0724" + - "M0725" + - "M0726" + - "M0727" + - "M0728" + - "M0729" + - "M073" + - "M0730" + - "M0731" + - "M0732" + - "M0733" + - "M0734" + - "M0735" + - "M0736" + - "M0737" + - "M0738" + - "M0739" + - "M074" + - "M0740" + - "M0741" + - "M0742" + - "M0743" + - "M0744" + - "M0745" + - "M0746" + - "M0747" + - "M0748" + - "M0749" + - "M075" + - name: "H43-H45 Disorders of vitreous body and globe" + codings: + - "H43" + - "H430" + - "H431" + - "H432" + - "H433" + - "H438" + - "H439" + - "H44" + - "H440" + - "H441" + - "H442" + - "H443" + - "H444" + - "H445" + - "H446" + - "H447" + - "H448" + - "H449" + - "H45" + - "H450" + - "H451" + - "H458" + - name: "H54 Blindness and low vision" + codings: + - "H540" + - "H541" + - "H542" + - "H543" + - "H544" + - "H545" + - "H546" + - "H547" + - "H549" + - name: "L80-L99 Other disorders of the skin and subcutaneous tissue" + codings: + - "L901" + - "L902" + - "L903" + - "L904" + - "L905" + - "L906" + - "L908" + - "L909" + - "L91" + - "L910" + - "L918" + - "L919" + - "L92" + - "L920" + - "L921" + - "L922" + - "L923" + - "L928" + - "L929" + - "L93" + - "L930" + - "L931" + - "L932" + - "L94" + - "L940" + - "L941" + - "L942" + - "L943" + - "L944" + - "L945" + - "L946" + - "L948" + - "L949" + - "L95" + - "L950" + - "L951" + - "L958" + - "L959" + - "L97" + - "L98" + - "L980" + - "L981" + - "L982" + - "L983" + - "L984" + - "L985" + - "L986" + - "L987" + - "L988" + - "L989" + - "L99" + - "L990" + - "L998" + - "L80" + - "L81" + - "L810" + - "L811" + - "L812" + - "L813" + - "L814" + - "L815" + - "L816" + - "L817" + - "L818" + - "L819" + - "L82" + - "L83" + - "L84" + - "L85" + - "L850" + - "L851" + - "L852" + - "L853" + - "L858" + - "L859" + - "L86" + - "L87" + - "L870" + - "L871" + - "L872" + - "L878" + - "L879" + - "L88" + - "L89" + - "L890" + - "L891" + - "L892" + - "L893" + - "L899" + - "L90" + - "L900" + - name: "H50 Other strabismus" + codings: + - "H500" + - "H501" + - "H502" + - "H503" + - "H504" + - "H505" + - "H506" + - "H508" + - "H509" + - name: "H52 Disorders of refraction and accommodation" + codings: + - "H527" + - "H520" + - "H521" + - "H522" + - "H523" + - "H524" + - "H525" + - "H526" + - name: "H53 Visual disturbances" + codings: + - "H530" + - "H531" + - "H532" + - "H533" + - "H534" + - "H535" + - "H536" + - "H538" + - "H539" + - name: "I30-I52 Other forms of heart disease" + codings: + - "I30" + - "I300" + - "I301" + - "I308" + - "I309" + - "I31" + - "I310" + - "I311" + - "I312" + - "I313" + - "I318" + - "I319" + - "I32" + - "I320" + - "I321" + - "I328" + - "I33" + - "I330" + - "I339" + - "I34" + - "I340" + - "I341" + - "I342" + - "I348" + - "I349" + - "I35" + - "I350" + - "I351" + - "I352" + - "I358" + - "I359" + - "I36" + - "I360" + - "I361" + - "I362" + - "I368" + - "I369" + - "I37" + - "I370" + - "I371" + - "I372" + - "I378" + - "I379" + - "I38" + - "I39" + - "I390" + - "I391" + - "I392" + - "I393" + - "I394" + - "I398" + - "I40" + - "I400" + - "I401" + - "I408" + - "I409" + - "I41" + - "I410" + - "I411" + - "I412" + - "I418" + - "I42" + - "I420" + - "I421" + - "I422" + - "I423" + - "I424" + - "I425" + - "I426" + - "I427" + - "I428" + - "I429" + - "I43" + - "I430" + - "I431" + - "I432" + - "I438" + - "I44" + - "I440" + - "I441" + - "I442" + - "I443" + - "I444" + - "I445" + - "I446" + - "I447" + - "I45" + - "I450" + - "I451" + - "I452" + - "I453" + - "I454" + - "I455" + - "I456" + - "I458" + - "I459" + - "I46" + - "I460" + - "I461" + - "I469" + - "I47" + - "I470" + - "I471" + - "I472" + - "I479" + - "I48" + - "I480" + - "I481" + - "I482" + - "I483" + - "I484" + - "I489" + - "I49" + - "I490" + - "I491" + - "I492" + - "I493" + - "I494" + - "I495" + - "I498" + - "I499" + - "I50" + - "I500" + - "I501" + - "I509" + - "I51" + - "I510" + - "I511" + - "I512" + - "I513" + - "I514" + - "I515" + - "I516" + - "I517" + - "I518" + - "I519" + - "I52" + - "I520" + - "I521" + - "I528" + - name: "L08 Other local infections of skin and subcutaneous tissue" + codings: + - "L080" + - "L081" + - "L088" + - "L089" + - name: "H90-H95 Other disorders of ear" + codings: + - "H90" + - "H900" + - "H901" + - "H902" + - "H903" + - "H904" + - "H905" + - "H906" + - "H907" + - "H908" + - "H91" + - "H910" + - "H911" + - "H912" + - "H913" + - "H918" + - "H919" + - "H92" + - "H920" + - "H921" + - "H922" + - "H93" + - "H930" + - "H931" + - "H932" + - "H933" + - "H938" + - "H939" + - "H94" + - "H940" + - "H948" + - "H95" + - "H950" + - "H951" + - "H958" + - "H959" + - name: "L05 Pilonidal cyst" + codings: + - "L059" + - "L050" + - name: "L03 Cellulitis" + codings: + - "L030" + - "L031" + - "L032" + - "L033" + - "L038" + - "L039" + - name: "J90-J94 Other diseases of pleura" + codings: + - "J948" + - "J949" + - "J90" + - "J91" + - "J92" + - "J920" + - "J929" + - "J93" + - "J930" + - "J931" + - "J938" + - "J939" + - "J94" + - "J940" + - "J941" + - "J942" + - name: "D70-D77 Other diseases of blood and blood-forming organs" + codings: + - "D70" + - "D71" + - "D72" + - "D720" + - "D721" + - "D728" + - "D729" + - "D73" + - "D730" + - "D731" + - "D732" + - "D733" + - "D734" + - "D735" + - "D738" + - "D739" + - "D74" + - "D740" + - "D748" + - "D749" + - "D75" + - "D750" + - "D751" + - "D752" + - "D758" + - "D759" + - "D76" + - "D760" + - "D761" + - "D762" + - "D763" + - "D77" + - name: "K81 Cholecystitis" + codings: + - "K810" + - "K811" + - "K818" + - "K819" + - name: "J09-J18 Influenza and pneumonia" + codings: + - "J09" + - "J10" + - "J100" + - "J101" + - "J108" + - "J11" + - "J110" + - "J111" + - "J118" + - "J12" + - "J120" + - "J121" + - "J122" + - "J123" + - "J128" + - "J129" + - "J13" + - "J14" + - "J15" + - "J150" + - "J151" + - "J152" + - "J153" + - "J154" + - "J155" + - "J156" + - "J157" + - "J158" + - "J159" + - "J16" + - "J160" + - "J168" + - "J17" + - "J170" + - "J171" + - "J172" + - "J173" + - "J178" + - "J18" + - "J180" + - "J181" + - "J182" + - "J188" + - "J189" + - name: "F00-F09 Organic, including symptomatic, mental disorders" + codings: + - "F00" + - "F000" + - "F001" + - "F002" + - "F009" + - "F01" + - "F010" + - "F011" + - "F012" + - "F013" + - "F018" + - "F019" + - "F02" + - "F020" + - "F021" + - "F022" + - "F023" + - "F024" + - "F028" + - "F03" + - "F04" + - "F05" + - "F050" + - "F051" + - "F058" + - "F059" + - "F06" + - "F060" + - "F061" + - "F062" + - "F063" + - "F064" + - "F065" + - "F066" + - "F067" + - "F068" + - "F069" + - "F07" + - "F070" + - "F071" + - "F072" + - "F078" + - "F079" + - "F09" + - name: "J84 Other interstitial pulmonary diseases" + codings: + - "J848" + - "J849" + - "J840" + - "J841" + - name: "G40 Epilepsy" + codings: + - "G400" + - "G401" + - "G402" + - "G403" + - "G404" + - "G405" + - "G406" + - "G407" + - "G408" + - "G409" + - name: "G43 Migraine" + codings: + - "G430" + - "G431" + - "G432" + - "G433" + - "G438" + - "G439" + - name: "G44 Other headache syndromes" + codings: + - "G444" + - "G448" + - "G440" + - "G441" + - "G442" + - "G443" + - name: "G45 Transient cerebral ischaemic attacks and related syndromes" + codings: + - "G450" + - "G451" + - "G452" + - "G453" + - "G454" + - "G458" + - "G459" + - name: "G47 Sleep disorders" + codings: + - "G470" + - "G471" + - "G472" + - "G473" + - "G474" + - "G478" + - "G479" + - name: "L40-L45 Papulosquamous disorders" + codings: + - "L40" + - "L400" + - "L401" + - "L402" + - "L403" + - "L404" + - "L405" + - "L408" + - "L409" + - "L41" + - "L410" + - "L411" + - "L412" + - "L413" + - "L414" + - "L415" + - "L418" + - "L419" + - "L42" + - "L43" + - "L430" + - "L431" + - "L432" + - "L433" + - "L438" + - "L439" + - "L44" + - "L440" + - "L441" + - "L442" + - "L443" + - "L444" + - "L448" + - "L449" + - "L45" + - name: "E53 Deficiency of other B group vitamins" + codings: + - "E531" + - "E538" + - "E539" + - "E530" + - name: "B34 Viral infection of unspecified site" + codings: + - "B340" + - "B341" + - "B342" + - "B343" + - "B344" + - "B348" + - "B349" + - name: "B37 Candidiasis" + codings: + - "B370" + - "B371" + - "B372" + - "B373" + - "B374" + - "B375" + - "B376" + - "B377" + - "B378" + - "B379" + - name: "O48 Prolonged pregnancy" + codings: + - "O48" + - name: "J35 Chronic diseases of tonsils and adenoids" + codings: + - "J353" + - "J358" + - "J359" + - "J350" + - "J351" + - "J352" + - name: "J30 Vasomotor and allergic rhinitis" + codings: + - "J300" + - "J301" + - "J302" + - "J303" + - "J304" + - name: "J31 Chronic rhinitis, nasopharyngitis and pharyngitis" + codings: + - "J312" + - "J310" + - "J311" + - name: "J32 Chronic sinusitis" + codings: + - "J320" + - "J321" + - "J322" + - "J323" + - "J324" + - "J328" + - "J329" + - name: "J33 Nasal polyp" + codings: + - "J330" + - "J331" + - "J338" + - "J339" + - name: "O42 Premature rupture of membranes" + codings: + - "O420" + - "O421" + - "O422" + - "O429" + - name: "J38 Diseases of vocal cords and larynx, not elsewhere classified" + codings: + - "J380" + - "J381" + - "J382" + - "J383" + - "J384" + - "J385" + - "J386" + - "J387" + - name: "J39 Other diseases of upper respiratory tract" + codings: + - "J390" + - "J391" + - "J392" + - "J393" + - "J398" + - "J399" + - name: "O46 Antepartum haemorrhage, not elsewhere classified" + codings: + - "O460" + - "O468" + - "O469" + - name: "O47 False labour" + codings: + - "O471" + - "O479" + - "O470" + - name: "G50-G59 Nerve, nerve root and plexus disorders" + codings: + - "G50" + - "G500" + - "G501" + - "G508" + - "G509" + - "G51" + - "G510" + - "G511" + - "G512" + - "G513" + - "G514" + - "G518" + - "G519" + - "G52" + - "G520" + - "G521" + - "G522" + - "G523" + - "G527" + - "G528" + - "G529" + - "G53" + - "G530" + - "G531" + - "G532" + - "G533" + - "G538" + - "G54" + - "G540" + - "G541" + - "G542" + - "G543" + - "G544" + - "G545" + - "G546" + - "G547" + - "G548" + - "G549" + - "G55" + - "G550" + - "G551" + - "G552" + - "G553" + - "G558" + - "G56" + - "G560" + - "G561" + - "G562" + - "G563" + - "G564" + - "G568" + - "G569" + - "G57" + - "G570" + - "G571" + - "G572" + - "G573" + - "G574" + - "G575" + - "G576" + - "G578" + - "G579" + - "G58" + - "G580" + - "G587" + - "G588" + - "G589" + - "G59" + - "G590" + - "G598" + - name: "I31 Other diseases of pericardium" + codings: + - "I310" + - "I311" + - "I312" + - "I313" + - "I318" + - "I319" + - name: "I35 Nonrheumatic aortic valve disorders" + codings: + - "I350" + - "I351" + - "I352" + - "I358" + - "I359" + - name: "I34 Nonrheumatic mitral valve disorders" + codings: + - "I340" + - "I341" + - "I342" + - "I348" + - "I349" + - name: "A41 Other septicaemia" + codings: + - "A418" + - "A419" + - "A410" + - "A411" + - "A412" + - "A413" + - "A414" + - "A415" + - name: "E15-E16 Other disorders of glucose regulation and pancreatic internal secretion" + codings: + - "E15" + - "E16" + - "E160" + - "E161" + - "E162" + - "E163" + - "E164" + - "E168" + - "E169" + - name: "F17 Mental and behavioural disorders due to use of tobacco" + codings: + - "F170" + - "F171" + - "F172" + - "F173" + - "F174" + - "F175" + - "F176" + - "F177" + - "F178" + - "F179" + - name: "A49 Bacterial infection of unspecified site" + codings: + - "A498" + - "A499" + - "A490" + - "A491" + - "A492" + - "A493" + - name: "N12 Tubulo-interstitial nephritis, not specified as acute or chronic" + codings: + - "N12" + - name: "N13 Obstructive and reflux uropathy" + codings: + - "N134" + - "N135" + - "N136" + - "N137" + - "N138" + - "N139" + - "N130" + - "N131" + - "N132" + - "N133" + - name: "N17 Acute renal failure" + codings: + - "N170" + - "N171" + - "N172" + - "N178" + - "N179" + - name: "G30-G32 Other degenerative diseases of the nervous system" + codings: + - "G30" + - "G300" + - "G301" + - "G308" + - "G309" + - "G31" + - "G310" + - "G311" + - "G312" + - "G318" + - "G319" + - "G32" + - "G320" + - "G328" + - name: "N18 Chronic renal failure" + codings: + - "N180" + - "N181" + - "N182" + - "N183" + - "N184" + - "N185" + - "N188" + - "N189" + - name: "N19 Unspecified renal failure" + codings: + - "N19" + - name: "K70 Alcoholic liver disease" + codings: + - "K700" + - "K701" + - "K702" + - "K703" + - "K704" + - "K709" + - name: "K75 Other inflammatory liver diseases" + codings: + - "K750" + - "K751" + - "K752" + - "K753" + - "K754" + - "K758" + - "K759" + - name: "K74 Fibrosis and cirrhosis of liver" + codings: + - "K744" + - "K745" + - "K746" + - "K740" + - "K741" + - "K742" + - "K743" + - name: "I49 Other cardiac arrhythmias" + codings: + - "I490" + - "I491" + - "I492" + - "I493" + - "I494" + - "I495" + - "I498" + - "I499" + - name: "I46 Cardiac arrest" + codings: + - "I461" + - "I469" + - "I460" + - name: "I47 Paroxysmal tachycardia" + codings: + - "I470" + - "I471" + - "I472" + - "I479" + - name: "I44 Atrioventricular and left bundle-branch block" + codings: + - "I440" + - "I441" + - "I442" + - "I443" + - "I444" + - "I445" + - "I446" + - "I447" + - name: "I45 Other conduction disorders" + codings: + - "I450" + - "I451" + - "I452" + - "I453" + - "I454" + - "I455" + - "I456" + - "I458" + - "I459" + - name: "I42 Cardiomyopathy" + codings: + - "I424" + - "I425" + - "I426" + - "I427" + - "I428" + - "I429" + - "I420" + - "I421" + - "I422" + - "I423" + - name: "M95-M99 Other disorders of the musculoskeletal system and connective tissue" + codings: + - "M95" + - "M950" + - "M951" + - "M952" + - "M953" + - "M954" + - "M955" + - "M958" + - "M959" + - "M9596" + - "M96" + - "M960" + - "M961" + - "M962" + - "M963" + - "M964" + - "M965" + - "M966" + - "M9663" + - "M9665" + - "M968" + - "M969" + - "M99" + - "M990" + - "M9900" + - "M9901" + - "M9902" + - "M9903" + - "M9904" + - "M9905" + - "M9906" + - "M9907" + - "M9908" + - "M9909" + - "M991" + - "M9910" + - "M9911" + - "M9912" + - "M9913" + - "M9914" + - "M9915" + - "M9916" + - "M9917" + - "M9918" + - "M9919" + - "M992" + - "M9920" + - "M9921" + - "M9922" + - "M9923" + - "M9924" + - "M9925" + - "M9926" + - "M9927" + - "M9928" + - "M9929" + - "M993" + - "M9930" + - "M9931" + - "M9932" + - "M9933" + - "M9934" + - "M9935" + - "M9936" + - "M9937" + - "M9938" + - "M9939" + - "M994" + - "M9940" + - "M9941" + - "M9942" + - "M9943" + - "M9944" + - "M9945" + - "M9946" + - "M9947" + - "M9948" + - "M9949" + - "M995" + - "M9950" + - "M9951" + - "M9952" + - "M9953" + - "M9954" + - "M9955" + - "M9956" + - "M9957" + - "M9958" + - "M9959" + - "M996" + - "M9960" + - "M9961" + - "M9962" + - "M9963" + - "M9964" + - "M9965" + - "M9966" + - "M9967" + - "M9968" + - "M9969" + - "M997" + - "M9970" + - "M9971" + - "M9972" + - "M9973" + - "M9974" + - "M9975" + - "M9976" + - "M9977" + - "M9978" + - "M9979" + - "M998" + - "M9980" + - "M9981" + - "M9982" + - "M9983" + - "M9984" + - "M9985" + - "M9986" + - "M9987" + - "M9988" + - "M9989" + - "M999" + - "M9990" + - "M9991" + - "M9992" + - "M9993" + - "M9994" + - "M9995" + - "M9996" + - "M9997" + - "M9998" + - "M9999" + - name: "H25 Senile cataract" + codings: + - "H259" + - "H250" + - "H251" + - "H252" + - "H258" + - name: "H26 Other cataract" + codings: + - "H260" + - "H261" + - "H262" + - "H263" + - "H264" + - "H268" + - "H269" + - name: "M65-M68 Disorders of synovium and tendon" + codings: + - "M6521" + - "M6522" + - "M6523" + - "M6524" + - "M6525" + - "M6526" + - "M6527" + - "M6528" + - "M6529" + - "M653" + - "M6530" + - "M6531" + - "M6532" + - "M6533" + - "M6534" + - "M6535" + - "M6536" + - "M6537" + - "M6538" + - "M6539" + - "M654" + - "M6540" + - "M6541" + - "M6542" + - "M6543" + - "M6544" + - "M6545" + - "M6546" + - "M6547" + - "M6548" + - "M6549" + - "M658" + - "M6580" + - "M6581" + - "M6582" + - "M6583" + - "M6584" + - "M6585" + - "M6586" + - "M6587" + - "M6588" + - "M6589" + - "M659" + - "M6590" + - "M6591" + - "M6592" + - "M6593" + - "M6594" + - "M6595" + - "M6596" + - "M6597" + - "M6598" + - "M6599" + - "M66" + - "M660" + - "M6600" + - "M6601" + - "M6602" + - "M6603" + - "M6604" + - "M6605" + - "M6606" + - "M6607" + - "M6608" + - "M6609" + - "M661" + - "M6610" + - "M6611" + - "M6612" + - "M6613" + - "M6614" + - "M6615" + - "M6616" + - "M6617" + - "M6618" + - "M6619" + - "M662" + - "M6620" + - "M6621" + - "M6622" + - "M6623" + - "M6624" + - "M6625" + - "M6626" + - "M6627" + - "M6628" + - "M6629" + - "M663" + - "M6630" + - "M6631" + - "M6632" + - "M6633" + - "M6634" + - "M6635" + - "M6636" + - "M6637" + - "M6638" + - "M6639" + - "M664" + - "M6640" + - "M6641" + - "M6642" + - "M6643" + - "M6644" + - "M6645" + - "M6646" + - "M6647" + - "M6648" + - "M6649" + - "M665" + - "M6650" + - "M6651" + - "M6652" + - "M6653" + - "M6654" + - "M6655" + - "M6656" + - "M6657" + - "M6658" + - "M6659" + - "M67" + - "M670" + - "M671" + - "M672" + - "M673" + - "M674" + - "M6743" + - "M6745" + - "M6747" + - "M6749" + - "M678" + - "M679" + - "M6796" + - "M68" + - "M680" + - "M688" + - "M65" + - "M650" + - "M6500" + - "M6501" + - "M6502" + - "M6503" + - "M6504" + - "M6505" + - "M6506" + - "M6507" + - "M6508" + - "M6509" + - "M651" + - "M6510" + - "M6511" + - "M6512" + - "M6513" + - "M6514" + - "M6515" + - "M6516" + - "M6517" + - "M6518" + - "M6519" + - "M652" + - "M6520" + - name: "O85-O92 Complications predominantly related to the puerperium" + codings: + - "O923" + - "O924" + - "O925" + - "O926" + - "O927" + - "O85" + - "O86" + - "O860" + - "O861" + - "O862" + - "O863" + - "O864" + - "O868" + - "O87" + - "O870" + - "O871" + - "O872" + - "O873" + - "O878" + - "O879" + - "O88" + - "O880" + - "O881" + - "O882" + - "O883" + - "O888" + - "O89" + - "O890" + - "O891" + - "O892" + - "O893" + - "O894" + - "O895" + - "O896" + - "O898" + - "O899" + - "O90" + - "O900" + - "O901" + - "O902" + - "O903" + - "O904" + - "O905" + - "O908" + - "O909" + - "O91" + - "O910" + - "O911" + - "O912" + - "O92" + - "O920" + - "O921" + - "O922" + - name: "N99 Postprocedural disorders of genito-urinary system, not elsewhere classified" + codings: + - "N990" + - "N991" + - "N992" + - "N993" + - "N994" + - "N995" + - "N998" + - "N999" + - name: "G35-G37 Demyelinating diseases of the central nervous system" + codings: + - "G375" + - "G378" + - "G379" + - "G35" + - "G36" + - "G360" + - "G361" + - "G368" + - "G369" + - "G37" + - "G370" + - "G371" + - "G372" + - "G373" + - "G374" + - name: "O00-O08 Pregnancy with abortive outcome" + codings: + - "O00" + - "O000" + - "O001" + - "O002" + - "O008" + - "O009" + - "O01" + - "O010" + - "O011" + - "O019" + - "O02" + - "O020" + - "O021" + - "O028" + - "O029" + - "O03" + - "O030" + - "O031" + - "O032" + - "O033" + - "O034" + - "O035" + - "O036" + - "O037" + - "O038" + - "O039" + - "O04" + - "O040" + - "O041" + - "O042" + - "O043" + - "O044" + - "O045" + - "O046" + - "O047" + - "O048" + - "O049" + - "O05" + - "O050" + - "O051" + - "O052" + - "O053" + - "O054" + - "O055" + - "O056" + - "O057" + - "O058" + - "O059" + - "O06" + - "O060" + - "O061" + - "O062" + - "O063" + - "O064" + - "O065" + - "O066" + - "O067" + - "O068" + - "O069" + - "O07" + - "O070" + - "O071" + - "O072" + - "O073" + - "O074" + - "O075" + - "O076" + - "O077" + - "O078" + - "O079" + - "O08" + - "O080" + - "O081" + - "O082" + - "O083" + - "O084" + - "O085" + - "O086" + - "O087" + - "O088" + - "O089" + - name: "I80-I89 Diseases of veins, lymphatic vessels and lymph nodes, not elsewhere classified" + codings: + - "I80" + - "I800" + - "I801" + - "I802" + - "I803" + - "I808" + - "I809" + - "I81" + - "I82" + - "I820" + - "I821" + - "I822" + - "I823" + - "I828" + - "I829" + - "I83" + - "I830" + - "I831" + - "I832" + - "I839" + - "I84" + - "I840" + - "I841" + - "I842" + - "I843" + - "I844" + - "I845" + - "I846" + - "I847" + - "I848" + - "I849" + - "I85" + - "I850" + - "I859" + - "I86" + - "I860" + - "I861" + - "I862" + - "I863" + - "I864" + - "I868" + - "I87" + - "I870" + - "I871" + - "I872" + - "I878" + - "I879" + - "I88" + - "I880" + - "I881" + - "I888" + - "I889" + - "I89" + - "I890" + - "I891" + - "I898" + - "I899" + - name: "E00-E07 Disorders of thyroid gland" + codings: + - "E011" + - "E012" + - "E018" + - "E02" + - "E03" + - "E030" + - "E031" + - "E032" + - "E033" + - "E034" + - "E035" + - "E038" + - "E039" + - "E04" + - "E040" + - "E041" + - "E042" + - "E048" + - "E049" + - "E05" + - "E050" + - "E051" + - "E052" + - "E053" + - "E054" + - "E055" + - "E058" + - "E059" + - "E06" + - "E060" + - "E061" + - "E062" + - "E063" + - "E064" + - "E065" + - "E069" + - "E07" + - "E070" + - "E071" + - "E078" + - "E079" + - "E00" + - "E000" + - "E001" + - "E002" + - "E009" + - "E01" + - "E010" + - name: "M80-M85 Disorders of bone density and structure" + codings: + - "M80" + - "M800" + - "M8000" + - "M8001" + - "M8002" + - "M8003" + - "M8004" + - "M8005" + - "M8006" + - "M8007" + - "M8008" + - "M8009" + - "M801" + - "M8010" + - "M8011" + - "M8012" + - "M8013" + - "M8014" + - "M8015" + - "M8016" + - "M8017" + - "M8018" + - "M8019" + - "M802" + - "M8020" + - "M8021" + - "M8022" + - "M8023" + - "M8024" + - "M8025" + - "M8026" + - "M8027" + - "M8028" + - "M8029" + - "M803" + - "M8030" + - "M8031" + - "M8032" + - "M8033" + - "M8034" + - "M8035" + - "M8036" + - "M8037" + - "M8038" + - "M8039" + - "M804" + - "M8040" + - "M8041" + - "M8042" + - "M8043" + - "M8044" + - "M8045" + - "M8046" + - "M8047" + - "M8048" + - "M8049" + - "M805" + - "M8050" + - "M8051" + - "M8052" + - "M8053" + - "M8054" + - "M8055" + - "M8056" + - "M8057" + - "M8058" + - "M8059" + - "M808" + - "M8080" + - "M8081" + - "M8082" + - "M8083" + - "M8084" + - "M8085" + - "M8086" + - "M8087" + - "M8088" + - "M8089" + - "M809" + - "M8090" + - "M8091" + - "M8092" + - "M8093" + - "M8094" + - "M8095" + - "M8096" + - "M8097" + - "M8098" + - "M8099" + - "M81" + - "M810" + - "M8100" + - "M8101" + - "M8102" + - "M8103" + - "M8104" + - "M8105" + - "M8106" + - "M8107" + - "M8108" + - "M8109" + - "M811" + - "M8110" + - "M8111" + - "M8112" + - "M8113" + - "M8114" + - "M8115" + - "M8116" + - "M8117" + - "M8118" + - "M8119" + - "M812" + - "M8120" + - "M8121" + - "M8122" + - "M8123" + - "M8124" + - "M8125" + - "M8126" + - "M8127" + - "M8128" + - "M8129" + - "M813" + - "M8130" + - "M8131" + - "M8132" + - "M8133" + - "M8134" + - "M8135" + - "M8136" + - "M8137" + - "M8138" + - "M8139" + - "M814" + - "M8140" + - "M8141" + - "M8142" + - "M8143" + - "M8144" + - "M8145" + - "M8146" + - "M8147" + - "M8148" + - "M8149" + - "M815" + - "M8150" + - "M8151" + - "M8152" + - "M8153" + - "M8154" + - "M8155" + - "M8156" + - "M8157" + - "M8158" + - "M8159" + - "M816" + - "M8160" + - "M8161" + - "M8162" + - "M8163" + - "M8164" + - "M8165" + - "M8166" + - "M8167" + - "M8168" + - "M8169" + - "M818" + - "M8180" + - "M8181" + - "M8182" + - "M8183" + - "M8184" + - "M8185" + - "M8186" + - "M8187" + - "M8188" + - "M8189" + - "M819" + - "M8190" + - "M8191" + - "M8192" + - "M8193" + - "M8194" + - "M8195" + - "M8196" + - "M8197" + - "M8198" + - "M8199" + - "M82" + - "M820" + - "M8200" + - "M8201" + - "M8202" + - "M8203" + - "M8204" + - "M8205" + - "M8206" + - "M8207" + - "M8208" + - "M8209" + - "M821" + - "M8210" + - "M8211" + - "M8212" + - "M8213" + - "M8214" + - "M8215" + - "M8216" + - "M8217" + - "M8218" + - "M8219" + - "M823" + - "M828" + - "M8280" + - "M8281" + - "M8282" + - "M8283" + - "M8284" + - "M8285" + - "M8286" + - "M8287" + - "M8288" + - "M8289" + - "M83" + - "M830" + - "M8300" + - "M8301" + - "M8302" + - "M8303" + - "M8304" + - "M8305" + - "M8306" + - "M8307" + - "M8308" + - "M8309" + - "M831" + - "M8310" + - "M8311" + - "M8312" + - "M8313" + - "M8314" + - "M8315" + - "M8316" + - "M8317" + - "M8318" + - "M8319" + - "M832" + - "M8320" + - "M8321" + - "M8322" + - "M8323" + - "M8324" + - "M8325" + - "M8326" + - "M8327" + - "M8328" + - "M8329" + - "M833" + - "M8330" + - "M8331" + - "M8332" + - "M8333" + - "M8334" + - "M8335" + - "M8336" + - "M8337" + - "M8338" + - "M8339" + - "M834" + - "M8340" + - "M8341" + - "M8342" + - "M8343" + - "M8344" + - "M8345" + - "M8346" + - "M8347" + - "M8348" + - "M8349" + - "M835" + - "M8350" + - "M8351" + - "M8352" + - "M8353" + - "M8354" + - "M8355" + - "M8356" + - "M8357" + - "M8358" + - "M8359" + - "M838" + - "M8380" + - "M8381" + - "M8382" + - "M8383" + - "M8384" + - "M8385" + - "M8386" + - "M8387" + - "M8388" + - "M8389" + - "M839" + - "M8390" + - "M8391" + - "M8392" + - "M8393" + - "M8394" + - "M8395" + - "M8396" + - "M8397" + - "M8398" + - "M8399" + - "M84" + - "M840" + - "M8400" + - "M8401" + - "M8402" + - "M8403" + - "M8404" + - "M8405" + - "M8406" + - "M8407" + - "M8408" + - "M8409" + - "M841" + - "M8410" + - "M8411" + - "M8412" + - "M8413" + - "M8414" + - "M8415" + - "M8416" + - "M8417" + - "M8418" + - "M8419" + - "M842" + - "M8420" + - "M8421" + - "M8422" + - "M8423" + - "M8424" + - "M8425" + - "M8426" + - "M8427" + - "M8428" + - "M8429" + - "M843" + - "M8430" + - "M8431" + - "M8432" + - "M8433" + - "M8434" + - "M8435" + - "M8436" + - "M8437" + - "M8438" + - "M8439" + - "M844" + - "M8440" + - "M8441" + - "M8442" + - "M8443" + - "M8444" + - "M8445" + - "M8446" + - "M8447" + - "M8448" + - "M8449" + - "M848" + - "M8480" + - "M8481" + - "M8482" + - "M8483" + - "M8484" + - "M8485" + - "M8486" + - "M8487" + - "M8488" + - "M8489" + - "M849" + - "M8490" + - "M8491" + - "M8492" + - "M8493" + - "M8494" + - "M8495" + - "M8496" + - "M8497" + - "M8498" + - "M8499" + - "M85" + - "M850" + - "M8500" + - "M8501" + - "M8502" + - "M8503" + - "M8504" + - "M8505" + - "M8506" + - "M8507" + - "M8508" + - "M8509" + - "M851" + - "M8510" + - "M8511" + - "M8512" + - "M8513" + - "M8514" + - "M8515" + - "M8516" + - "M8517" + - "M8518" + - "M8519" + - "M852" + - "M8520" + - "M8521" + - "M8522" + - "M8523" + - "M8524" + - "M8525" + - "M8526" + - "M8527" + - "M8528" + - "M8529" + - "M853" + - "M8530" + - "M8531" + - "M8532" + - "M8533" + - "M8534" + - "M8535" + - "M8536" + - "M8537" + - "M8538" + - "M8539" + - "M854" + - "M8540" + - "M8541" + - "M8542" + - "M8543" + - "M8544" + - "M8545" + - "M8546" + - "M8547" + - "M8548" + - "M8549" + - "M855" + - "M8550" + - "M8551" + - "M8552" + - "M8553" + - "M8554" + - "M8555" + - "M8556" + - "M8557" + - "M8558" + - "M8559" + - "M856" + - "M8560" + - "M8561" + - "M8562" + - "M8563" + - "M8564" + - "M8565" + - "M8566" + - "M8567" + - "M8568" + - "M8569" + - "M858" + - "M8580" + - "M8581" + - "M8582" + - "M8583" + - "M8584" + - "M8585" + - "M8586" + - "M8587" + - "M8588" + - "M8589" + - "M859" + - "M8590" + - "M8591" + - "M8592" + - "M8593" + - "M8594" + - "M8595" + - "M8596" + - "M8597" + - "M8598" + - "M8599" + - name: "I10-I15 Hypertensive diseases" + codings: + - "I15" + - "I150" + - "I151" + - "I152" + - "I158" + - "I159" + - "I10" + - "I11" + - "I110" + - "I119" + - "I12" + - "I120" + - "I129" + - "I13" + - "I130" + - "I131" + - "I132" + - "I139" + - name: "J00-J06 Acute upper respiratory infections" + codings: + - "J00" + - "J01" + - "J010" + - "J011" + - "J012" + - "J013" + - "J014" + - "J018" + - "J019" + - "J02" + - "J020" + - "J028" + - "J029" + - "J03" + - "J030" + - "J038" + - "J039" + - "J04" + - "J040" + - "J041" + - "J042" + - "J05" + - "J050" + - "J051" + - "J06" + - "J060" + - "J068" + - "J069" + - name: "M10 Gout" + codings: + - "M100" + - "M1000" + - "M1001" + - "M1002" + - "M1003" + - "M1004" + - "M1005" + - "M1006" + - "M1007" + - "M1008" + - "M1009" + - "M101" + - "M1010" + - "M1011" + - "M1012" + - "M1013" + - "M1014" + - "M1015" + - "M1016" + - "M1017" + - "M1018" + - "M1019" + - "M102" + - "M1020" + - "M1021" + - "M1022" + - "M1023" + - "M1024" + - "M1025" + - "M1026" + - "M1027" + - "M1028" + - "M1029" + - "M103" + - "M1030" + - "M1031" + - "M1032" + - "M1033" + - "M1034" + - "M1035" + - "M1036" + - "M1037" + - "M1038" + - "M1039" + - "M104" + - "M1040" + - "M1041" + - "M1042" + - "M1043" + - "M1044" + - "M1045" + - "M1046" + - "M1047" + - "M1048" + - "M1049" + - "M109" + - "M1090" + - "M1091" + - "M1092" + - "M1093" + - "M1094" + - "M1095" + - "M1096" + - "M1097" + - "M1098" + - "M1099" + - name: "M13 Other arthritis" + codings: + - "M1394" + - "M1395" + - "M1396" + - "M1397" + - "M1398" + - "M1399" + - "M130" + - "M1300" + - "M1301" + - "M1302" + - "M1303" + - "M1304" + - "M1305" + - "M1306" + - "M1307" + - "M1308" + - "M1309" + - "M131" + - "M1310" + - "M1311" + - "M1312" + - "M1313" + - "M1314" + - "M1315" + - "M1316" + - "M1317" + - "M1318" + - "M1319" + - "M138" + - "M1380" + - "M1381" + - "M1382" + - "M1383" + - "M1384" + - "M1385" + - "M1386" + - "M1387" + - "M1388" + - "M1389" + - "M139" + - "M1390" + - "M1391" + - "M1392" + - "M1393" + - name: "M15 Polyarthrosis" + codings: + - "M150" + - "M1500" + - "M151" + - "M152" + - "M153" + - "M154" + - "M158" + - "M159" + - "M1599" + - name: "M17 Gonarthrosis [arthrosis of knee]" + codings: + - "M170" + - "M171" + - "M172" + - "M173" + - "M174" + - "M175" + - "M179" + - name: "M16 Coxarthrosis [arthrosis of hip]" + codings: + - "M166" + - "M167" + - "M169" + - "M160" + - "M161" + - "M162" + - "M163" + - "M164" + - "M165" + - name: "M19 Other arthrosis" + codings: + - "M190" + - "M1900" + - "M1901" + - "M1902" + - "M1903" + - "M1904" + - "M1905" + - "M1906" + - "M1907" + - "M1908" + - "M1909" + - "M191" + - "M1910" + - "M1911" + - "M1912" + - "M1913" + - "M1914" + - "M1915" + - "M1916" + - "M1917" + - "M1918" + - "M1919" + - "M192" + - "M1920" + - "M1921" + - "M1922" + - "M1923" + - "M1924" + - "M1925" + - "M1926" + - "M1927" + - "M1928" + - "M1929" + - "M198" + - "M1980" + - "M1981" + - "M1982" + - "M1983" + - "M1984" + - "M1985" + - "M1986" + - "M1987" + - "M1988" + - "M1989" + - "M199" + - "M1990" + - "M1991" + - "M1992" + - "M1993" + - "M1994" + - "M1995" + - "M1996" + - "M1997" + - "M1998" + - "M1999" + - name: "M18 Arthrosis of first carpometacarpal joint" + codings: + - "M180" + - "M181" + - "M182" + - "M183" + - "M184" + - "M185" + - "M189" + - name: "L53 Other erythematous conditions" + codings: + - "L530" + - "L531" + - "L532" + - "L533" + - "L538" + - "L539" + - name: "L57 Skin changes due to chronic exposure to nonionising radiation" + codings: + - "L570" + - "L571" + - "L572" + - "L573" + - "L574" + - "L575" + - "L578" + - "L579" + - name: "E11 Non-insulin-dependent diabetes mellitus" + codings: + - "E110" + - "E111" + - "E112" + - "E113" + - "E114" + - "E115" + - "E116" + - "E117" + - "E118" + - "E119" + - name: "E10 Insulin-dependent diabetes mellitus" + codings: + - "E100" + - "E101" + - "E102" + - "E103" + - "E104" + - "E105" + - "E106" + - "E107" + - "E108" + - "E109" + - name: "J47 Bronchiectasis" + codings: + - "J47" + - name: "E14 Unspecified diabetes mellitus" + codings: + - "E140" + - "E141" + - "E142" + - "E143" + - "E144" + - "E145" + - "E146" + - "E147" + - "E148" + - "E149" + - name: "J43 Emphysema" + codings: + - "J432" + - "J438" + - "J439" + - "J430" + - "J431" + - name: "E16 Other disorders of pancreatic internal secretion" + codings: + - "E160" + - "E161" + - "E162" + - "E163" + - "E164" + - "E168" + - "E169" + - name: "O04 Medical abortion" + codings: + - "O040" + - "O041" + - "O042" + - "O043" + - "O044" + - "O045" + - "O046" + - "O047" + - "O048" + - "O049" + - name: "O02 Other abnormal products of conception" + codings: + - "O020" + - "O021" + - "O028" + - "O029" + - name: "O03 Spontaneous abortion" + codings: + - "O031" + - "O032" + - "O033" + - "O034" + - "O035" + - "O036" + - "O037" + - "O038" + - "O039" + - "O030" + - name: "G95 Other diseases of spinal cord" + codings: + - "G950" + - "G951" + - "G952" + - "G958" + - "G959" + - name: "G93 Other disorders of brain" + codings: + - "G930" + - "G931" + - "G932" + - "G933" + - "G934" + - "G935" + - "G936" + - "G937" + - "G938" + - "G939" + - name: "G91 Hydrocephalus" + codings: + - "G910" + - "G911" + - "G912" + - "G913" + - "G918" + - "G919" + - name: "G99 Other disorders of nervous system in diseases classified elsewhere" + codings: + - "G990" + - "G991" + - "G992" + - "G998" + - name: "K29 Gastritis and duodenitis" + codings: + - "K290" + - "K291" + - "K292" + - "K293" + - "K294" + - "K295" + - "K296" + - "K297" + - "K298" + - "K299" + - name: "K22 Other diseases of oesophagus" + codings: + - "K220" + - "K221" + - "K222" + - "K223" + - "K224" + - "K225" + - "K226" + - "K227" + - "K228" + - "K229" + - name: "K20 Oesophagitis" + codings: + - "K20" + - name: "I26-I28 Pulmonary heart disease and diseases of pulmonary circulation" + codings: + - "I26" + - "I260" + - "I269" + - "I27" + - "I270" + - "I271" + - "I272" + - "I278" + - "I279" + - "I28" + - "I280" + - "I281" + - "I288" + - "I289" + - name: "K26 Duodenal ulcer" + codings: + - "K260" + - "K261" + - "K262" + - "K263" + - "K264" + - "K265" + - "K266" + - "K267" + - "K269" + - name: "K25 Gastric ulcer" + codings: + - "K259" + - "K250" + - "K251" + - "K252" + - "K253" + - "K254" + - "K255" + - "K256" + - "K257" + - name: "E86 Volume depletion" + codings: + - "E86" + - name: "E87 Other disorders of fluid, electrolyte and acid-base balance" + codings: + - "E876" + - "E877" + - "E878" + - "E870" + - "E871" + - "E872" + - "E873" + - "E874" + - "E875" + - name: "E83 Disorders of mineral metabolism" + codings: + - "E830" + - "E831" + - "E832" + - "E833" + - "E834" + - "E835" + - "E838" + - "E839" + - name: "E89 Postprocedural endocrine and metabolic disorders, not elsewhere classified" + codings: + - "E890" + - "E891" + - "E892" + - "E893" + - "E894" + - "E895" + - "E896" + - "E898" + - "E899" + - name: "N50 Other disorders of male genital organs" + codings: + - "N500" + - "N501" + - "N508" + - "N509" + - name: "I60-I69 Cerebrovascular diseases" + codings: + - "I60" + - "I600" + - "I601" + - "I602" + - "I603" + - "I604" + - "I605" + - "I606" + - "I607" + - "I608" + - "I609" + - "I61" + - "I610" + - "I611" + - "I612" + - "I613" + - "I614" + - "I615" + - "I616" + - "I618" + - "I619" + - "I62" + - "I620" + - "I621" + - "I629" + - "I63" + - "I630" + - "I631" + - "I632" + - "I633" + - "I634" + - "I635" + - "I636" + - "I638" + - "I639" + - "I64" + - "I65" + - "I650" + - "I651" + - "I652" + - "I653" + - "I658" + - "I659" + - "I66" + - "I660" + - "I661" + - "I662" + - "I663" + - "I664" + - "I668" + - "I669" + - "I67" + - "I670" + - "I671" + - "I672" + - "I673" + - "I674" + - "I675" + - "I676" + - "I677" + - "I678" + - "I679" + - "I68" + - "I680" + - "I681" + - "I682" + - "I688" + - "I69" + - "I690" + - "I691" + - "I692" + - "I693" + - "I694" + - "I698" + - name: "M54 Dorsalgia" + codings: + - "M540" + - "M5400" + - "M5401" + - "M5402" + - "M5403" + - "M5404" + - "M5405" + - "M5406" + - "M5407" + - "M5408" + - "M5409" + - "M541" + - "M5410" + - "M5411" + - "M5412" + - "M5413" + - "M5414" + - "M5415" + - "M5416" + - "M5417" + - "M5418" + - "M5419" + - "M542" + - "M5420" + - "M5421" + - "M5422" + - "M5423" + - "M5424" + - "M5425" + - "M5426" + - "M5427" + - "M5428" + - "M5429" + - "M543" + - "M5430" + - "M5431" + - "M5432" + - "M5433" + - "M5434" + - "M5435" + - "M5436" + - "M5437" + - "M5438" + - "M5439" + - "M544" + - "M5440" + - "M5441" + - "M5442" + - "M5443" + - "M5444" + - "M5445" + - "M5446" + - "M5447" + - "M5448" + - "M5449" + - "M545" + - "M5450" + - "M5451" + - "M5452" + - "M5453" + - "M5454" + - "M5455" + - "M5456" + - "M5457" + - "M5458" + - "M5459" + - "M546" + - "M5460" + - "M5461" + - "M5462" + - "M5463" + - "M5464" + - "M5465" + - "M5466" + - "M5467" + - "M5468" + - "M5469" + - "M548" + - "M5480" + - "M5481" + - "M5482" + - "M5483" + - "M5484" + - "M5485" + - "M5486" + - "M5487" + - "M5488" + - "M5489" + - "M549" + - "M5490" + - "M5491" + - "M5492" + - "M5493" + - "M5494" + - "M5495" + - "M5496" + - "M5497" + - "M5498" + - "M5499" + - name: "B35-B49 Mycoses" + codings: + - "B35" + - "B350" + - "B351" + - "B352" + - "B353" + - "B354" + - "B355" + - "B356" + - "B358" + - "B359" + - "B36" + - "B360" + - "B361" + - "B362" + - "B363" + - "B368" + - "B369" + - "B37" + - "B370" + - "B371" + - "B372" + - "B373" + - "B374" + - "B375" + - "B376" + - "B377" + - "B378" + - "B379" + - "B38" + - "B380" + - "B381" + - "B382" + - "B383" + - "B384" + - "B387" + - "B388" + - "B389" + - "B39" + - "B390" + - "B391" + - "B392" + - "B393" + - "B394" + - "B395" + - "B399" + - "B40" + - "B400" + - "B401" + - "B402" + - "B403" + - "B407" + - "B408" + - "B409" + - "B41" + - "B410" + - "B417" + - "B418" + - "B419" + - "B42" + - "B420" + - "B421" + - "B427" + - "B428" + - "B429" + - "B43" + - "B430" + - "B431" + - "B432" + - "B438" + - "B439" + - "B44" + - "B440" + - "B441" + - "B442" + - "B447" + - "B448" + - "B449" + - "B45" + - "B450" + - "B451" + - "B452" + - "B453" + - "B457" + - "B458" + - "B459" + - "B46" + - "B460" + - "B461" + - "B462" + - "B463" + - "B464" + - "B465" + - "B468" + - "B469" + - "B47" + - "B470" + - "B471" + - "B479" + - "B48" + - "B480" + - "B481" + - "B482" + - "B483" + - "B484" + - "B487" + - "B488" + - "B49" + - name: "F20 Schizophrenia" + codings: + - "F200" + - "F201" + - "F202" + - "F203" + - "F204" + - "F205" + - "F206" + - "F208" + - "F209" + - name: "D50 Iron deficiency anaemia" + codings: + - "D501" + - "D508" + - "D509" + - "D500" + - name: "N99-N99 Other disorders of the genitourinary system" + codings: + - "N99" + - "N990" + - "N991" + - "N992" + - "N993" + - "N994" + - "N995" + - "N998" + - "N999" + - name: "N25-N29 Other disorders of kidney and ureter" + codings: + - "N279" + - "N28" + - "N280" + - "N281" + - "N288" + - "N289" + - "N29" + - "N290" + - "N291" + - "N298" + - "N25" + - "N250" + - "N251" + - "N258" + - "N259" + - "N26" + - "N27" + - "N270" + - "N271" + - name: "K70-K77 Diseases of liver" + codings: + - "K70" + - "K700" + - "K701" + - "K702" + - "K703" + - "K704" + - "K709" + - "K71" + - "K710" + - "K711" + - "K712" + - "K713" + - "K714" + - "K715" + - "K716" + - "K717" + - "K718" + - "K719" + - "K72" + - "K720" + - "K721" + - "K729" + - "K73" + - "K730" + - "K731" + - "K732" + - "K738" + - "K739" + - "K74" + - "K740" + - "K741" + - "K742" + - "K743" + - "K744" + - "K745" + - "K746" + - "K75" + - "K750" + - "K751" + - "K752" + - "K753" + - "K754" + - "K758" + - "K759" + - "K76" + - "K760" + - "K761" + - "K762" + - "K763" + - "K764" + - "K765" + - "K766" + - "K767" + - "K768" + - "K769" + - "K77" + - "K770" + - "K778" + - name: "I77 Other disorders of arteries and arterioles" + codings: + - "I770" + - "I771" + - "I772" + - "I773" + - "I774" + - "I775" + - "I776" + - "I778" + - "I779" + - name: "N28 Other disorders of kidney and ureter, not elsewhere classified" + codings: + - "N280" + - "N281" + - "N288" + - "N289" + - name: "I73 Other peripheral vascular diseases" + codings: + - "I730" + - "I731" + - "I738" + - "I739" + - name: "I05-I09 Chronic rheumatic heart diseases" + codings: + - "I05" + - "I050" + - "I051" + - "I052" + - "I058" + - "I059" + - "I06" + - "I060" + - "I061" + - "I062" + - "I068" + - "I069" + - "I07" + - "I070" + - "I071" + - "I072" + - "I078" + - "I079" + - "I08" + - "I080" + - "I081" + - "I082" + - "I083" + - "I088" + - "I089" + - "I09" + - "I090" + - "I091" + - "I092" + - "I098" + - "I099" + - name: "I71 Aortic aneurysm and dissection" + codings: + - "I710" + - "I711" + - "I712" + - "I713" + - "I714" + - "I715" + - "I716" + - "I718" + - "I719" + - name: "I70 Atherosclerosis" + codings: + - "I7081" + - "I709" + - "I7090" + - "I7091" + - "I700" + - "I7000" + - "I7001" + - "I701" + - "I7010" + - "I7011" + - "I702" + - "I7020" + - "I7021" + - "I708" + - "I7080" + - name: "N23 Unspecified renal colic" + codings: + - "N23" + - name: "N21 Calculus of lower urinary tract" + codings: + - "N211" + - "N218" + - "N219" + - "N210" + - name: "N20 Calculus of kidney and ureter" + codings: + - "N200" + - "N201" + - "N202" + - "N209" + - name: "I78 Diseases of capillaries" + codings: + - "I780" + - "I781" + - "I788" + - "I789" + - name: "E20-E35 Disorders of other endocrine glands" + codings: + - "E20" + - "E200" + - "E201" + - "E208" + - "E209" + - "E21" + - "E210" + - "E211" + - "E212" + - "E213" + - "E214" + - "E215" + - "E22" + - "E220" + - "E221" + - "E222" + - "E228" + - "E229" + - "E23" + - "E230" + - "E231" + - "E232" + - "E233" + - "E236" + - "E237" + - "E24" + - "E240" + - "E241" + - "E242" + - "E243" + - "E244" + - "E248" + - "E249" + - "E25" + - "E250" + - "E258" + - "E259" + - "E26" + - "E260" + - "E261" + - "E268" + - "E269" + - "E27" + - "E270" + - "E271" + - "E272" + - "E273" + - "E274" + - "E275" + - "E278" + - "E279" + - "E28" + - "E280" + - "E281" + - "E282" + - "E283" + - "E288" + - "E289" + - "E29" + - "E290" + - "E291" + - "E298" + - "E299" + - "E30" + - "E300" + - "E301" + - "E308" + - "E309" + - "E31" + - "E310" + - "E311" + - "E318" + - "E319" + - "E32" + - "E320" + - "E321" + - "E328" + - "E329" + - "E34" + - "E340" + - "E341" + - "E342" + - "E343" + - "E344" + - "E345" + - "E348" + - "E349" + - "E35" + - "E350" + - "E351" + - "E358" + - name: "M43 Other deforming dorsopathies" + codings: + - "M430" + - "M4300" + - "M4301" + - "M4302" + - "M4303" + - "M4304" + - "M4305" + - "M4306" + - "M4307" + - "M4308" + - "M4309" + - "M431" + - "M4310" + - "M4311" + - "M4312" + - "M4313" + - "M4314" + - "M4315" + - "M4316" + - "M4317" + - "M4318" + - "M4319" + - "M432" + - "M4320" + - "M4321" + - "M4322" + - "M4323" + - "M4324" + - "M4325" + - "M4326" + - "M4327" + - "M4328" + - "M4329" + - "M433" + - "M4330" + - "M4331" + - "M4332" + - "M4333" + - "M4334" + - "M4335" + - "M4336" + - "M4337" + - "M4338" + - "M4339" + - "M434" + - "M4340" + - "M4341" + - "M4342" + - "M4343" + - "M4344" + - "M4345" + - "M4346" + - "M4347" + - "M4348" + - "M4349" + - "M435" + - "M4350" + - "M4351" + - "M4352" + - "M4353" + - "M4354" + - "M4355" + - "M4356" + - "M4357" + - "M4358" + - "M4359" + - "M436" + - "M4360" + - "M4361" + - "M4362" + - "M4363" + - "M4364" + - "M4365" + - "M4366" + - "M4367" + - "M4368" + - "M4369" + - "M438" + - "M4380" + - "M4381" + - "M4382" + - "M4383" + - "M4384" + - "M4385" + - "M4386" + - "M4387" + - "M4388" + - "M4389" + - "M439" + - "M4390" + - "M4391" + - "M4392" + - "M4393" + - "M4394" + - "M4395" + - "M4396" + - "M4397" + - "M4398" + - "M4399" + - name: "M41 Scoliosis" + codings: + - "M410" + - "M4100" + - "M4101" + - "M4102" + - "M4103" + - "M4104" + - "M4105" + - "M4106" + - "M4107" + - "M4108" + - "M4109" + - "M411" + - "M4110" + - "M4111" + - "M4112" + - "M4113" + - "M4114" + - "M4115" + - "M4116" + - "M4117" + - "M4118" + - "M4119" + - "M412" + - "M4120" + - "M4121" + - "M4122" + - "M4123" + - "M4124" + - "M4125" + - "M4126" + - "M4127" + - "M4128" + - "M4129" + - "M413" + - "M4130" + - "M4131" + - "M4132" + - "M4133" + - "M4134" + - "M4135" + - "M4136" + - "M4137" + - "M4138" + - "M4139" + - "M414" + - "M4140" + - "M4141" + - "M4142" + - "M4143" + - "M4144" + - "M4145" + - "M4146" + - "M4147" + - "M4148" + - "M4149" + - "M415" + - "M4150" + - "M4151" + - "M4152" + - "M4153" + - "M4154" + - "M4155" + - "M4156" + - "M4157" + - "M4158" + - "M4159" + - "M418" + - "M4180" + - "M4181" + - "M4182" + - "M4183" + - "M4184" + - "M4185" + - "M4186" + - "M4187" + - "M4188" + - "M4189" + - "M419" + - "M4190" + - "M4191" + - "M4192" + - "M4193" + - "M4194" + - "M4195" + - "M4196" + - "M4197" + - "M4198" + - "M4199" + - name: "M46 Other inflammatory spondylopathies" + codings: + - "M460" + - "M4600" + - "M4601" + - "M4602" + - "M4603" + - "M4604" + - "M4605" + - "M4606" + - "M4607" + - "M4608" + - "M4609" + - "M461" + - "M4610" + - "M4611" + - "M4612" + - "M4613" + - "M4614" + - "M4615" + - "M4616" + - "M4617" + - "M4618" + - "M4619" + - "M462" + - "M4620" + - "M4621" + - "M4622" + - "M4623" + - "M4624" + - "M4625" + - "M4626" + - "M4627" + - "M4628" + - "M4629" + - "M463" + - "M4630" + - "M4631" + - "M4632" + - "M4633" + - "M4634" + - "M4635" + - "M4636" + - "M4637" + - "M4638" + - "M4639" + - "M464" + - "M4640" + - "M4641" + - "M4642" + - "M4643" + - "M4644" + - "M4645" + - "M4646" + - "M4647" + - "M4648" + - "M4649" + - "M465" + - "M4650" + - "M4651" + - "M4652" + - "M4653" + - "M4654" + - "M4655" + - "M4656" + - "M4657" + - "M4658" + - "M4659" + - "M468" + - "M4680" + - "M4681" + - "M4682" + - "M4683" + - "M4684" + - "M4685" + - "M4686" + - "M4687" + - "M4688" + - "M4689" + - "M469" + - "M4690" + - "M4691" + - "M4692" + - "M4693" + - "M4694" + - "M4695" + - "M4696" + - "M4697" + - "M4698" + - "M4699" + - name: "M47 Spondylosis" + codings: + - "M4729" + - "M478" + - "M4780" + - "M4781" + - "M4782" + - "M4783" + - "M4784" + - "M4785" + - "M4786" + - "M4787" + - "M4788" + - "M4789" + - "M479" + - "M4790" + - "M4791" + - "M4792" + - "M4793" + - "M4794" + - "M4795" + - "M4796" + - "M4797" + - "M4798" + - "M4799" + - "M470" + - "M4700" + - "M4701" + - "M4702" + - "M4703" + - "M4704" + - "M4705" + - "M4706" + - "M4707" + - "M4708" + - "M4709" + - "M471" + - "M4710" + - "M4711" + - "M4712" + - "M4713" + - "M4714" + - "M4715" + - "M4716" + - "M4717" + - "M4718" + - "M4719" + - "M472" + - "M4720" + - "M4721" + - "M4722" + - "M4723" + - "M4724" + - "M4725" + - "M4726" + - "M4727" + - "M4728" + - name: "K51 Ulcerative colitis" + codings: + - "K510" + - "K511" + - "K512" + - "K513" + - "K514" + - "K515" + - "K518" + - "K519" + - name: "N35 Urethral stricture" + codings: + - "N350" + - "N351" + - "N358" + - "N359" + - name: "F20-F29 Schizophrenia, schizotypal and delusional disorders" + codings: + - "F20" + - "F200" + - "F201" + - "F202" + - "F203" + - "F204" + - "F205" + - "F206" + - "F208" + - "F209" + - "F21" + - "F22" + - "F220" + - "F228" + - "F229" + - "F23" + - "F230" + - "F231" + - "F232" + - "F233" + - "F238" + - "F239" + - "F24" + - "F25" + - "F250" + - "F251" + - "F252" + - "F258" + - "F259" + - "F28" + - "F29" + - name: "H61 Other disorders of external ear" + codings: + - "H610" + - "H611" + - "H612" + - "H613" + - "H618" + - "H619" + - name: "H60 Otitis externa" + codings: + - "H600" + - "H601" + - "H602" + - "H603" + - "H604" + - "H605" + - "H608" + - "H609" + - name: "N40-N51 Diseases of male genital organs" + codings: + - "N40" + - "N41" + - "N410" + - "N411" + - "N412" + - "N413" + - "N418" + - "N419" + - "N42" + - "N420" + - "N421" + - "N422" + - "N423" + - "N428" + - "N429" + - "N43" + - "N430" + - "N431" + - "N432" + - "N433" + - "N434" + - "N44" + - "N45" + - "N450" + - "N459" + - "N46" + - "N47" + - "N48" + - "N480" + - "N481" + - "N482" + - "N483" + - "N484" + - "N485" + - "N486" + - "N488" + - "N489" + - "N49" + - "N490" + - "N491" + - "N492" + - "N498" + - "N499" + - "N50" + - "N500" + - "N501" + - "N508" + - "N509" + - "N51" + - "N510" + - "N511" + - "N512" + - "N518" + - name: "H65 Nonsuppurative otitis media" + codings: + - "H654" + - "H659" + - "H650" + - "H651" + - "H652" + - "H653" + - name: "H66 Suppurative and unspecified otitis media" + codings: + - "H660" + - "H661" + - "H662" + - "H663" + - "H664" + - "H669" + - name: "H83 Other diseases of inner ear" + codings: + - "H830" + - "H831" + - "H832" + - "H833" + - "H838" + - "H839" + - name: "H81 Disorders of vestibular function" + codings: + - "H810" + - "H811" + - "H812" + - "H813" + - "H814" + - "H818" + - "H819" + - name: "M86-M90 Other osteopathies" + codings: + - "M86" + - "M860" + - "M8600" + - "M8601" + - "M8602" + - "M8603" + - "M8604" + - "M8605" + - "M8606" + - "M8607" + - "M8608" + - "M8609" + - "M861" + - "M8610" + - "M8611" + - "M8612" + - "M8613" + - "M8614" + - "M8615" + - "M8616" + - "M8617" + - "M8618" + - "M8619" + - "M862" + - "M8620" + - "M8621" + - "M8622" + - "M8623" + - "M8624" + - "M8625" + - "M8626" + - "M8627" + - "M8628" + - "M8629" + - "M863" + - "M8630" + - "M8631" + - "M8632" + - "M8633" + - "M8634" + - "M8635" + - "M8636" + - "M8637" + - "M8638" + - "M8639" + - "M864" + - "M8640" + - "M8641" + - "M8642" + - "M8643" + - "M8644" + - "M8645" + - "M8646" + - "M8647" + - "M8648" + - "M8649" + - "M865" + - "M8650" + - "M8651" + - "M8652" + - "M8653" + - "M8654" + - "M8655" + - "M8656" + - "M8657" + - "M8658" + - "M8659" + - "M866" + - "M8660" + - "M8661" + - "M8662" + - "M8663" + - "M8664" + - "M8665" + - "M8666" + - "M8667" + - "M8668" + - "M8669" + - "M868" + - "M8680" + - "M8681" + - "M8682" + - "M8683" + - "M8684" + - "M8685" + - "M8686" + - "M8687" + - "M8688" + - "M8689" + - "M869" + - "M8690" + - "M8691" + - "M8692" + - "M8693" + - "M8694" + - "M8695" + - "M8696" + - "M8697" + - "M8698" + - "M8699" + - "M87" + - "M870" + - "M8700" + - "M8701" + - "M8702" + - "M8703" + - "M8704" + - "M8705" + - "M8706" + - "M8707" + - "M8708" + - "M8709" + - "M871" + - "M8710" + - "M8711" + - "M8712" + - "M8713" + - "M8714" + - "M8715" + - "M8716" + - "M8717" + - "M8718" + - "M8719" + - "M872" + - "M8720" + - "M8721" + - "M8722" + - "M8723" + - "M8724" + - "M8725" + - "M8726" + - "M8727" + - "M8728" + - "M8729" + - "M873" + - "M8730" + - "M8731" + - "M8732" + - "M8733" + - "M8734" + - "M8735" + - "M8736" + - "M8737" + - "M8738" + - "M8739" + - "M878" + - "M8780" + - "M8781" + - "M8782" + - "M8783" + - "M8784" + - "M8785" + - "M8786" + - "M8787" + - "M8788" + - "M8789" + - "M879" + - "M8790" + - "M8791" + - "M8792" + - "M8793" + - "M8794" + - "M8795" + - "M8796" + - "M8797" + - "M8798" + - "M8799" + - "M88" + - "M880" + - "M8800" + - "M8801" + - "M8802" + - "M8803" + - "M8804" + - "M8805" + - "M8806" + - "M8807" + - "M8808" + - "M8809" + - "M888" + - "M8880" + - "M8881" + - "M8882" + - "M8883" + - "M8884" + - "M8885" + - "M8886" + - "M8887" + - "M8888" + - "M8889" + - "M889" + - "M8890" + - "M8891" + - "M8892" + - "M8893" + - "M8894" + - "M8895" + - "M8896" + - "M8897" + - "M8898" + - "M8899" + - "M89" + - "M890" + - "M8900" + - "M8901" + - "M8902" + - "M8903" + - "M8904" + - "M8905" + - "M8906" + - "M8907" + - "M8908" + - "M8909" + - "M891" + - "M8910" + - "M8911" + - "M8912" + - "M8913" + - "M8914" + - "M8915" + - "M8916" + - "M8917" + - "M8918" + - "M8919" + - "M892" + - "M8920" + - "M8921" + - "M8922" + - "M8923" + - "M8924" + - "M8925" + - "M8926" + - "M8927" + - "M8928" + - "M8929" + - "M893" + - "M8930" + - "M8931" + - "M8932" + - "M8933" + - "M8934" + - "M8935" + - "M8936" + - "M8937" + - "M8938" + - "M8939" + - "M894" + - "M8940" + - "M8941" + - "M8942" + - "M8943" + - "M8944" + - "M8945" + - "M8946" + - "M8947" + - "M8948" + - "M8949" + - "M895" + - "M8950" + - "M8951" + - "M8952" + - "M8953" + - "M8954" + - "M8955" + - "M8956" + - "M8957" + - "M8958" + - "M8959" + - "M896" + - "M8960" + - "M8961" + - "M8962" + - "M8963" + - "M8964" + - "M8965" + - "M8966" + - "M8967" + - "M8968" + - "M8969" + - "M898" + - "M8980" + - "M8981" + - "M8982" + - "M8983" + - "M8984" + - "M8985" + - "M8986" + - "M8987" + - "M8988" + - "M8989" + - "M899" + - "M8990" + - "M8991" + - "M8992" + - "M8993" + - "M8994" + - "M8995" + - "M8996" + - "M8997" + - "M8998" + - "M8999" + - "M90" + - "M900" + - "M9000" + - "M9001" + - "M9002" + - "M9003" + - "M9004" + - "M9005" + - "M9006" + - "M9007" + - "M9008" + - "M9009" + - "M901" + - "M9010" + - "M9011" + - "M9012" + - "M9013" + - "M9014" + - "M9015" + - "M9016" + - "M9017" + - "M9018" + - "M9019" + - "M902" + - "M9020" + - "M9021" + - "M9022" + - "M9023" + - "M9024" + - "M9025" + - "M9026" + - "M9027" + - "M9028" + - "M9029" + - "M903" + - "M9030" + - "M9031" + - "M9032" + - "M9033" + - "M9034" + - "M9035" + - "M9036" + - "M9037" + - "M9038" + - "M9039" + - "M904" + - "M9040" + - "M9041" + - "M9042" + - "M9043" + - "M9044" + - "M9045" + - "M9046" + - "M9047" + - "M9048" + - "M9049" + - "M905" + - "M9050" + - "M9051" + - "M9052" + - "M9053" + - "M9054" + - "M9055" + - "M9056" + - "M9057" + - "M9058" + - "M9059" + - "M906" + - "M9060" + - "M9061" + - "M9062" + - "M9063" + - "M9064" + - "M9065" + - "M9066" + - "M9067" + - "M9068" + - "M9069" + - "M907" + - "M9070" + - "M9071" + - "M9072" + - "M9073" + - "M9074" + - "M9075" + - "M9076" + - "M9077" + - "M9078" + - "M9079" + - "M908" + - "M9080" + - "M9081" + - "M9082" + - "M9083" + - "M9084" + - "M9085" + - "M9086" + - "M9087" + - "M9088" + - "M9089" + - name: "N60-N64 Disorders of breast" + codings: + - "N640" + - "N641" + - "N642" + - "N643" + - "N644" + - "N645" + - "N648" + - "N649" + - "N60" + - "N600" + - "N601" + - "N602" + - "N603" + - "N604" + - "N608" + - "N609" + - "N61" + - "N62" + - "N63" + - "N64" + - name: "K40-K46 Hernia" + codings: + - "K40" + - "K400" + - "K401" + - "K402" + - "K403" + - "K404" + - "K409" + - "K41" + - "K410" + - "K411" + - "K412" + - "K413" + - "K414" + - "K419" + - "K42" + - "K420" + - "K421" + - "K429" + - "K43" + - "K430" + - "K431" + - "K432" + - "K433" + - "K434" + - "K435" + - "K436" + - "K437" + - "K439" + - "K44" + - "K440" + - "K441" + - "K449" + - "K45" + - "K450" + - "K451" + - "K458" + - "K46" + - "K460" + - "K461" + - "K469" + - name: "L85 Other epidermal thickening" + codings: + - "L850" + - "L851" + - "L852" + - "L853" + - "L858" + - "L859" + - name: "L82 Seborrhoeic keratosis" + codings: + - "L82" + - name: "L81 Other disorders of pigmentation" + codings: + - "L814" + - "L815" + - "L816" + - "L817" + - "L818" + - "L819" + - "L810" + - "L811" + - "L812" + - "L813" + - name: "L89 Decubitus ulcer" + codings: + - "L890" + - "L891" + - "L892" + - "L893" + - "L899" + - name: "M25 Other joint disorders, not elsewhere classified" + codings: + - "M250" + - "M2500" + - "M2501" + - "M2502" + - "M2503" + - "M2504" + - "M2505" + - "M2506" + - "M2507" + - "M2508" + - "M2509" + - "M251" + - "M2510" + - "M2511" + - "M2512" + - "M2513" + - "M2514" + - "M2515" + - "M2516" + - "M2517" + - "M2518" + - "M2519" + - "M252" + - "M2520" + - "M2521" + - "M2522" + - "M2523" + - "M2524" + - "M2525" + - "M2526" + - "M2527" + - "M2528" + - "M2529" + - "M253" + - "M2530" + - "M2531" + - "M2532" + - "M2533" + - "M2534" + - "M2535" + - "M2536" + - "M2537" + - "M2538" + - "M2539" + - "M254" + - "M2540" + - "M2541" + - "M2542" + - "M2543" + - "M2544" + - "M2545" + - "M2546" + - "M2547" + - "M2548" + - "M2549" + - "M255" + - "M2550" + - "M2551" + - "M2552" + - "M2553" + - "M2554" + - "M2555" + - "M2556" + - "M2557" + - "M2558" + - "M2559" + - "M256" + - "M2560" + - "M2561" + - "M2562" + - "M2563" + - "M2564" + - "M2565" + - "M2566" + - "M2567" + - "M2568" + - "M2569" + - "M257" + - "M2570" + - "M2571" + - "M2572" + - "M2573" + - "M2574" + - "M2575" + - "M2576" + - "M2577" + - "M2578" + - "M2579" + - "M258" + - "M2580" + - "M2581" + - "M2582" + - "M2583" + - "M2584" + - "M2585" + - "M2586" + - "M2587" + - "M2588" + - "M2589" + - "M259" + - "M2590" + - "M2591" + - "M2592" + - "M2593" + - "M2594" + - "M2595" + - "M2596" + - "M2597" + - "M2598" + - "M2599" + - name: "J96 Respiratory failure, not elsewhere classified" + codings: + - "J960" + - "J9600" + - "J9601" + - "J9609" + - "J961" + - "J9610" + - "J9611" + - "J9619" + - "J969" + - "J9690" + - "J9691" + - "J9699" + - name: "J92 Pleural plaque" + codings: + - "J920" + - "J929" + - name: "J93 Pneumothorax" + codings: + - "J930" + - "J931" + - "J938" + - "J939" + - name: "J90 Pleural effusion, not elsewhere classified" + codings: + - "J90" + - name: "J98 Other respiratory disorders" + codings: + - "J988" + - "J989" + - "J980" + - "J981" + - "J982" + - "J983" + - "J984" + - "J985" + - "J986" + - name: "D60-D64 Aplastic and other anaemias" + codings: + - "D630" + - "D631" + - "D638" + - "D64" + - "D640" + - "D641" + - "D642" + - "D643" + - "D644" + - "D648" + - "D649" + - "D60" + - "D600" + - "D601" + - "D608" + - "D609" + - "D61" + - "D610" + - "D611" + - "D612" + - "D613" + - "D618" + - "D619" + - "D62" + - "D63" + - name: "B07 Viral warts" + codings: + - "B07" + - name: "E65-E68 Obesity and other hyperalimentation" + codings: + - "E65" + - "E66" + - "E660" + - "E661" + - "E662" + - "E668" + - "E669" + - "E67" + - "E670" + - "E671" + - "E672" + - "E673" + - "E678" + - "E68" + - name: "J40 Bronchitis, not specified as acute or chronic" + codings: + - "J40" + - name: "O75 Other complications of labour and delivery, not elsewhere classified" + codings: + - "O750" + - "O751" + - "O752" + - "O753" + - "O754" + - "O755" + - "O756" + - "O757" + - "O758" + - "O759" + - name: "J03 Acute tonsillitis" + codings: + - "J030" + - "J038" + - "J039" + - name: "J02 Acute pharyngitis" + codings: + - "J020" + - "J028" + - "J029" + - name: "O70 Perineal laceration during delivery" + codings: + - "O700" + - "O701" + - "O702" + - "O703" + - "O709" + - name: "O72 Postpartum haemorrhage" + codings: + - "O720" + - "O721" + - "O722" + - "O723" + - name: "K13 Other diseases of lip and oral mucosa" + codings: + - "K130" + - "K131" + - "K132" + - "K1329" + - "K133" + - "K134" + - "K135" + - "K136" + - "K137" + - name: "K12 Stomatitis and related lesions" + codings: + - "K120" + - "K121" + - "K122" + - "K123" + - name: "K11 Diseases of salivary glands" + codings: + - "K110" + - "K111" + - "K112" + - "K113" + - "K114" + - "K115" + - "K116" + - "K117" + - "K118" + - "K119" + - name: "K14 Diseases of tongue" + codings: + - "K145" + - "K146" + - "K148" + - "K149" + - "K140" + - "K141" + - "K142" + - "K143" + - "K144" + - name: "I20 Angina pectoris" + codings: + - "I201" + - "I208" + - "I209" + - "I200" + - name: "I21 Acute myocardial infarction" + codings: + - "I210" + - "I211" + - "I212" + - "I213" + - "I214" + - "I219" + - "I21X" + - name: "I22 Subsequent myocardial infarction" + codings: + - "I220" + - "I221" + - "I228" + - "I229" + - name: "I24 Other acute ischaemic heart diseases" + codings: + - "I240" + - "I241" + - "I248" + - "I249" + - name: "I25 Chronic ischaemic heart disease" + codings: + - "I250" + - "I251" + - "I252" + - "I253" + - "I254" + - "I255" + - "I256" + - "I258" + - "I259" + - name: "I26 Pulmonary embolism" + codings: + - "I260" + - "I269" + - name: "I27 Other pulmonary heart diseases" + codings: + - "I279" + - "I270" + - "I271" + - "I272" + - "I278" + - name: "M40-M43 Deforming dorsopathies" + codings: + - "M4034" + - "M4035" + - "M4036" + - "M4037" + - "M4038" + - "M4039" + - "M404" + - "M4040" + - "M4041" + - "M4042" + - "M4043" + - "M4044" + - "M4045" + - "M4046" + - "M4047" + - "M4048" + - "M4049" + - "M405" + - "M4050" + - "M4051" + - "M4052" + - "M4053" + - "M4054" + - "M4055" + - "M4056" + - "M4057" + - "M4058" + - "M4059" + - "M41" + - "M410" + - "M4100" + - "M4101" + - "M4102" + - "M4103" + - "M4104" + - "M4105" + - "M4106" + - "M4107" + - "M4108" + - "M4109" + - "M411" + - "M4110" + - "M4111" + - "M4112" + - "M4113" + - "M4114" + - "M4115" + - "M4116" + - "M4117" + - "M4118" + - "M4119" + - "M412" + - "M4120" + - "M4121" + - "M4122" + - "M4123" + - "M4124" + - "M4125" + - "M4126" + - "M4127" + - "M4128" + - "M4129" + - "M413" + - "M4130" + - "M4131" + - "M4132" + - "M4133" + - "M4134" + - "M4135" + - "M4136" + - "M4137" + - "M4138" + - "M4139" + - "M414" + - "M4140" + - "M4141" + - "M4142" + - "M4143" + - "M4144" + - "M4145" + - "M4146" + - "M4147" + - "M4148" + - "M4149" + - "M415" + - "M4150" + - "M4151" + - "M4152" + - "M4153" + - "M4154" + - "M4155" + - "M4156" + - "M4157" + - "M4158" + - "M4159" + - "M418" + - "M4180" + - "M4181" + - "M4182" + - "M4183" + - "M4184" + - "M4185" + - "M4186" + - "M4187" + - "M4188" + - "M4189" + - "M419" + - "M4190" + - "M4191" + - "M4192" + - "M4193" + - "M4194" + - "M4195" + - "M4196" + - "M4197" + - "M4198" + - "M4199" + - "M42" + - "M420" + - "M4200" + - "M4201" + - "M4202" + - "M4203" + - "M4204" + - "M4205" + - "M4206" + - "M4207" + - "M4208" + - "M4209" + - "M421" + - "M4210" + - "M4211" + - "M4212" + - "M4213" + - "M4214" + - "M4215" + - "M4216" + - "M4217" + - "M4218" + - "M4219" + - "M429" + - "M4290" + - "M4291" + - "M4292" + - "M4293" + - "M4294" + - "M4295" + - "M4296" + - "M4297" + - "M4298" + - "M4299" + - "M43" + - "M430" + - "M4300" + - "M4301" + - "M4302" + - "M4303" + - "M4304" + - "M4305" + - "M4306" + - "M4307" + - "M4308" + - "M4309" + - "M431" + - "M4310" + - "M4311" + - "M4312" + - "M4313" + - "M4314" + - "M4315" + - "M4316" + - "M4317" + - "M4318" + - "M4319" + - "M432" + - "M4320" + - "M4321" + - "M4322" + - "M4323" + - "M4324" + - "M4325" + - "M4326" + - "M4327" + - "M4328" + - "M4329" + - "M433" + - "M4330" + - "M4331" + - "M4332" + - "M4333" + - "M4334" + - "M4335" + - "M4336" + - "M4337" + - "M4338" + - "M4339" + - "M434" + - "M4340" + - "M4341" + - "M4342" + - "M4343" + - "M4344" + - "M4345" + - "M4346" + - "M4347" + - "M4348" + - "M4349" + - "M435" + - "M4350" + - "M4351" + - "M4352" + - "M4353" + - "M4354" + - "M4355" + - "M4356" + - "M4357" + - "M4358" + - "M4359" + - "M436" + - "M4360" + - "M4361" + - "M4362" + - "M4363" + - "M4364" + - "M4365" + - "M4366" + - "M4367" + - "M4368" + - "M4369" + - "M438" + - "M4380" + - "M4381" + - "M4382" + - "M4383" + - "M4384" + - "M4385" + - "M4386" + - "M4387" + - "M4388" + - "M4389" + - "M439" + - "M4390" + - "M4391" + - "M4392" + - "M4393" + - "M4394" + - "M4395" + - "M4396" + - "M4397" + - "M4398" + - "M4399" + - "M40" + - "M400" + - "M4000" + - "M4001" + - "M4002" + - "M4003" + - "M4004" + - "M4005" + - "M4006" + - "M4007" + - "M4008" + - "M4009" + - "M401" + - "M4010" + - "M4011" + - "M4012" + - "M4013" + - "M4014" + - "M4015" + - "M4016" + - "M4017" + - "M4018" + - "M4019" + - "M402" + - "M4020" + - "M4021" + - "M4022" + - "M4023" + - "M4024" + - "M4025" + - "M4026" + - "M4027" + - "M4028" + - "M4029" + - "M403" + - "M4030" + - "M4031" + - "M4032" + - "M4033" + - name: "J30-J39 Other diseases of upper respiratory tract" + codings: + - "J353" + - "J358" + - "J359" + - "J36" + - "J37" + - "J370" + - "J371" + - "J38" + - "J380" + - "J381" + - "J382" + - "J383" + - "J384" + - "J385" + - "J386" + - "J387" + - "J39" + - "J390" + - "J391" + - "J392" + - "J393" + - "J398" + - "J399" + - "J30" + - "J300" + - "J301" + - "J302" + - "J303" + - "J304" + - "J31" + - "J310" + - "J311" + - "J312" + - "J32" + - "J320" + - "J321" + - "J322" + - "J323" + - "J324" + - "J328" + - "J329" + - "J33" + - "J330" + - "J331" + - "J338" + - "J339" + - "J34" + - "J340" + - "J341" + - "J342" + - "J343" + - "J348" + - "J35" + - "J350" + - "J351" + - "J352" + - name: "N64 Other disorders of breast" + codings: + - "N640" + - "N641" + - "N642" + - "N643" + - "N644" + - "N645" + - "N648" + - "N649" + - name: "N63 Unspecified lump in breast" + codings: + - "N63" + - name: "N62 Hypertrophy of breast" + codings: + - "N62" + - name: "N60 Benign mammary dysplasia" + codings: + - "N600" + - "N601" + - "N602" + - "N603" + - "N604" + - "N608" + - "N609" + - name: "K66 Other disorders of peritoneum" + codings: + - "K669" + - "K660" + - "K661" + - "K668" + - name: "J45 Asthma" + codings: + - "J450" + - "J451" + - "J458" + - "J459" + - name: "K62 Other diseases of anus and rectum" + codings: + - "K620" + - "K621" + - "K622" + - "K623" + - "K624" + - "K625" + - "K626" + - "K627" + - "K628" + - "K629" + - name: "K63 Other diseases of intestine" + codings: + - "K631" + - "K632" + - "K633" + - "K634" + - "K635" + - "K638" + - "K639" + - "K630" + - name: "K60 Fissure and fistula of anal and rectal regions" + codings: + - "K600" + - "K601" + - "K602" + - "K603" + - "K604" + - "K605" + - name: "J44 Other chronic obstructive pulmonary disease" + codings: + - "J440" + - "J441" + - "J448" + - "J449" + - name: "L60-L75 Disorders of skin appendages" + codings: + - "L60" + - "L600" + - "L601" + - "L602" + - "L603" + - "L604" + - "L605" + - "L608" + - "L609" + - "L62" + - "L620" + - "L628" + - "L63" + - "L630" + - "L631" + - "L632" + - "L638" + - "L639" + - "L64" + - "L640" + - "L648" + - "L649" + - "L65" + - "L650" + - "L651" + - "L652" + - "L658" + - "L659" + - "L66" + - "L660" + - "L661" + - "L662" + - "L663" + - "L664" + - "L668" + - "L669" + - "L67" + - "L670" + - "L671" + - "L678" + - "L679" + - "L68" + - "L680" + - "L681" + - "L682" + - "L683" + - "L688" + - "L689" + - "L70" + - "L700" + - "L701" + - "L702" + - "L703" + - "L704" + - "L705" + - "L708" + - "L709" + - "L71" + - "L710" + - "L711" + - "L718" + - "L719" + - "L72" + - "L720" + - "L721" + - "L722" + - "L728" + - "L729" + - "L73" + - "L730" + - "L731" + - "L732" + - "L738" + - "L739" + - "L74" + - "L740" + - "L741" + - "L742" + - "L743" + - "L744" + - "L748" + - "L749" + - "L75" + - "L750" + - "L751" + - "L752" + - "L758" + - "L759" + - name: "I95 Hypotension" + codings: + - "I959" + - "I950" + - "I951" + - "I952" + - "I958" + - name: "E10-E14 Diabetes mellitus" + codings: + - "E10" + - "E100" + - "E101" + - "E102" + - "E103" + - "E104" + - "E105" + - "E106" + - "E107" + - "E108" + - "E109" + - "E11" + - "E110" + - "E111" + - "E112" + - "E113" + - "E114" + - "E115" + - "E116" + - "E117" + - "E118" + - "E119" + - "E12" + - "E120" + - "E121" + - "E122" + - "E123" + - "E124" + - "E125" + - "E126" + - "E127" + - "E128" + - "E129" + - "E13" + - "E130" + - "E131" + - "E132" + - "E133" + - "E134" + - "E135" + - "E136" + - "E137" + - "E138" + - "E139" + - "E14" + - "E140" + - "E141" + - "E142" + - "E143" + - "E144" + - "E145" + - "E146" + - "E147" + - "E148" + - "E149" + - name: "M94 Other disorders of cartilage" + codings: + - "M9417" + - "M9418" + - "M9419" + - "M942" + - "M9420" + - "M9421" + - "M9422" + - "M9423" + - "M9424" + - "M9425" + - "M9426" + - "M9427" + - "M9428" + - "M9429" + - "M943" + - "M9430" + - "M9431" + - "M9432" + - "M9433" + - "M9434" + - "M9435" + - "M9436" + - "M9437" + - "M9438" + - "M9439" + - "M948" + - "M9480" + - "M9481" + - "M9482" + - "M9483" + - "M9484" + - "M9485" + - "M9486" + - "M9487" + - "M9488" + - "M9489" + - "M949" + - "M9490" + - "M9491" + - "M9492" + - "M9493" + - "M9494" + - "M9495" + - "M9496" + - "M9497" + - "M9498" + - "M9499" + - "M940" + - "M9400" + - "M9401" + - "M9402" + - "M9403" + - "M9404" + - "M9405" + - "M9406" + - "M9407" + - "M9408" + - "M9409" + - "M941" + - "M9410" + - "M9411" + - "M9412" + - "M9413" + - "M9414" + - "M9415" + - "M9416" + - name: "F30-F39 Mood [affective] disorders" + codings: + - "F30" + - "F300" + - "F301" + - "F302" + - "F308" + - "F309" + - "F31" + - "F310" + - "F311" + - "F312" + - "F313" + - "F314" + - "F315" + - "F316" + - "F317" + - "F318" + - "F319" + - "F32" + - "F320" + - "F321" + - "F322" + - "F323" + - "F328" + - "F329" + - "F33" + - "F330" + - "F331" + - "F332" + - "F333" + - "F334" + - "F338" + - "F339" + - "F34" + - "F340" + - "F341" + - "F348" + - "F349" + - "F38" + - "F380" + - "F381" + - "F388" + - "F39" + - name: "M15-M19 Arthrosis" + codings: + - "M15" + - "M150" + - "M1500" + - "M151" + - "M152" + - "M153" + - "M154" + - "M158" + - "M159" + - "M1599" + - "M16" + - "M160" + - "M161" + - "M162" + - "M163" + - "M164" + - "M165" + - "M166" + - "M167" + - "M169" + - "M17" + - "M170" + - "M171" + - "M172" + - "M173" + - "M174" + - "M175" + - "M179" + - "M18" + - "M180" + - "M181" + - "M182" + - "M183" + - "M184" + - "M185" + - "M189" + - "M19" + - "M190" + - "M1900" + - "M1901" + - "M1902" + - "M1903" + - "M1904" + - "M1905" + - "M1906" + - "M1907" + - "M1908" + - "M1909" + - "M191" + - "M1910" + - "M1911" + - "M1912" + - "M1913" + - "M1914" + - "M1915" + - "M1916" + - "M1917" + - "M1918" + - "M1919" + - "M192" + - "M1920" + - "M1921" + - "M1922" + - "M1923" + - "M1924" + - "M1925" + - "M1926" + - "M1927" + - "M1928" + - "M1929" + - "M198" + - "M1980" + - "M1981" + - "M1982" + - "M1983" + - "M1984" + - "M1985" + - "M1986" + - "M1987" + - "M1988" + - "M1989" + - "M199" + - "M1990" + - "M1991" + - "M1992" + - "M1993" + - "M1994" + - "M1995" + - "M1996" + - "M1997" + - "M1998" + - "M1999" + - name: "H10-H13 Disorders of conjunctiva" + codings: + - "H10" + - "H100" + - "H101" + - "H102" + - "H103" + - "H104" + - "H105" + - "H108" + - "H109" + - "H11" + - "H110" + - "H111" + - "H112" + - "H113" + - "H114" + - "H118" + - "H119" + - "H13" + - "H130" + - "H131" + - "H132" + - "H133" + - "H138" + - name: "M72 Fibroblastic disorders" + codings: + - "M720" + - "M7200" + - "M7201" + - "M7202" + - "M7203" + - "M7204" + - "M7205" + - "M7206" + - "M7207" + - "M7208" + - "M7209" + - "M721" + - "M7210" + - "M7211" + - "M7212" + - "M7213" + - "M7214" + - "M7215" + - "M7216" + - "M7217" + - "M7218" + - "M7219" + - "M722" + - "M7220" + - "M7221" + - "M7222" + - "M7223" + - "M7224" + - "M7225" + - "M7226" + - "M7227" + - "M7228" + - "M7229" + - "M723" + - "M7230" + - "M7231" + - "M7232" + - "M7233" + - "M7234" + - "M7235" + - "M7236" + - "M7237" + - "M7238" + - "M7239" + - "M724" + - "M7240" + - "M7241" + - "M7242" + - "M7243" + - "M7244" + - "M7245" + - "M7246" + - "M7247" + - "M7248" + - "M7249" + - "M725" + - "M7250" + - "M7251" + - "M7252" + - "M7253" + - "M7254" + - "M7255" + - "M7256" + - "M7257" + - "M7258" + - "M7259" + - "M726" + - "M7260" + - "M7261" + - "M7262" + - "M7263" + - "M7264" + - "M7265" + - "M7266" + - "M7267" + - "M7268" + - "M7269" + - "M728" + - "M7280" + - "M7281" + - "M7282" + - "M7283" + - "M7284" + - "M7285" + - "M7286" + - "M7287" + - "M7288" + - "M7289" + - "M729" + - "M7290" + - "M7291" + - "M7292" + - "M7293" + - "M7294" + - "M7295" + - "M7296" + - "M7297" + - "M7298" + - "M7299" + - name: "M71 Other bursopathies" + codings: + - "M710" + - "M7100" + - "M7101" + - "M7102" + - "M7103" + - "M7104" + - "M7105" + - "M7106" + - "M7107" + - "M7108" + - "M7109" + - "M711" + - "M7110" + - "M7111" + - "M7112" + - "M7113" + - "M7114" + - "M7115" + - "M7116" + - "M7117" + - "M7118" + - "M7119" + - "M712" + - "M7120" + - "M7121" + - "M7122" + - "M7123" + - "M7124" + - "M7125" + - "M7126" + - "M7127" + - "M7128" + - "M7129" + - "M713" + - "M7130" + - "M7131" + - "M7132" + - "M7133" + - "M7134" + - "M7135" + - "M7136" + - "M7137" + - "M7138" + - "M7139" + - "M714" + - "M7140" + - "M7141" + - "M7142" + - "M7143" + - "M7144" + - "M7145" + - "M7146" + - "M7147" + - "M7148" + - "M7149" + - "M715" + - "M7150" + - "M7151" + - "M7152" + - "M7153" + - "M7154" + - "M7155" + - "M7156" + - "M7157" + - "M7158" + - "M7159" + - "M718" + - "M7180" + - "M7181" + - "M7182" + - "M7183" + - "M7184" + - "M7185" + - "M7186" + - "M7187" + - "M7188" + - "M7189" + - "M719" + - "M7190" + - "M7191" + - "M7192" + - "M7193" + - "M7194" + - "M7195" + - "M7196" + - "M7197" + - "M7198" + - "M7199" + - name: "M70 Soft tissue disorders related to use, overuse and pressure" + codings: + - "M700" + - "M7000" + - "M7001" + - "M7002" + - "M7003" + - "M7004" + - "M7005" + - "M7006" + - "M7007" + - "M7008" + - "M7009" + - "M701" + - "M7010" + - "M7011" + - "M7012" + - "M7013" + - "M7014" + - "M7015" + - "M7016" + - "M7017" + - "M7018" + - "M7019" + - "M702" + - "M7020" + - "M7021" + - "M7022" + - "M7023" + - "M7024" + - "M7025" + - "M7026" + - "M7027" + - "M7028" + - "M7029" + - "M703" + - "M7030" + - "M7031" + - "M7032" + - "M7033" + - "M7034" + - "M7035" + - "M7036" + - "M7037" + - "M7038" + - "M7039" + - "M704" + - "M7040" + - "M7041" + - "M7042" + - "M7043" + - "M7044" + - "M7045" + - "M7046" + - "M7047" + - "M7048" + - "M7049" + - "M705" + - "M7050" + - "M7051" + - "M7052" + - "M7053" + - "M7054" + - "M7055" + - "M7056" + - "M7057" + - "M7058" + - "M7059" + - "M706" + - "M7060" + - "M7061" + - "M7062" + - "M7063" + - "M7064" + - "M7065" + - "M7066" + - "M7067" + - "M7068" + - "M7069" + - "M707" + - "M7070" + - "M7071" + - "M7072" + - "M7073" + - "M7074" + - "M7075" + - "M7076" + - "M7077" + - "M7078" + - "M7079" + - "M708" + - "M7080" + - "M7081" + - "M7082" + - "M7083" + - "M7084" + - "M7085" + - "M7086" + - "M7087" + - "M7088" + - "M7089" + - "M709" + - "M7090" + - "M7091" + - "M7092" + - "M7093" + - "M7094" + - "M7095" + - "M7096" + - "M7097" + - "M7098" + - "M7099" + - name: "M77 Other enthesopathies" + codings: + - "M770" + - "M7700" + - "M7701" + - "M7702" + - "M7703" + - "M7704" + - "M7705" + - "M7706" + - "M7707" + - "M7708" + - "M7709" + - "M771" + - "M7710" + - "M7711" + - "M7712" + - "M7713" + - "M7714" + - "M7715" + - "M7716" + - "M7717" + - "M7718" + - "M7719" + - "M772" + - "M7720" + - "M7721" + - "M7722" + - "M7723" + - "M7724" + - "M7725" + - "M7726" + - "M7727" + - "M7728" + - "M7729" + - "M773" + - "M7730" + - "M7731" + - "M7732" + - "M7733" + - "M7734" + - "M7735" + - "M7736" + - "M7737" + - "M7738" + - "M7739" + - "M774" + - "M7740" + - "M7741" + - "M7742" + - "M7743" + - "M7744" + - "M7745" + - "M7746" + - "M7747" + - "M7748" + - "M7749" + - "M775" + - "M7750" + - "M7751" + - "M7752" + - "M7753" + - "M7754" + - "M7755" + - "M7756" + - "M7757" + - "M7758" + - "M7759" + - "M778" + - "M7780" + - "M7781" + - "M7782" + - "M7783" + - "M7784" + - "M7785" + - "M7786" + - "M7787" + - "M7788" + - "M7789" + - "M779" + - "M7790" + - "M7791" + - "M7792" + - "M7793" + - "M7794" + - "M7795" + - "M7796" + - "M7797" + - "M7798" + - "M7799" + - name: "M75 Shoulder lesions" + codings: + - "M750" + - "M751" + - "M752" + - "M753" + - "M754" + - "M755" + - "M758" + - "M7581" + - "M759" + - name: "M79 Other soft tissue disorders, not elsewhere classified" + codings: + - "M790" + - "M7900" + - "M7901" + - "M7902" + - "M7903" + - "M7904" + - "M7905" + - "M7906" + - "M7907" + - "M7908" + - "M7909" + - "M791" + - "M7910" + - "M7911" + - "M7912" + - "M7913" + - "M7914" + - "M7915" + - "M7916" + - "M7917" + - "M7918" + - "M7919" + - "M792" + - "M7920" + - "M7921" + - "M7922" + - "M7923" + - "M7924" + - "M7925" + - "M7926" + - "M7927" + - "M7928" + - "M7929" + - "M793" + - "M7930" + - "M7931" + - "M7932" + - "M7933" + - "M7934" + - "M7935" + - "M7936" + - "M7937" + - "M7938" + - "M7939" + - "M794" + - "M7940" + - "M7941" + - "M7942" + - "M7943" + - "M7944" + - "M7945" + - "M7946" + - "M7947" + - "M7948" + - "M7949" + - "M795" + - "M7950" + - "M7951" + - "M7952" + - "M7953" + - "M7954" + - "M7955" + - "M7956" + - "M7957" + - "M7958" + - "M7959" + - "M796" + - "M7960" + - "M7961" + - "M7962" + - "M7963" + - "M7964" + - "M7965" + - "M7966" + - "M7967" + - "M7968" + - "M7969" + - "M797" + - "M7970" + - "M7971" + - "M7972" + - "M7973" + - "M7974" + - "M7975" + - "M7976" + - "M7977" + - "M7978" + - "M7979" + - "M798" + - "M7980" + - "M7981" + - "M7982" + - "M7983" + - "M7984" + - "M7985" + - "M7986" + - "M7987" + - "M7988" + - "M7989" + - "M799" + - "M7990" + - "M7991" + - "M7992" + - "M7993" + - "M7994" + - "M7995" + - "M7996" + - "M7997" + - "M7998" + - "M7999" + - name: "F40-F48 Neurotic, stress-related and somatoform disorders" + codings: + - "F411" + - "F412" + - "F413" + - "F418" + - "F419" + - "F42" + - "F420" + - "F421" + - "F422" + - "F428" + - "F429" + - "F43" + - "F430" + - "F431" + - "F432" + - "F438" + - "F439" + - "F44" + - "F440" + - "F441" + - "F442" + - "F443" + - "F444" + - "F445" + - "F446" + - "F447" + - "F448" + - "F449" + - "F45" + - "F450" + - "F451" + - "F452" + - "F453" + - "F454" + - "F458" + - "F459" + - "F48" + - "F480" + - "F481" + - "F488" + - "F489" + - "F40" + - "F400" + - "F401" + - "F402" + - "F408" + - "F409" + - "F41" + - "F410" + - name: "G90-G99 Other disorders of the nervous system" + codings: + - "G90" + - "G900" + - "G901" + - "G902" + - "G903" + - "G904" + - "G908" + - "G909" + - "G91" + - "G910" + - "G911" + - "G912" + - "G913" + - "G918" + - "G919" + - "G92" + - "G93" + - "G930" + - "G931" + - "G932" + - "G933" + - "G934" + - "G935" + - "G936" + - "G937" + - "G938" + - "G939" + - "G94" + - "G940" + - "G941" + - "G942" + - "G948" + - "G95" + - "G950" + - "G951" + - "G952" + - "G958" + - "G959" + - "G96" + - "G960" + - "G961" + - "G968" + - "G969" + - "G97" + - "G970" + - "G971" + - "G972" + - "G978" + - "G979" + - "G98" + - "G99" + - "G990" + - "G991" + - "G992" + - "G998" + - name: "M06 Other rheumatoid arthritis" + codings: + - "M0605" + - "M0606" + - "M0607" + - "M0608" + - "M0609" + - "M061" + - "M0610" + - "M0611" + - "M0612" + - "M0613" + - "M0614" + - "M0615" + - "M0616" + - "M0617" + - "M0618" + - "M0619" + - "M062" + - "M0620" + - "M0621" + - "M0622" + - "M0623" + - "M0624" + - "M0625" + - "M0626" + - "M0627" + - "M0628" + - "M0629" + - "M063" + - "M0630" + - "M0631" + - "M0632" + - "M0633" + - "M0634" + - "M0635" + - "M0636" + - "M0637" + - "M0638" + - "M0639" + - "M064" + - "M0640" + - "M0641" + - "M0642" + - "M0643" + - "M0644" + - "M0645" + - "M0646" + - "M0647" + - "M0648" + - "M0649" + - "M068" + - "M0680" + - "M0681" + - "M0682" + - "M0683" + - "M0684" + - "M0685" + - "M0686" + - "M0687" + - "M0688" + - "M0689" + - "M069" + - "M0690" + - "M0691" + - "M0692" + - "M0693" + - "M0694" + - "M0695" + - "M0696" + - "M0697" + - "M0698" + - "M0699" + - "M060" + - "M0600" + - "M0601" + - "M0602" + - "M0603" + - "M0604" + - name: "H33 Retinal detachments and breaks" + codings: + - "H330" + - "H331" + - "H332" + - "H333" + - "H334" + - "H335" + - name: "M05 Seropositive rheumatoid arthritis" + codings: + - "M050" + - "M0500" + - "M0501" + - "M0502" + - "M0503" + - "M0504" + - "M0505" + - "M0506" + - "M0507" + - "M0508" + - "M0509" + - "M051" + - "M0510" + - "M0511" + - "M0512" + - "M0513" + - "M0514" + - "M0515" + - "M0516" + - "M0517" + - "M0518" + - "M0519" + - "M052" + - "M0520" + - "M0521" + - "M0522" + - "M0523" + - "M0524" + - "M0525" + - "M0526" + - "M0527" + - "M0528" + - "M0529" + - "M053" + - "M0530" + - "M0531" + - "M0532" + - "M0533" + - "M0534" + - "M0535" + - "M0536" + - "M0537" + - "M0538" + - "M0539" + - "M058" + - "M0580" + - "M0581" + - "M0582" + - "M0583" + - "M0584" + - "M0585" + - "M0586" + - "M0587" + - "M0588" + - "M0589" + - "M059" + - "M0590" + - "M0591" + - "M0592" + - "M0593" + - "M0594" + - "M0595" + - "M0596" + - "M0597" + - "M0598" + - "M0599" + - name: "H36 Retinal disorders in diseases classified elsewhere" + codings: + - "H360" + - "H368" + - name: "H34 Retinal vascular occlusions" + codings: + - "H349" + - "H340" + - "H341" + - "H342" + - "H348" + - name: "H35 Other retinal disorders" + codings: + - "H350" + - "H351" + - "H352" + - "H353" + - "H354" + - "H355" + - "H356" + - "H357" + - "H358" + - "H359" + - name: "G31 Other degenerative diseases of nervous system, not elsewhere classified" + codings: + - "G319" + - "G310" + - "G311" + - "G312" + - "G318" + - name: "G35 Multiple sclerosis" + codings: + - "G35" + - name: "L60 Nail disorders" + codings: + - "L600" + - "L601" + - "L602" + - "L603" + - "L604" + - "L605" + - "L608" + - "L609" + - name: "E04 Other non-toxic goitre" + codings: + - "E042" + - "E048" + - "E049" + - "E040" + - "E041" + - name: "H40-H42 Glaucoma" + codings: + - "H40" + - "H400" + - "H401" + - "H402" + - "H403" + - "H404" + - "H405" + - "H406" + - "H408" + - "H409" + - "H42" + - "H420" + - "H428" + - name: "E03 Other hypothyroidism" + codings: + - "E030" + - "E031" + - "E032" + - "E033" + - "E034" + - "E035" + - "E038" + - "E039" + - name: "L02 Cutaneous abscess, furuncle and carbuncle" + codings: + - "L020" + - "L021" + - "L022" + - "L023" + - "L024" + - "L028" + - "L029" + - name: "K80-K87 Disorders of gallbladder, biliary tract and pancreas" + codings: + - "K860" + - "K861" + - "K862" + - "K863" + - "K868" + - "K869" + - "K87" + - "K870" + - "K871" + - "K80" + - "K800" + - "K801" + - "K802" + - "K803" + - "K8036" + - "K804" + - "K805" + - "K808" + - "K81" + - "K810" + - "K811" + - "K818" + - "K819" + - "K82" + - "K820" + - "K821" + - "K822" + - "K823" + - "K824" + - "K828" + - "K829" + - "K83" + - "K830" + - "K831" + - "K832" + - "K833" + - "K834" + - "K835" + - "K838" + - "K839" + - "K85" + - "K850" + - "K851" + - "K852" + - "K853" + - "K858" + - "K859" + - "K86" + - name: "L50-L54 Urticaria and erythema" + codings: + - "L50" + - "L500" + - "L501" + - "L502" + - "L503" + - "L504" + - "L505" + - "L506" + - "L508" + - "L509" + - "L51" + - "L510" + - "L511" + - "L512" + - "L518" + - "L519" + - "L52" + - "L53" + - "L530" + - "L531" + - "L532" + - "L533" + - "L538" + - "L539" + - "L54" + - "L540" + - "L548" + - name: "G80-G83 Cerebral palsy and other paralytic syndromes" + codings: + - "G80" + - "G800" + - "G801" + - "G802" + - "G803" + - "G804" + - "G808" + - "G809" + - "G81" + - "G810" + - "G811" + - "G819" + - "G82" + - "G820" + - "G821" + - "G822" + - "G823" + - "G824" + - "G825" + - "G83" + - "G830" + - "G831" + - "G832" + - "G833" + - "G834" + - "G835" + - "G838" + - "G839" + - name: "O32 Maternal care for known or suspected malpresentation of foetus" + codings: + - "O320" + - "O321" + - "O322" + - "O323" + - "O324" + - "O325" + - "O326" + - "O328" + - "O329" + - name: "O34 Maternal care for known or suspected abnormality of pelvic organs" + codings: + - "O346" + - "O347" + - "O348" + - "O349" + - "O340" + - "O341" + - "O342" + - "O343" + - "O344" + - "O345" + - name: "O36 Maternal care for other known or suspected foetal problems" + codings: + - "O360" + - "O361" + - "O362" + - "O363" + - "O364" + - "O365" + - "O366" + - "O367" + - "O368" + - "O369" + - name: "G81 Hemiplegia" + codings: + - "G810" + - "G811" + - "G819" + - name: "H65-H75 Diseases of middle ear and mastoid" + codings: + - "H65" + - "H650" + - "H651" + - "H652" + - "H653" + - "H654" + - "H659" + - "H66" + - "H660" + - "H661" + - "H662" + - "H663" + - "H664" + - "H669" + - "H67" + - "H670" + - "H671" + - "H678" + - "H68" + - "H680" + - "H681" + - "H69" + - "H690" + - "H698" + - "H699" + - "H70" + - "H700" + - "H701" + - "H702" + - "H708" + - "H709" + - "H71" + - "H72" + - "H720" + - "H721" + - "H722" + - "H728" + - "H729" + - "H73" + - "H730" + - "H731" + - "H738" + - "H739" + - "H74" + - "H740" + - "H741" + - "H742" + - "H743" + - "H744" + - "H748" + - "H749" + - "H75" + - "H750" + - "H758" + - name: "J06 Acute upper respiratory infections of multiple and unspecified sites" + codings: + - "J068" + - "J069" + - "J060" + - name: "D80-D89 Certain disorders involving the immune mechanism" + codings: + - "D80" + - "D800" + - "D801" + - "D802" + - "D803" + - "D804" + - "D805" + - "D806" + - "D807" + - "D808" + - "D809" + - "D81" + - "D810" + - "D811" + - "D812" + - "D813" + - "D814" + - "D815" + - "D816" + - "D817" + - "D818" + - "D819" + - "D82" + - "D820" + - "D821" + - "D822" + - "D823" + - "D824" + - "D828" + - "D829" + - "D83" + - "D830" + - "D831" + - "D832" + - "D838" + - "D839" + - "D84" + - "D840" + - "D841" + - "D848" + - "D849" + - "D86" + - "D860" + - "D861" + - "D862" + - "D863" + - "D868" + - "D869" + - "D89" + - "D890" + - "D891" + - "D892" + - "D893" + - "D898" + - "D899" + - name: "K50-K52 Noninfective enteritis and colitis" + codings: + - "K523" + - "K528" + - "K529" + - "K50" + - "K500" + - "K501" + - "K508" + - "K509" + - "K51" + - "K510" + - "K511" + - "K512" + - "K513" + - "K514" + - "K515" + - "K518" + - "K519" + - "K52" + - "K520" + - "K521" + - "K522" + - name: "K59 Other functional intestinal disorders" + codings: + - "K591" + - "K592" + - "K593" + - "K594" + - "K598" + - "K599" + - "K590" + - name: "K58 Irritable bowel syndrome" + codings: + - "K580" + - "K589" + - name: "K57 Diverticular disease of intestine" + codings: + - "K570" + - "K571" + - "K572" + - "K573" + - "K574" + - "K575" + - "K578" + - "K579" + - name: "K56 Paralytic ileus and intestinal obstruction without hernia" + codings: + - "K560" + - "K561" + - "K562" + - "K563" + - "K564" + - "K565" + - "K566" + - "K567" + - name: "K55 Vascular disorders of intestine" + codings: + - "K559" + - "K550" + - "K551" + - "K552" + - "K558" + - name: "K52 Other non-infective gastro-enteritis and colitis" + codings: + - "K523" + - "K528" + - "K529" + - "K520" + - "K521" + - "K522" + - name: "J60-J70 Lung diseases due to external agents" + codings: + - "J60" + - "J61" + - "J62" + - "J620" + - "J628" + - "J63" + - "J630" + - "J631" + - "J632" + - "J633" + - "J634" + - "J635" + - "J638" + - "J64" + - "J65" + - "J66" + - "J660" + - "J661" + - "J662" + - "J668" + - "J67" + - "J670" + - "J671" + - "J672" + - "J673" + - "J674" + - "J675" + - "J676" + - "J677" + - "J678" + - "J679" + - "J68" + - "J680" + - "J681" + - "J682" + - "J683" + - "J684" + - "J688" + - "J689" + - "J69" + - "J690" + - "J691" + - "J698" + - "J70" + - "J700" + - "J701" + - "J702" + - "J703" + - "J704" + - "J708" + - "J709" + - name: "K50 Crohn's disease [regional enteritis]" + codings: + - "K501" + - "K508" + - "K509" + - "K500" + - name: "E78 Disorders of lipoprotein metabolism and other lipidaemias" + codings: + - "E780" + - "E781" + - "E782" + - "E783" + - "E784" + - "E785" + - "E786" + - "E788" + - "E789" + - name: "G70-G73 Diseases of myoneural junction and muscle" + codings: + - "G701" + - "G702" + - "G708" + - "G709" + - "G71" + - "G710" + - "G711" + - "G712" + - "G713" + - "G718" + - "G719" + - "G72" + - "G720" + - "G721" + - "G722" + - "G723" + - "G724" + - "G728" + - "G729" + - "G73" + - "G730" + - "G731" + - "G732" + - "G733" + - "G734" + - "G735" + - "G736" + - "G737" + - "G70" + - "G700" + - name: "N10-N16 Renal tubulo-interstitial diseases" + codings: + - "N10" + - "N11" + - "N110" + - "N111" + - "N118" + - "N119" + - "N12" + - "N13" + - "N130" + - "N131" + - "N132" + - "N133" + - "N134" + - "N135" + - "N136" + - "N137" + - "N138" + - "N139" + - "N14" + - "N140" + - "N141" + - "N142" + - "N143" + - "N144" + - "N15" + - "N150" + - "N151" + - "N158" + - "N159" + - "N16" + - "N160" + - "N161" + - "N162" + - "N163" + - "N164" + - "N165" + - "N168" + - name: "N85 Other noninflammatory disorders of uterus, except cervix" + codings: + - "N850" + - "N851" + - "N852" + - "N853" + - "N854" + - "N855" + - "N856" + - "N857" + - "N858" + - "N859" + - name: "N84 Polyp of female genital tract" + codings: + - "N843" + - "N848" + - "N849" + - "N840" + - "N841" + - "N842" + - name: "N87 Dysplasia of cervix uteri" + codings: + - "N870" + - "N871" + - "N872" + - "N879" + - name: "N86 Erosion and ectropion of cervix uteri" + codings: + - "N86" + - name: "N81 Female genital prolapse" + codings: + - "N811" + - "N812" + - "N813" + - "N814" + - "N815" + - "N816" + - "N818" + - "N819" + - "N810" + - name: "N80 Endometriosis" + codings: + - "N800" + - "N801" + - "N802" + - "N803" + - "N804" + - "N805" + - "N806" + - "N808" + - "N809" + - name: "N83 Noninflammatory disorders of ovary, Fallopian tube and broad ligament" + codings: + - "N830" + - "N831" + - "N832" + - "N833" + - "N834" + - "N835" + - "N836" + - "N837" + - "N838" + - "N839" + - name: "N89 Other noninflammatory disorders of vagina" + codings: + - "N893" + - "N894" + - "N895" + - "N896" + - "N897" + - "N898" + - "N899" + - "N890" + - "N891" + - "N892" + - name: "N88 Other noninflammatory disorders of cervix uteri" + codings: + - "N880" + - "N881" + - "N882" + - "N883" + - "N884" + - "N888" + - "N889" + - name: "H53-H54 Visual disturbances and blindness" + codings: + - "H53" + - "H530" + - "H531" + - "H532" + - "H533" + - "H534" + - "H535" + - "H536" + - "H538" + - "H539" + - "H54" + - "H540" + - "H541" + - "H542" + - "H543" + - "H544" + - "H545" + - "H546" + - "H547" + - "H549" + - name: "F31 Bipolar affective disorder" + codings: + - "F310" + - "F311" + - "F312" + - "F313" + - "F314" + - "F315" + - "F316" + - "F317" + - "F318" + - "F319" + - name: "F32 Depressive episode" + codings: + - "F320" + - "F321" + - "F322" + - "F323" + - "F328" + - "F329" + - name: "F33 Recurrent depressive disorder" + codings: + - "F330" + - "F331" + - "F332" + - "F333" + - "F334" + - "F338" + - "F339" + - name: "D69 Purpura and other haemorrhagic conditions" + codings: + - "D698" + - "D699" + - "D690" + - "D691" + - "D692" + - "D693" + - "D694" + - "D695" + - "D696" + - name: "D68 Other coagulation defects" + codings: + - "D680" + - "D681" + - "D682" + - "D683" + - "D684" + - "D685" + - "D686" + - "D688" + - "D689" + - name: "D64 Other anaemias" + codings: + - "D640" + - "D641" + - "D642" + - "D643" + - "D644" + - "D648" + - "D649" + - name: "D63 Anaemia in chronic diseases classified elsewhere" + codings: + - "D630" + - "D631" + - "D638" + - name: "N00-N08 Glomerular diseases" + codings: + - "N069" + - "N07" + - "N070" + - "N071" + - "N072" + - "N073" + - "N074" + - "N075" + - "N076" + - "N077" + - "N078" + - "N079" + - "N08" + - "N080" + - "N081" + - "N082" + - "N083" + - "N084" + - "N085" + - "N088" + - "N00" + - "N000" + - "N001" + - "N002" + - "N003" + - "N004" + - "N005" + - "N006" + - "N007" + - "N008" + - "N009" + - "N01" + - "N010" + - "N011" + - "N012" + - "N013" + - "N014" + - "N015" + - "N016" + - "N017" + - "N018" + - "N019" + - "N02" + - "N020" + - "N021" + - "N022" + - "N023" + - "N024" + - "N025" + - "N026" + - "N027" + - "N028" + - "N029" + - "N03" + - "N030" + - "N031" + - "N032" + - "N033" + - "N034" + - "N035" + - "N036" + - "N037" + - "N038" + - "N039" + - "N04" + - "N040" + - "N041" + - "N042" + - "N043" + - "N044" + - "N045" + - "N046" + - "N047" + - "N048" + - "N049" + - "N05" + - "N050" + - "N051" + - "N052" + - "N053" + - "N054" + - "N055" + - "N056" + - "N057" + - "N058" + - "N059" + - "N06" + - "N060" + - "N061" + - "N062" + - "N063" + - "N064" + - "N065" + - "N066" + - "N067" + - "N068" + - name: "I64 Stroke, not specified as haemorrhage or infarction" + codings: + - "I64" + - name: "N39 Other disorders of urinary system" + codings: + - "N390" + - "N391" + - "N392" + - "N393" + - "N394" + - "N398" + - "N399" + - name: "I67 Other cerebrovascular diseases" + codings: + - "I672" + - "I673" + - "I674" + - "I675" + - "I676" + - "I677" + - "I678" + - "I679" + - "I670" + - "I671" + - name: "B00-B09 Viral infections characterized by skin and mucous membrane lesions" + codings: + - "B02" + - "B020" + - "B021" + - "B022" + - "B023" + - "B027" + - "B028" + - "B029" + - "B03" + - "B04" + - "B05" + - "B050" + - "B051" + - "B052" + - "B053" + - "B054" + - "B058" + - "B059" + - "B06" + - "B060" + - "B068" + - "B069" + - "B07" + - "B08" + - "B080" + - "B081" + - "B082" + - "B083" + - "B084" + - "B085" + - "B088" + - "B09" + - "B00" + - "B000" + - "B001" + - "B002" + - "B003" + - "B004" + - "B005" + - "B007" + - "B008" + - "B009" + - "B01" + - "B010" + - "B011" + - "B012" + - "B018" + - "B019" + - name: "I61 Intracerebral haemorrhage" + codings: + - "I610" + - "I611" + - "I612" + - "I613" + - "I614" + - "I615" + - "I616" + - "I618" + - "I619" + - name: "I63 Cerebral infarction" + codings: + - "I630" + - "I631" + - "I632" + - "I633" + - "I634" + - "I635" + - "I636" + - "I638" + - "I639" + - name: "N30 Cystitis" + codings: + - "N300" + - "N301" + - "N302" + - "N303" + - "N304" + - "N308" + - "N309" + - name: "N31 Neuromuscular dysfunction of bladder, not elsewhere classified" + codings: + - "N310" + - "N311" + - "N312" + - "N318" + - "N319" + - name: "N32 Other disorders of bladder" + codings: + - "N320" + - "N321" + - "N322" + - "N323" + - "N324" + - "N328" + - "N329" + - name: "O80-O84 Delivery" + codings: + - "O80" + - "O800" + - "O801" + - "O808" + - "O809" + - "O81" + - "O810" + - "O811" + - "O812" + - "O813" + - "O814" + - "O815" + - "O82" + - "O820" + - "O821" + - "O822" + - "O828" + - "O829" + - "O83" + - "O830" + - "O831" + - "O832" + - "O833" + - "O834" + - "O838" + - "O839" + - "O84" + - "O840" + - "O841" + - "O842" + - "O848" + - "O849" + - name: "N36 Other disorders of urethra" + codings: + - "N360" + - "N361" + - "N362" + - "N363" + - "N368" + - "N369" + - name: "N20-N23 Urolithiasis" + codings: + - "N20" + - "N200" + - "N201" + - "N202" + - "N209" + - "N21" + - "N210" + - "N211" + - "N218" + - "N219" + - "N22" + - "N220" + - "N228" + - "N23" + - name: "H02 Other disorders of eyelid" + codings: + - "H028" + - "H029" + - "H020" + - "H021" + - "H022" + - "H023" + - "H024" + - "H025" + - "H026" + - "H027" + - name: "H01 Other inflammation of eyelid" + codings: + - "H010" + - "H011" + - "H018" + - "H019" + - name: "H00 Hordeolum and chalazion" + codings: + - "H000" + - "H001" + - name: "M31 Other necrotising vasculopathies" + codings: + - "M310" + - "M311" + - "M312" + - "M313" + - "M314" + - "M315" + - "M316" + - "M317" + - "M318" + - "M319" + - name: "H04 Disorders of lachrymal system" + codings: + - "H040" + - "H041" + - "H042" + - "H043" + - "H044" + - "H045" + - "H046" + - "H048" + - "H049" + - name: "M00-M03 Infectious arthropathies" + codings: + - "M00" + - "M000" + - "M0000" + - "M0001" + - "M0002" + - "M0003" + - "M0004" + - "M0005" + - "M0006" + - "M0007" + - "M0008" + - "M0009" + - "M001" + - "M0010" + - "M0011" + - "M0012" + - "M0013" + - "M0014" + - "M0015" + - "M0016" + - "M0017" + - "M0018" + - "M0019" + - "M002" + - "M0020" + - "M0021" + - "M0022" + - "M0023" + - "M0024" + - "M0025" + - "M0026" + - "M0027" + - "M0028" + - "M0029" + - "M008" + - "M0080" + - "M0081" + - "M0082" + - "M0083" + - "M0084" + - "M0085" + - "M0086" + - "M0087" + - "M0088" + - "M0089" + - "M009" + - "M0090" + - "M0091" + - "M0092" + - "M0093" + - "M0094" + - "M0095" + - "M0096" + - "M0097" + - "M0098" + - "M0099" + - "M01" + - "M010" + - "M0100" + - "M0101" + - "M0102" + - "M0103" + - "M0104" + - "M0105" + - "M0106" + - "M0107" + - "M0108" + - "M0109" + - "M011" + - "M0110" + - "M0111" + - "M0112" + - "M0113" + - "M0114" + - "M0115" + - "M0116" + - "M0117" + - "M0118" + - "M0119" + - "M012" + - "M0120" + - "M0121" + - "M0122" + - "M0123" + - "M0124" + - "M0125" + - "M0126" + - "M0127" + - "M0128" + - "M0129" + - "M013" + - "M0130" + - "M0131" + - "M0132" + - "M0133" + - "M0134" + - "M0135" + - "M0136" + - "M0137" + - "M0138" + - "M0139" + - "M014" + - "M0140" + - "M0141" + - "M0142" + - "M0143" + - "M0144" + - "M0145" + - "M0146" + - "M0147" + - "M0148" + - "M0149" + - "M015" + - "M0150" + - "M0151" + - "M0152" + - "M0153" + - "M0154" + - "M0155" + - "M0156" + - "M0157" + - "M0158" + - "M0159" + - "M016" + - "M0160" + - "M0161" + - "M0162" + - "M0163" + - "M0164" + - "M0165" + - "M0166" + - "M0167" + - "M0168" + - "M0169" + - "M018" + - "M0180" + - "M0181" + - "M0182" + - "M0183" + - "M0184" + - "M0185" + - "M0186" + - "M0187" + - "M0188" + - "M0189" + - "M02" + - "M020" + - "M0200" + - "M0201" + - "M0202" + - "M0203" + - "M0204" + - "M0205" + - "M0206" + - "M0207" + - "M0208" + - "M0209" + - "M021" + - "M0210" + - "M0211" + - "M0212" + - "M0213" + - "M0214" + - "M0215" + - "M0216" + - "M0217" + - "M0218" + - "M0219" + - "M022" + - "M0220" + - "M0221" + - "M0222" + - "M0223" + - "M0224" + - "M0225" + - "M0226" + - "M0227" + - "M0228" + - "M0229" + - "M023" + - "M0230" + - "M0231" + - "M0232" + - "M0233" + - "M0234" + - "M0235" + - "M0236" + - "M0237" + - "M0238" + - "M0239" + - "M028" + - "M0280" + - "M0281" + - "M0282" + - "M0283" + - "M0284" + - "M0285" + - "M0286" + - "M0287" + - "M0288" + - "M0289" + - "M029" + - "M0290" + - "M0291" + - "M0292" + - "M0293" + - "M0294" + - "M0295" + - "M0296" + - "M0297" + - "M0298" + - "M0299" + - "M03" + - "M030" + - "M0300" + - "M0301" + - "M0302" + - "M0303" + - "M0304" + - "M0305" + - "M0306" + - "M0307" + - "M0308" + - "M0309" + - "M031" + - "M0310" + - "M0311" + - "M0312" + - "M0313" + - "M0314" + - "M0315" + - "M0316" + - "M0317" + - "M0318" + - "M0319" + - "M032" + - "M0320" + - "M0321" + - "M0322" + - "M0323" + - "M0324" + - "M0325" + - "M0326" + - "M0327" + - "M0328" + - "M0329" + - "M036" + - "M0360" + - "M0361" + - "M0362" + - "M0363" + - "M0364" + - "M0365" + - "M0366" + - "M0367" + - "M0368" + - "M0369" + - name: "O30-O48 Maternal care related to the fetus and amniotic cavity and possible delivery problems" + codings: + - "O30" + - "O300" + - "O301" + - "O302" + - "O308" + - "O309" + - "O31" + - "O310" + - "O311" + - "O312" + - "O318" + - "O32" + - "O320" + - "O321" + - "O322" + - "O323" + - "O324" + - "O325" + - "O326" + - "O328" + - "O329" + - "O33" + - "O330" + - "O331" + - "O332" + - "O333" + - "O334" + - "O335" + - "O336" + - "O337" + - "O338" + - "O339" + - "O34" + - "O340" + - "O341" + - "O342" + - "O343" + - "O344" + - "O345" + - "O346" + - "O347" + - "O348" + - "O349" + - "O35" + - "O350" + - "O351" + - "O352" + - "O353" + - "O354" + - "O355" + - "O356" + - "O357" + - "O358" + - "O359" + - "O36" + - "O360" + - "O361" + - "O362" + - "O363" + - "O364" + - "O365" + - "O366" + - "O367" + - "O368" + - "O369" + - "O40" + - "O41" + - "O410" + - "O411" + - "O418" + - "O419" + - "O42" + - "O420" + - "O421" + - "O422" + - "O429" + - "O43" + - "O430" + - "O431" + - "O432" + - "O438" + - "O439" + - "O44" + - "O440" + - "O441" + - "O45" + - "O450" + - "O458" + - "O459" + - "O46" + - "O460" + - "O468" + - "O469" + - "O47" + - "O470" + - "O471" + - "O479" + - "O48" + - name: "N80-N98 Noninflammatory disorders of female genital tract" + codings: + - "N80" + - "N800" + - "N801" + - "N802" + - "N803" + - "N804" + - "N805" + - "N806" + - "N808" + - "N809" + - "N81" + - "N810" + - "N811" + - "N812" + - "N813" + - "N814" + - "N815" + - "N816" + - "N818" + - "N819" + - "N82" + - "N820" + - "N821" + - "N822" + - "N823" + - "N824" + - "N825" + - "N828" + - "N829" + - "N83" + - "N830" + - "N831" + - "N832" + - "N833" + - "N834" + - "N835" + - "N836" + - "N837" + - "N838" + - "N839" + - "N84" + - "N840" + - "N841" + - "N842" + - "N843" + - "N848" + - "N849" + - "N85" + - "N850" + - "N851" + - "N852" + - "N853" + - "N854" + - "N855" + - "N856" + - "N857" + - "N858" + - "N859" + - "N86" + - "N87" + - "N870" + - "N871" + - "N872" + - "N879" + - "N88" + - "N880" + - "N881" + - "N882" + - "N883" + - "N884" + - "N888" + - "N889" + - "N89" + - "N890" + - "N891" + - "N892" + - "N893" + - "N894" + - "N895" + - "N896" + - "N897" + - "N898" + - "N899" + - "N90" + - "N900" + - "N901" + - "N902" + - "N903" + - "N904" + - "N905" + - "N906" + - "N907" + - "N908" + - "N909" + - "N91" + - "N910" + - "N911" + - "N912" + - "N913" + - "N914" + - "N915" + - "N92" + - "N920" + - "N921" + - "N922" + - "N923" + - "N924" + - "N925" + - "N926" + - "N93" + - "N930" + - "N938" + - "N939" + - "N94" + - "N940" + - "N941" + - "N942" + - "N943" + - "N944" + - "N945" + - "N946" + - "N948" + - "N949" + - "N95" + - "N950" + - "N951" + - "N952" + - "N953" + - "N958" + - "N959" + - "N96" + - "N97" + - "N970" + - "N971" + - "N972" + - "N973" + - "N974" + - "N978" + - "N979" + - "N98" + - "N980" + - "N981" + - "N982" + - "N983" + - "N988" + - "N989" + - name: "I65 Occlusion and stenosis of precerebral arteries, not resulting in cerebral infarction" + codings: + - "I650" + - "I651" + - "I652" + - "I653" + - "I658" + - "I659" + - name: "L40 Psoriasis" + codings: + - "L400" + - "L401" + - "L402" + - "L403" + - "L404" + - "L405" + - "L408" + - "L409" + - name: "I60 Subarachnoid haemorrhage" + codings: + - "I600" + - "I601" + - "I602" + - "I603" + - "I604" + - "I605" + - "I606" + - "I607" + - "I608" + - "I609" + - name: "H72 Perforation of tympanic membrane" + codings: + - "H729" + - "H720" + - "H721" + - "H722" + - "H728" + - name: "M45-M49 Spondylopathies" + codings: + - "M4913" + - "M4914" + - "M4915" + - "M4916" + - "M4917" + - "M4918" + - "M4919" + - "M492" + - "M4920" + - "M4921" + - "M4922" + - "M4923" + - "M4924" + - "M4925" + - "M4926" + - "M4927" + - "M4928" + - "M4929" + - "M493" + - "M4930" + - "M4931" + - "M4932" + - "M4933" + - "M4934" + - "M4935" + - "M4936" + - "M4937" + - "M4938" + - "M4939" + - "M494" + - "M4940" + - "M4941" + - "M4942" + - "M4943" + - "M4944" + - "M4945" + - "M4946" + - "M4947" + - "M4948" + - "M4949" + - "M495" + - "M4950" + - "M4951" + - "M4952" + - "M4953" + - "M4954" + - "M4955" + - "M4956" + - "M4957" + - "M4958" + - "M4959" + - "M498" + - "M4980" + - "M4981" + - "M4982" + - "M4983" + - "M4984" + - "M4985" + - "M4986" + - "M4987" + - "M4988" + - "M4989" + - "M45" + - "M45X0" + - "M45X1" + - "M45X2" + - "M45X3" + - "M45X4" + - "M45X5" + - "M45X6" + - "M45X7" + - "M45X8" + - "M45X9" + - "M46" + - "M460" + - "M4600" + - "M4601" + - "M4602" + - "M4603" + - "M4604" + - "M4605" + - "M4606" + - "M4607" + - "M4608" + - "M4609" + - "M461" + - "M4610" + - "M4611" + - "M4612" + - "M4613" + - "M4614" + - "M4615" + - "M4616" + - "M4617" + - "M4618" + - "M4619" + - "M462" + - "M4620" + - "M4621" + - "M4622" + - "M4623" + - "M4624" + - "M4625" + - "M4626" + - "M4627" + - "M4628" + - "M4629" + - "M463" + - "M4630" + - "M4631" + - "M4632" + - "M4633" + - "M4634" + - "M4635" + - "M4636" + - "M4637" + - "M4638" + - "M4639" + - "M464" + - "M4640" + - "M4641" + - "M4642" + - "M4643" + - "M4644" + - "M4645" + - "M4646" + - "M4647" + - "M4648" + - "M4649" + - "M465" + - "M4650" + - "M4651" + - "M4652" + - "M4653" + - "M4654" + - "M4655" + - "M4656" + - "M4657" + - "M4658" + - "M4659" + - "M468" + - "M4680" + - "M4681" + - "M4682" + - "M4683" + - "M4684" + - "M4685" + - "M4686" + - "M4687" + - "M4688" + - "M4689" + - "M469" + - "M4690" + - "M4691" + - "M4692" + - "M4693" + - "M4694" + - "M4695" + - "M4696" + - "M4697" + - "M4698" + - "M4699" + - "M47" + - "M470" + - "M4700" + - "M4701" + - "M4702" + - "M4703" + - "M4704" + - "M4705" + - "M4706" + - "M4707" + - "M4708" + - "M4709" + - "M471" + - "M4710" + - "M4711" + - "M4712" + - "M4713" + - "M4714" + - "M4715" + - "M4716" + - "M4717" + - "M4718" + - "M4719" + - "M472" + - "M4720" + - "M4721" + - "M4722" + - "M4723" + - "M4724" + - "M4725" + - "M4726" + - "M4727" + - "M4728" + - "M4729" + - "M478" + - "M4780" + - "M4781" + - "M4782" + - "M4783" + - "M4784" + - "M4785" + - "M4786" + - "M4787" + - "M4788" + - "M4789" + - "M479" + - "M4790" + - "M4791" + - "M4792" + - "M4793" + - "M4794" + - "M4795" + - "M4796" + - "M4797" + - "M4798" + - "M4799" + - "M48" + - "M480" + - "M4800" + - "M4801" + - "M4802" + - "M4803" + - "M4804" + - "M4805" + - "M4806" + - "M4807" + - "M4808" + - "M4809" + - "M481" + - "M4810" + - "M4811" + - "M4812" + - "M4813" + - "M4814" + - "M4815" + - "M4816" + - "M4817" + - "M4818" + - "M4819" + - "M482" + - "M4820" + - "M4821" + - "M4822" + - "M4823" + - "M4824" + - "M4825" + - "M4826" + - "M4827" + - "M4828" + - "M4829" + - "M483" + - "M4830" + - "M4831" + - "M4832" + - "M4833" + - "M4834" + - "M4835" + - "M4836" + - "M4837" + - "M4838" + - "M4839" + - "M484" + - "M4840" + - "M4841" + - "M4842" + - "M4843" + - "M4844" + - "M4845" + - "M4846" + - "M4847" + - "M4848" + - "M4849" + - "M485" + - "M4850" + - "M4851" + - "M4852" + - "M4853" + - "M4854" + - "M4855" + - "M4856" + - "M4857" + - "M4858" + - "M4859" + - "M488" + - "M4880" + - "M4881" + - "M4882" + - "M4883" + - "M4884" + - "M4885" + - "M4886" + - "M4887" + - "M4888" + - "M4889" + - "M489" + - "M4890" + - "M4891" + - "M4892" + - "M4893" + - "M4894" + - "M4895" + - "M4896" + - "M4897" + - "M4898" + - "M4899" + - "M49" + - "M490" + - "M4900" + - "M4901" + - "M4902" + - "M4903" + - "M4904" + - "M4905" + - "M4906" + - "M4907" + - "M4908" + - "M4909" + - "M491" + - "M4910" + - "M4911" + - "M4912" + - name: "K21 Gastro-oesophageal reflux disease" + codings: + - "K210" + - "K219" + - name: "H90 Conductive and sensorineural hearing loss" + codings: + - "H900" + - "H901" + - "H902" + - "H903" + - "H904" + - "H905" + - "H906" + - "H907" + - "H908" + - name: "H91 Other hearing loss" + codings: + - "H910" + - "H911" + - "H912" + - "H913" + - "H918" + - "H919" + - name: "H92 Otalgia and effusion of ear" + codings: + - "H920" + - "H921" + - "H922" + - name: "H93 Other disorders of ear, not elsewhere classified" + codings: + - "H933" + - "H938" + - "H939" + - "H930" + - "H931" + - "H932" + - name: "J80-J84 Other respiratory diseases principally affecting the interstitium" + codings: + - "J80" + - "J81" + - "J82" + - "J84" + - "J840" + - "J841" + - "J848" + - "J849" + - name: "I95-I99 Other and unspecified disorders of the circulatory system" + codings: + - "I980" + - "I981" + - "I982" + - "I983" + - "I988" + - "I99" + - "I95" + - "I950" + - "I951" + - "I952" + - "I958" + - "I959" + - "I97" + - "I970" + - "I971" + - "I972" + - "I978" + - "I979" + - "I98" + - name: "L97 Ulcer of lower limb, not elsewhere classified" + codings: + - "L97" + - name: "L90 Atrophic disorders of skin" + codings: + - "L901" + - "L902" + - "L903" + - "L904" + - "L905" + - "L906" + - "L908" + - "L909" + - "L900" + - name: "L91 Hypertrophic disorders of skin" + codings: + - "L910" + - "L918" + - "L919" + - name: "L92 Granulomatous disorders of skin and subcutaneous tissue" + codings: + - "L920" + - "L921" + - "L922" + - "L923" + - "L928" + - "L929" + - name: "L98 Other disorders of skin and subcutaneous tissue, not elsewhere classified" + codings: + - "L980" + - "L981" + - "L982" + - "L983" + - "L984" + - "L985" + - "L986" + - "L987" + - "L988" + - "L989" + - name: "N17-N19 Renal failure" + codings: + - "N180" + - "N181" + - "N182" + - "N183" + - "N184" + - "N185" + - "N188" + - "N189" + - "N19" + - "N17" + - "N170" + - "N171" + - "N172" + - "N178" + - "N179" + - "N18" + - name: "M20-M25 Other joint disorders" + codings: + - "M20" + - "M200" + - "M201" + - "M202" + - "M203" + - "M204" + - "M205" + - "M206" + - "M21" + - "M210" + - "M2100" + - "M2101" + - "M2102" + - "M2103" + - "M2104" + - "M2105" + - "M2106" + - "M2107" + - "M2108" + - "M2109" + - "M211" + - "M2110" + - "M2111" + - "M2112" + - "M2113" + - "M2114" + - "M2115" + - "M2116" + - "M2117" + - "M2118" + - "M2119" + - "M212" + - "M2120" + - "M2121" + - "M2122" + - "M2123" + - "M2124" + - "M2125" + - "M2126" + - "M2127" + - "M2128" + - "M2129" + - "M213" + - "M2130" + - "M2131" + - "M2132" + - "M2133" + - "M2134" + - "M2135" + - "M2136" + - "M2137" + - "M2138" + - "M2139" + - "M214" + - "M2140" + - "M2141" + - "M2142" + - "M2143" + - "M2144" + - "M2145" + - "M2146" + - "M2147" + - "M2148" + - "M2149" + - "M215" + - "M2150" + - "M2151" + - "M2152" + - "M2153" + - "M2154" + - "M2155" + - "M2156" + - "M2157" + - "M2158" + - "M2159" + - "M216" + - "M2160" + - "M2161" + - "M2162" + - "M2163" + - "M2164" + - "M2165" + - "M2166" + - "M2167" + - "M2168" + - "M2169" + - "M217" + - "M2170" + - "M2171" + - "M2172" + - "M2173" + - "M2174" + - "M2175" + - "M2176" + - "M2177" + - "M2178" + - "M2179" + - "M218" + - "M2180" + - "M2181" + - "M2182" + - "M2183" + - "M2184" + - "M2185" + - "M2186" + - "M2187" + - "M2188" + - "M2189" + - "M219" + - "M2190" + - "M2191" + - "M2192" + - "M2193" + - "M2194" + - "M2195" + - "M2196" + - "M2197" + - "M2198" + - "M2199" + - "M22" + - "M220" + - "M221" + - "M2210" + - "M222" + - "M223" + - "M224" + - "M228" + - "M229" + - "M23" + - "M230" + - "M2300" + - "M2301" + - "M2302" + - "M2303" + - "M2304" + - "M2305" + - "M2306" + - "M2307" + - "M2309" + - "M231" + - "M2310" + - "M2311" + - "M2312" + - "M2313" + - "M2314" + - "M2315" + - "M2316" + - "M2317" + - "M2319" + - "M232" + - "M2320" + - "M2321" + - "M2322" + - "M2323" + - "M2324" + - "M2325" + - "M2326" + - "M2327" + - "M2329" + - "M233" + - "M2330" + - "M2331" + - "M2332" + - "M2333" + - "M2334" + - "M2335" + - "M2336" + - "M2337" + - "M2339" + - "M234" + - "M2340" + - "M2341" + - "M2342" + - "M2343" + - "M2344" + - "M2345" + - "M2346" + - "M2347" + - "M2349" + - "M235" + - "M2350" + - "M2351" + - "M2352" + - "M2353" + - "M2354" + - "M2355" + - "M2356" + - "M2357" + - "M2359" + - "M236" + - "M2360" + - "M2361" + - "M2362" + - "M2363" + - "M2364" + - "M2365" + - "M2366" + - "M2367" + - "M2369" + - "M238" + - "M2380" + - "M2381" + - "M2382" + - "M2383" + - "M2384" + - "M2385" + - "M2386" + - "M2387" + - "M2389" + - "M239" + - "M2390" + - "M2391" + - "M2392" + - "M2393" + - "M2394" + - "M2395" + - "M2396" + - "M2397" + - "M2399" + - "M24" + - "M240" + - "M2400" + - "M2401" + - "M2402" + - "M2403" + - "M2404" + - "M2405" + - "M2406" + - "M2407" + - "M2408" + - "M2409" + - "M241" + - "M2410" + - "M2411" + - "M2412" + - "M2413" + - "M2414" + - "M2415" + - "M2416" + - "M2417" + - "M2418" + - "M2419" + - "M242" + - "M2420" + - "M2421" + - "M2422" + - "M2423" + - "M2424" + - "M2425" + - "M2426" + - "M2427" + - "M2428" + - "M2429" + - "M243" + - "M2430" + - "M2431" + - "M2432" + - "M2433" + - "M2434" + - "M2435" + - "M2436" + - "M2437" + - "M2438" + - "M2439" + - "M244" + - "M2440" + - "M2441" + - "M2442" + - "M2443" + - "M2444" + - "M2445" + - "M2446" + - "M2447" + - "M2448" + - "M2449" + - "M245" + - "M2450" + - "M2451" + - "M2452" + - "M2453" + - "M2454" + - "M2455" + - "M2456" + - "M2457" + - "M2458" + - "M2459" + - "M246" + - "M2460" + - "M2461" + - "M2462" + - "M2463" + - "M2464" + - "M2465" + - "M2466" + - "M2467" + - "M2468" + - "M2469" + - "M247" + - "M2470" + - "M2471" + - "M2472" + - "M2473" + - "M2474" + - "M2475" + - "M2476" + - "M2477" + - "M2478" + - "M2479" + - "M248" + - "M2480" + - "M2481" + - "M2482" + - "M2483" + - "M2484" + - "M2485" + - "M2486" + - "M2487" + - "M2488" + - "M2489" + - "M249" + - "M2490" + - "M2491" + - "M2492" + - "M2493" + - "M2494" + - "M2495" + - "M2496" + - "M2497" + - "M2498" + - "M2499" + - "M25" + - "M250" + - "M2500" + - "M2501" + - "M2502" + - "M2503" + - "M2504" + - "M2505" + - "M2506" + - "M2507" + - "M2508" + - "M2509" + - "M251" + - "M2510" + - "M2511" + - "M2512" + - "M2513" + - "M2514" + - "M2515" + - "M2516" + - "M2517" + - "M2518" + - "M2519" + - "M252" + - "M2520" + - "M2521" + - "M2522" + - "M2523" + - "M2524" + - "M2525" + - "M2526" + - "M2527" + - "M2528" + - "M2529" + - "M253" + - "M2530" + - "M2531" + - "M2532" + - "M2533" + - "M2534" + - "M2535" + - "M2536" + - "M2537" + - "M2538" + - "M2539" + - "M254" + - "M2540" + - "M2541" + - "M2542" + - "M2543" + - "M2544" + - "M2545" + - "M2546" + - "M2547" + - "M2548" + - "M2549" + - "M255" + - "M2550" + - "M2551" + - "M2552" + - "M2553" + - "M2554" + - "M2555" + - "M2556" + - "M2557" + - "M2558" + - "M2559" + - "M256" + - "M2560" + - "M2561" + - "M2562" + - "M2563" + - "M2564" + - "M2565" + - "M2566" + - "M2567" + - "M2568" + - "M2569" + - "M257" + - "M2570" + - "M2571" + - "M2572" + - "M2573" + - "M2574" + - "M2575" + - "M2576" + - "M2577" + - "M2578" + - "M2579" + - "M258" + - "M2580" + - "M2581" + - "M2582" + - "M2583" + - "M2584" + - "M2585" + - "M2586" + - "M2587" + - "M2588" + - "M2589" + - "M259" + - "M2590" + - "M2591" + - "M2592" + - "M2593" + - "M2594" + - "M2595" + - "M2596" + - "M2597" + - "M2598" + - "M2599" + - "M30" + - "M300" + - "M301" + - "M302" + - "M303" + - "M308" + - "M31" + - "M310" + - "M311" + - "M312" + - "M313" + - "M314" + - "M315" + - "M316" + - "M317" + - "M318" + - "M319" + - "M32" + - "M320" + - "M321" + - "M328" + - "M329" + - "M3290" + - "M33" + - "M330" + - "M331" + - "M332" + - "M339" + - "M34" + - "M340" + - "M341" + - "M342" + - "M348" + - "M349" + - "M35" + - "M350" + - "M351" + - "M352" + - "M353" + - "M354" + - "M355" + - "M356" + - "M357" + - "M358" + - "M359" + - "M3599" + - "M36" + - "M360" + - "M361" + - "M362" + - "M363" + - "M364" + - "M368" + - name: "E70-E90 Metabolic disorders" + codings: + - "E70" + - "E700" + - "E701" + - "E702" + - "E703" + - "E708" + - "E709" + - "E71" + - "E710" + - "E711" + - "E712" + - "E713" + - "E72" + - "E720" + - "E721" + - "E722" + - "E723" + - "E724" + - "E725" + - "E728" + - "E729" + - "E73" + - "E730" + - "E731" + - "E738" + - "E739" + - "E74" + - "E740" + - "E741" + - "E742" + - "E743" + - "E744" + - "E748" + - "E749" + - "E75" + - "E750" + - "E751" + - "E752" + - "E753" + - "E754" + - "E755" + - "E756" + - "E76" + - "E760" + - "E761" + - "E762" + - "E763" + - "E768" + - "E769" + - "E77" + - "E770" + - "E771" + - "E778" + - "E779" + - "E78" + - "E780" + - "E781" + - "E782" + - "E783" + - "E784" + - "E785" + - "E786" + - "E788" + - "E789" + - "E79" + - "E790" + - "E791" + - "E798" + - "E799" + - "E80" + - "E800" + - "E801" + - "E802" + - "E803" + - "E804" + - "E805" + - "E806" + - "E807" + - "E83" + - "E830" + - "E831" + - "E832" + - "E833" + - "E834" + - "E835" + - "E838" + - "E839" + - "E84" + - "E840" + - "E841" + - "E848" + - "E849" + - "E85" + - "E850" + - "E851" + - "E852" + - "E853" + - "E854" + - "E858" + - "E859" + - "E86" + - "E87" + - "E870" + - "E871" + - "E872" + - "E873" + - "E874" + - "E875" + - "E876" + - "E877" + - "E878" + - "E88" + - "E880" + - "E881" + - "E882" + - "E883" + - "E888" + - "E889" + - "E89" + - "E890" + - "E891" + - "E892" + - "E893" + - "E894" + - "E895" + - "E896" + - "E898" + - "E899" + - "E90" + - name: "J69 Pneumonitis due to solids and liquids" + codings: + - "J691" + - "J698" + - "J690" + - name: "O99 Other maternal diseases classifiable elsewhere but complicating pregnancy, childbirth and the puerperium" + codings: + - "O995" + - "O996" + - "O997" + - "O998" + - "O990" + - "O991" + - "O992" + - "O993" + - "O994" + - name: "G62 Other polyneuropathies" + codings: + - "G621" + - "G622" + - "G628" + - "G629" + - "G620" + - name: "O63 Long labour" + codings: + - "O632" + - "O639" + - "O630" + - "O631" + - name: "O68 Labour and delivery complicated by foetal stress [distress]" + codings: + - "O680" + - "O681" + - "O682" + - "O683" + - "O688" + - "O689" + - name: "O69 Labour and delivery complicated by umbilical cord complications" + codings: + - "O699" + - "O690" + - "O691" + - "O692" + - "O693" + - "O694" + - "O695" + - "O698" + - name: "K65 Peritonitis" + codings: + - "K650" + - "K658" + - "K659" + - name: "J18 Pneumonia, organism unspecified" + codings: + - "J180" + - "J181" + - "J182" + - "J188" + - "J189" + - name: "L29 Pruritus" + codings: + - "L290" + - "L291" + - "L292" + - "L293" + - "L298" + - "L299" + - name: "M35 Other systemic involvement of connective tissue" + codings: + - "M350" + - "M351" + - "M352" + - "M353" + - "M354" + - "M355" + - "M356" + - "M357" + - "M358" + - "M359" + - "M3599" + - name: "F10-F19 Mental and behavioural disorders due to psychoactive substance use" + codings: + - "F10" + - "F100" + - "F101" + - "F102" + - "F103" + - "F104" + - "F105" + - "F106" + - "F107" + - "F108" + - "F109" + - "F11" + - "F110" + - "F111" + - "F112" + - "F113" + - "F114" + - "F115" + - "F116" + - "F117" + - "F118" + - "F119" + - "F12" + - "F120" + - "F121" + - "F122" + - "F123" + - "F124" + - "F125" + - "F126" + - "F127" + - "F128" + - "F129" + - "F13" + - "F130" + - "F131" + - "F132" + - "F133" + - "F134" + - "F135" + - "F136" + - "F137" + - "F138" + - "F139" + - "F14" + - "F140" + - "F141" + - "F142" + - "F143" + - "F144" + - "F145" + - "F146" + - "F147" + - "F148" + - "F149" + - "F15" + - "F150" + - "F151" + - "F152" + - "F153" + - "F154" + - "F155" + - "F156" + - "F157" + - "F158" + - "F159" + - "F16" + - "F160" + - "F161" + - "F162" + - "F163" + - "F164" + - "F165" + - "F166" + - "F167" + - "F168" + - "F169" + - "F17" + - "F170" + - "F171" + - "F172" + - "F173" + - "F174" + - "F175" + - "F176" + - "F177" + - "F178" + - "F179" + - "F18" + - "F180" + - "F181" + - "F182" + - "F183" + - "F184" + - "F185" + - "F186" + - "F187" + - "F188" + - "F189" + - "F19" + - "F190" + - "F191" + - "F192" + - "F193" + - "F194" + - "F195" + - "F196" + - "F197" + - "F198" + - "F199" + - name: "K01 Embedded and impacted teeth" + codings: + - "K010" + - "K011" + - name: "K02 Dental caries" + codings: + - "K020" + - "K021" + - "K022" + - "K023" + - "K024" + - "K025" + - "K028" + - "K029" + - name: "K04 Diseases of pulp and periapical tissues" + codings: + - "K040" + - "K041" + - "K042" + - "K043" + - "K044" + - "K045" + - "K046" + - "K047" + - "K048" + - "K049" + - name: "K05 Gingivitis and periodontal diseases" + codings: + - "K050" + - "K051" + - "K052" + - "K0522" + - "K053" + - "K054" + - "K055" + - "K056" + - name: "K07 Dentofacial anomalies [including malocclusion]" + codings: + - "K070" + - "K071" + - "K072" + - "K073" + - "K074" + - "K075" + - "K076" + - "K078" + - "K079" + - name: "K08 Other disorders of teeth and supporting structures" + codings: + - "K080" + - "K081" + - "K082" + - "K083" + - "K088" + - "K089" + - name: "K61 Abscess of anal and rectal regions" + codings: + - "K612" + - "K613" + - "K614" + - "K610" + - "K611" + - name: "I10 Essential (primary) hypertension" + codings: + - "I10" + - name: "I12 Hypertensive renal disease" + codings: + - "I120" + - "I129" + - name: "G60-G64 Polyneuropathies and other disorders of the peripheral nervous system" + codings: + - "G60" + - "G600" + - "G601" + - "G602" + - "G603" + - "G608" + - "G609" + - "G61" + - "G610" + - "G611" + - "G618" + - "G619" + - "G62" + - "G620" + - "G621" + - "G622" + - "G628" + - "G629" + - "G63" + - "G630" + - "G631" + - "G632" + - "G633" + - "G634" + - "G635" + - "G636" + - "G638" + - "G64" + - name: "N75 Diseases of Bartholin's gland" + codings: + - "N750" + - "N751" + - "N758" + - "N759" + - name: "N76 Other inflammation of vagina and vulva" + codings: + - "N760" + - "N761" + - "N762" + - "N763" + - "N764" + - "N765" + - "N766" + - "N768" + - name: "N70 Salpingitis and oophoritis" + codings: + - "N700" + - "N701" + - "N709" + - name: "N72 Inflammatory disease of cervix uteri" + codings: + - "N72" + - name: "N73 Other female pelvic inflammatory diseases" + codings: + - "N730" + - "N731" + - "N732" + - "N733" + - "N734" + - "N735" + - "N736" + - "N738" + - "N739" + - name: "I70-I79 Diseases of arteries, arterioles and capillaries" + codings: + - "I7081" + - "I709" + - "I7090" + - "I7091" + - "I71" + - "I710" + - "I711" + - "I712" + - "I713" + - "I714" + - "I715" + - "I716" + - "I718" + - "I719" + - "I72" + - "I720" + - "I721" + - "I722" + - "I723" + - "I724" + - "I725" + - "I726" + - "I728" + - "I729" + - "I73" + - "I730" + - "I731" + - "I738" + - "I739" + - "I74" + - "I740" + - "I741" + - "I742" + - "I743" + - "I744" + - "I745" + - "I748" + - "I749" + - "I77" + - "I770" + - "I771" + - "I772" + - "I773" + - "I774" + - "I775" + - "I776" + - "I778" + - "I779" + - "I78" + - "I780" + - "I781" + - "I788" + - "I789" + - "I79" + - "I790" + - "I791" + - "I792" + - "I798" + - "I70" + - "I700" + - "I7000" + - "I7001" + - "I701" + - "I7010" + - "I7011" + - "I702" + - "I7020" + - "I7021" + - "I708" + - "I7080" + - name: "K92 Other diseases of digestive system" + codings: + - "K920" + - "K921" + - "K922" + - "K928" + - "K929" + - name: "K91 Postprocedural disorders of digestive system, not elsewhere classified" + codings: + - "K910" + - "K911" + - "K912" + - "K913" + - "K914" + - "K915" + - "K918" + - "K919" + - name: "K90 Intestinal malabsorption" + codings: + - "K900" + - "K901" + - "K902" + - "K903" + - "K904" + - "K908" + - "K909" + - name: "L55-L59 Radiation-related disorders of the skin and subcutaneous tissue" + codings: + - "L598" + - "L599" + - "L55" + - "L550" + - "L551" + - "L552" + - "L558" + - "L559" + - "L56" + - "L560" + - "L561" + - "L562" + - "L563" + - "L564" + - "L568" + - "L569" + - "L57" + - "L570" + - "L571" + - "L572" + - "L573" + - "L574" + - "L575" + - "L578" + - "L579" + - "L58" + - "L580" + - "L581" + - "L589" + - "L59" + - "L590" + - name: "H60-H62 Diseases of external ear" + codings: + - "H60" + - "H600" + - "H601" + - "H602" + - "H603" + - "H604" + - "H605" + - "H608" + - "H609" + - "H61" + - "H610" + - "H611" + - "H612" + - "H613" + - "H618" + - "H619" + - "H62" + - "H620" + - "H621" + - "H622" + - "H623" + - "H624" + - "H628" + - name: "H30-H36 Disorders of choroid and retina" + codings: + - "H30" + - "H300" + - "H301" + - "H302" + - "H308" + - "H309" + - "H31" + - "H310" + - "H311" + - "H312" + - "H313" + - "H314" + - "H318" + - "H319" + - "H32" + - "H320" + - "H328" + - "H33" + - "H330" + - "H331" + - "H332" + - "H333" + - "H334" + - "H335" + - "H34" + - "H340" + - "H341" + - "H342" + - "H348" + - "H349" + - "H35" + - "H350" + - "H351" + - "H352" + - "H353" + - "H354" + - "H355" + - "H356" + - "H357" + - "H358" + - "H359" + - "H36" + - "H360" + - "H368" + - name: "I89 Other non-infective disorders of lymphatic vessels and lymph nodes" + codings: + - "I891" + - "I898" + - "I899" + - "I890" + - name: "K35-K38 Diseases of appendix" + codings: + - "K380" + - "K381" + - "K382" + - "K383" + - "K388" + - "K389" + - "K35" + - "K350" + - "K351" + - "K352" + - "K353" + - "K358" + - "K359" + - "K36" + - "K37" + - "K38" + - name: "I83 Varicose veins of lower extremities" + codings: + - "I830" + - "I831" + - "I832" + - "I839" + - name: "I80 Phlebitis and thrombophlebitis" + codings: + - "I809" + - "I800" + - "I801" + - "I802" + - "I803" + - "I808" + - name: "I20-I25 Ischaemic heart diseases" + codings: + - "I238" + - "I24" + - "I240" + - "I241" + - "I248" + - "I249" + - "I25" + - "I250" + - "I251" + - "I252" + - "I253" + - "I254" + - "I255" + - "I256" + - "I258" + - "I259" + - "I20" + - "I200" + - "I201" + - "I208" + - "I209" + - "I21" + - "I210" + - "I211" + - "I212" + - "I213" + - "I214" + - "I219" + - "I21X" + - "I22" + - "I220" + - "I221" + - "I228" + - "I229" + - "I23" + - "I230" + - "I231" + - "I232" + - "I233" + - "I234" + - "I235" + - "I236" + - name: "I84 Haemorrhoids" + codings: + - "I840" + - "I841" + - "I842" + - "I843" + - "I844" + - "I845" + - "I846" + - "I847" + - "I848" + - "I849" + - name: "I85 Oesophageal varices" + codings: + - "I850" + - "I859" + - name: "M89 Other disorders of bone" + codings: + - "M8947" + - "M8948" + - "M8949" + - "M895" + - "M8950" + - "M8951" + - "M8952" + - "M8953" + - "M8954" + - "M8955" + - "M8956" + - "M8957" + - "M8958" + - "M8959" + - "M896" + - "M8960" + - "M8961" + - "M8962" + - "M8963" + - "M8964" + - "M8965" + - "M8966" + - "M8967" + - "M8968" + - "M8969" + - "M898" + - "M8980" + - "M8981" + - "M8982" + - "M8983" + - "M8984" + - "M8985" + - "M8986" + - "M8987" + - "M8988" + - "M8989" + - "M899" + - "M8990" + - "M8991" + - "M8992" + - "M8993" + - "M8994" + - "M8995" + - "M8996" + - "M8997" + - "M8998" + - "M8999" + - "M890" + - "M8900" + - "M8901" + - "M8902" + - "M8903" + - "M8904" + - "M8905" + - "M8906" + - "M8907" + - "M8908" + - "M8909" + - "M891" + - "M8910" + - "M8911" + - "M8912" + - "M8913" + - "M8914" + - "M8915" + - "M8916" + - "M8917" + - "M8918" + - "M8919" + - "M892" + - "M8920" + - "M8921" + - "M8922" + - "M8923" + - "M8924" + - "M8925" + - "M8926" + - "M8927" + - "M8928" + - "M8929" + - "M893" + - "M8930" + - "M8931" + - "M8932" + - "M8933" + - "M8934" + - "M8935" + - "M8936" + - "M8937" + - "M8938" + - "M8939" + - "M894" + - "M8940" + - "M8941" + - "M8942" + - "M8943" + - "M8944" + - "M8945" + - "M8946" + - name: "M86 Osteomyelitis" + codings: + - "M860" + - "M8600" + - "M8601" + - "M8602" + - "M8603" + - "M8604" + - "M8605" + - "M8606" + - "M8607" + - "M8608" + - "M8609" + - "M861" + - "M8610" + - "M8611" + - "M8612" + - "M8613" + - "M8614" + - "M8615" + - "M8616" + - "M8617" + - "M8618" + - "M8619" + - "M862" + - "M8620" + - "M8621" + - "M8622" + - "M8623" + - "M8624" + - "M8625" + - "M8626" + - "M8627" + - "M8628" + - "M8629" + - "M863" + - "M8630" + - "M8631" + - "M8632" + - "M8633" + - "M8634" + - "M8635" + - "M8636" + - "M8637" + - "M8638" + - "M8639" + - "M864" + - "M8640" + - "M8641" + - "M8642" + - "M8643" + - "M8644" + - "M8645" + - "M8646" + - "M8647" + - "M8648" + - "M8649" + - "M865" + - "M8650" + - "M8651" + - "M8652" + - "M8653" + - "M8654" + - "M8655" + - "M8656" + - "M8657" + - "M8658" + - "M8659" + - "M866" + - "M8660" + - "M8661" + - "M8662" + - "M8663" + - "M8664" + - "M8665" + - "M8666" + - "M8667" + - "M8668" + - "M8669" + - "M868" + - "M8680" + - "M8681" + - "M8682" + - "M8683" + - "M8684" + - "M8685" + - "M8686" + - "M8687" + - "M8688" + - "M8689" + - "M869" + - "M8690" + - "M8691" + - "M8692" + - "M8693" + - "M8694" + - "M8695" + - "M8696" + - "M8697" + - "M8698" + - "M8699" + - name: "M87 Osteonecrosis" + codings: + - "M8722" + - "M8723" + - "M8724" + - "M8725" + - "M8726" + - "M8727" + - "M8728" + - "M8729" + - "M873" + - "M8730" + - "M8731" + - "M8732" + - "M8733" + - "M8734" + - "M8735" + - "M8736" + - "M8737" + - "M8738" + - "M8739" + - "M878" + - "M8780" + - "M8781" + - "M8782" + - "M8783" + - "M8784" + - "M8785" + - "M8786" + - "M8787" + - "M8788" + - "M8789" + - "M879" + - "M8790" + - "M8791" + - "M8792" + - "M8793" + - "M8794" + - "M8795" + - "M8796" + - "M8797" + - "M8798" + - "M8799" + - "M870" + - "M8700" + - "M8701" + - "M8702" + - "M8703" + - "M8704" + - "M8705" + - "M8706" + - "M8707" + - "M8708" + - "M8709" + - "M871" + - "M8710" + - "M8711" + - "M8712" + - "M8713" + - "M8714" + - "M8715" + - "M8716" + - "M8717" + - "M8718" + - "M8719" + - "M872" + - "M8720" + - "M8721" + - name: "M84 Disorders of continuity of bone" + codings: + - "M8442" + - "M8443" + - "M8444" + - "M8445" + - "M8446" + - "M8447" + - "M8448" + - "M8449" + - "M848" + - "M8480" + - "M8481" + - "M8482" + - "M8483" + - "M8484" + - "M8485" + - "M8486" + - "M8487" + - "M8488" + - "M8489" + - "M849" + - "M8490" + - "M8491" + - "M8492" + - "M8493" + - "M8494" + - "M8495" + - "M8496" + - "M8497" + - "M8498" + - "M8499" + - "M840" + - "M8400" + - "M8401" + - "M8402" + - "M8403" + - "M8404" + - "M8405" + - "M8406" + - "M8407" + - "M8408" + - "M8409" + - "M841" + - "M8410" + - "M8411" + - "M8412" + - "M8413" + - "M8414" + - "M8415" + - "M8416" + - "M8417" + - "M8418" + - "M8419" + - "M842" + - "M8420" + - "M8421" + - "M8422" + - "M8423" + - "M8424" + - "M8425" + - "M8426" + - "M8427" + - "M8428" + - "M8429" + - "M843" + - "M8430" + - "M8431" + - "M8432" + - "M8433" + - "M8434" + - "M8435" + - "M8436" + - "M8437" + - "M8438" + - "M8439" + - "M844" + - "M8440" + - "M8441" + - name: "M85 Other disorders of bone density and structure" + codings: + - "M850" + - "M8500" + - "M8501" + - "M8502" + - "M8503" + - "M8504" + - "M8505" + - "M8506" + - "M8507" + - "M8508" + - "M8509" + - "M851" + - "M8510" + - "M8511" + - "M8512" + - "M8513" + - "M8514" + - "M8515" + - "M8516" + - "M8517" + - "M8518" + - "M8519" + - "M852" + - "M8520" + - "M8521" + - "M8522" + - "M8523" + - "M8524" + - "M8525" + - "M8526" + - "M8527" + - "M8528" + - "M8529" + - "M853" + - "M8530" + - "M8531" + - "M8532" + - "M8533" + - "M8534" + - "M8535" + - "M8536" + - "M8537" + - "M8538" + - "M8539" + - "M854" + - "M8540" + - "M8541" + - "M8542" + - "M8543" + - "M8544" + - "M8545" + - "M8546" + - "M8547" + - "M8548" + - "M8549" + - "M855" + - "M8550" + - "M8551" + - "M8552" + - "M8553" + - "M8554" + - "M8555" + - "M8556" + - "M8557" + - "M8558" + - "M8559" + - "M856" + - "M8560" + - "M8561" + - "M8562" + - "M8563" + - "M8564" + - "M8565" + - "M8566" + - "M8567" + - "M8568" + - "M8569" + - "M858" + - "M8580" + - "M8581" + - "M8582" + - "M8583" + - "M8584" + - "M8585" + - "M8586" + - "M8587" + - "M8588" + - "M8589" + - "M859" + - "M8590" + - "M8591" + - "M8592" + - "M8593" + - "M8594" + - "M8595" + - "M8596" + - "M8597" + - "M8598" + - "M8599" + - name: "M80 Osteoporosis with pathological fracture" + codings: + - "M800" + - "M8000" + - "M8001" + - "M8002" + - "M8003" + - "M8004" + - "M8005" + - "M8006" + - "M8007" + - "M8008" + - "M8009" + - "M801" + - "M8010" + - "M8011" + - "M8012" + - "M8013" + - "M8014" + - "M8015" + - "M8016" + - "M8017" + - "M8018" + - "M8019" + - "M802" + - "M8020" + - "M8021" + - "M8022" + - "M8023" + - "M8024" + - "M8025" + - "M8026" + - "M8027" + - "M8028" + - "M8029" + - "M803" + - "M8030" + - "M8031" + - "M8032" + - "M8033" + - "M8034" + - "M8035" + - "M8036" + - "M8037" + - "M8038" + - "M8039" + - "M804" + - "M8040" + - "M8041" + - "M8042" + - "M8043" + - "M8044" + - "M8045" + - "M8046" + - "M8047" + - "M8048" + - "M8049" + - "M805" + - "M8050" + - "M8051" + - "M8052" + - "M8053" + - "M8054" + - "M8055" + - "M8056" + - "M8057" + - "M8058" + - "M8059" + - "M808" + - "M8080" + - "M8081" + - "M8082" + - "M8083" + - "M8084" + - "M8085" + - "M8086" + - "M8087" + - "M8088" + - "M8089" + - "M809" + - "M8090" + - "M8091" + - "M8092" + - "M8093" + - "M8094" + - "M8095" + - "M8096" + - "M8097" + - "M8098" + - "M8099" + - name: "M81 Osteoporosis without pathological fracture" + codings: + - "M810" + - "M8100" + - "M8101" + - "M8102" + - "M8103" + - "M8104" + - "M8105" + - "M8106" + - "M8107" + - "M8108" + - "M8109" + - "M811" + - "M8110" + - "M8111" + - "M8112" + - "M8113" + - "M8114" + - "M8115" + - "M8116" + - "M8117" + - "M8118" + - "M8119" + - "M812" + - "M8120" + - "M8121" + - "M8122" + - "M8123" + - "M8124" + - "M8125" + - "M8126" + - "M8127" + - "M8128" + - "M8129" + - "M813" + - "M8130" + - "M8131" + - "M8132" + - "M8133" + - "M8134" + - "M8135" + - "M8136" + - "M8137" + - "M8138" + - "M8139" + - "M814" + - "M8140" + - "M8141" + - "M8142" + - "M8143" + - "M8144" + - "M8145" + - "M8146" + - "M8147" + - "M8148" + - "M8149" + - "M815" + - "M8150" + - "M8151" + - "M8152" + - "M8153" + - "M8154" + - "M8155" + - "M8156" + - "M8157" + - "M8158" + - "M8159" + - "M816" + - "M8160" + - "M8161" + - "M8162" + - "M8163" + - "M8164" + - "M8165" + - "M8166" + - "M8167" + - "M8168" + - "M8169" + - "M818" + - "M8180" + - "M8181" + - "M8182" + - "M8183" + - "M8184" + - "M8185" + - "M8186" + - "M8187" + - "M8188" + - "M8189" + - "M819" + - "M8190" + - "M8191" + - "M8192" + - "M8193" + - "M8194" + - "M8195" + - "M8196" + - "M8197" + - "M8198" + - "M8199" + - name: "B15-B19 Viral hepatitis" + codings: + - "B15" + - "B150" + - "B159" + - "B16" + - "B160" + - "B161" + - "B162" + - "B169" + - "B17" + - "B170" + - "B171" + - "B172" + - "B178" + - "B179" + - "B18" + - "B180" + - "B181" + - "B182" + - "B188" + - "B189" + - "B19" + - "B190" + - "B199" + - name: "M62 Other disorders of muscle" + codings: + - "M620" + - "M6200" + - "M6201" + - "M6202" + - "M6203" + - "M6204" + - "M6205" + - "M6206" + - "M6207" + - "M6208" + - "M6209" + - "M621" + - "M6210" + - "M6211" + - "M6212" + - "M6213" + - "M6214" + - "M6215" + - "M6216" + - "M6217" + - "M6218" + - "M6219" + - "M622" + - "M6220" + - "M6221" + - "M6222" + - "M6223" + - "M6224" + - "M6225" + - "M6226" + - "M6227" + - "M6228" + - "M6229" + - "M623" + - "M6230" + - "M6231" + - "M6232" + - "M6233" + - "M6234" + - "M6235" + - "M6236" + - "M6237" + - "M6238" + - "M6239" + - "M624" + - "M6240" + - "M6241" + - "M6242" + - "M6243" + - "M6244" + - "M6245" + - "M6246" + - "M6247" + - "M6248" + - "M6249" + - "M625" + - "M6250" + - "M6251" + - "M6252" + - "M6253" + - "M6254" + - "M6255" + - "M6256" + - "M6257" + - "M6258" + - "M6259" + - "M626" + - "M6260" + - "M6261" + - "M6262" + - "M6263" + - "M6264" + - "M6265" + - "M6266" + - "M6267" + - "M6268" + - "M6269" + - "M628" + - "M6280" + - "M6281" + - "M6282" + - "M6283" + - "M6284" + - "M6285" + - "M6286" + - "M6287" + - "M6288" + - "M6289" + - "M629" + - "M6290" + - "M6291" + - "M6292" + - "M6293" + - "M6294" + - "M6295" + - "M6296" + - "M6297" + - "M6298" + - "M6299" + - name: "M65 Synovitis and tenosynovitis" + codings: + - "M6521" + - "M6522" + - "M6523" + - "M6524" + - "M6525" + - "M6526" + - "M6527" + - "M6528" + - "M6529" + - "M653" + - "M6530" + - "M6531" + - "M6532" + - "M6533" + - "M6534" + - "M6535" + - "M6536" + - "M6537" + - "M6538" + - "M6539" + - "M654" + - "M6540" + - "M6541" + - "M6542" + - "M6543" + - "M6544" + - "M6545" + - "M6546" + - "M6547" + - "M6548" + - "M6549" + - "M658" + - "M6580" + - "M6581" + - "M6582" + - "M6583" + - "M6584" + - "M6585" + - "M6586" + - "M6587" + - "M6588" + - "M6589" + - "M659" + - "M6590" + - "M6591" + - "M6592" + - "M6593" + - "M6594" + - "M6595" + - "M6596" + - "M6597" + - "M6598" + - "M6599" + - "M650" + - "M6500" + - "M6501" + - "M6502" + - "M6503" + - "M6504" + - "M6505" + - "M6506" + - "M6507" + - "M6508" + - "M6509" + - "M651" + - "M6510" + - "M6511" + - "M6512" + - "M6513" + - "M6514" + - "M6515" + - "M6516" + - "M6517" + - "M6518" + - "M6519" + - "M652" + - "M6520" + - name: "M66 Spontaneous rupture of synovium and tendon" + codings: + - "M660" + - "M6600" + - "M6601" + - "M6602" + - "M6603" + - "M6604" + - "M6605" + - "M6606" + - "M6607" + - "M6608" + - "M6609" + - "M661" + - "M6610" + - "M6611" + - "M6612" + - "M6613" + - "M6614" + - "M6615" + - "M6616" + - "M6617" + - "M6618" + - "M6619" + - "M662" + - "M6620" + - "M6621" + - "M6622" + - "M6623" + - "M6624" + - "M6625" + - "M6626" + - "M6627" + - "M6628" + - "M6629" + - "M663" + - "M6630" + - "M6631" + - "M6632" + - "M6633" + - "M6634" + - "M6635" + - "M6636" + - "M6637" + - "M6638" + - "M6639" + - "M664" + - "M6640" + - "M6641" + - "M6642" + - "M6643" + - "M6644" + - "M6645" + - "M6646" + - "M6647" + - "M6648" + - "M6649" + - "M665" + - "M6650" + - "M6651" + - "M6652" + - "M6653" + - "M6654" + - "M6655" + - "M6656" + - "M6657" + - "M6658" + - "M6659" + - name: "M67 Other disorders of synovium and tendon" + codings: + - "M6747" + - "M6749" + - "M678" + - "M679" + - "M6796" + - "M670" + - "M671" + - "M672" + - "M673" + - "M674" + - "M6743" + - "M6745" + - name: "H80-H83 Diseases of inner ear" + codings: + - "H83" + - "H830" + - "H831" + - "H832" + - "H833" + - "H838" + - "H839" + - "H80" + - "H800" + - "H801" + - "H802" + - "H808" + - "H809" + - "H81" + - "H810" + - "H811" + - "H812" + - "H813" + - "H814" + - "H818" + - "H819" + - "H82" + - name: "M50-M54 Other dorsopathies" + codings: + - "M50" + - "M500" + - "M501" + - "M502" + - "M503" + - "M508" + - "M509" + - "M51" + - "M510" + - "M511" + - "M5116" + - "M5119" + - "M512" + - "M513" + - "M5137" + - "M514" + - "M518" + - "M519" + - "M53" + - "M530" + - "M5300" + - "M5301" + - "M5302" + - "M5303" + - "M5304" + - "M5305" + - "M5306" + - "M5307" + - "M5308" + - "M5309" + - "M531" + - "M5310" + - "M5311" + - "M5312" + - "M5313" + - "M5314" + - "M5315" + - "M5316" + - "M5317" + - "M5318" + - "M5319" + - "M532" + - "M5320" + - "M5321" + - "M5322" + - "M5323" + - "M5324" + - "M5325" + - "M5326" + - "M5327" + - "M5328" + - "M5329" + - "M533" + - "M5330" + - "M5331" + - "M5332" + - "M5333" + - "M5334" + - "M5335" + - "M5336" + - "M5337" + - "M5338" + - "M5339" + - "M538" + - "M5380" + - "M5381" + - "M5382" + - "M5383" + - "M5384" + - "M5385" + - "M5386" + - "M5387" + - "M5388" + - "M5389" + - "M539" + - "M5390" + - "M5391" + - "M5392" + - "M5393" + - "M5394" + - "M5395" + - "M5396" + - "M5397" + - "M5398" + - "M5399" + - "M54" + - "M540" + - "M5400" + - "M5401" + - "M5402" + - "M5403" + - "M5404" + - "M5405" + - "M5406" + - "M5407" + - "M5408" + - "M5409" + - "M541" + - "M5410" + - "M5411" + - "M5412" + - "M5413" + - "M5414" + - "M5415" + - "M5416" + - "M5417" + - "M5418" + - "M5419" + - "M542" + - "M5420" + - "M5421" + - "M5422" + - "M5423" + - "M5424" + - "M5425" + - "M5426" + - "M5427" + - "M5428" + - "M5429" + - "M543" + - "M5430" + - "M5431" + - "M5432" + - "M5433" + - "M5434" + - "M5435" + - "M5436" + - "M5437" + - "M5438" + - "M5439" + - "M544" + - "M5440" + - "M5441" + - "M5442" + - "M5443" + - "M5444" + - "M5445" + - "M5446" + - "M5447" + - "M5448" + - "M5449" + - "M545" + - "M5450" + - "M5451" + - "M5452" + - "M5453" + - "M5454" + - "M5455" + - "M5456" + - "M5457" + - "M5458" + - "M5459" + - "M546" + - "M5460" + - "M5461" + - "M5462" + - "M5463" + - "M5464" + - "M5465" + - "M5466" + - "M5467" + - "M5468" + - "M5469" + - "M548" + - "M5480" + - "M5481" + - "M5482" + - "M5483" + - "M5484" + - "M5485" + - "M5486" + - "M5487" + - "M5488" + - "M5489" + - "M549" + - "M5490" + - "M5491" + - "M5492" + - "M5493" + - "M5494" + - "M5495" + - "M5496" + - "M5497" + - "M5498" + - "M5499" + - name: "N70-N77 Inflammatory diseases of female pelvic organs" + codings: + - "N744" + - "N748" + - "N75" + - "N750" + - "N751" + - "N758" + - "N759" + - "N76" + - "N760" + - "N761" + - "N762" + - "N763" + - "N764" + - "N765" + - "N766" + - "N768" + - "N77" + - "N770" + - "N771" + - "N778" + - "N70" + - "N700" + - "N701" + - "N709" + - "N71" + - "N710" + - "N711" + - "N719" + - "N72" + - "N73" + - "N730" + - "N731" + - "N732" + - "N733" + - "N734" + - "N735" + - "N736" + - "N738" + - "N739" + - "N74" + - "N740" + - "N741" + - "N742" + - "N743" + - name: "H43 Disorders of vitreous body" + codings: + - "H433" + - "H438" + - "H439" + - "H430" + - "H431" + - "H432" + - name: "H40 Glaucoma" + codings: + - "H400" + - "H401" + - "H402" + - "H403" + - "H404" + - "H405" + - "H406" + - "H408" + - "H409" + - name: "H00-H06 Disorders of eyelid, lacrimal system and orbit" + codings: + - "H028" + - "H029" + - "H03" + - "H030" + - "H031" + - "H038" + - "H04" + - "H040" + - "H041" + - "H042" + - "H043" + - "H044" + - "H045" + - "H046" + - "H048" + - "H049" + - "H05" + - "H050" + - "H051" + - "H052" + - "H053" + - "H054" + - "H055" + - "H058" + - "H059" + - "H06" + - "H060" + - "H061" + - "H062" + - "H063" + - "H00" + - "H000" + - "H001" + - "H01" + - "H010" + - "H011" + - "H018" + - "H019" + - "H02" + - "H020" + - "H021" + - "H022" + - "H023" + - "H024" + - "H025" + - "H026" + - "H027" + - fields: + - "20002" + phenotypes: + - name: "oesophageal disorder" + codings: + - "1134" + - "1139" + - "1140" + - "1141" + - "1138" + - "1474" + - name: "bacterial infection" + codings: + - "1442" + - "1440" + - "1574" + - "1572" + - "1677" + - "1678" + - "1566" + - name: "psychological/psychiatric problem" + codings: + - "1243" + - "1286" + - "1287" + - "1288" + - "1289" + - "1290" + - "1291" + - "1614" + - "1615" + - "1408" + - "1409" + - "1410" + - "1616" + - "1469" + - "1470" + - "1531" + - name: "heart valve problem/heart murmur" + codings: + - "1078" + - "1488" + - "1489" + - "1490" + - "1584" + - "1585" + - "1586" + - "1587" + - name: "other fractures" + codings: + - "1644" + - "1645" + - "1646" + - name: "glaucoma" + codings: + - "1277" + - name: "gastric/stomach ulcers" + codings: + - "1142" + - name: "mumps / epidemic parotitis" + codings: + - "1569" + - name: "other renal/kidney problem" + codings: + - "1405" + - "1427" + - "1607" + - "1608" + - "1609" + - "1519" + - "1520" + - name: "hypothyroidism/myxoedema" + codings: + - "1226" + - name: "epilepsy" + codings: + - "1264" + - name: "hiatus hernia" + codings: + - "1474" + - name: "eczema/dermatitis" + codings: + - "1452" + - name: "other neurological problem" + codings: + - "1434" + - "1659" + - "1436" + - "1437" + - "1526" + - "1683" + - "1525" + - name: "gastritis/gastric erosions" + codings: + - "1143" + - name: "kidney stone/ureter stone/bladder stone" + codings: + - "1197" + - name: "carpal tunnel syndrome" + codings: + - "1541" + - name: "breast disease (not cancer)" + codings: + - "1364" + - "1560" + - "1366" + - "1367" + - "1666" + - name: "gynaecological disorder (not cancer)" + codings: + - "1348" + - "1350" + - "1402" + - "1681" + - "1554" + - "1662" + - "1663" + - "1664" + - "1665" + - "1403" + - "1555" + - "1551" + - "1552" + - "1553" + - "1351" + - "1352" + - "1556" + - "1557" + - "1353" + - "1349" + - name: "depression" + codings: + - "1286" + - "1531" + - name: "pleurisy" + codings: + - "1125" + - name: "gestational hypertension/pre-eclampsia" + codings: + - "1073" + - name: "cerebrovascular disease" + codings: + - "1425" + - "1081" + - "1082" + - "1083" + - "1086" + - "1583" + - "1491" + - name: "disc problem" + codings: + - "1532" + - "1533" + - "1312" + - name: "mania/bipolar disorder/manic depression" + codings: + - "1291" + - name: "angina" + codings: + - "1074" + - name: "measles / morbillivirus" + codings: + - "1568" + - name: "urinary tract infection/kidney infection" + codings: + - "1196" + - "1514" + - "1515" + - name: "other respiratory problems" + codings: + - "1117" + - "1125" + - "1123" + - "1124" + - "1497" + - "1126" + - "1595" + - "1596" + - name: "appendicitis" + codings: + - "1502" + - name: "allergy/hypersensitivity/anaphylaxis" + codings: + - "1374" + - "1668" + - "1669" + - "1670" + - "1671" + - "1385" + - "1386" + - "1387" + - "1562" + - "1563" + - name: "other abdominal problem" + codings: + - "1137" + - "1509" + - "1400" + - "1511" + - "1512" + - "1513" + - "1605" + - "1606" + - "1190" + - "1191" + - "1510" + - name: "allergy or anaphylactic reaction to food" + codings: + - "1385" + - name: "heart arrhythmia" + codings: + - "1077" + - "1483" + - "1484" + - "1485" + - "1486" + - "1487" + - "1471" + - name: "sarcoidosis" + codings: + - "1371" + - name: "ankylosing spondylitis" + codings: + - "1313" + - name: "viral infection" + codings: + - "1439" + - "1568" + - "1570" + - "1674" + - "1571" + - "1573" + - "1575" + - "1567" + - "1569" + - name: "vasculitis" + codings: + - "1372" + - "1376" + - "1377" + - "1378" + - "1379" + - "1380" + - name: "cervical spondylosis" + codings: + - "1478" + - name: "soft tissue inflammation" + codings: + - "1618" + - "1619" + - "1620" + - "1621" + - "1622" + - "1623" + - "1624" + - name: "essential hypertension" + codings: + - "1072" + - name: "fracture head & neck" + codings: + - "1626" + - "1627" + - "1628" + - "1629" + - "1630" + - name: "anal problem" + codings: + - "1503" + - "1505" + - "1504" + - name: "colitis/not crohns or ulcerative colitis" + codings: + - "1459" + - name: "ent disorder/not cancer" + codings: + - "1418" + - "1419" + - "1420" + - "1421" + - "1598" + - "1500" + - "1499" + - "1597" + - "1413" + - "1414" + - "1415" + - "1416" + - "1417" + - name: "sciatica" + codings: + - "1476" + - name: "duodenal ulcer" + codings: + - "1457" + - name: "joint disorder" + codings: + - "1295" + - "1537" + - "1538" + - "1477" + - "1464" + - "1465" + - "1466" + - "1467" + - name: "bone disorder" + codings: + - "1293" + - "1308" + - "1309" + - "1310" + - "1617" + - name: "haematology" + codings: + - "1446" + - "1447" + - "1448" + - "1449" + - "1450" + - "1451" + - "1546" + - "1339" + - "1340" + - "1438" + - "1327" + - "1328" + - "1658" + - "1331" + - "1332" + - "1330" + - "1445" + - name: "rheumatic fever" + codings: + - "1479" + - name: "liver/biliary/pancreas problem" + codings: + - "1136" + - "1163" + - "1164" + - "1507" + - "1508" + - "1506" + - "1604" + - "1578" + - "1579" + - "1580" + - "1165" + - "1582" + - "1581" + - "1475" + - "1155" + - "1156" + - "1157" + - "1158" + - "1159" + - "1160" + - "1161" + - "1162" + - name: "diabetic eye disease" + codings: + - "1276" + - name: "tuberculosis (tb)" + codings: + - "1440" + - name: "eye/eyelid problem" + codings: + - "1242" + - "1527" + - "1282" + - "1528" + - "1613" + - "1435" + - "1274" + - "1275" + - "1276" + - "1277" + - "1529" + - "1530" + - "1281" + - "1279" + - "1278" + - name: "peripheral vascular disease" + codings: + - "1067" + - "1087" + - "1088" + - "1592" + - "1492" + - "1591" + - name: "pancreatic disease" + codings: + - "1164" + - "1165" + - name: "bowel problem" + codings: + - "1505" + - "1599" + - "1600" + - "1601" + - "1602" + - "1603" + - "1456" + - "1457" + - "1458" + - "1459" + - "1460" + - "1461" + - "1462" + - "1463" + - "1154" + - "1502" + - "1503" + - "1504" + - name: "hayfever/allergic rhinitis" + codings: + - "1387" + - name: "anaemia" + codings: + - "1446" + - "1330" + - "1331" + - "1332" + - name: "irritable bowel syndrome" + codings: + - "1154" + - name: "obstetric problem" + codings: + - "1558" + - "1559" + - name: "back pain" + codings: + - "1534" + - name: "transient ischaemic attack (tia)" + codings: + - "1082" + - name: "psoriasis" + codings: + - "1453" + - name: "blistering/desquamating skin disorder" + codings: + - "1454" + - "1344" + - "1345" + - name: "abdominal hernia" + codings: + - "1511" + - "1513" + - "1605" + - "1606" + - "1512" + - name: "neck problem/injury" + codings: + - "1545" + - "1478" + - name: "deep venous thrombosis (dvt)" + codings: + - "1094" + - name: "other urological problem (male)" + codings: + - "1396" + - "1516" + - "1517" + - "1404" + - "1679" + - "1207" + - "1210" + - "1214" + - "1518" + - name: "stomach disorder" + codings: + - "1135" + - "1143" + - "1142" + - "1501" + - name: "osteoarthritis" + codings: + - "1465" + - name: "hepatitis" + codings: + - "1155" + - "1578" + - "1579" + - "1580" + - "1581" + - "1582" + - "1156" + - "1157" + - name: "hypertension" + codings: + - "1065" + - "1072" + - "1073" + - name: "muscle or soft tissue injuries" + codings: + - "1406" + - name: "other joint disorder" + codings: + - "1467" + - "1537" + - name: "malabsorption/coeliac disease" + codings: + - "1456" + - name: "stroke" + codings: + - "1081" + - "1583" + - "1491" + - "1086" + - name: "dermatology" + codings: + - "1345" + - "1660" + - "1452" + - "1453" + - "1454" + - "1455" + - "1548" + - "1549" + - "1550" + - "1661" + - "1667" + - "1680" + - "1344" + - "1625" + - name: "head injury" + codings: + - "1266" + - name: "heart attack/myocardial infarction" + codings: + - "1075" + - name: "chronic obstructive airways disease/copd" + codings: + - "1112" + - name: "diverticular disease/diverticulitis" + codings: + - "1458" + - name: "peripheral nerve disorder" + codings: + - "1254" + - "1468" + - "1255" + - "1256" + - "1257" + - name: "prostate problem (not cancer)" + codings: + - "1207" + - "1396" + - "1516" + - "1517" + - name: "sleep apnoea" + codings: + - "1123" + - name: "helicobacter pylori" + codings: + - "1442" + - name: "allergy or anaphylactic reaction to drug" + codings: + - "1386" + - name: "osteomyelitis" + codings: + - "1308" + - name: "pulmonary embolism +/- dvt" + codings: + - "1093" + - name: "retinal problem" + codings: + - "1275" + - "1281" + - "1282" + - "1527" + - "1528" + - name: "heart/cardiac problem" + codings: + - "1066" + - "1479" + - "1483" + - "1484" + - "1485" + - "1486" + - "1487" + - "1488" + - "1489" + - "1490" + - "1426" + - "1074" + - "1075" + - "1076" + - "1077" + - "1078" + - "1079" + - "1080" + - "1584" + - "1585" + - "1586" + - "1587" + - "1588" + - "1589" + - "1590" + - "1471" + - name: "fracture pelvis & lower limb" + codings: + - "1654" + - "1655" + - "1656" + - "1647" + - "1648" + - "1649" + - "1650" + - "1651" + - "1652" + - "1653" + - name: "fracture upper limb & shoulder" + codings: + - "1631" + - "1632" + - "1633" + - "1634" + - "1635" + - "1636" + - "1637" + - "1638" + - "1639" + - "1640" + - name: "hyperthyroidism/thyrotoxicosis" + codings: + - "1225" + - name: "benign breast lump" + codings: + - "1666" + - name: "varicose veins" + codings: + - "1494" + - name: "back problem" + codings: + - "1294" + - "1476" + - "1311" + - "1312" + - "1313" + - "1532" + - "1533" + - "1534" + - "1535" + - "1536" + - name: "dyspepsia / indigestion" + codings: + - "1510" + - name: "bladder problem (not cancer)" + codings: + - "1201" + - "1202" + - name: "renal/kidney failure" + codings: + - "1192" + - "1193" + - "1194" + - name: "urinary frequency / incontinence" + codings: + - "1202" + - name: "spine arthritis/spondylitis" + codings: + - "1311" + - name: "rectal or colon adenoma/polyps" + codings: + - "1460" + - name: "substance abuse/dependency" + codings: + - "1408" + - "1409" + - "1410" + - name: "ovarian problem" + codings: + - "1551" + - "1350" + - "1681" + - "1349" + - name: "bronchiectasis" + codings: + - "1114" + - name: "bronchitis" + codings: + - "1412" + - name: "eye trauma" + codings: + - "1279" + - name: "migraine" + codings: + - "1265" + - name: "high cholesterol" + codings: + - "1473" + - name: "osteoporosis" + codings: + - "1309" + - name: "fracture" + codings: + - "1626" + - "1627" + - "1628" + - "1629" + - "1630" + - "1631" + - "1632" + - "1633" + - "1634" + - "1635" + - "1636" + - "1637" + - "1638" + - "1639" + - "1640" + - "1644" + - "1645" + - "1646" + - "1647" + - "1648" + - "1649" + - "1650" + - "1651" + - "1652" + - "1653" + - "1654" + - "1655" + - "1656" + - name: "ear/vestibular disorder" + codings: + - "1415" + - "1597" + - "1420" + - "1500" + - "1499" + - "1421" + - name: "oesophagitis/barretts oesophagus" + codings: + - "1139" + - name: "tropical & travel-related infections" + codings: + - "1441" + - "1443" + - "1576" + - "1577" + - "1675" + - "1676" + - name: "connective tissue disorder" + codings: + - "1373" + - "1376" + - "1372" + - "1481" + - "1480" + - "1377" + - "1378" + - "1379" + - "1380" + - "1381" + - "1382" + - "1383" + - "1384" + - "1561" + - name: "gall bladder disease" + codings: + - "1161" + - "1163" + - "1162" + - name: "thyroid problem (not cancer)" + codings: + - "1224" + - "1225" + - "1226" + - "1228" + - "1428" + - "1610" + - "1522" + - name: "fibromyalgia" + codings: + - "1542" + - name: "neurology" + codings: + - "1254" + - "1255" + - "1256" + - "1257" + - "1258" + - "1259" + - "1260" + - "1261" + - "1262" + - "1263" + - "1264" + - "1265" + - "1397" + - "1523" + - "1524" + - "1525" + - "1526" + - "1659" + - "1433" + - "1434" + - "1436" + - "1437" + - "1468" + - "1683" + - "1244" + - "1245" + - "1246" + - "1247" + - "1248" + - "1249" + - "1250" + - "1251" + - "1252" + - name: "diabetes" + codings: + - "1220" + - "1223" + - "1521" + - "1221" + - "1222" + - name: "respiratory infection" + codings: + - "1594" + - "1411" + - "1498" + - "1398" + - name: "cervical problem" + codings: + - "1553" + - "1662" + - "1554" + - "1555" + - "1663" + - name: "venous thromboembolic disease" + codings: + - "1068" + - "1094" + - "1093" + - name: "clotting disorder/excessive bleeding" + codings: + - "1445" + - "1546" + - "1327" + - "1328" + - name: "rosacea" + codings: + - "1660" + - name: "miscarriage" + codings: + - "1559" + - name: "varicella zoster virus" + codings: + - "1674" + - "1571" + - "1573" + - name: "emphysema/chronic bronchitis" + codings: + - "1113" + - "1412" + - "1472" + - "1496" + - name: "asthma" + codings: + - "1111" + - name: "cataract" + codings: + - "1278" + - name: "breast cysts" + codings: + - "1367" + - name: "muscle/soft tissue problem" + codings: + - "1297" + - "1540" + - "1541" + - "1542" + - "1544" + - "1619" + - "1322" + - "1618" + - "1406" + - "1620" + - "1621" + - "1622" + - "1623" + - "1624" + - name: "uterine problem" + codings: + - "1552" + - "1351" + - "1352" + - "1353" + - "1402" + - name: "rheumatoid arthritis" + codings: + - "1464" + - name: "spinal injury" + codings: + - "1267" + - name: "throat or larynx disorder" + codings: + - "1414" + - "1418" + - "1419" + - "1598" + - name: "peritonitis" + codings: + - "1190" + - name: "osteopenia" + codings: + - "1617" + - name: "nasal/sinus disorder" + codings: + - "1413" + - "1416" + - "1417" + - name: "inflammatory bowel disease" + codings: + - "1461" + - "1462" + - "1463" + - name: "disorder or pituitary gland" + codings: + - "1237" + - "1429" + - "1430" + - "1431" + - "1238" + - name: "dry eyes" + codings: + - "1529" + - name: "other venous/lymphatic disease" + codings: + - "1493" + - "1593" + - "1494" + - "1495" + - name: "infection of nervous system" + codings: + - "1244" + - "1246" + - "1247" + - "1248" + - "1245" + - name: "cranial nerve problem/palsy" + codings: + - "1249" + - "1523" + - "1250" + - name: "arthritis (nos)" + codings: + - "1538" + - name: "chronic fatigue syndrome" + codings: + - "1482" + - name: "pneumonia" + codings: + - "1398" + - name: "psoriatic arthropathy" + codings: + - "1477" + - name: "anxiety/panic attacks" + codings: + - "1287" + - name: "chronic/degenerative neurological problem" + codings: + - "1258" + - "1397" + - "1259" + - "1260" + - "1261" + - "1262" + - "1263" + - name: "type 2 diabetes" + codings: + - "1223" + - name: "gastro-oesophageal reflux (gord) / gastric reflux" + codings: + - "1138" + - name: "pneumothorax" + codings: + - "1497" + - "1126" + - name: "neurological injury/trauma" + codings: + - "1240" + - "1266" + - "1267" + - "1394" + - name: "gout" + codings: + - "1466" + - name: "testicular problems (not cancer)" + codings: + - "1214" + - name: "nervous breakdown" + codings: + - "1288" + - name: "menorrhagia (unknown cause)" + codings: + - "1556" + - fields: + - "40006" + phenotypes: + - name: "C43 Malignant melanoma of skin" + codings: + - "C430" + - "C431" + - "C432" + - "C433" + - "C434" + - "C435" + - "C436" + - "C437" + - "C438" + - "C439" + - name: "D37-D48 Neoplasms of uncertain or unknown behaviour" + codings: + - "D419" + - "D42" + - "D420" + - "D421" + - "D429" + - "D43" + - "D430" + - "D431" + - "D432" + - "D433" + - "D434" + - "D437" + - "D439" + - "D44" + - "D440" + - "D441" + - "D442" + - "D443" + - "D444" + - "D445" + - "D446" + - "D447" + - "D448" + - "D449" + - "D45" + - "D46" + - "D460" + - "D461" + - "D462" + - "D463" + - "D464" + - "D465" + - "D466" + - "D467" + - "D469" + - "D47" + - "D470" + - "D471" + - "D472" + - "D473" + - "D474" + - "D475" + - "D477" + - "D479" + - "D48" + - "D480" + - "D481" + - "D482" + - "D483" + - "D484" + - "D485" + - "D486" + - "D487" + - "D489" + - "D37" + - "D370" + - "D371" + - "D372" + - "D373" + - "D374" + - "D375" + - "D376" + - "D377" + - "D379" + - "D38" + - "D380" + - "D381" + - "D382" + - "D383" + - "D384" + - "D385" + - "D386" + - "D39" + - "D390" + - "D391" + - "D392" + - "D397" + - "D399" + - "D40" + - "D400" + - "D401" + - "D407" + - "D409" + - "D41" + - "D410" + - "D411" + - "D412" + - "D413" + - "D414" + - "D417" + - name: "D41 Neoplasm of uncertain or unknown behaviour of urinary organs" + codings: + - "D419" + - "D410" + - "D411" + - "D412" + - "D413" + - "D414" + - "D417" + - name: "C34 Malignant neoplasm of bronchus and lung" + codings: + - "C341" + - "C342" + - "C343" + - "C348" + - "C349" + - "C340" + - name: "D06 Carcinoma in situ of cervix uteri" + codings: + - "D069" + - "D060" + - "D061" + - "D067" + - name: "D05 Carcinoma in situ of breast" + codings: + - "D050" + - "D051" + - "D057" + - "D059" + - name: "D04 Carcinoma in situ of skin" + codings: + - "D040" + - "D041" + - "D042" + - "D043" + - "D044" + - "D045" + - "D046" + - "D047" + - "D048" + - "D049" + - name: "D03 Melanoma in situ" + codings: + - "D036" + - "D037" + - "D038" + - "D039" + - "D030" + - "D031" + - "D032" + - "D033" + - "D034" + - "D035" + - name: "C50-C50 Malignant neoplasm of breast" + codings: + - "C50" + - "C500" + - "C501" + - "C502" + - "C503" + - "C504" + - "C505" + - "C506" + - "C508" + - "C509" + - name: "C81-C96 Malignant neoplasms, stated or presumed to be primary, of lymphoid, haematopoietic and related tissue" + codings: + - "C81" + - "C810" + - "C811" + - "C812" + - "C813" + - "C814" + - "C817" + - "C819" + - "C82" + - "C820" + - "C821" + - "C822" + - "C823" + - "C824" + - "C825" + - "C826" + - "C827" + - "C829" + - "C83" + - "C830" + - "C831" + - "C832" + - "C833" + - "C834" + - "C835" + - "C836" + - "C837" + - "C838" + - "C839" + - "C84" + - "C840" + - "C841" + - "C842" + - "C843" + - "C844" + - "C845" + - "C846" + - "C847" + - "C848" + - "C849" + - "C85" + - "C850" + - "C851" + - "C852" + - "C857" + - "C859" + - "C86" + - "C860" + - "C861" + - "C862" + - "C863" + - "C864" + - "C865" + - "C866" + - "C88" + - "C880" + - "C881" + - "C882" + - "C883" + - "C884" + - "C887" + - "C889" + - "C90" + - "C900" + - "C901" + - "C902" + - "C903" + - "C91" + - "C910" + - "C911" + - "C912" + - "C913" + - "C914" + - "C915" + - "C916" + - "C917" + - "C918" + - "C919" + - "C92" + - "C920" + - "C921" + - "C922" + - "C923" + - "C924" + - "C925" + - "C926" + - "C927" + - "C928" + - "C929" + - "C93" + - "C930" + - "C931" + - "C932" + - "C933" + - "C937" + - "C939" + - "C94" + - "C940" + - "C941" + - "C942" + - "C943" + - "C944" + - "C945" + - "C946" + - "C947" + - "C95" + - "C950" + - "C951" + - "C952" + - "C957" + - "C959" + - "C96" + - "C960" + - "C961" + - "C962" + - "C963" + - "C964" + - "C965" + - "C966" + - "C967" + - "C968" + - "C969" + - name: "C20 Malignant neoplasm of rectum" + codings: + - "C20" + - name: "C43-C44 Melanoma and other malignant neoplasms of skin" + codings: + - "C43" + - "C430" + - "C431" + - "C432" + - "C433" + - "C434" + - "C435" + - "C436" + - "C437" + - "C438" + - "C439" + - "C44" + - "C440" + - "C441" + - "C442" + - "C443" + - "C444" + - "C445" + - "C446" + - "C447" + - "C448" + - "C449" + - name: "C44 Other malignant neoplasms of skin" + codings: + - "C440" + - "C441" + - "C442" + - "C443" + - "C444" + - "C445" + - "C446" + - "C447" + - "C448" + - "C449" + - name: "C64-C68 Malignant neoplasms of urinary tract" + codings: + - "C66" + - "C67" + - "C670" + - "C671" + - "C672" + - "C673" + - "C674" + - "C675" + - "C676" + - "C677" + - "C678" + - "C679" + - "C68" + - "C680" + - "C681" + - "C688" + - "C689" + - "C64" + - "C65" + - name: "D00-D09 In situ neoplasms" + codings: + - "D036" + - "D037" + - "D038" + - "D039" + - "D04" + - "D040" + - "D041" + - "D042" + - "D043" + - "D044" + - "D045" + - "D046" + - "D047" + - "D048" + - "D049" + - "D05" + - "D050" + - "D051" + - "D057" + - "D059" + - "D06" + - "D060" + - "D061" + - "D067" + - "D069" + - "D07" + - "D070" + - "D071" + - "D072" + - "D073" + - "D074" + - "D075" + - "D076" + - "D09" + - "D090" + - "D091" + - "D092" + - "D093" + - "D097" + - "D099" + - "D00" + - "D000" + - "D001" + - "D002" + - "D01" + - "D010" + - "D011" + - "D012" + - "D013" + - "D014" + - "D015" + - "D017" + - "D019" + - "D02" + - "D020" + - "D021" + - "D022" + - "D023" + - "D024" + - "D03" + - "D030" + - "D031" + - "D032" + - "D033" + - "D034" + - "D035" + - name: "C15-C26 Malignant neoplasms of digestive organs" + codings: + - "C15" + - "C150" + - "C151" + - "C152" + - "C153" + - "C154" + - "C155" + - "C158" + - "C159" + - "C16" + - "C160" + - "C161" + - "C162" + - "C163" + - "C164" + - "C165" + - "C166" + - "C168" + - "C169" + - "C17" + - "C170" + - "C171" + - "C172" + - "C173" + - "C178" + - "C179" + - "C18" + - "C180" + - "C181" + - "C182" + - "C183" + - "C184" + - "C185" + - "C186" + - "C187" + - "C188" + - "C189" + - "C19" + - "C20" + - "C21" + - "C210" + - "C211" + - "C212" + - "C218" + - "C22" + - "C220" + - "C221" + - "C222" + - "C223" + - "C224" + - "C227" + - "C229" + - "C23" + - "C24" + - "C240" + - "C241" + - "C248" + - "C249" + - "C25" + - "C250" + - "C251" + - "C252" + - "C253" + - "C254" + - "C257" + - "C258" + - "C259" + - "C26" + - "C260" + - "C261" + - "C268" + - "C269" + - name: "C67 Malignant neoplasm of bladder" + codings: + - "C670" + - "C671" + - "C672" + - "C673" + - "C674" + - "C675" + - "C676" + - "C677" + - "C678" + - "C679" + - name: "C64 Malignant neoplasm of kidney, except renal pelvis" + codings: + - "C64" + - name: "C61 Malignant neoplasm of prostate" + codings: + - "C61" + - name: "C18 Malignant neoplasm of colon" + codings: + - "C181" + - "C182" + - "C183" + - "C184" + - "C185" + - "C186" + - "C187" + - "C188" + - "C189" + - "C180" + - name: "C83 Diffuse non-Hodgkin's lymphoma" + codings: + - "C832" + - "C833" + - "C834" + - "C835" + - "C836" + - "C837" + - "C838" + - "C839" + - "C830" + - "C831" + - name: "C30-C39 Malignant neoplasms of respiratory and intrathoracic organs" + codings: + - "C30" + - "C300" + - "C301" + - "C31" + - "C310" + - "C311" + - "C312" + - "C313" + - "C318" + - "C319" + - "C32" + - "C320" + - "C321" + - "C322" + - "C323" + - "C328" + - "C329" + - "C33" + - "C34" + - "C340" + - "C341" + - "C342" + - "C343" + - "C348" + - "C349" + - "C37" + - "C38" + - "C380" + - "C381" + - "C382" + - "C383" + - "C384" + - "C388" + - "C39" + - "C390" + - "C398" + - "C399" + - name: "C56 Malignant neoplasm of ovary" + codings: + - "C56" + - name: "C54 Malignant neoplasm of corpus uteri" + codings: + - "C540" + - "C541" + - "C542" + - "C543" + - "C548" + - "C549" + - name: "C50 Malignant neoplasm of breast" + codings: + - "C500" + - "C501" + - "C502" + - "C503" + - "C504" + - "C505" + - "C506" + - "C508" + - "C509" + - name: "C00-C14 Malignant neoplasms of lip, oral cavity and pharynx" + codings: + - "C14" + - "C140" + - "C142" + - "C148" + - "C00" + - "C000" + - "C001" + - "C002" + - "C003" + - "C004" + - "C005" + - "C006" + - "C008" + - "C009" + - "C01" + - "C02" + - "C020" + - "C021" + - "C022" + - "C023" + - "C024" + - "C028" + - "C029" + - "C03" + - "C030" + - "C031" + - "C039" + - "C04" + - "C040" + - "C041" + - "C048" + - "C049" + - "C05" + - "C050" + - "C051" + - "C052" + - "C058" + - "C059" + - "C06" + - "C060" + - "C061" + - "C062" + - "C068" + - "C069" + - "C07" + - "C08" + - "C080" + - "C081" + - "C088" + - "C089" + - "C09" + - "C090" + - "C091" + - "C098" + - "C099" + - "C10" + - "C100" + - "C101" + - "C102" + - "C103" + - "C104" + - "C108" + - "C109" + - "C11" + - "C110" + - "C111" + - "C112" + - "C113" + - "C118" + - "C119" + - "C12" + - "C13" + - "C130" + - "C131" + - "C132" + - "C138" + - "C139" + - name: "C51-C58 Malignant neoplasms of female genital organs" + codings: + - "C51" + - "C510" + - "C511" + - "C512" + - "C518" + - "C519" + - "C52" + - "C53" + - "C530" + - "C531" + - "C538" + - "C539" + - "C54" + - "C540" + - "C541" + - "C542" + - "C543" + - "C548" + - "C549" + - "C55" + - "C56" + - "C57" + - "C570" + - "C571" + - "C572" + - "C573" + - "C574" + - "C577" + - "C578" + - "C579" + - "C58" + - name: "C60-C63 Malignant neoplasms of male genital organs" + codings: + - "C60" + - "C600" + - "C601" + - "C602" + - "C608" + - "C609" + - "C61" + - "C62" + - "C620" + - "C621" + - "C629" + - "C63" + - "C630" + - "C631" + - "C632" + - "C637" + - "C638" + - "C639" + - name: "D10-D36 Benign neoplasms" + codings: + - "D10" + - "D100" + - "D101" + - "D102" + - "D103" + - "D104" + - "D105" + - "D106" + - "D107" + - "D109" + - "D11" + - "D110" + - "D117" + - "D119" + - "D12" + - "D120" + - "D121" + - "D122" + - "D123" + - "D124" + - "D125" + - "D126" + - "D127" + - "D128" + - "D129" + - "D13" + - "D130" + - "D131" + - "D132" + - "D133" + - "D134" + - "D135" + - "D136" + - "D137" + - "D139" + - "D14" + - "D140" + - "D141" + - "D142" + - "D143" + - "D144" + - "D15" + - "D150" + - "D151" + - "D152" + - "D157" + - "D159" + - "D16" + - "D160" + - "D161" + - "D162" + - "D163" + - "D164" + - "D165" + - "D166" + - "D167" + - "D168" + - "D169" + - "D17" + - "D170" + - "D171" + - "D172" + - "D173" + - "D174" + - "D175" + - "D176" + - "D177" + - "D179" + - "D18" + - "D180" + - "D181" + - "D19" + - "D190" + - "D191" + - "D197" + - "D199" + - "D20" + - "D200" + - "D201" + - "D21" + - "D210" + - "D211" + - "D212" + - "D213" + - "D214" + - "D215" + - "D216" + - "D219" + - "D22" + - "D220" + - "D221" + - "D222" + - "D223" + - "D224" + - "D225" + - "D226" + - "D227" + - "D229" + - "D23" + - "D230" + - "D231" + - "D232" + - "D233" + - "D234" + - "D235" + - "D236" + - "D237" + - "D239" + - "D24" + - "D25" + - "D250" + - "D251" + - "D252" + - "D259" + - "D26" + - "D260" + - "D261" + - "D267" + - "D269" + - "D27" + - "D28" + - "D280" + - "D281" + - "D282" + - "D287" + - "D289" + - "D29" + - "D290" + - "D291" + - "D292" + - "D293" + - "D294" + - "D297" + - "D299" + - "D30" + - "D300" + - "D301" + - "D302" + - "D303" + - "D304" + - "D307" + - "D309" + - "D31" + - "D310" + - "D311" + - "D312" + - "D313" + - "D314" + - "D315" + - "D316" + - "D319" + - "D32" + - "D320" + - "D321" + - "D329" + - "D33" + - "D330" + - "D331" + - "D332" + - "D333" + - "D334" + - "D337" + - "D339" + - "D34" + - "D35" + - "D350" + - "D351" + - "D352" + - "D353" + - "D354" + - "D355" + - "D356" + - "D357" + - "D358" + - "D359" + - "D36" + - "D360" + - "D361" + - "D367" + - "D369" + - fields: + - "1408" + phenotypes: + - name: "Cheese intake" + - fields: + - "1777" + phenotypes: + - name: "Part of a multiple birth" + - fields: + - "1727" + phenotypes: + - name: "Ease of skin tanning" + - fields: + - "1548" + phenotypes: + - name: "Variation in diet" + - fields: + - "728" + phenotypes: + - name: "Number of vehicles in household" + - fields: + - "1717" + phenotypes: + - name: "Skin colour" + - fields: + - "1389" + phenotypes: + - name: "Pork intake" + - fields: + - "1478" + phenotypes: + - name: "Salt added to food" + - fields: + - "1518" + phenotypes: + - name: "Hot drink temperature" + - fields: + - "1558" + phenotypes: + - name: "Alcohol intake frequency." + - fields: + - "20117" + phenotypes: + - name: "Alcohol drinker status" + - fields: + - "1349" + phenotypes: + - name: "Processed meat intake" + - fields: + - "1359" + phenotypes: + - name: "Poultry intake" + - fields: + - "1369" + phenotypes: + - name: "Beef intake" + - fields: + - "1379" + phenotypes: + - name: "Lamb/mutton intake" + - fields: + - "1329" + phenotypes: + - name: "Oily fish intake" + - fields: + - "1339" + phenotypes: + - name: "Non-oily fish intake" + - fields: + - "20116" + phenotypes: + - name: "Smoking status" + - fields: + - "1239" + phenotypes: + - name: "Current tobacco smoking" + - fields: + - "1687" + phenotypes: + - name: "Comparative body size at age 10" + - fields: + - "1697" + phenotypes: + - name: "Comparative height size at age 10" + - fields: + - "1707" + phenotypes: + - name: "Handedness (chirality/laterality)" + - fields: + - "30260" + phenotypes: + - name: "Mean reticulocyte volume" + - fields: + - "30280" + phenotypes: + - name: "Immature reticulocyte fraction" + - fields: + - "30240" + phenotypes: + - name: "Reticulocyte percentage" + - fields: + - "30250" + phenotypes: + - name: "Reticulocyte count" + - fields: + - "30300" + phenotypes: + - name: "High light scatter reticulocyte count" + - fields: + - "30270" + phenotypes: + - name: "Mean sphered cell volume" + - fields: + - "30290" + phenotypes: + - name: "High light scatter reticulocyte percentage" + - fields: + - "30230" + phenotypes: + - name: "Nucleated red blood cell percentage" + - fields: + - "30170" + phenotypes: + - name: "Nucleated red blood cell count" + - fields: + - "30120" + phenotypes: + - name: "Lymphocyte count" + - fields: + - "30130" + phenotypes: + - name: "Monocyte count" + - fields: + - "30140" + phenotypes: + - name: "Neutrophill count" + - fields: + - "30150" + phenotypes: + - name: "Eosinophill count" + - fields: + - "30160" + phenotypes: + - name: "Basophill count" + - fields: + - "30180" + phenotypes: + - name: "Lymphocyte percentage" + - fields: + - "30190" + phenotypes: + - name: "Monocyte percentage" + - fields: + - "30200" + phenotypes: + - name: "Neutrophill percentage" + - fields: + - "30210" + phenotypes: + - name: "Eosinophill percentage" + - fields: + - "30220" + phenotypes: + - name: "Basophill percentage" + - fields: + - "30100" + phenotypes: + - name: "Mean platelet (thrombocyte) volume" + - fields: + - "30110" + phenotypes: + - name: "Platelet distribution width" + - fields: + - "30060" + phenotypes: + - name: "Mean corpuscular haemoglobin concentration" + - fields: + - "30090" + phenotypes: + - name: "Platelet crit" + - fields: + - "30000" + phenotypes: + - name: "White blood cell (leukocyte) count" + - fields: + - "30050" + phenotypes: + - name: "Mean corpuscular haemoglobin" + - fields: + - "30080" + phenotypes: + - name: "Platelet count" + - fields: + - "30040" + phenotypes: + - name: "Mean corpuscular volume" + - fields: + - "30070" + phenotypes: + - name: "Red blood cell (erythrocyte) distribution width" + - fields: + - "30010" + phenotypes: + - name: "Red blood cell (erythrocyte) count" + - fields: + - "30020" + phenotypes: + - name: "Haemoglobin concentration" + - fields: + - "30030" + phenotypes: + - name: "Haematocrit percentage" + - fields: + - "23100" + phenotypes: + - name: "Whole body fat mass" + - fields: + - "23130" + phenotypes: + - name: "Trunk predicted mass" + - fields: + - "23129" + phenotypes: + - name: "Trunk fat-free mass" + - fields: + - "23128" + phenotypes: + - name: "Trunk fat mass" + - fields: + - "23127" + phenotypes: + - name: "Trunk fat percentage" + - fields: + - "23099" + phenotypes: + - name: "Body fat percentage" + - fields: + - "23126" + phenotypes: + - name: "Arm predicted mass (left)" + - fields: + - "23125" + phenotypes: + - name: "Arm fat-free mass (left)" + - fields: + - "23124" + phenotypes: + - name: "Arm fat mass (left)" + - fields: + - "23123" + phenotypes: + - name: "Arm fat percentage (left)" + - fields: + - "23122" + phenotypes: + - name: "Arm predicted mass (right)" + - fields: + - "23121" + phenotypes: + - name: "Arm fat-free mass (right)" + - fields: + - "23120" + phenotypes: + - name: "Arm fat mass (right)" + - fields: + - "23119" + phenotypes: + - name: "Arm fat percentage (right)" + - fields: + - "23118" + phenotypes: + - name: "Leg predicted mass (left)" + - fields: + - "23117" + phenotypes: + - name: "Leg fat-free mass (left)" + - fields: + - "23116" + phenotypes: + - name: "Leg fat mass (left)" + - fields: + - "23115" + phenotypes: + - name: "Leg fat percentage (left)" + - fields: + - "23109" + phenotypes: + - name: "Impedance of arm (right)" + - fields: + - "23114" + phenotypes: + - name: "Leg predicted mass (right)" + - fields: + - "23113" + phenotypes: + - name: "Leg fat-free mass (right)" + - fields: + - "23106" + phenotypes: + - name: "Impedance of whole body" + - fields: + - "23101" + phenotypes: + - name: "Whole body fat-free mass" + - fields: + - "23112" + phenotypes: + - name: "Leg fat mass (right)" + - fields: + - "23110" + phenotypes: + - name: "Impedance of arm (left)" + - fields: + - "23111" + phenotypes: + - name: "Leg fat percentage (right)" + - fields: + - "23108" + phenotypes: + - name: "Impedance of leg (left)" + - fields: + - "23107" + phenotypes: + - name: "Impedance of leg (right)" + - fields: + - "23105" + phenotypes: + - name: "Basal metabolic rate" + - fields: + - "23102" + phenotypes: + - name: "Whole body water mass" + - fields: + - "20015" + phenotypes: + - name: "Sitting height" + - fields: + - "21001" + phenotypes: + - name: "Body mass index (BMI)" + - fields: + - "21002" + phenotypes: + - name: "Weight" + - fields: + - "50" + phenotypes: + - name: "Standing height" + - fields: + - "49" + phenotypes: + - name: "Hip circumference" + - fields: + - "48" + phenotypes: + - name: "Waist circumference" + - fields: + - "1319" + phenotypes: + - name: "Dried fruit intake" + - fields: + - "1498" + phenotypes: + - name: "Coffee intake" + - fields: + - "1528" + phenotypes: + - name: "Water intake" + - fields: + - "2277" + phenotypes: + - name: "Frequency of solarium/sunlamp use" + - fields: + - "1299" + phenotypes: + - name: "Salad / raw vegetable intake" + - fields: + - "1458" + phenotypes: + - name: "Cereal intake" + - fields: + - "1309" + phenotypes: + - name: "Fresh fruit intake" + - fields: + - "1488" + phenotypes: + - name: "Tea intake" + - fields: + - "1289" + phenotypes: + - name: "Cooked vegetable intake" + - fields: + - "1438" + phenotypes: + - name: "Bread intake" + - fields: + - "1873" + phenotypes: + - name: "Number of full brothers" + - fields: + - "1883" + phenotypes: + - name: "Number of full sisters" + - fields: + - "709" + phenotypes: + - name: "Number in household" + - fields: + - "46" + phenotypes: + - name: "Hand grip strength (left)" + - fields: + - "47" + phenotypes: + - name: "Hand grip strength (right)" + - fields: + - "134" + phenotypes: + - name: "Number of self-reported cancers" + - fields: + - "135" + phenotypes: + - name: "Number of self-reported non-cancer illnesses" + - fields: + - "136" + phenotypes: + - name: "Number of operations, self-reported" + - fields: + - "137" + phenotypes: + - name: "Number of treatments/medications taken" + - fields: + - "1160" + phenotypes: + - name: "Sleep duration" + - fields: + - "20023" + phenotypes: + - name: "Mean time to correctly identify matches" + - fields: + - "3079" + phenotypes: + - name: "Pace-maker" + - fields: + - "21003" + phenotypes: + - name: "Age-Assessment" + - fields: + - "22001" + phenotypes: + - name: "Genetic-Sex" + +subset: + - fields: + - "21000" + phenotypes: + - name: "White" + codings: + - "1001" + - "1002" + - "1003" + - "1" \ No newline at end of file diff --git a/main.nf b/main.nf index d4ba9319..0b4cd48d 100644 --- a/main.nf +++ b/main.nf @@ -2,20 +2,20 @@ nextflow.enable.dsl = 2 params.VERBOSITY = 0 -params.TRAITS_DATASET = "NO_TRAITS_DATASET" -params.UKB_ENCODING_FILE = "NO_UKB_ENCODING_FILE" +params.TRAITS_DATASET = "You need to provide a Traits dataset." +params.UKB_ENCODING_FILE = "data/NO_UKB_ENCODING_FILE" params.CALL_THRESHOLD = 0.9 params.POSITIVITY_CONSTRAINT = 0.01 params.MAF_THRESHOLD = 0.01 params.COHORT = "UKBB" -params.UKB_CONFIG = "NO_UKB_TRAIT_CONFIG" -params.UKB_WITHDRAWAL_LIST = 'NO_WITHDRAWAL_LIST' +params.UKB_CONFIG = "data/ukbconfig.yaml" +params.UKB_WITHDRAWAL_LIST = 'data/NO_WITHDRAWAL_LIST' params.OUTDIR = "${launchDir}/results" // Confounding adjustment by PCA params.NB_PCS = 6 -params.QC_FILE = "NO_QC_FILE" -params.LD_BLOCKS = "NO_LD_BLOCKS" +params.QC_FILE = "data/NO_QC_FILE" +params.LD_BLOCKS = "data/NO_LD_BLOCKS" params.FLASHPCA_EXCLUSION_REGIONS = "data/exclusion_regions_hg19.txt" // Estimands Generation @@ -26,9 +26,9 @@ params.STUDY_DESIGN = "CUSTOM" params.ESTIMANDS_FILE = "NO_ESTIMANDS_FILE" // FROM_ACTORS -params.EXTRA_CONFOUNDERS = 'NO_EXTRA_CONFOUNDER' -params.EXTRA_COVARIATES = 'NO_EXTRA_COVARIATE' -params.ENVIRONMENTALS = 'NO_EXTRA_TREATMENT' +params.EXTRA_CONFOUNDERS = 'data/NO_EXTRA_CONFOUNDER' +params.EXTRA_COVARIATES = 'data/NO_EXTRA_COVARIATE' +params.ENVIRONMENTALS = 'data/NO_EXTRA_TREATMENT' params.ORDERS = "1,2" // Sieve Variance Plateau @@ -61,16 +61,28 @@ workflow { // Define Parameters verbosity = params.VERBOSITY + study_design = params.STUDY_DESIGN + bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() + estimands_file = Channel.value(file("$params.ESTIMANDS_FILE")) + bqtls_file = Channel.value(file("$params.BQTLS")) + transactors_files = Channel.fromPath("$params.TRANS_ACTORS").collect() + extra_confounders = Channel.value(file("$params.EXTRA_CONFOUNDERS")) + extra_treatments = Channel.value(file("$params.ENVIRONMENTALS")) + extra_covariates = Channel.value(file("$params.EXTRA_COVARIATES")) + batch_size = params.BATCH_SIZE + call_threshold = params.CALL_THRESHOLD + positivity_constraint = params.POSITIVITY_CONSTRAINT + cohort = params.COHORT ukb_encoding_file = params.UKB_ENCODING_FILE - ukb_config = Channel.value(file("$params.UKB_CONFIG")) - ukb_withdrawal_list = Channel.value(file("$params.UKB_WITHDRAWAL_LIST")) - traits_dataset = Channel.value(file("$params.TRAITS_DATASET")) + ukb_config = Channel.value(file("$params.UKB_CONFIG", checkIfExists: true)) + ukb_withdrawal_list = Channel.value(file("$params.UKB_WITHDRAWAL_LIST", checkIfExists: true)) + traits_dataset = Channel.value(file("$params.TRAITS_DATASET", checkIfExists: true)) maf_threshold = params.MAF_THRESHOLD - qc_file = Channel.value(file("$params.QC_FILE")) - flashpca_excl_reg = Channel.value(file("$params.FLASHPCA_EXCLUSION_REGIONS")) - ld_blocks = Channel.value(file("$params.LD_BLOCKS")) + qc_file = Channel.value(file("$params.QC_FILE", checkIfExists: true)) + flashpca_excl_reg = Channel.value(file("$params.FLASHPCA_EXCLUSION_REGIONS", checkIfExists: true)) + ld_blocks = Channel.value(file("$params.LD_BLOCKS", checkIfExists: true)) bed_files = Channel.fromFilePairs("$params.BED_FILES", size: 3, checkIfExists: true){ file -> file.baseName } estimator_config = Channel.value(file("${params.ESTIMATOR_FILE}")) @@ -110,8 +122,19 @@ workflow { // generate main dataset and estimand configuration files EstimationInputs( + study_design, + bgen_files, ExtractTraits.out, - GeneticConfounders.out + GeneticConfounders.out, + estimands_file, + bqtls_file, + transactors_files, + extra_confounders, + extra_treatments, + extra_covariates, + batch_size, + call_threshold, + positivity_constraint ) // generate estimates diff --git a/modules/estimation_inputs.nf b/modules/estimation_inputs.nf index c99d2e7b..abadf42f 100644 --- a/modules/estimation_inputs.nf +++ b/modules/estimation_inputs.nf @@ -11,6 +11,9 @@ process TMLEInputsFromParamFile { path traits path genetic_confounders path parameter + val batch_size + val call_threshold + val positivity_constraint output: path "final.data.arrow", emit: dataset @@ -18,16 +21,16 @@ process TMLEInputsFromParamFile { script: bgen_prefix = longest_prefix(bgenfiles) - batch_size = params.BATCH_SIZE == 0 ? "" : "--batch-size ${params.BATCH_SIZE}" + batch_size = batch_size == 0 ? "" : "--batch-size ${batch_size}" """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/tmle_inputs.jl \ --traits $traits \ --bgen-prefix $bgen_prefix \ - --call-threshold ${params.CALL_THRESHOLD} \ + --call-threshold ${call_threshold} \ --pcs $genetic_confounders \ $batch_size \ - --positivity-constraint ${params.POSITIVITY_CONSTRAINT} \ + --positivity-constraint ${positivity_constraint} \ from-param-file $parameter """ } @@ -47,6 +50,9 @@ process TMLEInputsFromActors { path extra_covariates path bqtls path trans_actors + val batch_size + val call_threshold + val positivity_constraint output: path "final.data.arrow", emit: dataset @@ -55,7 +61,7 @@ process TMLEInputsFromActors { script: bgen_prefix = longest_prefix(bgenfiles) trans_actors_prefix = longest_prefix(trans_actors) - batch_size = params.BATCH_SIZE == 0 ? "" : "--batch-size ${params.BATCH_SIZE}" + batch_size = batch_size == 0 ? "" : "--batch-size ${batch_size}" extra_confounders = extra_confounders.name != 'NO_EXTRA_CONFOUNDER' ? "--extra-confounders $extra_confounders" : '' extra_treatments = extra_treatments.name != 'NO_EXTRA_TREATMENT' ? "--extra-treatments $extra_treatments" : '' extra_covariates = extra_covariates.name != 'NO_EXTRA_COVARIATE' ? "--extra-covariates $extra_covariates" : '' @@ -64,9 +70,9 @@ process TMLEInputsFromActors { JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/tmle_inputs.jl \ --traits $traits \ --bgen-prefix $bgen_prefix \ - --call-threshold ${params.CALL_THRESHOLD} \ + --call-threshold ${call_threshold} \ --pcs $genetic_confounders \ - --positivity-constraint ${params.POSITIVITY_CONSTRAINT} \ + --positivity-constraint ${positivity_constraint} \ $batch_size \ from-actors $bqtls $trans_actors_prefix $extra_confounders $extra_treatments $extra_covariates --orders ${params.ORDERS} """ @@ -74,18 +80,22 @@ process TMLEInputsFromActors { workflow EstimationInputs { take: + study_design + bgen_files traits genetic_confounders + estimands_file + bqtls_file + transactors_files + extra_confounders + extra_treatments + extra_covariates + batch_size + call_threshold + positivity_constraint main: - bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() - - if (params.STUDY_DESIGN == "FROM_ACTORS") { - bqtls = Channel.value(file("$params.BQTLS")) - trans_actors = Channel.fromPath("$params.TRANS_ACTORS", checkIfExists: true).collect() - extra_confounders = Channel.value(file("$params.EXTRA_CONFOUNDERS")) - extra_treatments = Channel.value(file("$params.ENVIRONMENTALS")) - extra_covariates = Channel.value(file("$params.EXTRA_COVARIATES")) + if (study_design == "FROM_ACTORS") { tmle_inputs = TMLEInputsFromActors( bgen_files, traits, @@ -93,16 +103,23 @@ workflow EstimationInputs { extra_confounders, extra_treatments, extra_covariates, - bqtls, - trans_actors) + bqtls_file, + transactors_files, + batch_size, + call_threshold, + positivity_constraint + ) } - else if (params.STUDY_DESIGN == "CUSTOM"){ - estimands_file = Channel.value(file("$params.ESTIMANDS_FILE")) + else if (study_design == "CUSTOM"){ tmle_inputs = TMLEInputsFromParamFile( bgen_files, traits, genetic_confounders, - estimands_file) + estimands_file, + batch_size, + call_threshold, + positivity_constraint + ) } else { throw new Exception("This STUDY_DESIGN is not available.") diff --git a/modules/svp.nf b/modules/svp.nf index c4ee3174..10c2c5c8 100644 --- a/modules/svp.nf +++ b/modules/svp.nf @@ -38,7 +38,7 @@ process SVP { publishDir "$params.OUTDIR", mode: 'symlink' input: - path tmle_files + path hdf5_results path GRM_ids path GRM_matrix val n_estimators @@ -50,10 +50,11 @@ process SVP { path "svp.hdf5" script: + hdf5_prefix = longest_prefix(hdf5_results) """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no /opt/bin/tmle sieve-variance-plateau \ - tmle_result \ + $hdf5_prefix \ --n-estimators=$n_estimators \ --max-tau=$max_tau \ --estimator-key=$estimator_key \ diff --git a/test/custom_from_actors.jl b/test/custom_from_actors.jl index c0a386b9..b5d0deb9 100644 --- a/test/custom_from_actors.jl +++ b/test/custom_from_actors.jl @@ -23,7 +23,7 @@ include("utils.jl") # Sieve Variance Plateau File svp = jldopen(joinpath("results", "svp.hdf5")) - @test haskey(svp, "taus") + @test length(svp["taus"]) == 10 @test haskey(svp, "variances") @test length(svp["results"]) > 200 @test all(x.TMLE isa TMLE.TMLEstimate for x in svp["results"]) From 6181d95163f7e8ad08da3f8b495f750ee29a579f Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Fri, 15 Dec 2023 15:05:08 +0000 Subject: [PATCH 20/65] add log and include --- main.nf | 13 +++++++++++++ modules/svp.nf | 2 ++ nextflow.config | 4 ++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/main.nf b/main.nf index 0b4cd48d..53de3662 100644 --- a/main.nf +++ b/main.nf @@ -57,6 +57,19 @@ include { ExtractTraits } from './modules/traits.nf' include { EstimationWorkflow } from './modules/estimation.nf' include { SVPWorkflow } from './modules/svp.nf' +log.info """\ + ${params.manifest.name} v${params.manifest.version} + ========================== + Cohort Type : ${params.COHORT} + Study Design : ${params.STUDY_DESIGN} + -- + run as : ${workflow.commandLine} + started at : ${workflow.start} + config files : ${workflow.configFiles} + container : ${workflow.containerEngine} + """ + .stripIndent() + workflow { // Define Parameters verbosity = params.VERBOSITY diff --git a/modules/svp.nf b/modules/svp.nf index 10c2c5c8..f2249030 100644 --- a/modules/svp.nf +++ b/modules/svp.nf @@ -1,3 +1,5 @@ +include { longest_prefix } from './utils.nf' + process GRMPart { container "olivierlabayle/tl-core:0.6" label "bigmem" diff --git a/nextflow.config b/nextflow.config index 8b95168d..da942909 100644 --- a/nextflow.config +++ b/nextflow.config @@ -1,11 +1,11 @@ manifest { - name = 'targene-pipeline' + name = 'TarGene' author = 'Olivier Labayle' homePage = 'https://github.com/TARGENE/targene-pipeline' description = 'Pipeline for the estimation of genetic effects using Targeted Learning' mainScript = 'main.nf' nextflowVersion = '>=22.04' - version = '0.3.5' + version = '0.9.0' } process { From ea8cde61c85f4e439b40cc318a04170cc7b6873e Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Fri, 15 Dec 2023 15:11:25 +0000 Subject: [PATCH 21/65] remove info for now --- main.nf | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/main.nf b/main.nf index 53de3662..0b4cd48d 100644 --- a/main.nf +++ b/main.nf @@ -57,19 +57,6 @@ include { ExtractTraits } from './modules/traits.nf' include { EstimationWorkflow } from './modules/estimation.nf' include { SVPWorkflow } from './modules/svp.nf' -log.info """\ - ${params.manifest.name} v${params.manifest.version} - ========================== - Cohort Type : ${params.COHORT} - Study Design : ${params.STUDY_DESIGN} - -- - run as : ${workflow.commandLine} - started at : ${workflow.start} - config files : ${workflow.configFiles} - container : ${workflow.containerEngine} - """ - .stripIndent() - workflow { // Define Parameters verbosity = params.VERBOSITY From c33624dad771deb773a233b1da0a992e3112e421 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Fri, 15 Dec 2023 16:18:21 +0000 Subject: [PATCH 22/65] update pipeline --- data/NO_UKB_ENCODING_FILE | 0 main.nf | 16 +++++++++++++++- modules/traits.nf | 14 +++++++++----- 3 files changed, 24 insertions(+), 6 deletions(-) delete mode 100644 data/NO_UKB_ENCODING_FILE diff --git a/data/NO_UKB_ENCODING_FILE b/data/NO_UKB_ENCODING_FILE deleted file mode 100644 index e69de29b..00000000 diff --git a/main.nf b/main.nf index 0b4cd48d..b9955852 100644 --- a/main.nf +++ b/main.nf @@ -3,7 +3,7 @@ nextflow.enable.dsl = 2 params.VERBOSITY = 0 params.TRAITS_DATASET = "You need to provide a Traits dataset." -params.UKB_ENCODING_FILE = "data/NO_UKB_ENCODING_FILE" +params.UKB_ENCODING_FILE = "NO_UKB_ENCODING_FILE" params.CALL_THRESHOLD = 0.9 params.POSITIVITY_CONSTRAINT = 0.01 params.MAF_THRESHOLD = 0.01 @@ -57,6 +57,20 @@ include { ExtractTraits } from './modules/traits.nf' include { EstimationWorkflow } from './modules/estimation.nf' include { SVPWorkflow } from './modules/svp.nf' +log.info """\ + ${workflow.manifest.name} v${workflow.manifest.version} + ========================== + Cohort Type : ${params.COHORT} + Study Design : ${params.STUDY_DESIGN} + -- + run as : ${workflow.commandLine} + started at : ${workflow.start} + config files : ${workflow.configFiles} + container : ${workflow.containerEngine} + """ + .stripIndent() + + workflow { // Define Parameters verbosity = params.VERBOSITY diff --git a/modules/traits.nf b/modules/traits.nf index 67b5d753..d9ce1822 100644 --- a/modules/traits.nf +++ b/modules/traits.nf @@ -38,19 +38,19 @@ process TraitsFromUKB { input: path dataset - path traits_config + path ukbconfig path withdrawal_list output: path 'traits.csv' script: - traits_config = traits_config.name != 'NO_UKB_TRAIT_CONFIG' ? "--conf $traits_config" : '' - withdrawal_list = withdrawal_list.name != 'NO_WITHDRAWAL_LIST' ? "--withdrawal-list $withdrawal_list" : '' + ukbconfig = ukbconfig.getName() != 'NO_UKB_TRAIT_CONFIG' ? "--conf $ukbconfig" : '' + withdrawal_list = withdrawal_list.getName() != 'NO_WITHDRAWAL_LIST' ? "--withdrawal-list $withdrawal_list" : '' """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/UKBMain.jl --startup-file=no --threads $task.cpus /UKBMain.jl/scripts/process_main_dataset.jl \ - $dataset $traits_config $withdrawal_list + $dataset $ukbconfig $withdrawal_list """ } @@ -66,7 +66,11 @@ workflow ExtractTraits { if (cohort == "UKBB") { if (ukb_encoding_file != "NO_UKB_ENCODING_FILE") { UKBFieldsList(ukb_config) - decrypted_dataset = UKBConv(UKBFieldsList.out, traits_dataset, ukb_encoding_file) + decrypted_dataset = UKBConv( + UKBFieldsList.out, + traits_dataset, + Channel.value(file("${ukb_encoding_file}", checkIfExists: true)) + ) } else { decrypted_dataset = traits_dataset From c8764ee89c3c6d91cd8fbd2137fb3af0b56ca594 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Fri, 15 Dec 2023 16:19:24 +0000 Subject: [PATCH 23/65] remove ld block print --- modules/genotypes.nf | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/genotypes.nf b/modules/genotypes.nf index f226c3f2..08c8eccf 100644 --- a/modules/genotypes.nf +++ b/modules/genotypes.nf @@ -17,7 +17,6 @@ process filterBED{ prefix = bedfiles[0].toString().minus('.bed') qc_file = qcfile.getName() != 'NO_QC_FILE' ? "--qcfile $qcfile" : '' ld_blocks = ld_blocks.getName() != 'NO_LD_BLOCKS' ? "--ld-blocks $ld_blocks" : '' - println(ld_blocks) """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/prepare_confounders.jl \ From 38ebe0adbe6303d8b3698acb44c152ed9dade128 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Fri, 15 Dec 2023 17:17:08 +0000 Subject: [PATCH 24/65] try solve neg control --- main.nf | 6 +++--- modules/negative_control.nf | 41 ++++++++++++++++++++++++------------- test/ukb_from_actors.jl | 2 +- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/main.nf b/main.nf index b9955852..1c99101d 100644 --- a/main.nf +++ b/main.nf @@ -31,21 +31,21 @@ params.EXTRA_COVARIATES = 'data/NO_EXTRA_COVARIATE' params.ENVIRONMENTALS = 'data/NO_EXTRA_TREATMENT' params.ORDERS = "1,2" -// Sieve Variance Plateau +// SVP Parameters params.SVP = false params.GRM_NSPLITS = 100 params.NB_SVP_ESTIMATORS = 100 params.MAX_SVP_THRESHOLD = 0.9 params.SVP_ESTIMATOR_KEY = "TMLE" -// TMLE +// TMLE Parameters params.KEEP_IC = params.SVP == true ? true : false params.PVAL_THRESHOLD = 0.05 params.TMLE_SAVE_EVERY = 100 params.AGGREGATED_DATASET = "results/dataset.arrow" params.ESTIMATOR_FILE = "glmnet" -// Outputs +// Outputs Parameters params.ARROW_OUTPUT = "dataset.arrow" params.JSON_OUTPUT = "NO_JSON_OUTPUT" params.HDF5_OUTPUT = "results.hdf5" diff --git a/modules/negative_control.nf b/modules/negative_control.nf index cb0afe81..7e8dbc23 100644 --- a/modules/negative_control.nf +++ b/modules/negative_control.nf @@ -1,13 +1,11 @@ +// Negative Control Parameters params.PERMUTATION_HDF5_OUTPUT = "permutation_results.hdf5" params.PERMUTATION_JSON_OUTPUT = "NO_JSON_OUTPUT" - -// Permutation Tests Parameters -params.MAX_PERMUTATION_TESTS = null +params.MAX_PERMUTATION_TESTS = "" params.PERMUTATION_ORDERS = "1" params.RNG = 123 params.MAF_MATCHING_RELTOL = 0.05 params.N_RANDOM_VARIANTS = 10 - include { longest_prefix } from './utils.nf' process GeneratePermutationTestsData { @@ -25,7 +23,7 @@ process GeneratePermutationTestsData { path "*.jls", emit: estimands script: - limit = params.MAX_PERMUTATION_TESTS == null ? "" : "--limit=${params.MAX_PERMUTATION_TESTS}" + limit = params.MAX_PERMUTATION_TESTS == "" ? "" : "--limit=${params.MAX_PERMUTATION_TESTS}" """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/NegativeControl --startup-file=no /NegativeControl/bin/generate_permutation_data.jl \ @@ -68,20 +66,35 @@ process GenerateRandomVariantsTestsData { """ } -workflow NegativeControl { +workflow { results_file = Channel.value(file("${params.OUTDIR}/${params.HDF5_OUTPUT}")) // Permutation Tests dataset = Channel.value(file("${params.OUTDIR}/${params.ARROW_OUTPUT}")) - estimator_file = Channel.value(file("${params.ESTIMATOR_FILE}")) - GeneratePermutationTestsData(dataset, results_file) - TMLE( - GeneratePermutationTestsData.output.dataset, - GeneratePermutationTestsData.output.estimands.flatten(), - estimator_file + estimator_config = Channel.value(file("${params.ESTIMATOR_FILE}")) + keep_ic = false + do_svp = false + pval_threshold = params.PVAL_THRESHOLD + save_every = params.TMLE_SAVE_EVERY + hdf5_output = params.PERMUTATION_HDF5_OUTPUT + json_output = params.PERMUTATION_JSON_OUTPUT + + GeneratePermutationTestsData( + dataset, + results_file ) - MergeOutputs(TMLE.out.collect(), params.PERMUTATION_HDF5_OUTPUT, params.PERMUTATION_JSON_OUTPUT) - + EstimationWorkflow( + GeneratePermutationTestsData.output.dataset, + GeneratePermutationTestsData.output.estimands.flatten(), + estimator_config, + keep_ic, + do_svp, + pval_threshold, + save_every, + hdf5_output, + json_output + ) + // Random Variants parameter files generation if (params.STUDY_DESIGN == "FROM_ACTORS") { bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() diff --git a/test/ukb_from_actors.jl b/test/ukb_from_actors.jl index 18de9b17..41b67a29 100644 --- a/test/ukb_from_actors.jl +++ b/test/ukb_from_actors.jl @@ -53,7 +53,7 @@ include("utils.jl") end @testset "Test negative controls" begin - cmd = `nextflow run main.nf -entry negativeControl -c conf/ci_jobs/ukb_from_actors.config $args` + cmd = `nextflow run main.nf -main-script modules/negative_control.nf -c conf/ci_jobs/ukb_from_actors.config $args` @info string("The following command will be run:\n", cmd) r = run(cmd) From ac125812fbf12e3e607f686242d7ac408f0cc09d Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Fri, 15 Dec 2023 17:55:03 +0000 Subject: [PATCH 25/65] try other syntax --- test/ukb_from_actors.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ukb_from_actors.jl b/test/ukb_from_actors.jl index 41b67a29..cb9aa44d 100644 --- a/test/ukb_from_actors.jl +++ b/test/ukb_from_actors.jl @@ -53,7 +53,7 @@ include("utils.jl") end @testset "Test negative controls" begin - cmd = `nextflow run main.nf -main-script modules/negative_control.nf -c conf/ci_jobs/ukb_from_actors.config $args` + cmd = `nextflow run -main-script modules/negative_control.nf -c conf/ci_jobs/ukb_from_actors.config $args` @info string("The following command will be run:\n", cmd) r = run(cmd) From 0f57c6951df3f88ea6cbab35bf131893d2e49a12 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Fri, 15 Dec 2023 18:15:44 +0000 Subject: [PATCH 26/65] maybe fix --- modules/negative_control.nf | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/modules/negative_control.nf b/modules/negative_control.nf index 7e8dbc23..c7497393 100644 --- a/modules/negative_control.nf +++ b/modules/negative_control.nf @@ -1,4 +1,11 @@ +#!/usr/bin/env nextflow +nextflow.enable.dsl = 2 + // Negative Control Parameters +params.OUTDIR = "${launchDir}/results" +params.BATCH_SIZE = 400 +params.VERBOSITY = 1 +params.HDF5_OUTPUT = "results.hdf5" params.PERMUTATION_HDF5_OUTPUT = "permutation_results.hdf5" params.PERMUTATION_JSON_OUTPUT = "NO_JSON_OUTPUT" params.MAX_PERMUTATION_TESTS = "" @@ -6,7 +13,11 @@ params.PERMUTATION_ORDERS = "1" params.RNG = 123 params.MAF_MATCHING_RELTOL = 0.05 params.N_RANDOM_VARIANTS = 10 +params.TMLE_SAVE_EVERY = 100 +params.ARROW_OUTPUT = "dataset.arrow" + include { longest_prefix } from './utils.nf' +include { EstimationWorkflow } from './estimation.nf' process GeneratePermutationTestsData { container "olivierlabayle/negative-controls:cvtmle" From 868f5d7ca17649b3ba400b4e9074b327b8e22700 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Sat, 16 Dec 2023 10:32:25 +0000 Subject: [PATCH 27/65] fix neg control --- test/ukb_from_actors.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ukb_from_actors.jl b/test/ukb_from_actors.jl index cb9aa44d..a59fcbfe 100644 --- a/test/ukb_from_actors.jl +++ b/test/ukb_from_actors.jl @@ -53,7 +53,7 @@ include("utils.jl") end @testset "Test negative controls" begin - cmd = `nextflow run -main-script modules/negative_control.nf -c conf/ci_jobs/ukb_from_actors.config $args` + cmd = `nextflow run . -main-script modules/negative_control.nf -c conf/ci_jobs/ukb_from_actors.config $args` @info string("The following command will be run:\n", cmd) r = run(cmd) From c93b9029c5566068c167ed4f62826ac69f84fc8b Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 19 Dec 2023 09:51:21 +0000 Subject: [PATCH 28/65] update test configs --- .github/workflows/CI.yml | 3 +- conf/ci_jobs/ukb_from_actors.config | 21 ------- conf/ci_jobs/ukb_from_param_file.config | 16 ------ modules/estimation_inputs.nf | 18 +++++- test/configs/base.config | 5 ++ .../configs}/custom_from_actors.config | 5 +- test/configs/ukb.config | 10 ++++ test/configs/ukb_allele_independent.config | 6 ++ test/configs/ukb_custom.config | 7 +++ test/configs/ukb_from_actors.config | 12 ++++ test/custom_from_actors.jl | 2 +- test/ukb_allele_independent.jl | 55 +++++++++++++++++++ .../{ukb_from_param_file.jl => ukb_custom.jl} | 2 +- test/ukb_from_actors.jl | 2 +- 14 files changed, 118 insertions(+), 46 deletions(-) delete mode 100644 conf/ci_jobs/ukb_from_actors.config delete mode 100644 conf/ci_jobs/ukb_from_param_file.config create mode 100644 test/configs/base.config rename {conf/ci_jobs => test/configs}/custom_from_actors.config (64%) create mode 100644 test/configs/ukb.config create mode 100644 test/configs/ukb_allele_independent.config create mode 100644 test/configs/ukb_custom.config create mode 100644 test/configs/ukb_from_actors.config create mode 100644 test/ukb_allele_independent.jl rename test/{ukb_from_param_file.jl => ukb_custom.jl} (93%) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 0f642bb5..1542f010 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -16,7 +16,8 @@ jobs: matrix: testrun: - "ukb_from_actors.jl" - - "ukb_from_param_file.jl" + - "ukb_custom.jl" + - "ukb_allele_independent.jl" - "custom_from_actors.jl" steps: - uses: actions/checkout@v2 diff --git a/conf/ci_jobs/ukb_from_actors.config b/conf/ci_jobs/ukb_from_actors.config deleted file mode 100644 index 1e8b9b1a..00000000 --- a/conf/ci_jobs/ukb_from_actors.config +++ /dev/null @@ -1,21 +0,0 @@ -params { - STUDY_DESIGN = "FROM_ACTORS" - TRAITS_DATASET = "test/data/dataset.csv" - COHORT = "UKBB" - BED_FILES = "test/data/unphased_bed/ukb_chr{1,2,3}.{bed,bim,fam}" - BGEN_FILES = "test/data/unphased_bgen/ukb_chr{1,2,3}.{bgen,bgen.bgi,sample}" - QC_FILE = "test/data/qc_file.csv" - LD_BLOCKS = "test/data/ld_blocks.txt" - UKB_WITHDRAWAL_LIST = "test/data/withdrawal_list.txt" - UKB_CONFIG = "test/data/ukbconfig_small.yaml" - ESTIMATOR_FILE = "test/data/estimator.jl" - JSON_OUTPUT = "results.json" - PVAL_THRESHOLD = 1 - BQTLS = "test/data/actors/bqtls.csv" - TRANS_ACTORS = "test/data/actors/eqtls.csv" - POSITIVITY_CONSTRAINT = 0.01 - GRM_NSPLITS = 10 - MAX_PERMUTATION_TESTS = 100 - MAF_MATCHING_RELTOL = 0.9 - N_RANDOM_VARIANTS = 5 -} diff --git a/conf/ci_jobs/ukb_from_param_file.config b/conf/ci_jobs/ukb_from_param_file.config deleted file mode 100644 index e162bd94..00000000 --- a/conf/ci_jobs/ukb_from_param_file.config +++ /dev/null @@ -1,16 +0,0 @@ -params { - STUDY_DESIGN = "CUSTOM" - ESTIMANDS_FILE = "test/data/parameters/parameters.yaml" - TRAITS_DATASET = "test/data/dataset.csv" - COHORT = "UKBB" - BED_FILES = "test/data/unphased_bed/ukb_chr{1,2,3}.{bed,bim,fam}" - BGEN_FILES = "test/data/unphased_bgen/ukb_chr{1,2,3}.{bgen,bgen.bgi,sample}" - QC_FILE = "test/data/qc_file.csv" - LD_BLOCKS = "test/data/ld_blocks.txt" - UKB_WITHDRAWAL_LIST = "test/data/withdrawal_list.txt" - NB_PCS = 6 - UKB_CONFIG = "test/data/ukbconfig_small.yaml" - ESTIMATOR_FILE = "test/data/estimator.jl" - - POSITIVITY_CONSTRAINT = 0.0 -} diff --git a/modules/estimation_inputs.nf b/modules/estimation_inputs.nf index abadf42f..33a7231a 100644 --- a/modules/estimation_inputs.nf +++ b/modules/estimation_inputs.nf @@ -14,6 +14,7 @@ process TMLEInputsFromParamFile { val batch_size val call_threshold val positivity_constraint + val command output: path "final.data.arrow", emit: dataset @@ -31,7 +32,7 @@ process TMLEInputsFromParamFile { --pcs $genetic_confounders \ $batch_size \ --positivity-constraint ${positivity_constraint} \ - from-param-file $parameter + $command $parameter """ } @@ -118,7 +119,20 @@ workflow EstimationInputs { estimands_file, batch_size, call_threshold, - positivity_constraint + positivity_constraint, + "from-param-file" + ) + } + else if (study_design == "ALLELE_INDEPENDENT"){ + tmle_inputs = TMLEInputsFromParamFile( + bgen_files, + traits, + genetic_confounders, + estimands_file, + batch_size, + call_threshold, + positivity_constraint, + "allele-independent" ) } else { diff --git a/test/configs/base.config b/test/configs/base.config new file mode 100644 index 00000000..220275e8 --- /dev/null +++ b/test/configs/base.config @@ -0,0 +1,5 @@ +params { + BED_FILES = "test/data/unphased_bed/ukb_chr{1,2,3}.{bed,bim,fam}" + BGEN_FILES = "test/data/unphased_bgen/ukb_chr{1,2,3}.{bgen,bgen.bgi,sample}" + ESTIMATOR_FILE = "test/data/estimator.jl" +} \ No newline at end of file diff --git a/conf/ci_jobs/custom_from_actors.config b/test/configs/custom_from_actors.config similarity index 64% rename from conf/ci_jobs/custom_from_actors.config rename to test/configs/custom_from_actors.config index 1cecb8c3..7c2cfe3e 100644 --- a/conf/ci_jobs/custom_from_actors.config +++ b/test/configs/custom_from_actors.config @@ -1,11 +1,10 @@ +includeConfig 'base.config' + params { STUDY_DESIGN = "FROM_ACTORS" TRAITS_DATASET = "test/data/traits.csv" COHORT = "CUSTOM" - BED_FILES = "test/data/unphased_bed/ukb_chr{1,2,3}.{bed,bim,fam}" - BGEN_FILES = "test/data/unphased_bgen/ukb_chr{1,2,3}.{bgen,bgen.bgi,sample}" TRAITS_CONFIG = "test/data/ukbconfig_small.yaml" - ESTIMATOR_FILE = "test/data/estimator.jl" SVP = true NB_SVP_ESTIMATORS = 10 PVAL_THRESHOLD = 1 diff --git a/test/configs/ukb.config b/test/configs/ukb.config new file mode 100644 index 00000000..17a218ed --- /dev/null +++ b/test/configs/ukb.config @@ -0,0 +1,10 @@ +includeConfig 'base.config' + +params { + COHORT = "UKBB" + TRAITS_DATASET = "test/data/dataset.csv" + QC_FILE = "test/data/qc_file.csv" + LD_BLOCKS = "test/data/ld_blocks.txt" + UKB_WITHDRAWAL_LIST = "test/data/withdrawal_list.txt" + UKB_CONFIG = "test/data/ukbconfig_small.yaml" +} \ No newline at end of file diff --git a/test/configs/ukb_allele_independent.config b/test/configs/ukb_allele_independent.config new file mode 100644 index 00000000..90f1ee18 --- /dev/null +++ b/test/configs/ukb_allele_independent.config @@ -0,0 +1,6 @@ +includeConfig 'ukb.config' + +params { + STUDY_DESIGN = "ALLELE_INDEPENDENT" + ESTIMANDS_FILE = "test/data/interactions_allele_independent.yaml" +} diff --git a/test/configs/ukb_custom.config b/test/configs/ukb_custom.config new file mode 100644 index 00000000..fac20b0d --- /dev/null +++ b/test/configs/ukb_custom.config @@ -0,0 +1,7 @@ +includeConfig 'ukb.config' + +params { + STUDY_DESIGN = "CUSTOM" + ESTIMANDS_FILE = "test/data/parameters/parameters.yaml" + POSITIVITY_CONSTRAINT = 0.0 +} diff --git a/test/configs/ukb_from_actors.config b/test/configs/ukb_from_actors.config new file mode 100644 index 00000000..962ba61c --- /dev/null +++ b/test/configs/ukb_from_actors.config @@ -0,0 +1,12 @@ +includeConfig 'ukb.config' + +params { + STUDY_DESIGN = "FROM_ACTORS" + JSON_OUTPUT = "results.json" + PVAL_THRESHOLD = 1 + BQTLS = "test/data/actors/bqtls.csv" + TRANS_ACTORS = "test/data/actors/eqtls.csv" + MAX_PERMUTATION_TESTS = 100 + MAF_MATCHING_RELTOL = 0.9 + N_RANDOM_VARIANTS = 5 +} diff --git a/test/custom_from_actors.jl b/test/custom_from_actors.jl index b5d0deb9..5ca1ec11 100644 --- a/test/custom_from_actors.jl +++ b/test/custom_from_actors.jl @@ -15,7 +15,7 @@ args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] include("utils.jl") @testset "Test custom_from_actors.config" begin - cmd = `nextflow run main.nf -c conf/ci_jobs/custom_from_actors.config $args` + cmd = `nextflow run main.nf -c test/configs/custom_from_actors.config $args` @info string("The following command will be run:\n", cmd) r = run(cmd) diff --git a/test/ukb_allele_independent.jl b/test/ukb_allele_independent.jl new file mode 100644 index 00000000..65e58b43 --- /dev/null +++ b/test/ukb_allele_independent.jl @@ -0,0 +1,55 @@ +module TestUKBAlleleIndependent + +using Test +using JLD2 +using Arrow +using DataFrames +using TMLE +using CSV +using TargetedEstimation +using Serialization + +#Β "local" profile assumes singularity is installed +args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] + +include("utils.jl") + +@testset "Test ukb_from_actors.config" begin + cmd = `nextflow run main.nf -c test/configs/ukb_allele_independent.config $args` + @info string("The following command will be run:\n", cmd) + + r = run(cmd) + @test r.exitcode == 0 + + ##Β Checking main output + # Results + hdf5_results_file = jldopen(joinpath("results", "results.hdf5")) + results_from_hdf5 = vcat((hdf5_results_file[key] for key in keys(hdf5_results_file))...) + results_from_json = TMLE.read_json(joinpath("results", "results.json")) + @test length(results_from_json) == length(results_from_hdf5) > 300 + + failed_results = retrieve_failed_results(results_from_hdf5; expected_keys=(:TMLE, :OSE)) + # All fails are due to fluctuation failure due non positive definite matrix + # This does not affect the OSE + @test isempty(failed_results.OSE) + # Less than 1/3 affected: this is still quite significant + @test length(failed_results.TMLE) / length(results_from_hdf5) < 1/3 + @test all(startswith(x.msg, "Could not fluctuate") for x ∈ failed_results.TMLE) + + dataset = Arrow.Table(joinpath("results", "dataset.arrow")) |> DataFrame + + check_fails_are_extremely_rare_traits(failed_results.TMLE, dataset; ncases=3) + + ##Β Checking parameter files correspond to either bQTL only or bQTL/eQTL + bQTLs = Symbol.(CSV.read(joinpath("test", "data", "actors", "bqtls.csv"), DataFrame).ID) + + config_1 = deserialize(joinpath("results", "estimands", "final.estimands_1.jls")) + @test length(config_1.estimands) == 400 + config_2 = deserialize(joinpath("results", "estimands", "final.estimands_2.jls")) + @test 0 < length(config_2.estimands) <= 400 + for Ξ¨ in vcat(config_1.estimands, config_2.estimands) + @test length(intersect(keys(Ξ¨.treatment_values), bQTLs)) == 1 + end +end + +end \ No newline at end of file diff --git a/test/ukb_from_param_file.jl b/test/ukb_custom.jl similarity index 93% rename from test/ukb_from_param_file.jl rename to test/ukb_custom.jl index a5c67e89..5b7d70c5 100644 --- a/test/ukb_from_param_file.jl +++ b/test/ukb_custom.jl @@ -13,7 +13,7 @@ args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] include("utils.jl") @testset "Test ukb_from_param_files.config" begin - cmd = `nextflow run main.nf -c conf/ci_jobs/ukb_from_param_file.config $args` + cmd = `nextflow run main.nf -c test/configs/ukb_custom.config $args` @info string("The following command will be run:\n", cmd) r = run(cmd) diff --git a/test/ukb_from_actors.jl b/test/ukb_from_actors.jl index a59fcbfe..20935109 100644 --- a/test/ukb_from_actors.jl +++ b/test/ukb_from_actors.jl @@ -15,7 +15,7 @@ args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] include("utils.jl") @testset "Test ukb_from_actors.config" begin - cmd = `nextflow run main.nf -c conf/ci_jobs/ukb_from_actors.config $args` + cmd = `nextflow run main.nf -c test/configs/ukb_from_actors.config $args` @info string("The following command will be run:\n", cmd) r = run(cmd) From c992f787c98b4c9abab4529bddb29a1554b7a840 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 19 Dec 2023 13:21:09 +0000 Subject: [PATCH 29/65] rename some variables --- docs/src/data_sources.md | 12 ++++-- docs/src/miscellaneous.md | 6 ++- docs/src/negative_control.md | 13 +++--- docs/src/nextflow_params.md | 41 +++++++++++-------- docs/src/study_designs.md | 40 +++++++++++++++++- modules/negative_control.nf | 3 ++ modules/traits.nf | 6 +-- test/configs/custom_from_actors.config | 1 - .../data/interactions_allele_independent.yaml | 9 ++++ 9 files changed, 97 insertions(+), 34 deletions(-) create mode 100644 test/data/interactions_allele_independent.yaml diff --git a/docs/src/data_sources.md b/docs/src/data_sources.md index 179261ea..be12c18f 100644 --- a/docs/src/data_sources.md +++ b/docs/src/data_sources.md @@ -4,17 +4,21 @@ The following section describes the data sources that are currently supported by ## Custom Dataset -TarGene supports custom datasets which must include both genetic data (see [Genetic Data](@ref)) and trait data (a .csv file). Please ensure that the annotation of SNPs in your .bgen files matches the annotation used when speicfying the parameters. When running a custom dataset, you must set the `COHORT` parameter in the nextflow configuration file to the name of your cohort or custom dataset (anything **else** than "UKBB"). The trait data for this mode must also be specified in the `DECRYPTED_DATASET` parameter in the nextflow configuration file. Please ensure the Sample IDs that map the genetic data to the trait data are included as the first column of your trait data, with the column name `SAMPLE_ID`. +Select with COHORT = "MY_COHORT". + +TarGene supports custom datasets which must include both genetic data (see [Genetic Data](@ref)) and trait data (a .csv file). Please ensure that the annotation of SNPs in your .bgen files matches the annotation used when speicfying the parameters. When running a custom dataset, you must set the `COHORT` parameter in the nextflow configuration file to the name of your cohort or custom dataset (anything **else** than "UKBB"). The trait data for this mode must also be specified in the `TRAITS_DATASET` parameter in the nextflow configuration file. Please ensure the Sample IDs that map the genetic data to the trait data are included as the first column of your trait data, with the column name `SAMPLE_ID`. ## UK-Biobank +Select with COHORT = "UKBB". + The UK-Biobank is composed of both genetic data (.bed and .bgen files) and trait data. While there is a plan to use only bgen and trait data, the pipeline currently uses all sources of information. Below we explain how to specify those arguments to TarGene. For more information on the structure of the UK-Biobank data, please refer to their [User Guide](https://biobank.ndph.ox.ac.uk/crystal/exinfo.cgi?src=accessing_data_guide). ### Main Dataset -The trait dataset is often called the "main dataset" and consists of an encrypted file containing individuals' trait information accessible via your project. The first option is thus to provide this dataset using the `ENCRYPTED_DATASET` parameter. Since the data is encrypted, the pipeline will also need the encoding file that you can provide with `ENCODING_FILE`. +The trait dataset is often called the "main dataset" and consists of an encrypted file containing individuals' trait information accessible via your project. The first option is thus to provide this dataset using the `TRAITS_DATASET` parameter. Since the data is encrypted, the pipeline will also need the encoding file that you can provide with `UKB_ENCODING_FILE`. -A "main dataset" is typically very large and only a few traits will be of interest to a given study. To extract those relevant traits from the dataset, a `TRAITS_CONFIG` YAML file must be provided. Since, writing by hand such a file for large scale study can quickly become tenuous, we provide a configuration file corresponding to the [GeneAtlas](http://geneatlas.roslin.ed.ac.uk/) study [here](https://github.com/TARGENE/UKBMain.jl/blob/main/config/geneatlas_config.yaml). +A "main dataset" is typically very large and only a few traits will be of interest to a given study. To extract those relevant traits from the dataset, a `UKB_CONFIG` YAML file must be provided. Since, writing by hand such a file for large scale study can quickly become tenuous, we provide a configuration file corresponding to the [GeneAtlas](http://geneatlas.roslin.ed.ac.uk/) study [here](https://github.com/TARGENE/UKBMain.jl/blob/main/config/geneatlas_config.yaml). The structure of a file is composed of extraction rules that convert UK-Biobank fields to traits of interest. An example is presented below: @@ -83,7 +87,7 @@ We now describe the currently available extraction rules based on variable types - Categorical variables: For those variables again, the first visit assessment value for the specified field is used. An additional `codings` field can be provided. In that case the variable is turned into a indicator variable indicating whether an individual is included in the criterion given by the `codings` list. In the previous `subset` section, "White" is such a transformation into a binary variable. Note that we could add more elements to the list to subset on a wider population. - Categorical Arrayed variables: Some fields in the UK-Biobank consist in list of traits for individuals. This is the case for at least the fields: 41202, 41204, 20002 and 40006. For those fields it is essential to define a `codings` section that describes a trait. For instance "Malignant melanoma of skin" corresponds to the declaration of any of the `codings` for an individual. Moreover, some fields share the same encoding, this is the case for 41202 and 41204. In that situation it may be useful to aggregate those sources of information. For that purpose multiple fields can be provided to the `fields` section. In that scenario the declaration of any of the coding in a `codings` section for any of the `fields` will define the trait. -To come back to the pipeline specification, if a "typical" main dataset has already been decrypted outside of the pipeline, one may use the `DECRYPTED_DATASET` as an input to the pipeline instead of the `ENCRYPTED_DATASET` and `ENCODING_FILE` arguments. However, please make sure that all the fields in the `TRAITS_CONFIG` file described above are contained in this dataset. +To come back to the pipeline specification, if a "typical" main dataset has already been decrypted outside of the pipeline, one may use the `TRAITS_DATASET` as an input to the pipeline and leave the `UKB_ENCODING_FILE` argument unspecified. However, please make sure that all the fields in the `UKB_CONFIG` file described above are contained in this dataset. Note: Since this decrypted dataset is a plain CSV file, one may build and add extra columns to it. Any column in the decrypted dataset which does not correspond to a UK-Biobank field will be considered as such. diff --git a/docs/src/miscellaneous.md b/docs/src/miscellaneous.md index a8668018..df342184 100644 --- a/docs/src/miscellaneous.md +++ b/docs/src/miscellaneous.md @@ -3,6 +3,8 @@ Further Nextflow parameter affecting the behaviour of the pipeline but that does not fit in any previously described category is listed here: - `CALL_THRESHOLD` (optional, default: 0.9): For putative causal variants (listed in the parameter files described in the [Study Designs](@ref) section). If an individual's allele's probability is greater than the threshold, then it is called, otherwise it is considered missing. -- `BATCH_SIZE` (optional, default: 400): The set of parameters to be estimated is batched and the TMLE processes will run in parallel across batches on your platform. -- `SAVE_IC` (optional, default: true): For all parameters with an p-value below `PVAL_THRESHOLD`, the influence curve is saved. Make sure to keep to `true` if you want to use sieve variance correction, i.e. if `NB_SVP_ESTIMATORS` != 0. +- `BATCH_SIZE` (optional, default: 400): The set of estimands to be estimated is batched and the TMLE processes will run in parallel across batches on your platform. +- `SVP` (optional, default: false): To activate Sieve Variance Plateau correction. If set to true, `KEEP_IC` will automatically be set to true as well. +- `KEEP_IC` (optional, default: false): For all estimands with a p-value below `PVAL_THRESHOLD`, the influence curve is saved. +- `NB_SVP_ESTIMATORS` (optional, default: 100): The number of estimators in Sieve Variance Plateau. - `OUTDIR` (optional, default: "results"): Output directory diff --git a/docs/src/negative_control.md b/docs/src/negative_control.md index 8b71b1e8..3e7a8e46 100644 --- a/docs/src/negative_control.md +++ b/docs/src/negative_control.md @@ -8,11 +8,11 @@ nextflow run https://github.com/TARGENE/targene-pipeline -entry negativeControl see the [Overview](@ref) section for more info on the command line options. -At the moment, there are two types of analyses you can perform with this sub-pipeline: permutation tests and comparisons with "non-functional" random variants drawn from the genome. Furthermore, this is restricted to interaction parameters (IATE). In both cases, you will need to define positive hits. This is traditionally done via p-value filtering, you will thus need to specify both a pvalue column (from the "summary.csv" file) and a threshold: `PVAL_COL` and `PVAL_THRESHOLD` parameters. +At the moment, there are two types of analyses you can perform with this sub-workflow: permutation tests and comparisons with "non-functional" random variants drawn from the genome. In both cases, you will need to define positive hits. This is traditionally done via p-value filtering. Since TarGene allows the use of multiple estimators, you need to specify for which one you would like to run negative controls. This is done via the `ESTIMATOR_KEY` (default: "TMLE") parameter. You can also modify the `PVAL_THRESHOLD` (default: 0.05), only those estimates below the threshold are considered for negative control. ## Permutation tests -For each IATE hit, we can perturb the data by independently shuffling one or more columns in the data. By doing so, the interaction will be broken and become "non-significant". Because there are up to K variables in a IATE parameter, we can also permute up to K+1 variables. For instance, assuming we found a significant interaction between rs1234 and rs5678 on diabetes, we could permute: +For each IATE hit, we can perturb the data by independently shuffling one or more columns in the data. By doing so, the interaction will be broken and become "non-significant". Because there are up to K variables in a IATE estimand, we can also permute up to K+1 variables. For instance, assuming we found a significant interaction between rs1234 and rs5678 on diabetes, we could permute: - Any one of (rs1234, rs5678, diabetes) leading to 3 order 1 permutation tests. - Any two of (rs1234, rs5678, diabetes) resulting also in 3 order 2 permutation tests. @@ -20,13 +20,16 @@ For each IATE hit, we can perturb the data by independently shuffling one or mor Specifying those orders is made via the `PERMUTATION_ORDERS` variable which is a comma separated string of orders (e.g. "1,2"). -The results of those permutation tests will be found in the `$(OUTDIR)/permutation_summary.csv` file. +Just like the main pipeline, the outputs will be found in: + +- `PERMUTATION_HDF5_OUTPUT` (default: "permutation_results.hdf5") +- `PERMUTATION_JSON_OUTPUT` if specified ## Non-functional randomly drawn variants -If you are using the `STUDY_DESIGN` = `FROM_ACTORS`, it is likely that you have not chosen the genetic variants at random. Mainly trans-acting variants have been defined because of a likely role in a biological mechanism. If this is the case, replacing a trans-actor by a random variant anywhere on the genome is likely to break the interaction. While unlikely, by chance alone (or lack thereof), one could pick a random trans-actor which is also interacting with any of the bQTLs. In order to account for that it is recommended to instead select a certain number of rancom variants, denoted by `N_RANDOM_VARIANTS` (default: 10). Furthermore, we enforce two criteria on each of the randomly chosen random variants: +If you are using the `STUDY_DESIGN` = `FROM_ACTORS`, it is likely that you have not chosen the genetic variants at random. Mainly trans-acting variants have been defined because of a likely role in a biological mechanism. If this is the case, replacing a trans-actor by a random variant anywhere on the genome is likely to break the interaction. While unlikely, by chance alone (or lack thereof), one could pick a random trans-actor which is also interacting with any of the bQTLs. In order to account for that it is recommended to instead select a certain number of random variants, denoted by `N_RANDOM_VARIANTS` (default: 10). Furthermore, we enforce two criteria on each of the randomly chosen random variants: - Its minor allele frequency should match that of the original trans-actor up to `MAF_MATCHING_RELTOL` (relative tolerance, default: 0.05). - It shouldn't lie in a known regulatory region. -The result of this part of the pipeline is a parameter file located at `$(OUTDIR)/random_variants_parameters.yaml` directory. To perform the actual tests, you will have to run TarGene again on that parameter file with the `STUDY_DESIGN` = `CUSTOM` mode. +The result of this part of the pipeline is a file named `random_variants_estimands.jls`. To perform the actual tests, you will have to run TarGene again on that using this file with the `STUDY_DESIGN` = `CUSTOM` mode. diff --git a/docs/src/nextflow_params.md b/docs/src/nextflow_params.md index ac6fe550..25a776bf 100644 --- a/docs/src/nextflow_params.md +++ b/docs/src/nextflow_params.md @@ -4,52 +4,57 @@ Here is a list of all the pipeline parameters: ## [Setting a data source](@ref) -- **`COHORT` (required):** Current default for this is UKBB. If set to a value other than UKBB, this will not run UKBB-specific trait extraction. If `COHORT` is not UKBB, you must specify your trait data in the `DECRYPTED_DATASET` parameter. -- **`ENCRYPTED_DATASET` (required unless a `DECRYPTED_DATASET` is given)**: Path to a UK-Biobank encrypted main dataset. -- **`ENCODING_FILE` (required unless a `DECRYPTED_DATASET` is given)**: If an encrypted dataset is provided, an encoding file must accompany it. -- `DECRYPTED_DATASET` (optional): Path to a UK-Biobank decrypted main dataset. If set, `ENCRYPTED_DATASET` is ignored. **If you are running this for a non-UKBB cohort, your sample IDs must be specified in the first column of this CSV file, with the column name `SAMPLE_ID`.** -- **`TRAITS_CONFIG` (required)**: Configuration file describing which traits should be extracted from the main dataset. -- **`WITHDRAWAL_LIST` (required)**: List of participants withdrawn from the study. -- `QC_FILE` (optional): Genotyping quality control file from the UK-Biobank study. This is **required** when `COHORT`="UKBB". +- **`COHORT` (required):** Current default for this is UKBB. If set to a value other than UKBB, this will not run UKBB-specific trait extraction. If `COHORT` is not UKBB, you must specify your trait data in the `TRAITS_DATASET` parameter. +- **`TRAITS_DATASET` (required):** Path to a traits dataset. If you are running this for a non-UKBB cohort, your sample IDs must be specified in the first column of this CSV file, with the column name `SAMPLE_ID`. - **`BED_FILES` (required)**: Path expression to PLINK BED files. - **`BGEN_FILES` (required)**: Path expression to imputed BGEN files. +- **`UKB_CONFIG` (required for COHORT=UKBB)**: Configuration file describing which traits should be extracted from the main dataset. +- `UKB_ENCODING_FILE` (optional): If the `TRAITS_DATASET` is encrypted, an encoding file must be provided. +- `WITHDRAWAL_LIST` (optional): List of participants withdrawn from the study. +- `QC_FILE` (optional): Genotyping quality control file from the UK-Biobank study. ## [Adjusting for confounders](@ref) -- **`LD_BLOCKS` (optional)**: A path to pre-identified linkage disequlibrium blocks around the variants that will be queried for causal effect estimation. Those will be removed from the data. It is good practice to specify `LD_BLOCKS`, as it will remove SNPs correlated with your variants-of-interest before running PCA. -- **`FLASHPCA_EXCLUSION_REGIONS` (required)**: A path to the flashpca special exclusion regions which is provided in their repository. -- `MAF_THRESHOLD` (optional): Only variants with that minor allele frequency are considered +- `LD_BLOCKS` (optional): A path to pre-identified linkage disequlibrium blocks around the variants that will be queried for causal effect estimation. Those will be removed from the data. It is good practice to specify `LD_BLOCKS`, as it will remove SNPs correlated with your variants-of-interest before running PCA. +- `FLASHPCA_EXCLUSION_REGIONS` (optional, default: data/exclusion_regions_hg19.txt): A path to the flashpca special exclusion regions. +- `MAF_THRESHOLD` (optional, default: 0.01): Only variants with that minor allele frequency are considered - `NB_PCS` (optional, default: 6): The number of PCA components to extract. ## [Study Designs](@ref) - **`STUDY_DESIGN`** (required, default: "FROM\_PARAM\_FILE"): One of "FROM\_PARAM\_FILE", "FROM\_ACTORS". -If `STUDY_DESIGN`="FROM\_PARAM\_FILE": +If `STUDY_DESIGN`=`CUSTOM`: -- `ESTIMANDS_FILE` (required): Path expression to the parameter files. +- `ESTIMANDS_FILE` (required): Path expression to the estimands file. -If `STUDY_DESIGN`="FROM_ACTORS": +If `STUDY_DESIGN`=`ALLELE_INDEPENDENT`: + +- `ESTIMANDS_FILE` (required): YAML configuration file. + +If `STUDY_DESIGN`=`FROM_ACTORS`: - **`BQTLS` (required)**: A CSV file containing binding quantitative trait loci (bQTLs). If multiple transcription factors (TFs) are included in a single run, you must include a column called `TF`, which specifies the TF associated with each bQTL. - **`TRANS_ACTORS` (required)**: A prefix to CSV files containing quantitative trait loci potentially interacting with the previous bqtls. If multiple transcription factors (TFs) are included in a single run, you must include a column called `TF`, which specifies the TF associated with each transactor. - `EXTRA_CONFOUNDERS` (optional, default: nothing): Path to additional confounders file, one per line, no header. - `EXTRA_COVARIATES` (optional, default: nothing): Path to additional covariates file, one per line, no header. - `ENVIRONMENTALS` (optional, default: nothing): Path to additional environmental treatments file, one per line, no header. -- `ORDERS` (optional, default: "1,2"): Comma separated list describing the order of desired interaction parameters, 1 for the ATE (no interaction), 2 for pairwise interactions etc... e.g. "1,2" +- `ORDERS` (optional, default: "1,2"): Comma separated list describing the order of desired interaction estimands, 1 for the ATE (no interaction), 2 for pairwise interactions etc... e.g. "1,2" ## [Specifying a Targeted Estimator](@ref) -- **`ESTIMATOR_FILE` (required)**: Julia configuration file describing the nuisance parameters learners. +- **`ESTIMATOR_FILE` (required)**: Julia configuration file describing the nuisance function learning algorithms. - `POSITIVITY_CONSTRAINT` (optional, default: 0.01): Treatment variables rarest configuration should have at least that frequency. -- `SAVE_IC` (optional, default: true): For all parameters with an p-value below `PVAL_THRESHOLD`, the influence curve is saved. Make sure to keep to `true` if you want to use sieve variance correction, i.e. if `NB_SVP_ESTIMATORS` != 0. +- `KEEP_IC` (optional, default: false): For all parameters with an p-value below `PVAL_THRESHOLD`, the influence curve is saved. ## [Correcting for population relatedness](@ref) +- `SVP` (optional, default: false): To perform Sieve Variance Correction. - `GRM_NSPLITS` (optional, default: 100): To fasten GRM computation, it is typically split in batches. -- `NB_SVP_ESTIMATORS` (optional, default: 0): Number of sieve variance estimates per curve. Setting this value to 0 results in skipping sieve variance correction. +- `NB_SVP_ESTIMATORS` (optional, default: 100): Number of sieve variance estimates per curve. Setting this value to 0 results in skipping sieve variance correction. - `MAX_SVP_THRESHOLD` (optional, default: 0.9): Variance estimates are computed for tau ranging from 0 to MAX_SVP_THRESHOLD - `PVAL_THRESHOLD` (optional, default: 0.05): To save computation time and disk, only parameters with a p-value below this threshold are considered for sieve variance correction. +- `SVP_ESTIMATOR_KEY` (optional, default: "TMLE"): The estimator to use for Sieve Variance Plateau correction. ## [Tweaking additional behaviour](@ref) @@ -61,7 +66,7 @@ If `STUDY_DESIGN`="FROM_ACTORS": ## [Running negative control checks](@ref) - `MAX_PERMUTATION_TESTS` (optional, default: null): Arbitrarily limits the number of permutation tests performed. -- `PVAL_COL` (optional, default: TMLE_PVALUE): In the output `summary.csv`, the p-value column used to define significant hits. +- `ESTIMATOR_KEY` (optional, default: "TMLE"): The estimator from `ESTIMATOR_FILE` to use to asses significance. - `PERMUTATION_ORDERS` (optional, default: "1"): A comma separating string defining the permutation test orders to be performed. (see [Permutation tests](@ref)) - `MAF_MATCHING_RELTOL`(optional, default:0.05): Random variants are chosen with a similar MAF matched with the given relative tolerance. - `N_RANDOM_VARIANTS`(optional, default: 10): For each hit, that many variants are randomly picked. diff --git a/docs/src/study_designs.md b/docs/src/study_designs.md index a0770b21..28b6e4e4 100644 --- a/docs/src/study_designs.md +++ b/docs/src/study_designs.md @@ -81,13 +81,51 @@ For each estimand: - ATE: Average Treatment Effect - IATE: Interaction Average Treatment Effect - CM: Conditional Mean -- `outcome`: The trait of interest. If using the Uk-Biobank datasource it must match the `phenotypes/name` field in the associated `TRAITS_CONFIG` file. You can also use the wildcard "ALL" to specify that you want to estimate this parameter accross all traits in the dataset. +- `outcome`: The trait of interest. If using the Uk-Biobank datasource it must match the `phenotypes/name` field in the associated `UKB_CONFIG` file. You can also use the wildcard "ALL" to specify that you want to estimate this parameter accross all traits in the dataset. - `treatment_values`: For each treatment variable (genetic-variant / environmental variables), the control/case contrasts. - `treatment_confounders`: For each treatment variable, a list of confounding variables. If only a single list is provided, then all treatment variables are assumed to share the same confounding variables. Note that principal components will be added to that list automatically and must not be provided here. You can provide an empty list. - `outcome_extra_covariates`: This is optional and correspond to a list of additional covariates for the prediction of the trait. Note that variants must be encoded via an explicit genotype string representation (e.g. "AC"), the order of the alleles in the genotype is not important. +## `STUDY_DESIGN` = `ALLELE_INDEPENDENT` + +This mode will generate all estimands corresponding to the provided `ESTIMANDS_FILE`. In this case, this file is a plain YAML file as follows: + +```yaml +orders: [2] +estimands: interactions +variants: + TF1: + bQTLs: + - RSID_17 + - RSID_99 + eQTLs: + - RSID_102 + TF2: + bQTLs: + - RSID_17 + - RSID_198 + eQTLs: + - RSID_2 +extra_treatments: + - TREAT_1 +outcome_extra_covariates: + - COV_1 +extra_confounders: + - 21003 + - 22001 +``` + +where: + +- `orders`: Defines the orders of treatment combinations to generate +- `estimands`: The type of generated estimands (only interactions for now) +- `variants`: Two nested levels of variant groups. For each top level group, the cartesian product of variants in each sub group is produced. +- `extra_treatments`: These are added to the treatments combinations. +- `outcome_extra_covariates`: Additional covariates predictive of the outcomes +- `extra_confounders`: Confounding variables other than Principal Components. + ## `STUDY_DESIGN` = `FROM_ACTORS` In this setting the goal is to infer the interaction effect between multiple variants and potential external factors, interacting together via a specific biological mechanism. Typically, multiple sets of variants are of interest and each set is identified with a specific molecule, contributing to the mechanism. In particular, it is assumed that a set of variants, usually binding quantitative trait loci (bQTLs) play a pivotal role. All interactions of interest are thus defined with respect to that set of genetic variations. Let's Consider the following scenario: we know that a transcription factor binds to molecules `x` and `y` and then differentially binds to specific regions in the genome (`bQTLs`) to regulate downstream genes. We suspect that an alteration of this mechanism is responsible for some diseases. A set of `xQTLs`, associated with the expression of `x` and a set of `yQTLs` associated with the expression of `y` have been identified. Together `xQTLs` and `yQTLs` variants are termed "trans actors". We further suspect that some environmental factors may influence this process. From that scenario, there are many questions that can be asked, for instance : "What is the interaction effects of a bQTL with an environmental factor?". This is a simple pairwise interaction setting and more complex scenarios can be envisaged as described in the following graph. diff --git a/modules/negative_control.nf b/modules/negative_control.nf index c7497393..cb9f8d8a 100644 --- a/modules/negative_control.nf +++ b/modules/negative_control.nf @@ -15,6 +15,7 @@ params.MAF_MATCHING_RELTOL = 0.05 params.N_RANDOM_VARIANTS = 10 params.TMLE_SAVE_EVERY = 100 params.ARROW_OUTPUT = "dataset.arrow" +params.ESTIMATOR_KEY = "TMLE" include { longest_prefix } from './utils.nf' include { EstimationWorkflow } from './estimation.nf' @@ -41,6 +42,7 @@ process GeneratePermutationTestsData { ${dataset} ${results} \ ${limit} \ --pval-threshold=${params.PVAL_THRESHOLD} \ + --estimator-key=${params.ESTIMATOR_KEY} \ --orders=${params.PERMUTATION_ORDERS} \ --chunksize=${params.BATCH_SIZE} \ --rng=${params.RNG} \ @@ -71,6 +73,7 @@ process GenerateRandomVariantsTestsData { --out=random_variants_estimands.jls \ --p=${params.N_RANDOM_VARIANTS} \ --reltol=${params.MAF_MATCHING_RELTOL} \ + --estimator-key=${params.ESTIMATOR_KEY} \ --pval-threshold=${params.PVAL_THRESHOLD} \ --rng=${params.RNG} \ --verbosity=${params.VERBOSITY} diff --git a/modules/traits.nf b/modules/traits.nf index d9ce1822..f9fe9539 100644 --- a/modules/traits.nf +++ b/modules/traits.nf @@ -2,16 +2,16 @@ process UKBFieldsList { container "olivierlabayle/ukbmain:0.4" input: - path traits_config + path ukb_config output: path "fields_list.txt" script: - traits_config = traits_config.name != 'NO_UKB_TRAIT_CONFIG' ? "--conf $traits_config" : '' + ukb_config = ukb_config.getName() != 'NO_UKB_TRAIT_CONFIG' ? "--conf $ukb_config" : '' """ TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/UKBMain.jl --startup-file=no /UKBMain.jl/scripts/build_fields_list.jl $traits_config + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/UKBMain.jl --startup-file=no /UKBMain.jl/scripts/build_fields_list.jl $ukb_config """ } diff --git a/test/configs/custom_from_actors.config b/test/configs/custom_from_actors.config index 7c2cfe3e..1288bcbd 100644 --- a/test/configs/custom_from_actors.config +++ b/test/configs/custom_from_actors.config @@ -4,7 +4,6 @@ params { STUDY_DESIGN = "FROM_ACTORS" TRAITS_DATASET = "test/data/traits.csv" COHORT = "CUSTOM" - TRAITS_CONFIG = "test/data/ukbconfig_small.yaml" SVP = true NB_SVP_ESTIMATORS = 10 PVAL_THRESHOLD = 1 diff --git a/test/data/interactions_allele_independent.yaml b/test/data/interactions_allele_independent.yaml new file mode 100644 index 00000000..bc0cc8a0 --- /dev/null +++ b/test/data/interactions_allele_independent.yaml @@ -0,0 +1,9 @@ +orders: [2] +estimands: interactions +variants: + TF1: + bQTLs: + - "1:238411180:T:C" + - "3:3502414:T:C" + eQTLs: + - "2:14983:G:A" From 27a14929d335e92661554d433185de32255c9ee5 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 19 Dec 2023 13:33:43 +0000 Subject: [PATCH 30/65] remove deprecated estimator files --- docs/src/data_sources.md | 2 +- docs/src/estimators/G-superlearning-Q-glm.jl | 33 -------- .../estimators/G-superlearning-Q-glmnet.jl | 33 -------- .../estimators/glm-with-interactions-for-Q.jl | 22 ----- docs/src/estimators/glm.jl | 14 ---- .../glmnet-with-interactions-for-Q.jl | 22 ----- docs/src/estimators/glmnet.jl | 14 ---- .../superlearning-with-interactions-for-Q.jl | 84 ------------------- docs/src/estimators/superlearning.jl | 68 --------------- docs/src/estimators/tuned-xgboost.jl | 47 ----------- docs/src/nextflow_params.md | 2 +- docs/src/study_designs.md | 2 - 12 files changed, 2 insertions(+), 341 deletions(-) delete mode 100644 docs/src/estimators/G-superlearning-Q-glm.jl delete mode 100644 docs/src/estimators/G-superlearning-Q-glmnet.jl delete mode 100644 docs/src/estimators/glm-with-interactions-for-Q.jl delete mode 100644 docs/src/estimators/glm.jl delete mode 100644 docs/src/estimators/glmnet-with-interactions-for-Q.jl delete mode 100644 docs/src/estimators/glmnet.jl delete mode 100644 docs/src/estimators/superlearning-with-interactions-for-Q.jl delete mode 100644 docs/src/estimators/superlearning.jl delete mode 100644 docs/src/estimators/tuned-xgboost.jl diff --git a/docs/src/data_sources.md b/docs/src/data_sources.md index be12c18f..2ec1676d 100644 --- a/docs/src/data_sources.md +++ b/docs/src/data_sources.md @@ -96,7 +96,7 @@ Note: Since this decrypted dataset is a plain CSV file, one may build and add ex Additional UK-Biobank required files for preprocessing and filtering are: - `QC_FILE`: A path to the UK-Biobank SNP quaility control [`ukb_snp_qc.txt`](https://biobank.ctsu.ox.ac.uk/crystal/refer.cgi?id=1955) file. -- `WITHDRAWAL_LIST`: A path to the withdrawal sample list to exclude removed participants from the study. +- `UKB_WITHDRAWAL_LIST`: A path to the withdrawal sample list to exclude removed participants from the study. ## Genetic Data diff --git a/docs/src/estimators/G-superlearning-Q-glm.jl b/docs/src/estimators/G-superlearning-Q-glm.jl deleted file mode 100644 index 83d44d09..00000000 --- a/docs/src/estimators/G-superlearning-Q-glm.jl +++ /dev/null @@ -1,33 +0,0 @@ -xgboost_classifier = XGBoostClassifier(tree_method="hist") - -tmle_spec = ( - #Β Controls caching of data by MLJ machines: turning to `true` may result in faster execution but higher memory usage - cache = false, - #Β Controls whether the fluctuation is weighted or not - weighted_fluctuation = false, - # Propensity score threshold - threshold = 1e-8, - #Β For the estimation of E[Y|W, T]: continuous target - Q_continuous = LinearRegressor(), - #Β For the estimation of E[Y|W, T]: binary target - Q_binary = LogisticClassifier(lambda=0.), - #Β For the estimation of p(T| W) - G = Stack( - metalearner = LogisticClassifier(lambda=0., fit_intercept=false), - resampling = StratifiedCV(nfolds=3), - cache = false, - glmnet = GLMNetClassifier(), - lr = LogisticClassifier(lambda=0.), - tuned_xgboost = TunedModel( - model = xgboost_classifier, - resampling = StratifiedCV(nfolds=3), - tuning = Grid(goal=20), - range = [ - range(xgboost_classifier, :max_depth, lower=3, upper=7), - range(xgboost_classifier, :lambda, lower=1e-5, upper=10, scale=:log) - ], - measure = log_loss, - cache=false - ) - ) -) \ No newline at end of file diff --git a/docs/src/estimators/G-superlearning-Q-glmnet.jl b/docs/src/estimators/G-superlearning-Q-glmnet.jl deleted file mode 100644 index 47094ef6..00000000 --- a/docs/src/estimators/G-superlearning-Q-glmnet.jl +++ /dev/null @@ -1,33 +0,0 @@ -xgboost_classifier = XGBoostClassifier(tree_method="hist") - -tmle_spec = ( - #Β Controls caching of data by MLJ machines: turning to `true` may result in faster execution but higher memory usage - cache = false, - #Β Controls whether the fluctuation is weighted or not - weighted_fluctuation = false, - # Propensity score threshold - threshold = 1e-8, - #Β For the estimation of E[Y|W, T]: continuous target - Q_continuous = GLMNetRegressor(resampling=CV(nfolds=3)), - #Β For the estimation of E[Y|W, T]: binary target - Q_binary = GLMNetClassifier(resampling=StratifiedCV(nfolds=3)), - #Β For the estimation of p(T| W) - G = Stack( - metalearner = LogisticClassifier(lambda=0., fit_intercept=false), - resampling = StratifiedCV(nfolds=3), - cache = false, - glmnet = GLMNetClassifier(), - lr = LogisticClassifier(lambda=0.), - tuned_xgboost = TunedModel( - model = xgboost_classifier, - resampling = StratifiedCV(nfolds=3), - tuning = Grid(goal=20), - range = [ - range(xgboost_classifier, :max_depth, lower=3, upper=7), - range(xgboost_classifier, :lambda, lower=1e-5, upper=10, scale=:log) - ], - measure = log_loss, - cache=false - ) - ) -) \ No newline at end of file diff --git a/docs/src/estimators/glm-with-interactions-for-Q.jl b/docs/src/estimators/glm-with-interactions-for-Q.jl deleted file mode 100644 index edaeca78..00000000 --- a/docs/src/estimators/glm-with-interactions-for-Q.jl +++ /dev/null @@ -1,22 +0,0 @@ -tmle_spec = ( - #Β Controls caching of data by MLJ machines: turning to `true` may result in faster execution but higher memory usage - cache = false, - #Β Controls whether the fluctuation is weighted or not - weighted_fluctuation = false, - # Propensity score threshold - threshold = 1e-8, - #Β For the estimation of E[Y|W, T]: continuous target - Q_continuous = Pipeline( - RestrictedInteractionTransformer(order=2, primary_variables_patterns=[r"^rs[0-9]+"]), - LinearRegressor(), - cache = false - ), - #Β For the estimation of E[Y|W, T]: binary target - Q_binary = Pipeline( - RestrictedInteractionTransformer(order=2, primary_variables_patterns=[r"^rs[0-9]+"]), - LogisticClassifier(lambda=0.), - cache = false - ), - #Β For the estimation of p(T| W) - G = LogisticClassifier(lambda=0.) -) \ No newline at end of file diff --git a/docs/src/estimators/glm.jl b/docs/src/estimators/glm.jl deleted file mode 100644 index 6aea32ac..00000000 --- a/docs/src/estimators/glm.jl +++ /dev/null @@ -1,14 +0,0 @@ -tmle_spec = ( - #Β Controls caching of data by MLJ machines: turning to `true` may result in faster execution but higher memory usage - cache = false, - #Β Controls whether the fluctuation is weighted or not - weighted_fluctuation = false, - # Propensity score threshold - threshold = 1e-8, - #Β For the estimation of E[Y|W, T]: continuous target - Q_continuous = LinearRegressor(), - #Β For the estimation of E[Y|W, T]: binary target - Q_binary = LogisticClassifier(lambda=0.), - #Β For the estimation of p(T| W) - G = LogisticClassifier(lambda=0.) -) \ No newline at end of file diff --git a/docs/src/estimators/glmnet-with-interactions-for-Q.jl b/docs/src/estimators/glmnet-with-interactions-for-Q.jl deleted file mode 100644 index 003cd7e5..00000000 --- a/docs/src/estimators/glmnet-with-interactions-for-Q.jl +++ /dev/null @@ -1,22 +0,0 @@ -tmle_spec = ( - #Β Controls caching of data by MLJ machines: turning to `true` may result in faster execution but higher memory usage - cache = false, - #Β Controls whether the fluctuation is weighted or not - weighted_fluctuation = false, - # Propensity score threshold - threshold = 1e-8, - #Β For the estimation of E[Y|W, T]: continuous target - Q_continuous = Pipeline( - RestrictedInteractionTransformer(order=2, primary_variables_patterns=[r"^rs[0-9]+"]), - GLMNetRegressor(resampling=CV(nfolds=3)), - cache = false - ), - #Β For the estimation of E[Y|W, T]: binary target - Q_binary = Pipeline( - RestrictedInteractionTransformer(order=2, primary_variables_patterns=[r"^rs[0-9]+"]), - GLMNetClassifier(resampling=StratifiedCV(nfolds=3)), - cache = false - ), - #Β For the estimation of p(T| W) - G = GLMNetClassifier(resampling=StratifiedCV(nfolds=3)) -) \ No newline at end of file diff --git a/docs/src/estimators/glmnet.jl b/docs/src/estimators/glmnet.jl deleted file mode 100644 index 27a89f36..00000000 --- a/docs/src/estimators/glmnet.jl +++ /dev/null @@ -1,14 +0,0 @@ -tmle_spec = ( - #Β Controls caching of data by MLJ machines: turning to `true` may result in faster execution but higher memory usage - cache = false, - #Β Controls whether the fluctuation is weighted or not - weighted_fluctuation = false, - # Propensity score threshold - threshold = 1e-8, - #Β For the estimation of E[Y|W, T]: continuous target - Q_continuous = GLMNetRegressor(resampling=CV(nfolds=3)), - #Β For the estimation of E[Y|W, T]: binary target - Q_binary = GLMNetClassifier(resampling=StratifiedCV(nfolds=3)), - #Β For the estimation of p(T| W) - G = GLMNetClassifier(resampling=StratifiedCV(nfolds=3)) -) \ No newline at end of file diff --git a/docs/src/estimators/superlearning-with-interactions-for-Q.jl b/docs/src/estimators/superlearning-with-interactions-for-Q.jl deleted file mode 100644 index f3d75ce3..00000000 --- a/docs/src/estimators/superlearning-with-interactions-for-Q.jl +++ /dev/null @@ -1,84 +0,0 @@ -xgboost_regressor = XGBoostRegressor(tree_method="hist") -xgboost_classifier = XGBoostClassifier(tree_method="hist") - -tmle_spec = ( - #Β Controls caching of data by MLJ machines: turning to `true` may result in faster execution but higher memory usage - cache = false, - #Β Controls whether the fluctuation is weighted or not - weighted_fluctuation = false, - # Propensity score threshold - threshold = 1e-8, - #Β For the estimation of E[Y|W, T]: continuous target - Q_continuous = Stack( - metalearner = LinearRegressor(fit_intercept=false), - resampling = CV(nfolds=3), - cache = false, - glmnet = Pipeline( - RestrictedInteractionTransformer(order=2, primary_variables_patterns=[r"^rs[0-9]+"]), - GLMNetRegressor(resampling=CV(nfolds=3)), - cache = false - ), - lr = Pipeline( - RestrictedInteractionTransformer(order=2, primary_variables_patterns=[r"^rs[0-9]+"]), - LinearRegressor(), - cache = false - ), - tuned_xgboost = TunedModel( - model = xgboost_regressor, - resampling = CV(nfolds=3), - tuning = Grid(goal=20), - range = [ - range(xgboost_regressor, :max_depth, lower=3, upper=7), - range(xgboost_regressor, :lambda, lower=1e-5, upper=10, scale=:log) - ], - measure = rmse, - cache=false - ) - ), - #Β For the estimation of E[Y|W, T]: binary target - Q_binary = Stack( - metalearner = LogisticClassifier(lambda=0., fit_intercept=false), - resampling = StratifiedCV(nfolds=3), - cache = false, - glmnet = Pipeline( - RestrictedInteractionTransformer(order=2, primary_variables_patterns=[r"^rs[0-9]+"]), - GLMNetClassifier(resampling=StratifiedCV(nfolds=3)), - cache = false - ), - lr = Pipeline( - RestrictedInteractionTransformer(order=2, primary_variables_patterns=[r"^rs[0-9]+"]), - LogisticClassifier(lambda=0.), - cache = false - ), - tuned_xgboost = TunedModel( - model = xgboost_classifier, - resampling = StratifiedCV(nfolds=3), - tuning = Grid(goal=20), - range = [ - range(xgboost_classifier, :max_depth, lower=3, upper=7), - range(xgboost_classifier, :lambda, lower=1e-5, upper=10, scale=:log) - ], - measure = log_loss, - cache=false - ) - ), - #Β For the estimation of p(T| W) - G = Stack( - metalearner = LogisticClassifier(lambda=0., fit_intercept=false), - resampling = StratifiedCV(nfolds=3), - cache = false, - glmnet = GLMNetClassifier(), - lr = LogisticClassifier(lambda=0.), - tuned_xgboost = TunedModel( - model = xgboost_classifier, - resampling = StratifiedCV(nfolds=3), - tuning = Grid(goal=20), - range = [ - range(xgboost_classifier, :max_depth, lower=3, upper=7), - range(xgboost_classifier, :lambda, lower=1e-5, upper=10, scale=:log) - ], - measure = log_loss, - cache=false - ) - ) -) \ No newline at end of file diff --git a/docs/src/estimators/superlearning.jl b/docs/src/estimators/superlearning.jl deleted file mode 100644 index 4bb72f65..00000000 --- a/docs/src/estimators/superlearning.jl +++ /dev/null @@ -1,68 +0,0 @@ -xgboost_regressor = XGBoostRegressor(tree_method="hist") -xgboost_classifier = XGBoostClassifier(tree_method="hist") - -tmle_spec = ( - #Β Controls caching of data by MLJ machines: turning to `true` may result in faster execution but higher memory usage - cache = false, - #Β Controls whether the fluctuation is weighted or not - weighted_fluctuation = false, - # Propensity score threshold - threshold = 1e-8, - #Β For the estimation of E[Y|W, T]: continuous target - Q_continuous = Stack( - metalearner = LinearRegressor(fit_intercept=false), - resampling = CV(nfolds=3), - cache = false, - glmnet = GLMNetRegressor(), - lr = LinearRegressor(), - tuned_xgboost = TunedModel( - model = xgboost_regressor, - resampling = CV(nfolds=3), - tuning = Grid(goal=20), - range = [ - range(xgboost_regressor, :max_depth, lower=3, upper=7), - range(xgboost_regressor, :lambda, lower=1e-5, upper=10, scale=:log) - ], - measure = rmse, - cache=false - ) - ), - #Β For the estimation of E[Y|W, T]: binary target - Q_binary = Stack( - metalearner = LogisticClassifier(lambda=0., fit_intercept=false), - resampling = StratifiedCV(nfolds=3), - cache = false, - glmnet = GLMNetClassifier(), - lr = LogisticClassifier(lambda=0.), - tuned_xgboost = TunedModel( - model = xgboost_classifier, - resampling = StratifiedCV(nfolds=3), - tuning = Grid(goal=20), - range = [ - range(xgboost_classifier, :max_depth, lower=3, upper=7), - range(xgboost_classifier, :lambda, lower=1e-5, upper=10, scale=:log) - ], - measure = log_loss, - cache=false - ) - ), - #Β For the estimation of p(T| W) - G = Stack( - metalearner = LogisticClassifier(lambda=0., fit_intercept=false), - resampling = StratifiedCV(nfolds=3), - cache = false, - glmnet = GLMNetClassifier(), - lr = LogisticClassifier(lambda=0.), - tuned_xgboost = TunedModel( - model = xgboost_classifier, - resampling = StratifiedCV(nfolds=3), - tuning = Grid(goal=20), - range = [ - range(xgboost_classifier, :max_depth, lower=3, upper=7), - range(xgboost_classifier, :lambda, lower=1e-5, upper=10, scale=:log) - ], - measure = log_loss, - cache=false - ) - ) -) \ No newline at end of file diff --git a/docs/src/estimators/tuned-xgboost.jl b/docs/src/estimators/tuned-xgboost.jl deleted file mode 100644 index 6432206b..00000000 --- a/docs/src/estimators/tuned-xgboost.jl +++ /dev/null @@ -1,47 +0,0 @@ -xgboost_regressor = XGBoostRegressor(tree_method="hist") -xgboost_classifier = XGBoostClassifier(tree_method="hist") - -tmle_spec = ( - #Β Controls caching of data by MLJ machines: turning to `true` may result in faster execution but higher memory usage - cache = false, - #Β Controls whether the fluctuation is weighted or not - weighted_fluctuation = false, - # Propensity score threshold - threshold = 1e-8, - #Β For the estimation of E[Y|W, T]: continuous target - Q_continuous = TunedModel( - model = xgboost_regressor, - resampling = CV(nfolds=3), - tuning = Grid(goal=20), - range = [ - range(xgboost_regressor, :max_depth, lower=3, upper=7), - range(xgboost_regressor, :lambda, lower=1e-5, upper=10, scale=:log) - ], - measure = log_loss, - cache=false - ), - #Β For the estimation of E[Y|W, T]: binary target - Q_binary = TunedModel( - model = xgboost_classifier, - resampling = StratifiedCV(nfolds=3), - tuning = Grid(goal=20), - range = [ - range(xgboost_classifier, :max_depth, lower=3, upper=7), - range(xgboost_classifier, :lambda, lower=1e-5, upper=10, scale=:log) - ], - measure = log_loss, - cache=false - ), - #Β For the estimation of p(T| W) - G = TunedModel( - model = xgboost_classifier, - resampling = StratifiedCV(nfolds=3), - tuning = Grid(goal=20), - range = [ - range(xgboost_classifier, :max_depth, lower=3, upper=7), - range(xgboost_classifier, :lambda, lower=1e-5, upper=10, scale=:log) - ], - measure = log_loss, - cache=false -) -) \ No newline at end of file diff --git a/docs/src/nextflow_params.md b/docs/src/nextflow_params.md index 25a776bf..179b25a5 100644 --- a/docs/src/nextflow_params.md +++ b/docs/src/nextflow_params.md @@ -10,7 +10,7 @@ Here is a list of all the pipeline parameters: - **`BGEN_FILES` (required)**: Path expression to imputed BGEN files. - **`UKB_CONFIG` (required for COHORT=UKBB)**: Configuration file describing which traits should be extracted from the main dataset. - `UKB_ENCODING_FILE` (optional): If the `TRAITS_DATASET` is encrypted, an encoding file must be provided. -- `WITHDRAWAL_LIST` (optional): List of participants withdrawn from the study. +- `UKB_WITHDRAWAL_LIST` (optional): List of participants withdrawn from the study. - `QC_FILE` (optional): Genotyping quality control file from the UK-Biobank study. ## [Adjusting for confounders](@ref) diff --git a/docs/src/study_designs.md b/docs/src/study_designs.md index 28b6e4e4..cbf1033e 100644 --- a/docs/src/study_designs.md +++ b/docs/src/study_designs.md @@ -93,7 +93,6 @@ Note that variants must be encoded via an explicit genotype string representatio This mode will generate all estimands corresponding to the provided `ESTIMANDS_FILE`. In this case, this file is a plain YAML file as follows: ```yaml -orders: [2] estimands: interactions variants: TF1: @@ -119,7 +118,6 @@ extra_confounders: where: -- `orders`: Defines the orders of treatment combinations to generate - `estimands`: The type of generated estimands (only interactions for now) - `variants`: Two nested levels of variant groups. For each top level group, the cartesian product of variants in each sub group is produced. - `extra_treatments`: These are added to the treatments combinations. From 9ba829f95cc56ccf96dec4c891f935af7366026f Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 19 Dec 2023 14:45:59 +0000 Subject: [PATCH 31/65] add new test --- test/ukb_allele_independent.jl | 49 +++++++++++++--------------------- 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/test/ukb_allele_independent.jl b/test/ukb_allele_independent.jl index 65e58b43..c55e6f10 100644 --- a/test/ukb_allele_independent.jl +++ b/test/ukb_allele_independent.jl @@ -2,18 +2,13 @@ module TestUKBAlleleIndependent using Test using JLD2 -using Arrow -using DataFrames using TMLE -using CSV using TargetedEstimation using Serialization #Β "local" profile assumes singularity is installed args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] -include("utils.jl") - @testset "Test ukb_from_actors.config" begin cmd = `nextflow run main.nf -c test/configs/ukb_allele_independent.config $args` @info string("The following command will be run:\n", cmd) @@ -23,33 +18,25 @@ include("utils.jl") ##Β Checking main output # Results - hdf5_results_file = jldopen(joinpath("results", "results.hdf5")) - results_from_hdf5 = vcat((hdf5_results_file[key] for key in keys(hdf5_results_file))...) - results_from_json = TMLE.read_json(joinpath("results", "results.json")) - @test length(results_from_json) == length(results_from_hdf5) > 300 - - failed_results = retrieve_failed_results(results_from_hdf5; expected_keys=(:TMLE, :OSE)) - # All fails are due to fluctuation failure due non positive definite matrix - # This does not affect the OSE - @test isempty(failed_results.OSE) - # Less than 1/3 affected: this is still quite significant - @test length(failed_results.TMLE) / length(results_from_hdf5) < 1/3 - @test all(startswith(x.msg, "Could not fluctuate") for x ∈ failed_results.TMLE) - - dataset = Arrow.Table(joinpath("results", "dataset.arrow")) |> DataFrame - - check_fails_are_extremely_rare_traits(failed_results.TMLE, dataset; ncases=3) - - ##Β Checking parameter files correspond to either bQTL only or bQTL/eQTL - bQTLs = Symbol.(CSV.read(joinpath("test", "data", "actors", "bqtls.csv"), DataFrame).ID) - - config_1 = deserialize(joinpath("results", "estimands", "final.estimands_1.jls")) - @test length(config_1.estimands) == 400 - config_2 = deserialize(joinpath("results", "estimands", "final.estimands_2.jls")) - @test 0 < length(config_2.estimands) <= 400 - for Ξ¨ in vcat(config_1.estimands, config_2.estimands) - @test length(intersect(keys(Ξ¨.treatment_values), bQTLs)) == 1 + results_from_hdf5 = jldopen(joinpath("results", "results.hdf5"))["Batch_1"] + nresults = length(results_from_hdf5) + @test nresults > 50 + nfails = 0 + treatment_combinations = Set([]) + for result in results_from_hdf5 + Ξ¨Μ‚ = result.TMLE + if Ξ¨Μ‚ isa TargetedEstimation.FailedEstimate + nfails += 1 + else + Ξ¨c = first(Ξ¨Μ‚.estimand.args) + push!(treatment_combinations, keys(Ξ¨c.treatment_values)) + end end + @test nfails / nresults < 1/4 + @test treatment_combinations == Set([ + (Symbol("2:14983:G:A"), Symbol("3:3502414:T:C")), + (Symbol("1:238411180:T:C"), Symbol("2:14983:G:A")) + ]) end end \ No newline at end of file From 0109211c9e71c9c94de53dc7a3f3c24c9249e000 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 19 Dec 2023 15:05:10 +0000 Subject: [PATCH 32/65] fix negative control conf file --- test/ukb_allele_independent.jl | 2 +- test/ukb_from_actors.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ukb_allele_independent.jl b/test/ukb_allele_independent.jl index c55e6f10..89b5cec5 100644 --- a/test/ukb_allele_independent.jl +++ b/test/ukb_allele_independent.jl @@ -9,7 +9,7 @@ using Serialization #Β "local" profile assumes singularity is installed args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] -@testset "Test ukb_from_actors.config" begin +@testset "Test ukb_allele_independent.config" begin cmd = `nextflow run main.nf -c test/configs/ukb_allele_independent.config $args` @info string("The following command will be run:\n", cmd) diff --git a/test/ukb_from_actors.jl b/test/ukb_from_actors.jl index 20935109..714cd78c 100644 --- a/test/ukb_from_actors.jl +++ b/test/ukb_from_actors.jl @@ -53,7 +53,7 @@ include("utils.jl") end @testset "Test negative controls" begin - cmd = `nextflow run . -main-script modules/negative_control.nf -c conf/ci_jobs/ukb_from_actors.config $args` + cmd = `nextflow run . -main-script modules/negative_control.nf -c test/configs/ukb_from_actors.config $args` @info string("The following command will be run:\n", cmd) r = run(cmd) From 679d801062a98772d0bb11f5d754e13b1d355083 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Sat, 23 Dec 2023 14:10:53 +0000 Subject: [PATCH 33/65] update to argparse branch dep --- modules/estimation.nf | 25 ++++++++++++------------- modules/svp.nf | 4 ++-- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/modules/estimation.nf b/modules/estimation.nf index 4cd17ae6..03e1e9ad 100644 --- a/modules/estimation.nf +++ b/modules/estimation.nf @@ -2,7 +2,7 @@ nextflow.enable.dsl = 2 process MergeOutputs { - container "olivierlabayle/targeted-estimation:cv_tmle" + container "olivierlabayle/targeted-estimation:argparse" publishDir "$params.OUTDIR", mode: 'symlink' label "bigmem" @@ -13,21 +13,21 @@ process MergeOutputs { output: path "${hdf5_output}", emit: hdf5_file - path "${json_output}", optional: true, emit:json_file + path "${json_output}", optional: true, emit: json_file script: - json_option = json_output != "NO_JSON_OUTPUT" ? "--outputs.json.filename=${json_output}" : "" + json_option = json_output != "NO_JSON_OUTPUT" ? "--json-output=${json_output}" : "" """ TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no /opt/bin/tmle make-summary \ + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --sysimage=/TargetedEstimation.jl/TMLESysimage.so --project=/TargetedEstimation.jl --startup-file=no /TargetedEstimation.jl/tmle.jl merge \ tmle_result \ - --outputs.hdf5.filename=${hdf5_output} \ - ${json_option} + ${json_option} \ + --hdf5-output=${hdf5_output} """ } process TMLE { - container "olivierlabayle/targeted-estimation:cv_tmle" + container "olivierlabayle/targeted-estimation:argparse" publishDir "$params.OUTDIR/tmle_outputs/", mode: 'symlink', pattern: "*.hdf5" label "bigmem" label "multithreaded" @@ -47,17 +47,16 @@ process TMLE { script: basename = "tmle_result." + estimands_file.getName().take(estimands_file.getName().lastIndexOf('.')) hdf5out = basename + ".hdf5" - pval_threshold = keep_ic == true ? "--outputs.hdf5.pval_threshold=${pval_threshold}" : "" - sample_ids = do_svp == true ? "--outputs.hdf5.sample_ids=true" : "" + pval_option = keep_ic == true ? ",${pval_threshold}" : "" + sample_ids = do_svp == true ? ",true" : "" + output_option = "--hdf5-output=${hdf5out}${pval_option}${sample_ids}" """ TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --threads=${task.cpus} --startup-file=no /opt/bin/tmle tmle \ + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --sysimage=/TargetedEstimation.jl/TMLESysimage.so --project=/TargetedEstimation.jl --threads=${task.cpus} --startup-file=no /TargetedEstimation.jl/tmle.jl tmle \ $data \ --estimands=$estimands_file \ --estimators=$estimator_file \ - --outputs.hdf5.filename=$hdf5out \ - $pval_threshold \ - $sample_ids \ + $output_option \ --chunksize=$save_every \ """ } diff --git a/modules/svp.nf b/modules/svp.nf index f2249030..d42e6dcd 100644 --- a/modules/svp.nf +++ b/modules/svp.nf @@ -36,7 +36,7 @@ process AggregateGRM { } process SVP { - container "olivierlabayle/targeted-estimation:cv_tmle" + container "olivierlabayle/targeted-estimation:argparse" publishDir "$params.OUTDIR", mode: 'symlink' input: @@ -55,7 +55,7 @@ process SVP { hdf5_prefix = longest_prefix(hdf5_results) """ TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargetedEstimation.jl --startup-file=no /opt/bin/tmle sieve-variance-plateau \ + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --sysimage=/TargetedEstimation.jl/TMLESysimage.so --project=/TargetedEstimation.jl --startup-file=no /TargetedEstimation.jl/tmle.jl svp \ $hdf5_prefix \ --n-estimators=$n_estimators \ --max-tau=$max_tau \ From b913c05b0d24e90ddce396e77dca2045b3da7c2f Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Sat, 23 Dec 2023 16:00:40 +0000 Subject: [PATCH 34/65] update default args to point to projectdir --- main.nf | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/main.nf b/main.nf index 1c99101d..9681aae6 100644 --- a/main.nf +++ b/main.nf @@ -8,15 +8,15 @@ params.CALL_THRESHOLD = 0.9 params.POSITIVITY_CONSTRAINT = 0.01 params.MAF_THRESHOLD = 0.01 params.COHORT = "UKBB" -params.UKB_CONFIG = "data/ukbconfig.yaml" -params.UKB_WITHDRAWAL_LIST = 'data/NO_WITHDRAWAL_LIST' +params.UKB_CONFIG = "${projectDir}/data/ukbconfig.yaml" +params.UKB_WITHDRAWAL_LIST = '${projectDir}/data/NO_WITHDRAWAL_LIST' params.OUTDIR = "${launchDir}/results" // Confounding adjustment by PCA params.NB_PCS = 6 -params.QC_FILE = "data/NO_QC_FILE" -params.LD_BLOCKS = "data/NO_LD_BLOCKS" -params.FLASHPCA_EXCLUSION_REGIONS = "data/exclusion_regions_hg19.txt" +params.QC_FILE = "${projectDir}/data/NO_QC_FILE" +params.LD_BLOCKS = "${projectDir}/data/NO_LD_BLOCKS" +params.FLASHPCA_EXCLUSION_REGIONS = "${projectDir}/data/exclusion_regions_hg19.txt" // Estimands Generation params.BATCH_SIZE = 400 @@ -26,9 +26,9 @@ params.STUDY_DESIGN = "CUSTOM" params.ESTIMANDS_FILE = "NO_ESTIMANDS_FILE" // FROM_ACTORS -params.EXTRA_CONFOUNDERS = 'data/NO_EXTRA_CONFOUNDER' -params.EXTRA_COVARIATES = 'data/NO_EXTRA_COVARIATE' -params.ENVIRONMENTALS = 'data/NO_EXTRA_TREATMENT' +params.EXTRA_CONFOUNDERS = "${projectDir}/data/NO_EXTRA_CONFOUNDER" +params.EXTRA_COVARIATES = "${projectDir}/data/NO_EXTRA_COVARIATE" +params.ENVIRONMENTALS = "${projectDir}/data/NO_EXTRA_TREATMENT" params.ORDERS = "1,2" // SVP Parameters From 9511940932ff182e1c48244b3d044ecb594eac75 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 26 Dec 2023 10:21:02 +0000 Subject: [PATCH 35/65] try rename batchsize --- modules/estimation_inputs.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/estimation_inputs.nf b/modules/estimation_inputs.nf index 33a7231a..a8f8f9e2 100644 --- a/modules/estimation_inputs.nf +++ b/modules/estimation_inputs.nf @@ -22,7 +22,7 @@ process TMLEInputsFromParamFile { script: bgen_prefix = longest_prefix(bgenfiles) - batch_size = batch_size == 0 ? "" : "--batch-size ${batch_size}" + batchsize = batch_size == 0 ? "" : "--batch-size ${batch_size}" """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/tmle_inputs.jl \ @@ -30,7 +30,7 @@ process TMLEInputsFromParamFile { --bgen-prefix $bgen_prefix \ --call-threshold ${call_threshold} \ --pcs $genetic_confounders \ - $batch_size \ + $batchsize \ --positivity-constraint ${positivity_constraint} \ $command $parameter """ From d378dcb48f2b7b8be85962137e4887e2473a44fe Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 26 Dec 2023 15:47:11 +0000 Subject: [PATCH 36/65] fix string interpolation --- main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.nf b/main.nf index 9681aae6..96b5e2b4 100644 --- a/main.nf +++ b/main.nf @@ -9,7 +9,7 @@ params.POSITIVITY_CONSTRAINT = 0.01 params.MAF_THRESHOLD = 0.01 params.COHORT = "UKBB" params.UKB_CONFIG = "${projectDir}/data/ukbconfig.yaml" -params.UKB_WITHDRAWAL_LIST = '${projectDir}/data/NO_WITHDRAWAL_LIST' +params.UKB_WITHDRAWAL_LIST = "${projectDir}/data/NO_WITHDRAWAL_LIST" params.OUTDIR = "${launchDir}/results" // Confounding adjustment by PCA From 38dfc23580e275e38418b7ca9a91d56d3bd42b39 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Thu, 11 Jan 2024 15:06:31 +0000 Subject: [PATCH 37/65] extract PCA to a workflow --- main.nf | 1 + modules/pca.nf | 11 ----------- workflows/pca.nf | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 11 deletions(-) delete mode 100644 modules/pca.nf create mode 100644 workflows/pca.nf diff --git a/main.nf b/main.nf index 96b5e2b4..e2c0a450 100644 --- a/main.nf +++ b/main.nf @@ -56,6 +56,7 @@ include { GeneticConfounders } from './modules/confounders.nf' include { ExtractTraits } from './modules/traits.nf' include { EstimationWorkflow } from './modules/estimation.nf' include { SVPWorkflow } from './modules/svp.nf' +include { PCA } from './workflows/pca.nf' log.info """\ ${workflow.manifest.name} v${workflow.manifest.version} diff --git a/modules/pca.nf b/modules/pca.nf deleted file mode 100644 index 09a2bcc7..00000000 --- a/modules/pca.nf +++ /dev/null @@ -1,11 +0,0 @@ -workflow PCA { - // Extract traits - extractTraits() - - // Generate IID Genotypes - IIDGenotypes(extractTraits.out) - - // Genetic confounders up to NB_PCS - geneticConfounders(IIDGenotypes.out) - -} \ No newline at end of file diff --git a/workflows/pca.nf b/workflows/pca.nf new file mode 100644 index 00000000..f4b2a1ff --- /dev/null +++ b/workflows/pca.nf @@ -0,0 +1,40 @@ +include { IIDGenotypes } from '../modules/genotypes.nf' +include { GeneticConfounders } from '../modules/confounders.nf' +include { ExtractTraits } from '../modules/traits.nf' + +workflow PCA { + // Define Parameters + cohort = params.COHORT + ukb_encoding_file = params.UKB_ENCODING_FILE + ukb_config = Channel.value(file("$params.UKB_CONFIG", checkIfExists: true)) + ukb_withdrawal_list = Channel.value(file("$params.UKB_WITHDRAWAL_LIST", checkIfExists: true)) + traits_dataset = Channel.value(file("$params.TRAITS_DATASET", checkIfExists: true)) + + maf_threshold = params.MAF_THRESHOLD + qc_file = Channel.value(file("$params.QC_FILE", checkIfExists: true)) + flashpca_excl_reg = Channel.value(file("$params.FLASHPCA_EXCLUSION_REGIONS", checkIfExists: true)) + ld_blocks = Channel.value(file("$params.LD_BLOCKS", checkIfExists: true)) + bed_files = Channel.fromFilePairs("$params.BED_FILES", size: 3, checkIfExists: true){ file -> file.baseName } + + // Extract Traits + ExtractTraits( + traits_dataset, + cohort, + ukb_config, + ukb_withdrawal_list, + ukb_encoding_file, + ) + + // IID Genotypes + IIDGenotypes( + flashpca_excl_reg, + ld_blocks, + bed_files, + qc_file, + ExtractTraits.out, + maf_threshold + ) + + // Genetic confounders + GeneticConfounders(IIDGenotypes.out) +} \ No newline at end of file From 460bfe34d74e924dd8f36ef071fef3f4ba3fd666 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Thu, 11 Jan 2024 16:27:48 +0000 Subject: [PATCH 38/65] regorg code to workflows directory --- docs/src/nextflow_params.md | 2 +- docs/src/sieve_variance.md | 2 +- main.nf | 130 +++------------------ test/ukb_from_actors.jl | 2 +- {modules => workflows}/negative_control.nf | 25 +--- workflows/targene.nf | 113 ++++++++++++++++++ 6 files changed, 136 insertions(+), 138 deletions(-) rename {modules => workflows}/negative_control.nf (83%) create mode 100644 workflows/targene.nf diff --git a/docs/src/nextflow_params.md b/docs/src/nextflow_params.md index 179b25a5..5c28a475 100644 --- a/docs/src/nextflow_params.md +++ b/docs/src/nextflow_params.md @@ -54,7 +54,7 @@ If `STUDY_DESIGN`=`FROM_ACTORS`: - `NB_SVP_ESTIMATORS` (optional, default: 100): Number of sieve variance estimates per curve. Setting this value to 0 results in skipping sieve variance correction. - `MAX_SVP_THRESHOLD` (optional, default: 0.9): Variance estimates are computed for tau ranging from 0 to MAX_SVP_THRESHOLD - `PVAL_THRESHOLD` (optional, default: 0.05): To save computation time and disk, only parameters with a p-value below this threshold are considered for sieve variance correction. -- `SVP_ESTIMATOR_KEY` (optional, default: "TMLE"): The estimator to use for Sieve Variance Plateau correction. +- `ESTIMATOR_KEY` (optional, default: "TMLE"): The estimator to use for Sieve Variance Plateau correction. ## [Tweaking additional behaviour](@ref) diff --git a/docs/src/sieve_variance.md b/docs/src/sieve_variance.md index 211e8a20..c4979590 100644 --- a/docs/src/sieve_variance.md +++ b/docs/src/sieve_variance.md @@ -6,7 +6,7 @@ In brief, the SVP estimator computes a variance estimate for a range of threshol The following arguments can be changed to control the behaviour of the pipeline: - `SVP` (default: false): Must be set to true to enable variance adjustement. -- `SVP_ESTIMATOR_KEY` (default: TMLE): The estimator from the `ESTIMATOR_FILE` that will be used for sieve variance plateau adjustment. +- `ESTIMATOR_KEY` (default: TMLE): The estimator from the `ESTIMATOR_FILE` that will be used for sieve variance plateau adjustment. - `GRM_NSPLITS` (default: 100): This is a purely computational argument. The GRM is typically very large and splitting enables a good memory/parallelization tradeoff. - `MAX_SVP_THRESHOLD` (default: 0.8): Controls the maximum genetic distance considered. - `NB_SVP_ESTIMATORS` (default: 0): Controls the number of points in the interval [0, `MAX_SVP_THRESHOLD`]. If 0, the Sieve Variance Plateau method will not be applied. diff --git a/main.nf b/main.nf index e2c0a450..196fa0cb 100644 --- a/main.nf +++ b/main.nf @@ -1,7 +1,9 @@ #!/usr/bin/env nextflow nextflow.enable.dsl = 2 -params.VERBOSITY = 0 +// Misc Parameters +params.VERBOSITY = 0 +params.RNG = 123 params.TRAITS_DATASET = "You need to provide a Traits dataset." params.UKB_ENCODING_FILE = "NO_UKB_ENCODING_FILE" params.CALL_THRESHOLD = 0.9 @@ -36,7 +38,7 @@ params.SVP = false params.GRM_NSPLITS = 100 params.NB_SVP_ESTIMATORS = 100 params.MAX_SVP_THRESHOLD = 0.9 -params.SVP_ESTIMATOR_KEY = "TMLE" +params.ESTIMATOR_KEY = "TMLE" // TMLE Parameters params.KEEP_IC = params.SVP == true ? true : false @@ -50,12 +52,16 @@ params.ARROW_OUTPUT = "dataset.arrow" params.JSON_OUTPUT = "NO_JSON_OUTPUT" params.HDF5_OUTPUT = "results.hdf5" -include { EstimationInputs } from './modules/estimation_inputs.nf' -include { IIDGenotypes } from './modules/genotypes.nf' -include { GeneticConfounders } from './modules/confounders.nf' -include { ExtractTraits } from './modules/traits.nf' -include { EstimationWorkflow } from './modules/estimation.nf' -include { SVPWorkflow } from './modules/svp.nf' +// Negative Control Parameters +params.PERMUTATION_HDF5_OUTPUT = "permutation_results.hdf5" +params.PERMUTATION_JSON_OUTPUT = "NO_JSON_OUTPUT" +params.MAX_PERMUTATION_TESTS = "" +params.PERMUTATION_ORDERS = "1" +params.MAF_MATCHING_RELTOL = 0.05 +params.N_RANDOM_VARIANTS = 10 + +include { TARGENE } from './workflows/targene.nf' +include { NEGCONTROL } from './workflows/negative_control.nf' include { PCA } from './workflows/pca.nf' log.info """\ @@ -68,113 +74,11 @@ log.info """\ started at : ${workflow.start} config files : ${workflow.configFiles} container : ${workflow.containerEngine} + ========================== """ .stripIndent() -workflow { - // Define Parameters - verbosity = params.VERBOSITY - - study_design = params.STUDY_DESIGN - bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() - estimands_file = Channel.value(file("$params.ESTIMANDS_FILE")) - bqtls_file = Channel.value(file("$params.BQTLS")) - transactors_files = Channel.fromPath("$params.TRANS_ACTORS").collect() - extra_confounders = Channel.value(file("$params.EXTRA_CONFOUNDERS")) - extra_treatments = Channel.value(file("$params.ENVIRONMENTALS")) - extra_covariates = Channel.value(file("$params.EXTRA_COVARIATES")) - batch_size = params.BATCH_SIZE - call_threshold = params.CALL_THRESHOLD - positivity_constraint = params.POSITIVITY_CONSTRAINT - - cohort = params.COHORT - ukb_encoding_file = params.UKB_ENCODING_FILE - ukb_config = Channel.value(file("$params.UKB_CONFIG", checkIfExists: true)) - ukb_withdrawal_list = Channel.value(file("$params.UKB_WITHDRAWAL_LIST", checkIfExists: true)) - traits_dataset = Channel.value(file("$params.TRAITS_DATASET", checkIfExists: true)) - - maf_threshold = params.MAF_THRESHOLD - qc_file = Channel.value(file("$params.QC_FILE", checkIfExists: true)) - flashpca_excl_reg = Channel.value(file("$params.FLASHPCA_EXCLUSION_REGIONS", checkIfExists: true)) - ld_blocks = Channel.value(file("$params.LD_BLOCKS", checkIfExists: true)) - bed_files = Channel.fromFilePairs("$params.BED_FILES", size: 3, checkIfExists: true){ file -> file.baseName } - - estimator_config = Channel.value(file("${params.ESTIMATOR_FILE}")) - keep_ic = params.KEEP_IC - pval_threshold = params.PVAL_THRESHOLD - save_every = params.TMLE_SAVE_EVERY - hdf5_output = "${params.HDF5_OUTPUT}" - json_output = "${params.JSON_OUTPUT}" - - do_svp = params.SVP - n_svp_estimators = params.NB_SVP_ESTIMATORS - max_svp_threshold = params.MAX_SVP_THRESHOLD - svp_estimator_key = params.SVP_ESTIMATOR_KEY - grm_n_splits = params.GRM_NSPLITS - - // Extract Traits - ExtractTraits( - traits_dataset, - cohort, - ukb_config, - ukb_withdrawal_list, - ukb_encoding_file, - ) - - // IID Genotypes - IIDGenotypes( - flashpca_excl_reg, - ld_blocks, - bed_files, - qc_file, - ExtractTraits.out, - maf_threshold - ) - - // Genetic confounders - GeneticConfounders(IIDGenotypes.out) - - // generate main dataset and estimand configuration files - EstimationInputs( - study_design, - bgen_files, - ExtractTraits.out, - GeneticConfounders.out, - estimands_file, - bqtls_file, - transactors_files, - extra_confounders, - extra_treatments, - extra_covariates, - batch_size, - call_threshold, - positivity_constraint - ) - - // generate estimates - EstimationWorkflow( - EstimationInputs.out.aggregated_dataset, - EstimationInputs.out.estimands.flatten(), - estimator_config, - keep_ic, - do_svp, - pval_threshold, - save_every, - hdf5_output, - json_output - ) - - // Generate sieve estimates - if (do_svp == true){ - sieve_results = SVPWorkflow( - EstimationWorkflow.out.hdf5_result, - IIDGenotypes.out, - n_svp_estimators, - max_svp_threshold, - svp_estimator_key, - grm_n_splits, - verbosity - ) - } +workflow { + TARGENE() } diff --git a/test/ukb_from_actors.jl b/test/ukb_from_actors.jl index 714cd78c..f99f3a02 100644 --- a/test/ukb_from_actors.jl +++ b/test/ukb_from_actors.jl @@ -53,7 +53,7 @@ include("utils.jl") end @testset "Test negative controls" begin - cmd = `nextflow run . -main-script modules/negative_control.nf -c test/configs/ukb_from_actors.config $args` + cmd = `nextflow run . -entry NEGCONTROL -c test/configs/ukb_from_actors.config $args` @info string("The following command will be run:\n", cmd) r = run(cmd) diff --git a/modules/negative_control.nf b/workflows/negative_control.nf similarity index 83% rename from modules/negative_control.nf rename to workflows/negative_control.nf index cb9f8d8a..8a116f2e 100644 --- a/modules/negative_control.nf +++ b/workflows/negative_control.nf @@ -1,24 +1,5 @@ -#!/usr/bin/env nextflow -nextflow.enable.dsl = 2 - -// Negative Control Parameters -params.OUTDIR = "${launchDir}/results" -params.BATCH_SIZE = 400 -params.VERBOSITY = 1 -params.HDF5_OUTPUT = "results.hdf5" -params.PERMUTATION_HDF5_OUTPUT = "permutation_results.hdf5" -params.PERMUTATION_JSON_OUTPUT = "NO_JSON_OUTPUT" -params.MAX_PERMUTATION_TESTS = "" -params.PERMUTATION_ORDERS = "1" -params.RNG = 123 -params.MAF_MATCHING_RELTOL = 0.05 -params.N_RANDOM_VARIANTS = 10 -params.TMLE_SAVE_EVERY = 100 -params.ARROW_OUTPUT = "dataset.arrow" -params.ESTIMATOR_KEY = "TMLE" - -include { longest_prefix } from './utils.nf' -include { EstimationWorkflow } from './estimation.nf' +include { longest_prefix } from '../modules/utils.nf' +include { EstimationWorkflow } from '../modules/estimation.nf' process GeneratePermutationTestsData { container "olivierlabayle/negative-controls:cvtmle" @@ -80,7 +61,7 @@ process GenerateRandomVariantsTestsData { """ } -workflow { +workflow NEGCONTROL{ results_file = Channel.value(file("${params.OUTDIR}/${params.HDF5_OUTPUT}")) // Permutation Tests diff --git a/workflows/targene.nf b/workflows/targene.nf new file mode 100644 index 00000000..b76a29b4 --- /dev/null +++ b/workflows/targene.nf @@ -0,0 +1,113 @@ +include { EstimationInputs } from '../modules/estimation_inputs.nf' +include { IIDGenotypes } from '../modules/genotypes.nf' +include { GeneticConfounders } from '../modules/confounders.nf' +include { ExtractTraits } from '../modules/traits.nf' +include { EstimationWorkflow } from '../modules/estimation.nf' +include { SVPWorkflow } from '../modules/svp.nf' + +workflow TARGENE { + // Define Parameters + verbosity = params.VERBOSITY + + study_design = params.STUDY_DESIGN + bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() + estimands_file = Channel.value(file("$params.ESTIMANDS_FILE")) + bqtls_file = Channel.value(file("$params.BQTLS")) + transactors_files = Channel.fromPath("$params.TRANS_ACTORS").collect() + extra_confounders = Channel.value(file("$params.EXTRA_CONFOUNDERS")) + extra_treatments = Channel.value(file("$params.ENVIRONMENTALS")) + extra_covariates = Channel.value(file("$params.EXTRA_COVARIATES")) + batch_size = params.BATCH_SIZE + call_threshold = params.CALL_THRESHOLD + positivity_constraint = params.POSITIVITY_CONSTRAINT + + cohort = params.COHORT + ukb_encoding_file = params.UKB_ENCODING_FILE + ukb_config = Channel.value(file("$params.UKB_CONFIG", checkIfExists: true)) + ukb_withdrawal_list = Channel.value(file("$params.UKB_WITHDRAWAL_LIST", checkIfExists: true)) + traits_dataset = Channel.value(file("$params.TRAITS_DATASET", checkIfExists: true)) + + maf_threshold = params.MAF_THRESHOLD + qc_file = Channel.value(file("$params.QC_FILE", checkIfExists: true)) + flashpca_excl_reg = Channel.value(file("$params.FLASHPCA_EXCLUSION_REGIONS", checkIfExists: true)) + ld_blocks = Channel.value(file("$params.LD_BLOCKS", checkIfExists: true)) + bed_files = Channel.fromFilePairs("$params.BED_FILES", size: 3, checkIfExists: true){ file -> file.baseName } + + estimator_config = Channel.value(file("${params.ESTIMATOR_FILE}")) + keep_ic = params.KEEP_IC + pval_threshold = params.PVAL_THRESHOLD + save_every = params.TMLE_SAVE_EVERY + hdf5_output = "${params.HDF5_OUTPUT}" + json_output = "${params.JSON_OUTPUT}" + + do_svp = params.SVP + n_svp_estimators = params.NB_SVP_ESTIMATORS + max_svp_threshold = params.MAX_SVP_THRESHOLD + svp_estimator_key = params.ESTIMATOR_KEY + grm_n_splits = params.GRM_NSPLITS + + // Extract Traits + ExtractTraits( + traits_dataset, + cohort, + ukb_config, + ukb_withdrawal_list, + ukb_encoding_file, + ) + + // IID Genotypes + IIDGenotypes( + flashpca_excl_reg, + ld_blocks, + bed_files, + qc_file, + ExtractTraits.out, + maf_threshold + ) + + // Genetic confounders + GeneticConfounders(IIDGenotypes.out) + + // generate main dataset and estimand configuration files + EstimationInputs( + study_design, + bgen_files, + ExtractTraits.out, + GeneticConfounders.out, + estimands_file, + bqtls_file, + transactors_files, + extra_confounders, + extra_treatments, + extra_covariates, + batch_size, + call_threshold, + positivity_constraint + ) + + // generate estimates + EstimationWorkflow( + EstimationInputs.out.aggregated_dataset, + EstimationInputs.out.estimands.flatten(), + estimator_config, + keep_ic, + do_svp, + pval_threshold, + save_every, + hdf5_output, + json_output + ) + + // Generate sieve estimates + if (do_svp == true){ + sieve_results = SVPWorkflow( + EstimationWorkflow.out.hdf5_result, + IIDGenotypes.out, + n_svp_estimators, + max_svp_threshold, + svp_estimator_key, + grm_n_splits, + verbosity + ) + } +} \ No newline at end of file From be3ea9ee8ac5fcb1d2a4f25a5743eeb398b6959d Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Thu, 11 Jan 2024 17:33:02 +0000 Subject: [PATCH 39/65] update neg control worklow to support new mode --- main.nf | 1 + test/configs/ukb_from_actors.config | 1 + test/data/variants_to_randomize.txt | 1 + workflows/negative_control.nf | 11 +++++------ 4 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 test/data/variants_to_randomize.txt diff --git a/main.nf b/main.nf index 196fa0cb..b5ec56df 100644 --- a/main.nf +++ b/main.nf @@ -58,6 +58,7 @@ params.PERMUTATION_JSON_OUTPUT = "NO_JSON_OUTPUT" params.MAX_PERMUTATION_TESTS = "" params.PERMUTATION_ORDERS = "1" params.MAF_MATCHING_RELTOL = 0.05 +params.VARIANTS_TO_RANDOMIZE = "NO_VARIANT_TO_RANDOMIZE" params.N_RANDOM_VARIANTS = 10 include { TARGENE } from './workflows/targene.nf' diff --git a/test/configs/ukb_from_actors.config b/test/configs/ukb_from_actors.config index 962ba61c..d9179397 100644 --- a/test/configs/ukb_from_actors.config +++ b/test/configs/ukb_from_actors.config @@ -9,4 +9,5 @@ params { MAX_PERMUTATION_TESTS = 100 MAF_MATCHING_RELTOL = 0.9 N_RANDOM_VARIANTS = 5 + VARIANTS_TO_RANDOMIZE = "test/data/variants_to_randomize.txt" } diff --git a/test/data/variants_to_randomize.txt b/test/data/variants_to_randomize.txt new file mode 100644 index 00000000..3b79ec4a --- /dev/null +++ b/test/data/variants_to_randomize.txt @@ -0,0 +1 @@ +"2:14983:G:A" \ No newline at end of file diff --git a/workflows/negative_control.nf b/workflows/negative_control.nf index 8a116f2e..a81fb4e1 100644 --- a/workflows/negative_control.nf +++ b/workflows/negative_control.nf @@ -37,7 +37,7 @@ process GenerateRandomVariantsTestsData { label "bigmem" input: - path trans_actors + path variants_to_randomize path bgenfiles path results @@ -45,12 +45,11 @@ process GenerateRandomVariantsTestsData { path "random_variants_estimands.jls" script: - trans_actors_prefix = longest_prefix(trans_actors) bgen_prefix = longest_prefix(bgenfiles) """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/NegativeControl --startup-file=no /NegativeControl/bin/generate_random_variant_parameters.jl \ - ${trans_actors_prefix} ${results} ${bgen_prefix} \ + ${variants_to_randomize} ${results} ${bgen_prefix} \ --out=random_variants_estimands.jls \ --p=${params.N_RANDOM_VARIANTS} \ --reltol=${params.MAF_MATCHING_RELTOL} \ @@ -91,9 +90,9 @@ workflow NEGCONTROL{ ) // Random Variants parameter files generation - if (params.STUDY_DESIGN == "FROM_ACTORS") { + if (params.VARIANTS_TO_RANDOMIZE !== "NO_VARIANT_TO_RANDOMIZE") { bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() - trans_actors = Channel.fromPath("$params.TRANS_ACTORS", checkIfExists: true).collect() - GenerateRandomVariantsTestsData(trans_actors, bgen_files, results_file) + variants_to_randomize = Channel.value(file("$params.VARIANTS_TO_RANDOMIZE", checkIfExists: true)) + GenerateRandomVariantsTestsData(variants_to_randomize, bgen_files, results_file) } } \ No newline at end of file From 6de4e3ae6014c70105754e9589592a6600c47e7c Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Thu, 11 Jan 2024 18:02:10 +0000 Subject: [PATCH 40/65] fix test file --- main.nf | 4 ++-- test/data/variants_to_randomize.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/main.nf b/main.nf index b5ec56df..fb758137 100644 --- a/main.nf +++ b/main.nf @@ -53,8 +53,8 @@ params.JSON_OUTPUT = "NO_JSON_OUTPUT" params.HDF5_OUTPUT = "results.hdf5" // Negative Control Parameters -params.PERMUTATION_HDF5_OUTPUT = "permutation_results.hdf5" -params.PERMUTATION_JSON_OUTPUT = "NO_JSON_OUTPUT" +params.PERMUTATION_HDF5_OUTPUT = "permutation_${params.HDF5_OUTPUT}" +params.PERMUTATION_JSON_OUTPUT = params.JSON_OUTPUT == "NO_JSON_OUTPUT" ? params.JSON_OUTPUT : "permutation_${params.JSON_OUTPUT}" params.MAX_PERMUTATION_TESTS = "" params.PERMUTATION_ORDERS = "1" params.MAF_MATCHING_RELTOL = 0.05 diff --git a/test/data/variants_to_randomize.txt b/test/data/variants_to_randomize.txt index 3b79ec4a..50761a98 100644 --- a/test/data/variants_to_randomize.txt +++ b/test/data/variants_to_randomize.txt @@ -1 +1 @@ -"2:14983:G:A" \ No newline at end of file +2:14983:G:A \ No newline at end of file From 2ced408a24ab1a2b830ab7f69284e41a83167b39 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Sat, 27 Jan 2024 14:04:34 +0000 Subject: [PATCH 41/65] update neg control workflows --- main.nf | 4 ++-- modules/estimation.nf | 9 --------- test/configs/negcontrol.config | 7 +++++++ test/ukb_from_actors.jl | 14 ++++++++++---- workflows/negative_control.nf | 27 ++++++++++++++------------- 5 files changed, 33 insertions(+), 28 deletions(-) create mode 100644 test/configs/negcontrol.config diff --git a/main.nf b/main.nf index fb758137..74e8649b 100644 --- a/main.nf +++ b/main.nf @@ -44,7 +44,6 @@ params.ESTIMATOR_KEY = "TMLE" params.KEEP_IC = params.SVP == true ? true : false params.PVAL_THRESHOLD = 0.05 params.TMLE_SAVE_EVERY = 100 -params.AGGREGATED_DATASET = "results/dataset.arrow" params.ESTIMATOR_FILE = "glmnet" // Outputs Parameters @@ -56,13 +55,14 @@ params.HDF5_OUTPUT = "results.hdf5" params.PERMUTATION_HDF5_OUTPUT = "permutation_${params.HDF5_OUTPUT}" params.PERMUTATION_JSON_OUTPUT = params.JSON_OUTPUT == "NO_JSON_OUTPUT" ? params.JSON_OUTPUT : "permutation_${params.JSON_OUTPUT}" params.MAX_PERMUTATION_TESTS = "" +params.MAX_PERMUTATION_ATTEMPTS = 1 params.PERMUTATION_ORDERS = "1" params.MAF_MATCHING_RELTOL = 0.05 params.VARIANTS_TO_RANDOMIZE = "NO_VARIANT_TO_RANDOMIZE" params.N_RANDOM_VARIANTS = 10 include { TARGENE } from './workflows/targene.nf' -include { NEGCONTROL } from './workflows/negative_control.nf' +include { PERMUTATION_TEST; RANDOMIZATION_TEST } from './workflows/negative_control.nf' include { PCA } from './workflows/pca.nf' log.info """\ diff --git a/modules/estimation.nf b/modules/estimation.nf index 03e1e9ad..8bee974f 100644 --- a/modules/estimation.nf +++ b/modules/estimation.nf @@ -88,12 +88,3 @@ workflow EstimationWorkflow { emit: hdf5_result = MergeOutputs.out.hdf5_file } - -// workflow { -// dataset = Channel.value(file("${params.AGGREGATED_DATASET}")) -// estimands_configs = Channel.value(file("${params.ESTIMAND_CONFIG_FILES}")) -// estimators_config = Channel.value(file("${params.ESTIMATOR_FILE}", checkIfExists: false)) -// hdf5_output = "${params.HDF5_OUTPUT}" -// json_output = "${params.JSON_OUTPUT}" -// EstimationWorkflow(dataset, estimands_configs, estimators_config, hdf5_output, json_output) -// } \ No newline at end of file diff --git a/test/configs/negcontrol.config b/test/configs/negcontrol.config new file mode 100644 index 00000000..dec219e0 --- /dev/null +++ b/test/configs/negcontrol.config @@ -0,0 +1,7 @@ +includeConfig 'ukb_from_actors.config' + +params { + RESULTS_FILE = "results/results.hdf5" + AGGREGATED_DATASET = "results/dataset.arrow" + HDF5_OUTPUT = "permutation_results.hdf5" +} \ No newline at end of file diff --git a/test/ukb_from_actors.jl b/test/ukb_from_actors.jl index f99f3a02..7de290f9 100644 --- a/test/ukb_from_actors.jl +++ b/test/ukb_from_actors.jl @@ -52,14 +52,13 @@ include("utils.jl") end end -@testset "Test negative controls" begin - cmd = `nextflow run . -entry NEGCONTROL -c test/configs/ukb_from_actors.config $args` +@testset "Test PERMUTATION_TEST" begin + cmd = `nextflow run . -entry PERMUTATION_TEST -c test/configs/negcontrol.config $args` @info string("The following command will be run:\n", cmd) r = run(cmd) @test r.exitcode == 0 - # Check permutation test data = Arrow.Table(joinpath("results", "permutation_tests", "permutation_dataset.arrow")) |> DataFrame n_permuted_cols = 0 @@ -78,8 +77,15 @@ end @test length(results) == 100 failed_results = retrieve_failed_results(results; expected_keys=(:TMLE, :OSE)) @test failed_results == (TMLE=[], OSE=[]) +end + +@testset "Test RANDOMIZATION_TEST" begin + cmd = `nextflow run . -entry RANDOMIZATION_TEST -c test/configs/negcontrol.config $args` + @info string("The following command will be run:\n", cmd) + + r = run(cmd) + @test r.exitcode == 0 - # Check random variants data random_config = deserialize(joinpath("results", "random_variants_estimands.jls")) @test length(random_config.estimands) > 200 @test Set(typeof(Ξ¨) for Ξ¨ in random_config.estimands) == Set([TMLE.StatisticalATE, TMLE.StatisticalIATE]) diff --git a/workflows/negative_control.nf b/workflows/negative_control.nf index a81fb4e1..a4162459 100644 --- a/workflows/negative_control.nf +++ b/workflows/negative_control.nf @@ -19,7 +19,7 @@ process GeneratePermutationTestsData { limit = params.MAX_PERMUTATION_TESTS == "" ? "" : "--limit=${params.MAX_PERMUTATION_TESTS}" """ TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/NegativeControl --startup-file=no /NegativeControl/bin/generate_permutation_data.jl \ + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/NegativeControl --startup-file=no /NegativeControl/bin/generate_permutation_data.jl \ ${dataset} ${results} \ ${limit} \ --pval-threshold=${params.PVAL_THRESHOLD} \ @@ -27,6 +27,8 @@ process GeneratePermutationTestsData { --orders=${params.PERMUTATION_ORDERS} \ --chunksize=${params.BATCH_SIZE} \ --rng=${params.RNG} \ + --max-attempts=${params.MAX_PERMUTATION_ATTEMPTS} \ + --positivity-constraint=${params.POSITIVITY_CONSTRAINT} \ --verbosity=${params.VERBOSITY} """ } @@ -60,18 +62,17 @@ process GenerateRandomVariantsTestsData { """ } -workflow NEGCONTROL{ - results_file = Channel.value(file("${params.OUTDIR}/${params.HDF5_OUTPUT}")) - +workflow PERMUTATION_TEST { // Permutation Tests - dataset = Channel.value(file("${params.OUTDIR}/${params.ARROW_OUTPUT}")) + results_file = Channel.value(file("${params.RESULTS_FILE}")) + dataset = Channel.value(file("${params.AGGREGATED_DATASET}")) estimator_config = Channel.value(file("${params.ESTIMATOR_FILE}")) keep_ic = false do_svp = false pval_threshold = params.PVAL_THRESHOLD save_every = params.TMLE_SAVE_EVERY - hdf5_output = params.PERMUTATION_HDF5_OUTPUT - json_output = params.PERMUTATION_JSON_OUTPUT + hdf5_output = params.HDF5_OUTPUT + json_output = params.JSON_OUTPUT GeneratePermutationTestsData( dataset, @@ -88,11 +89,11 @@ workflow NEGCONTROL{ hdf5_output, json_output ) +} - // Random Variants parameter files generation - if (params.VARIANTS_TO_RANDOMIZE !== "NO_VARIANT_TO_RANDOMIZE") { - bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() - variants_to_randomize = Channel.value(file("$params.VARIANTS_TO_RANDOMIZE", checkIfExists: true)) - GenerateRandomVariantsTestsData(variants_to_randomize, bgen_files, results_file) - } +workflow RANDOMIZATION_TEST { + results_file = Channel.value(file("${params.RESULTS_FILE}")) + bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() + variants_to_randomize = Channel.value(file("$params.VARIANTS_TO_RANDOMIZE", checkIfExists: true)) + GenerateRandomVariantsTestsData(variants_to_randomize, bgen_files, results_file) } \ No newline at end of file From a72243e04ddb887d06f7499c82abf778eaeac3f2 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Sat, 27 Jan 2024 14:41:05 +0000 Subject: [PATCH 42/65] update config files --- conf/eddie.config | 7 ++++--- test/data/interactions_allele_independent.yaml | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/conf/eddie.config b/conf/eddie.config index d0207a7b..4d07ed50 100644 --- a/conf/eddie.config +++ b/conf/eddie.config @@ -8,7 +8,7 @@ executor { name = "sge" // Set the default maximum number of submitted jobs to 100 - queueSize = 500 + queueSize = 1000 } process { @@ -41,8 +41,9 @@ process { } withName: TMLE { - memory = { 25.GB * task.attempt } - cpus = 5 + memory = { 30.GB * task.attempt } + time = { 48.hour * task.attempt } + cpus = 2 } } diff --git a/test/data/interactions_allele_independent.yaml b/test/data/interactions_allele_independent.yaml index bc0cc8a0..bfb5294c 100644 --- a/test/data/interactions_allele_independent.yaml +++ b/test/data/interactions_allele_independent.yaml @@ -1,5 +1,6 @@ orders: [2] -estimands: interactions +estimands: + - IATE variants: TF1: bQTLs: From 8d2bedbc994d0cd1997cae5ea0d5d720b92ad6be Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 30 Jan 2024 11:04:04 +0000 Subject: [PATCH 43/65] update deps --- main.nf | 1 + modules/dataset.nf | 20 +++++++++++++++ modules/estimation_inputs.nf | 24 ++++++++++++------ workflows/dataset.nf | 47 +++++++++++++++++++++++++++++++++++ workflows/negative_control.nf | 16 ++++++------ 5 files changed, 92 insertions(+), 16 deletions(-) create mode 100644 modules/dataset.nf create mode 100644 workflows/dataset.nf diff --git a/main.nf b/main.nf index 74e8649b..4ffaf0ab 100644 --- a/main.nf +++ b/main.nf @@ -64,6 +64,7 @@ params.N_RANDOM_VARIANTS = 10 include { TARGENE } from './workflows/targene.nf' include { PERMUTATION_TEST; RANDOMIZATION_TEST } from './workflows/negative_control.nf' include { PCA } from './workflows/pca.nf' +include { MAKE_DATASET } from './workflows/dataset.nf' log.info """\ ${workflow.manifest.name} v${workflow.manifest.version} diff --git a/modules/dataset.nf b/modules/dataset.nf new file mode 100644 index 00000000..964b68e9 --- /dev/null +++ b/modules/dataset.nf @@ -0,0 +1,20 @@ +include { longest_prefix } from './utils.nf' + +process MakeDataset { + container "olivierlabayle/tl-core:cvtmle" + publishDir "${params.OUTDIR}", mode: 'symlink' + label "bigmem" + + input: + path bgenfiles + path traits + path confounders + + output: + path "dataset.arrow" + + script: + prefix = longest_prefix(bgenfiles) + """ + """ +} \ No newline at end of file diff --git a/modules/estimation_inputs.nf b/modules/estimation_inputs.nf index a8f8f9e2..eba9364e 100644 --- a/modules/estimation_inputs.nf +++ b/modules/estimation_inputs.nf @@ -25,14 +25,16 @@ process TMLEInputsFromParamFile { batchsize = batch_size == 0 ? "" : "--batch-size ${batch_size}" """ TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/tmle_inputs.jl \ + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no --sysimage=/TargeneCore.jl/TargeneCoreSysimage.so /TargeneCore.jl/bin/generate_tl_inputs.jl \ + --positivity-constraint ${positivity_constraint} \ + $batchsize \ + --out-prefix=final \ + --verbosity=${params.VERBOSITY} \ + $command $parameter \ --traits $traits \ --bgen-prefix $bgen_prefix \ --call-threshold ${call_threshold} \ --pcs $genetic_confounders \ - $batchsize \ - --positivity-constraint ${positivity_constraint} \ - $command $parameter """ } @@ -68,14 +70,20 @@ process TMLEInputsFromActors { extra_covariates = extra_covariates.name != 'NO_EXTRA_COVARIATE' ? "--extra-covariates $extra_covariates" : '' """ TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/tmle_inputs.jl \ + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no --sysimage=/TargeneCore.jl/TargeneCoreSysimage.so /TargeneCore.jl/bin/generate_tl_inputs.jl \ + --positivity-constraint ${positivity_constraint} \ + $batch_size \ + --out-prefix=final \ + --verbosity=${params.VERBOSITY} \ + from-actors $bqtls $trans_actors_prefix \ + $extra_confounders \ + $extra_treatments \ + $extra_covariates \ + --orders ${params.ORDERS} \ --traits $traits \ --bgen-prefix $bgen_prefix \ --call-threshold ${call_threshold} \ --pcs $genetic_confounders \ - --positivity-constraint ${positivity_constraint} \ - $batch_size \ - from-actors $bqtls $trans_actors_prefix $extra_confounders $extra_treatments $extra_covariates --orders ${params.ORDERS} """ } diff --git a/workflows/dataset.nf b/workflows/dataset.nf new file mode 100644 index 00000000..c9400e29 --- /dev/null +++ b/workflows/dataset.nf @@ -0,0 +1,47 @@ +include { MakeDataset } from '../modules/dataset.nf' +include { IIDGenotypes } from '../modules/genotypes.nf' +include { GeneticConfounders } from '../modules/confounders.nf' +include { ExtractTraits } from '../modules/traits.nf' + +workflow MAKE_DATASET { + cohort = params.COHORT + ukb_encoding_file = params.UKB_ENCODING_FILE + ukb_config = Channel.value(file("$params.UKB_CONFIG", checkIfExists: true)) + ukb_withdrawal_list = Channel.value(file("$params.UKB_WITHDRAWAL_LIST", checkIfExists: true)) + traits_dataset = Channel.value(file("$params.TRAITS_DATASET", checkIfExists: true)) + + maf_threshold = params.MAF_THRESHOLD + qc_file = Channel.value(file("$params.QC_FILE", checkIfExists: true)) + flashpca_excl_reg = Channel.value(file("$params.FLASHPCA_EXCLUSION_REGIONS", checkIfExists: true)) + ld_blocks = Channel.value(file("$params.LD_BLOCKS", checkIfExists: true)) + bed_files = Channel.fromFilePairs("$params.BED_FILES", size: 3, checkIfExists: true){ file -> file.baseName } + bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() + + ExtractTraits( + traits_dataset, + cohort, + ukb_config, + ukb_withdrawal_list, + ukb_encoding_file, + ) + + // IID Genotypes + IIDGenotypes( + flashpca_excl_reg, + ld_blocks, + bed_files, + qc_file, + ExtractTraits.out, + maf_threshold + ) + + // Genetic confounders + GeneticConfounders(IIDGenotypes.out) + + // Dataset + MakeDataset( + bgen_files, + ExtractTraits.out, + GeneticConfounders.out, + ) +} \ No newline at end of file diff --git a/workflows/negative_control.nf b/workflows/negative_control.nf index a4162459..c22ab257 100644 --- a/workflows/negative_control.nf +++ b/workflows/negative_control.nf @@ -2,7 +2,7 @@ include { longest_prefix } from '../modules/utils.nf' include { EstimationWorkflow } from '../modules/estimation.nf' process GeneratePermutationTestsData { - container "olivierlabayle/negative-controls:cvtmle" + container "olivierlabayle/tl-core:cvtmle" publishDir "${params.OUTDIR}/permutation_tests", mode: 'symlink', pattern: '*.arrow' publishDir "${params.OUTDIR}/permutation_tests/estimands", mode: 'symlink', pattern: '*.jls' label "bigmem" @@ -19,22 +19,22 @@ process GeneratePermutationTestsData { limit = params.MAX_PERMUTATION_TESTS == "" ? "" : "--limit=${params.MAX_PERMUTATION_TESTS}" """ TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/NegativeControl --startup-file=no /NegativeControl/bin/generate_permutation_data.jl \ - ${dataset} ${results} \ + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no --sysimage=/TargeneCore.jl/TargeneCoreSysimage.so /TargeneCore.jl/bin/generate_tl_inputs.jl \ + --positivity-constraint=${params.POSITIVITY_CONSTRAINT} \ + --verbosity=${params.VERBOSITY} \ + --batch-size=${params.BATCH_SIZE} \ + permutation-tests ${dataset} ${results} \ ${limit} \ --pval-threshold=${params.PVAL_THRESHOLD} \ --estimator-key=${params.ESTIMATOR_KEY} \ --orders=${params.PERMUTATION_ORDERS} \ - --chunksize=${params.BATCH_SIZE} \ --rng=${params.RNG} \ --max-attempts=${params.MAX_PERMUTATION_ATTEMPTS} \ - --positivity-constraint=${params.POSITIVITY_CONSTRAINT} \ - --verbosity=${params.VERBOSITY} """ } process GenerateRandomVariantsTestsData { - container "olivierlabayle/negative-controls:cvtmle" + container "olivierlabayle/tl-core:cvtmle" publishDir "${params.OUTDIR}", mode: 'symlink' label "bigmem" @@ -50,7 +50,7 @@ process GenerateRandomVariantsTestsData { bgen_prefix = longest_prefix(bgenfiles) """ TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/NegativeControl --startup-file=no /NegativeControl/bin/generate_random_variant_parameters.jl \ + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no --sysimage=/TargeneCore.jl/TargeneCoreSysimage.so /TargeneCore.jl/bin/generate_random_variant_estimands.jl \ ${variants_to_randomize} ${results} ${bgen_prefix} \ --out=random_variants_estimands.jls \ --p=${params.N_RANDOM_VARIANTS} \ From 99c45804b8e6ac167c90dde702f01a646bc10292 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 30 Jan 2024 12:13:53 +0000 Subject: [PATCH 44/65] add make_dataset workflow --- .github/workflows/CI.yml | 3 ++- modules/dataset.nf | 6 +++++ test/configs/dataset.config | 5 +++++ test/configs/ukb_from_actors.config | 2 +- ...nts_to_randomize.txt => variants_list.txt} | 0 test/make_dataset.jl | 22 +++++++++++++++++++ test/runtest.jl | 4 ---- test/ukb_from_actors.jl | 4 ++-- workflows/dataset.nf | 8 ++++++- workflows/negative_control.nf | 1 + 10 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 test/configs/dataset.config rename test/data/{variants_to_randomize.txt => variants_list.txt} (100%) create mode 100644 test/make_dataset.jl delete mode 100644 test/runtest.jl diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 1542f010..fd164845 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -19,6 +19,7 @@ jobs: - "ukb_custom.jl" - "ukb_allele_independent.jl" - "custom_from_actors.jl" + - "make_dataset.jl" steps: - uses: actions/checkout@v2 - uses: julia-actions/setup-julia@v1 @@ -39,7 +40,7 @@ jobs: - name: Instantiate test environment run: julia --project=test --startup-file=no -e'using Pkg;Pkg.instantiate()' - name: Run tests - run: julia --project=test --startup-file=no test/${{ matrix.testrun }} -profile ci + run: julia --project=test --startup-file=no test/${{ matrix.testrun }} -profile ci -resume docs: name: Documentation runs-on: ubuntu-latest diff --git a/modules/dataset.nf b/modules/dataset.nf index 964b68e9..227167c5 100644 --- a/modules/dataset.nf +++ b/modules/dataset.nf @@ -9,6 +9,7 @@ process MakeDataset { path bgenfiles path traits path confounders + path variants_list output: path "dataset.arrow" @@ -16,5 +17,10 @@ process MakeDataset { script: prefix = longest_prefix(bgenfiles) """ + TEMPD=\$(mktemp -d) + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no --sysimage=/TargeneCore.jl/TargeneCoreSysimage.so /TargeneCore.jl/bin/generate_dataset.jl \ + ${bgen-prefix} ${traits} ${confounders} ${variants_list} \ + --call-threshold ${params.CALL_THRESHOLD} \ + --out dataset.arrow """ } \ No newline at end of file diff --git a/test/configs/dataset.config b/test/configs/dataset.config new file mode 100644 index 00000000..c9d7256e --- /dev/null +++ b/test/configs/dataset.config @@ -0,0 +1,5 @@ +includeConfig 'ukb.config' + +params { + VARIANTS_LIST = "test/data/variants_list.txt" +} \ No newline at end of file diff --git a/test/configs/ukb_from_actors.config b/test/configs/ukb_from_actors.config index d9179397..7ca8c2ef 100644 --- a/test/configs/ukb_from_actors.config +++ b/test/configs/ukb_from_actors.config @@ -9,5 +9,5 @@ params { MAX_PERMUTATION_TESTS = 100 MAF_MATCHING_RELTOL = 0.9 N_RANDOM_VARIANTS = 5 - VARIANTS_TO_RANDOMIZE = "test/data/variants_to_randomize.txt" + VARIANTS_TO_RANDOMIZE = "test/data/variants_list.txt" } diff --git a/test/data/variants_to_randomize.txt b/test/data/variants_list.txt similarity index 100% rename from test/data/variants_to_randomize.txt rename to test/data/variants_list.txt diff --git a/test/make_dataset.jl b/test/make_dataset.jl new file mode 100644 index 00000000..fca5ff56 --- /dev/null +++ b/test/make_dataset.jl @@ -0,0 +1,22 @@ +module TestUKBAlleleIndependent + +using Test +using Arrow +using DataFrames + +args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] + +@testset "Test MAKE_DATASET" begin + cmd = `nextflow run main.nf -entry MAKE_DATASET -c test/configs/dataset.config $args` + @info string("The following command will be run:\n", cmd) + + r = run(cmd) + @test r.exitcode == 0 + + dataset = Arrow.Table("results/dataset.arrow") |> DataFrame + +end + +end + +true \ No newline at end of file diff --git a/test/runtest.jl b/test/runtest.jl deleted file mode 100644 index bc03cff7..00000000 --- a/test/runtest.jl +++ /dev/null @@ -1,4 +0,0 @@ - -include("ukb_from_actors.jl") -include("ukb_from_param_file.jl") -include("custom_from_actors.jl") diff --git a/test/ukb_from_actors.jl b/test/ukb_from_actors.jl index 7de290f9..baeb08b4 100644 --- a/test/ukb_from_actors.jl +++ b/test/ukb_from_actors.jl @@ -53,7 +53,7 @@ include("utils.jl") end @testset "Test PERMUTATION_TEST" begin - cmd = `nextflow run . -entry PERMUTATION_TEST -c test/configs/negcontrol.config $args` + cmd = `nextflow run main.nf -entry PERMUTATION_TEST -c test/configs/negcontrol.config $args` @info string("The following command will be run:\n", cmd) r = run(cmd) @@ -80,7 +80,7 @@ end end @testset "Test RANDOMIZATION_TEST" begin - cmd = `nextflow run . -entry RANDOMIZATION_TEST -c test/configs/negcontrol.config $args` + cmd = `nextflow run main.nf -entry RANDOMIZATION_TEST -c test/configs/negcontrol.config $args` @info string("The following command will be run:\n", cmd) r = run(cmd) diff --git a/workflows/dataset.nf b/workflows/dataset.nf index c9400e29..c582e9f3 100644 --- a/workflows/dataset.nf +++ b/workflows/dataset.nf @@ -4,18 +4,23 @@ include { GeneticConfounders } from '../modules/confounders.nf' include { ExtractTraits } from '../modules/traits.nf' workflow MAKE_DATASET { + // Traits params cohort = params.COHORT ukb_encoding_file = params.UKB_ENCODING_FILE ukb_config = Channel.value(file("$params.UKB_CONFIG", checkIfExists: true)) ukb_withdrawal_list = Channel.value(file("$params.UKB_WITHDRAWAL_LIST", checkIfExists: true)) traits_dataset = Channel.value(file("$params.TRAITS_DATASET", checkIfExists: true)) - + + // Confounders params maf_threshold = params.MAF_THRESHOLD qc_file = Channel.value(file("$params.QC_FILE", checkIfExists: true)) flashpca_excl_reg = Channel.value(file("$params.FLASHPCA_EXCLUSION_REGIONS", checkIfExists: true)) ld_blocks = Channel.value(file("$params.LD_BLOCKS", checkIfExists: true)) bed_files = Channel.fromFilePairs("$params.BED_FILES", size: 3, checkIfExists: true){ file -> file.baseName } + + // Variants params bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() + variant_list = Channel.value(file(params.VARIANTS_LIST, checkIfExists: true)) ExtractTraits( traits_dataset, @@ -43,5 +48,6 @@ workflow MAKE_DATASET { bgen_files, ExtractTraits.out, GeneticConfounders.out, + variant_list ) } \ No newline at end of file diff --git a/workflows/negative_control.nf b/workflows/negative_control.nf index c22ab257..12d7074d 100644 --- a/workflows/negative_control.nf +++ b/workflows/negative_control.nf @@ -23,6 +23,7 @@ process GeneratePermutationTestsData { --positivity-constraint=${params.POSITIVITY_CONSTRAINT} \ --verbosity=${params.VERBOSITY} \ --batch-size=${params.BATCH_SIZE} \ + --out-prefix="." \ permutation-tests ${dataset} ${results} \ ${limit} \ --pval-threshold=${params.PVAL_THRESHOLD} \ From be5b01567732e682d00d2fcffa03ff21278341a6 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 30 Jan 2024 14:14:43 +0000 Subject: [PATCH 45/65] potentially fix permutation test --- modules/confounders.nf | 2 +- modules/dataset.nf | 4 ++-- modules/genotypes.nf | 4 ++-- modules/svp.nf | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/confounders.nf b/modules/confounders.nf index b1e13bcb..44320830 100644 --- a/modules/confounders.nf +++ b/modules/confounders.nf @@ -14,7 +14,7 @@ process FlashPCA { } process AdaptFlashPCA { - container "olivierlabayle/tl-core:0.6" + container "olivierlabayle/tl-core:cvtmle" publishDir "$params.OUTDIR/covariates/", mode: 'symlink' label 'bigmem' diff --git a/modules/dataset.nf b/modules/dataset.nf index 227167c5..6d6ae6ff 100644 --- a/modules/dataset.nf +++ b/modules/dataset.nf @@ -15,11 +15,11 @@ process MakeDataset { path "dataset.arrow" script: - prefix = longest_prefix(bgenfiles) + bgenprefix = longest_prefix(bgenfiles) """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no --sysimage=/TargeneCore.jl/TargeneCoreSysimage.so /TargeneCore.jl/bin/generate_dataset.jl \ - ${bgen-prefix} ${traits} ${confounders} ${variants_list} \ + ${bgenprefix} ${traits} ${confounders} ${variants_list} \ --call-threshold ${params.CALL_THRESHOLD} \ --out dataset.arrow """ diff --git a/modules/genotypes.nf b/modules/genotypes.nf index 08c8eccf..5aebaac1 100644 --- a/modules/genotypes.nf +++ b/modules/genotypes.nf @@ -1,6 +1,6 @@ process filterBED{ label 'bigmem' - container "olivierlabayle/tl-core:0.6" + container "olivierlabayle/tl-core:cvtmle" publishDir "$params.OUTDIR/qc_filtered_chromosomes", mode: 'symlink' input: @@ -49,7 +49,7 @@ process thinByLD{ process mergeBEDS{ label 'bigmem' - container "olivierlabayle/tl-core:0.6" + container "olivierlabayle/tl-core:cvtmle" publishDir "$params.OUTDIR/merged_genotypes", mode: 'symlink' input: diff --git a/modules/svp.nf b/modules/svp.nf index d42e6dcd..6ed303dd 100644 --- a/modules/svp.nf +++ b/modules/svp.nf @@ -1,7 +1,7 @@ include { longest_prefix } from './utils.nf' process GRMPart { - container "olivierlabayle/tl-core:0.6" + container "olivierlabayle/tl-core:cvtmle" label "bigmem" label "multithreaded" From a034dc4c5dbbb7634e4727bc130dcf39ecb063df Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 30 Jan 2024 16:51:00 +0000 Subject: [PATCH 46/65] fix dataset generation --- test/make_dataset.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/make_dataset.jl b/test/make_dataset.jl index fca5ff56..b04f3fd2 100644 --- a/test/make_dataset.jl +++ b/test/make_dataset.jl @@ -14,7 +14,9 @@ args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] @test r.exitcode == 0 dataset = Arrow.Table("results/dataset.arrow") |> DataFrame - + @test size(dataset, 1) == 500 + # PCs, SAMPLE_ID and the variant from the list + @test all(n ∈ names(dataset) for n in ("SAMPLE_ID", "2:14983:G:A", "PC1", "PC2", "PC3", "PC4", "PC5", "PC6",)) end end From 195a9e72c4c8cc000f33e8e6e8fc71b287df489f Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 30 Jan 2024 17:16:03 +0000 Subject: [PATCH 47/65] add plot to estimation workflow --- modules/estimation.nf | 30 ------------------------------ modules/plot.nf | 20 ++++++++++++++++++++ subworkflows/estimation.nf | 35 +++++++++++++++++++++++++++++++++++ workflows/negative_control.nf | 2 +- workflows/targene.nf | 2 +- 5 files changed, 57 insertions(+), 32 deletions(-) create mode 100644 modules/plot.nf create mode 100644 subworkflows/estimation.nf diff --git a/modules/estimation.nf b/modules/estimation.nf index 8bee974f..169c9716 100644 --- a/modules/estimation.nf +++ b/modules/estimation.nf @@ -1,6 +1,3 @@ -#!/usr/bin/env nextflow -nextflow.enable.dsl = 2 - process MergeOutputs { container "olivierlabayle/targeted-estimation:argparse" publishDir "$params.OUTDIR", mode: 'symlink' @@ -61,30 +58,3 @@ process TMLE { """ } -workflow EstimationWorkflow { - take: - dataset - estimands_configs - estimators_config - keep_ic - do_svp - pval_threshold - save_every - hdf5_output - json_output - - main: - TMLE( - dataset, - estimands_configs, - estimators_config, - keep_ic, - do_svp, - pval_threshold, - save_every - ) - MergeOutputs(TMLE.out.collect(), hdf5_output, json_output) - - emit: - hdf5_result = MergeOutputs.out.hdf5_file -} diff --git a/modules/plot.nf b/modules/plot.nf new file mode 100644 index 00000000..954c7c2d --- /dev/null +++ b/modules/plot.nf @@ -0,0 +1,20 @@ +process GenerateSummaryPlots { + container "olivierlabayle/tl-core:cvtmle" + publishDir "${params.OUTDIR}", mode: 'symlink' + label "bigmem" + + input: + path resultsfile + + output: + path "*.png" + + script: + """ + TEMPD=\$(mktemp -d) + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no --sysimage=/TargeneCore.jl/TargeneCoreSysimage.so /TargeneCore.jl/bin/generate_summary_plots.jl \ + ${resultsfile} \ + --verbosity=${params.VERBOSITY} \ + --out-prefix="." + """ +} \ No newline at end of file diff --git a/subworkflows/estimation.nf b/subworkflows/estimation.nf new file mode 100644 index 00000000..afad592c --- /dev/null +++ b/subworkflows/estimation.nf @@ -0,0 +1,35 @@ +include { TMLE; MergeOutputs } from '../modules/estimation.nf' +include { GenerateSummaryPlots } from '../modules/plot.nf' + +workflow EstimationWorkflow { + take: + dataset + estimands_configs + estimators_config + keep_ic + do_svp + pval_threshold + save_every + hdf5_output + json_output + + main: + // Run the estimation process for each estimands configuration + TMLE( + dataset, + estimands_configs, + estimators_config, + keep_ic, + do_svp, + pval_threshold, + save_every + ) + // Merge results files together + MergeOutputs(TMLE.out.collect(), hdf5_output, json_output) + + // Generate Plots + GenerateSummaryPlots(MergeOutputs.out.hdf5_result) + + emit: + hdf5_result = MergeOutputs.out.hdf5_file +} \ No newline at end of file diff --git a/workflows/negative_control.nf b/workflows/negative_control.nf index 12d7074d..3bf2da82 100644 --- a/workflows/negative_control.nf +++ b/workflows/negative_control.nf @@ -1,5 +1,5 @@ include { longest_prefix } from '../modules/utils.nf' -include { EstimationWorkflow } from '../modules/estimation.nf' +include { EstimationWorkflow } from '../subworkflows/estimation.nf' process GeneratePermutationTestsData { container "olivierlabayle/tl-core:cvtmle" diff --git a/workflows/targene.nf b/workflows/targene.nf index b76a29b4..40c790e0 100644 --- a/workflows/targene.nf +++ b/workflows/targene.nf @@ -2,7 +2,7 @@ include { EstimationInputs } from '../modules/estimation_inputs.nf' include { IIDGenotypes } from '../modules/genotypes.nf' include { GeneticConfounders } from '../modules/confounders.nf' include { ExtractTraits } from '../modules/traits.nf' -include { EstimationWorkflow } from '../modules/estimation.nf' +include { EstimationWorkflow } from '../subworkflows/estimation.nf' include { SVPWorkflow } from '../modules/svp.nf' workflow TARGENE { From 3bc083a905d185734c333e7f2b558a84b9d5dff8 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Tue, 30 Jan 2024 17:46:05 +0000 Subject: [PATCH 48/65] fix typo --- subworkflows/estimation.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/estimation.nf b/subworkflows/estimation.nf index afad592c..1aadfabc 100644 --- a/subworkflows/estimation.nf +++ b/subworkflows/estimation.nf @@ -28,7 +28,7 @@ workflow EstimationWorkflow { MergeOutputs(TMLE.out.collect(), hdf5_output, json_output) // Generate Plots - GenerateSummaryPlots(MergeOutputs.out.hdf5_result) + GenerateSummaryPlots(MergeOutputs.out.hdf5_file) emit: hdf5_result = MergeOutputs.out.hdf5_file From 2ca5a9272dc84b606092ffac621b807758cbc112 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Thu, 1 Feb 2024 08:45:07 +0000 Subject: [PATCH 49/65] add test plot edists --- test/ukb_allele_independent.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/ukb_allele_independent.jl b/test/ukb_allele_independent.jl index 89b5cec5..d352e98a 100644 --- a/test/ukb_allele_independent.jl +++ b/test/ukb_allele_independent.jl @@ -37,6 +37,8 @@ args = length(ARGS) > 0 ? ARGS : ["-profile", "local", "-resume"] (Symbol("2:14983:G:A"), Symbol("3:3502414:T:C")), (Symbol("1:238411180:T:C"), Symbol("2:14983:G:A")) ]) + # QQ plot + @test isfile("results/QQ.png") end end \ No newline at end of file From 703f8bd104c52f18469b78ed3ef2e6b333deb199 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Thu, 1 Feb 2024 13:13:13 +0000 Subject: [PATCH 50/65] more refactor --- modules/confounders.nf | 97 ++++++++++++++++++--- modules/estimation_inputs.nf | 65 -------------- modules/{traits.nf => extract_traits.nf} | 31 ------- modules/genotypes.nf | 104 ----------------------- modules/negative_control.nf | 64 ++++++++++++++ modules/svp.nf | 27 ------ subworkflows/confounders.nf | 32 +++++++ subworkflows/estimation_inputs.nf | 66 ++++++++++++++ subworkflows/extract_traits.nf | 32 +++++++ subworkflows/svp.nf | 27 ++++++ workflows/dataset.nf | 5 +- workflows/negative_control.nf | 64 +------------- workflows/pca.nf | 5 +- workflows/targene.nf | 9 +- 14 files changed, 315 insertions(+), 313 deletions(-) rename modules/{traits.nf => extract_traits.nf} (64%) delete mode 100644 modules/genotypes.nf create mode 100644 modules/negative_control.nf create mode 100644 subworkflows/confounders.nf create mode 100644 subworkflows/estimation_inputs.nf create mode 100644 subworkflows/extract_traits.nf create mode 100644 subworkflows/svp.nf diff --git a/modules/confounders.nf b/modules/confounders.nf index 44320830..cc34c519 100644 --- a/modules/confounders.nf +++ b/modules/confounders.nf @@ -1,3 +1,88 @@ +process filterBED{ + label 'bigmem' + container "olivierlabayle/tl-core:cvtmle" + publishDir "$params.OUTDIR/qc_filtered_chromosomes", mode: 'symlink' + + input: + tuple val(chr_id), file(bedfiles) + path qcfile + path ld_blocks + path traits + val maf_threshold + + output: + path "filtered.*", emit: filtered_bedfiles + + script: + prefix = bedfiles[0].toString().minus('.bed') + qc_file = qcfile.getName() != 'NO_QC_FILE' ? "--qcfile $qcfile" : '' + ld_blocks = ld_blocks.getName() != 'NO_LD_BLOCKS' ? "--ld-blocks $ld_blocks" : '' + """ + TEMPD=\$(mktemp -d) + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/prepare_confounders.jl \ + --input $prefix --output filtered.$prefix $qc_file --maf-threshold $maf_threshold \ + $ld_blocks --traits $traits filter + """ +} + + +process thinByLD{ + label 'bigmem' + container "olivierlabayle/plink2:0.1.0" + publishDir "$params.OUTDIR/ld_pruned_chromosomes", mode: 'symlink' + + input: + path flashpca_excl_reg + path bedfiles + + output: + path "LDpruned.*" + + script: + prefix = bedfiles[0].toString().minus('.bed') + """ + plink2 --memory ${task.memory.toMega()} --bfile $prefix --indep-pairwise 1000 50 0.05 --exclude range $flashpca_excl_reg + plink2 --memory ${task.memory.toMega()} --bfile $prefix --extract plink2.prune.in --make-bed --out LDpruned.$prefix + """ +} + + +process mergeBEDS{ + label 'bigmem' + container "olivierlabayle/tl-core:cvtmle" + publishDir "$params.OUTDIR/merged_genotypes", mode: 'symlink' + + input: + path files + + output: + path "ukbb_merged*" + + script: + """ + TEMPD=\$(mktemp -d) + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/prepare_confounders.jl \ + --input LDpruned. \ + --output ukbb_merged merge + """ + +} + +process SampleQCFilter { + label 'bigmem' + container "olivierlabayle/plink2:0.1.0" + publishDir "$params.OUTDIR/iid_genotypes", mode: 'symlink' + + input: + path merged_bed_files + + output: + path "qc_filtered*" + + script: + "plink2 --bfile ukbb_merged --make-bed --hwe 1e-10 --geno --mind --out qc_filtered" +} + process FlashPCA { label "multithreaded" container "ktetleycampbell/flashpca:1.0" @@ -29,16 +114,4 @@ process AdaptFlashPCA { TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/prepare_confounders.jl --input $flashpca_out --output pcs.csv adapt """ -} - -workflow GeneticConfounders { - take: - iid_genotypes - - main: - FlashPCA(iid_genotypes) - AdaptFlashPCA(FlashPCA.out) - - emit: - AdaptFlashPCA.out } \ No newline at end of file diff --git a/modules/estimation_inputs.nf b/modules/estimation_inputs.nf index eba9364e..dd1ed26d 100644 --- a/modules/estimation_inputs.nf +++ b/modules/estimation_inputs.nf @@ -85,69 +85,4 @@ process TMLEInputsFromActors { --call-threshold ${call_threshold} \ --pcs $genetic_confounders \ """ -} - -workflow EstimationInputs { - take: - study_design - bgen_files - traits - genetic_confounders - estimands_file - bqtls_file - transactors_files - extra_confounders - extra_treatments - extra_covariates - batch_size - call_threshold - positivity_constraint - - main: - if (study_design == "FROM_ACTORS") { - tmle_inputs = TMLEInputsFromActors( - bgen_files, - traits, - genetic_confounders, - extra_confounders, - extra_treatments, - extra_covariates, - bqtls_file, - transactors_files, - batch_size, - call_threshold, - positivity_constraint - ) - } - else if (study_design == "CUSTOM"){ - tmle_inputs = TMLEInputsFromParamFile( - bgen_files, - traits, - genetic_confounders, - estimands_file, - batch_size, - call_threshold, - positivity_constraint, - "from-param-file" - ) - } - else if (study_design == "ALLELE_INDEPENDENT"){ - tmle_inputs = TMLEInputsFromParamFile( - bgen_files, - traits, - genetic_confounders, - estimands_file, - batch_size, - call_threshold, - positivity_constraint, - "allele-independent" - ) - } - else { - throw new Exception("This STUDY_DESIGN is not available.") - } - - emit: - aggregated_dataset = tmle_inputs.dataset - estimands = tmle_inputs.estimands } \ No newline at end of file diff --git a/modules/traits.nf b/modules/extract_traits.nf similarity index 64% rename from modules/traits.nf rename to modules/extract_traits.nf index f9fe9539..3ef3125b 100644 --- a/modules/traits.nf +++ b/modules/extract_traits.nf @@ -52,35 +52,4 @@ process TraitsFromUKB { JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/UKBMain.jl --startup-file=no --threads $task.cpus /UKBMain.jl/scripts/process_main_dataset.jl \ $dataset $ukbconfig $withdrawal_list """ -} - -workflow ExtractTraits { - take: - traits_dataset - cohort - ukb_config - ukb_withdrawal_list - ukb_encoding_file - - main: - if (cohort == "UKBB") { - if (ukb_encoding_file != "NO_UKB_ENCODING_FILE") { - UKBFieldsList(ukb_config) - decrypted_dataset = UKBConv( - UKBFieldsList.out, - traits_dataset, - Channel.value(file("${ukb_encoding_file}", checkIfExists: true)) - ) - } - else { - decrypted_dataset = traits_dataset - } - extracted_traits = TraitsFromUKB(decrypted_dataset, ukb_config, ukb_withdrawal_list) - } - else { - extracted_traits = traits_dataset - } - - emit: - extracted_traits } \ No newline at end of file diff --git a/modules/genotypes.nf b/modules/genotypes.nf deleted file mode 100644 index 5aebaac1..00000000 --- a/modules/genotypes.nf +++ /dev/null @@ -1,104 +0,0 @@ -process filterBED{ - label 'bigmem' - container "olivierlabayle/tl-core:cvtmle" - publishDir "$params.OUTDIR/qc_filtered_chromosomes", mode: 'symlink' - - input: - tuple val(chr_id), file(bedfiles) - path qcfile - path ld_blocks - path traits - val maf_threshold - - output: - path "filtered.*", emit: filtered_bedfiles - - script: - prefix = bedfiles[0].toString().minus('.bed') - qc_file = qcfile.getName() != 'NO_QC_FILE' ? "--qcfile $qcfile" : '' - ld_blocks = ld_blocks.getName() != 'NO_LD_BLOCKS' ? "--ld-blocks $ld_blocks" : '' - """ - TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/prepare_confounders.jl \ - --input $prefix --output filtered.$prefix $qc_file --maf-threshold $maf_threshold \ - $ld_blocks --traits $traits filter - """ -} - - -process thinByLD{ - label 'bigmem' - container "olivierlabayle/plink2:0.1.0" - publishDir "$params.OUTDIR/ld_pruned_chromosomes", mode: 'symlink' - - input: - path flashpca_excl_reg - path bedfiles - - output: - path "LDpruned.*" - - script: - prefix = bedfiles[0].toString().minus('.bed') - """ - plink2 --memory ${task.memory.toMega()} --bfile $prefix --indep-pairwise 1000 50 0.05 --exclude range $flashpca_excl_reg - plink2 --memory ${task.memory.toMega()} --bfile $prefix --extract plink2.prune.in --make-bed --out LDpruned.$prefix - """ -} - - -process mergeBEDS{ - label 'bigmem' - container "olivierlabayle/tl-core:cvtmle" - publishDir "$params.OUTDIR/merged_genotypes", mode: 'symlink' - - input: - path files - - output: - path "ukbb_merged*" - - script: - """ - TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/prepare_confounders.jl \ - --input LDpruned. \ - --output ukbb_merged merge - """ - -} - -process SampleQCFilter { - label 'bigmem' - container "olivierlabayle/plink2:0.1.0" - publishDir "$params.OUTDIR/iid_genotypes", mode: 'symlink' - - input: - path merged_bed_files - - output: - path "qc_filtered*" - - script: - "plink2 --bfile ukbb_merged --make-bed --hwe 1e-10 --geno --mind --out qc_filtered" -} - - -workflow IIDGenotypes{ - take: - flashpca_excl_reg - ld_blocks - bed_files - qc_file - traits - maf_threshold - - main: - filtered_bedfiles = filterBED(bed_files, qc_file, ld_blocks, traits, maf_threshold) - ld_pruned = thinByLD(flashpca_excl_reg, filtered_bedfiles) - mergeBEDS(ld_pruned.collect()) - SampleQCFilter(mergeBEDS.out.collect()) - - emit: - SampleQCFilter.out -} \ No newline at end of file diff --git a/modules/negative_control.nf b/modules/negative_control.nf new file mode 100644 index 00000000..688abb0b --- /dev/null +++ b/modules/negative_control.nf @@ -0,0 +1,64 @@ + +include { longest_prefix } from '../modules/utils.nf' + +process GeneratePermutationTestsData { + container "olivierlabayle/tl-core:cvtmle" + publishDir "${params.OUTDIR}/permutation_tests", mode: 'symlink', pattern: '*.arrow' + publishDir "${params.OUTDIR}/permutation_tests/estimands", mode: 'symlink', pattern: '*.jls' + label "bigmem" + + input: + path dataset + path results + + output: + path "permutation_dataset.arrow", emit: dataset + path "*.jls", emit: estimands + + script: + limit = params.MAX_PERMUTATION_TESTS == "" ? "" : "--limit=${params.MAX_PERMUTATION_TESTS}" + """ + TEMPD=\$(mktemp -d) + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no --sysimage=/TargeneCore.jl/TargeneCoreSysimage.so /TargeneCore.jl/bin/generate_tl_inputs.jl \ + --positivity-constraint=${params.POSITIVITY_CONSTRAINT} \ + --verbosity=${params.VERBOSITY} \ + --batch-size=${params.BATCH_SIZE} \ + --out-prefix="." \ + permutation-tests ${dataset} ${results} \ + ${limit} \ + --pval-threshold=${params.PVAL_THRESHOLD} \ + --estimator-key=${params.ESTIMATOR_KEY} \ + --orders=${params.PERMUTATION_ORDERS} \ + --rng=${params.RNG} \ + --max-attempts=${params.MAX_PERMUTATION_ATTEMPTS} \ + """ +} + +process GenerateRandomVariantsTestsData { + container "olivierlabayle/tl-core:cvtmle" + publishDir "${params.OUTDIR}", mode: 'symlink' + label "bigmem" + + input: + path variants_to_randomize + path bgenfiles + path results + + output: + path "random_variants_estimands.jls" + + script: + bgen_prefix = longest_prefix(bgenfiles) + """ + TEMPD=\$(mktemp -d) + JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no --sysimage=/TargeneCore.jl/TargeneCoreSysimage.so /TargeneCore.jl/bin/generate_random_variant_estimands.jl \ + ${variants_to_randomize} ${results} ${bgen_prefix} \ + --out=random_variants_estimands.jls \ + --p=${params.N_RANDOM_VARIANTS} \ + --reltol=${params.MAF_MATCHING_RELTOL} \ + --estimator-key=${params.ESTIMATOR_KEY} \ + --pval-threshold=${params.PVAL_THRESHOLD} \ + --rng=${params.RNG} \ + --verbosity=${params.VERBOSITY} + """ +} \ No newline at end of file diff --git a/modules/svp.nf b/modules/svp.nf index 6ed303dd..d93590da 100644 --- a/modules/svp.nf +++ b/modules/svp.nf @@ -63,30 +63,3 @@ process SVP { --verbosity=$verbosity """ } - - -workflow SVPWorkflow { - take: - hdf5_result - iid_genotypes - n_svp_estimators - max_svp_threshold - svp_estimator_key - grm_n_splits - verbosity - - main: - grm_parts = Channel.from( 1..grm_n_splits ) - GRMPart(iid_genotypes.collect(), grm_n_splits, grm_parts) - AggregateGRM(GRMPart.out.collect()) - // Sieve estimation - SVP( - hdf5_result.collect(), - AggregateGRM.out.grm_ids, - AggregateGRM.out.grm_matrix, - n_svp_estimators, - max_svp_threshold, - svp_estimator_key, - verbosity - ) -} \ No newline at end of file diff --git a/subworkflows/confounders.nf b/subworkflows/confounders.nf new file mode 100644 index 00000000..53da1177 --- /dev/null +++ b/subworkflows/confounders.nf @@ -0,0 +1,32 @@ +include { filterBED; thinByLD; mergeBEDS; SampleQCFilter; FlashPCA; AdaptFlashPCA } from '../modules/confounders.nf' + +workflow IIDGenotypes{ + take: + flashpca_excl_reg + ld_blocks + bed_files + qc_file + traits + maf_threshold + + main: + filtered_bedfiles = filterBED(bed_files, qc_file, ld_blocks, traits, maf_threshold) + ld_pruned = thinByLD(flashpca_excl_reg, filtered_bedfiles) + mergeBEDS(ld_pruned.collect()) + SampleQCFilter(mergeBEDS.out.collect()) + + emit: + SampleQCFilter.out +} + +workflow GeneticConfounders { + take: + iid_genotypes + + main: + FlashPCA(iid_genotypes) + AdaptFlashPCA(FlashPCA.out) + + emit: + AdaptFlashPCA.out +} \ No newline at end of file diff --git a/subworkflows/estimation_inputs.nf b/subworkflows/estimation_inputs.nf new file mode 100644 index 00000000..01baee44 --- /dev/null +++ b/subworkflows/estimation_inputs.nf @@ -0,0 +1,66 @@ +include { TMLEInputsFromActors; TMLEInputsFromParamFile } from '../modules/estimation_inputs.nf' + +workflow EstimationInputs { + take: + study_design + bgen_files + traits + genetic_confounders + estimands_file + bqtls_file + transactors_files + extra_confounders + extra_treatments + extra_covariates + batch_size + call_threshold + positivity_constraint + + main: + if (study_design == "FROM_ACTORS") { + tmle_inputs = TMLEInputsFromActors( + bgen_files, + traits, + genetic_confounders, + extra_confounders, + extra_treatments, + extra_covariates, + bqtls_file, + transactors_files, + batch_size, + call_threshold, + positivity_constraint + ) + } + else if (study_design == "CUSTOM"){ + tmle_inputs = TMLEInputsFromParamFile( + bgen_files, + traits, + genetic_confounders, + estimands_file, + batch_size, + call_threshold, + positivity_constraint, + "from-param-file" + ) + } + else if (study_design == "ALLELE_INDEPENDENT"){ + tmle_inputs = TMLEInputsFromParamFile( + bgen_files, + traits, + genetic_confounders, + estimands_file, + batch_size, + call_threshold, + positivity_constraint, + "allele-independent" + ) + } + else { + throw new Exception("This STUDY_DESIGN is not available.") + } + + emit: + aggregated_dataset = tmle_inputs.dataset + estimands = tmle_inputs.estimands +} \ No newline at end of file diff --git a/subworkflows/extract_traits.nf b/subworkflows/extract_traits.nf new file mode 100644 index 00000000..2ec59ddc --- /dev/null +++ b/subworkflows/extract_traits.nf @@ -0,0 +1,32 @@ +include { UKBConv; TraitsFromUKB; UKBFieldsList } from '../modules/extract_traits.nf' + +workflow ExtractTraits { + take: + traits_dataset + cohort + ukb_config + ukb_withdrawal_list + ukb_encoding_file + + main: + if (cohort == "UKBB") { + if (ukb_encoding_file != "NO_UKB_ENCODING_FILE") { + UKBFieldsList(ukb_config) + decrypted_dataset = UKBConv( + UKBFieldsList.out, + traits_dataset, + Channel.value(file("${ukb_encoding_file}", checkIfExists: true)) + ) + } + else { + decrypted_dataset = traits_dataset + } + extracted_traits = TraitsFromUKB(decrypted_dataset, ukb_config, ukb_withdrawal_list) + } + else { + extracted_traits = traits_dataset + } + + emit: + extracted_traits +} \ No newline at end of file diff --git a/subworkflows/svp.nf b/subworkflows/svp.nf new file mode 100644 index 00000000..ca29f3a6 --- /dev/null +++ b/subworkflows/svp.nf @@ -0,0 +1,27 @@ +include { SVP; AggregateGRM; GRMPart } from '../modules/svp.nf' + +workflow SVPWorkflow { + take: + hdf5_result + iid_genotypes + n_svp_estimators + max_svp_threshold + svp_estimator_key + grm_n_splits + verbosity + + main: + grm_parts = Channel.from( 1..grm_n_splits ) + GRMPart(iid_genotypes.collect(), grm_n_splits, grm_parts) + AggregateGRM(GRMPart.out.collect()) + // Sieve estimation + SVP( + hdf5_result.collect(), + AggregateGRM.out.grm_ids, + AggregateGRM.out.grm_matrix, + n_svp_estimators, + max_svp_threshold, + svp_estimator_key, + verbosity + ) +} \ No newline at end of file diff --git a/workflows/dataset.nf b/workflows/dataset.nf index c582e9f3..5724f39f 100644 --- a/workflows/dataset.nf +++ b/workflows/dataset.nf @@ -1,7 +1,6 @@ include { MakeDataset } from '../modules/dataset.nf' -include { IIDGenotypes } from '../modules/genotypes.nf' -include { GeneticConfounders } from '../modules/confounders.nf' -include { ExtractTraits } from '../modules/traits.nf' +include { IIDGenotypes; GeneticConfounders } from '../subworkflows/confounders.nf' +include { ExtractTraits } from '../subworkflows/extract_traits.nf' workflow MAKE_DATASET { // Traits params diff --git a/workflows/negative_control.nf b/workflows/negative_control.nf index 3bf2da82..607e8840 100644 --- a/workflows/negative_control.nf +++ b/workflows/negative_control.nf @@ -1,67 +1,5 @@ -include { longest_prefix } from '../modules/utils.nf' include { EstimationWorkflow } from '../subworkflows/estimation.nf' - -process GeneratePermutationTestsData { - container "olivierlabayle/tl-core:cvtmle" - publishDir "${params.OUTDIR}/permutation_tests", mode: 'symlink', pattern: '*.arrow' - publishDir "${params.OUTDIR}/permutation_tests/estimands", mode: 'symlink', pattern: '*.jls' - label "bigmem" - - input: - path dataset - path results - - output: - path "permutation_dataset.arrow", emit: dataset - path "*.jls", emit: estimands - - script: - limit = params.MAX_PERMUTATION_TESTS == "" ? "" : "--limit=${params.MAX_PERMUTATION_TESTS}" - """ - TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no --sysimage=/TargeneCore.jl/TargeneCoreSysimage.so /TargeneCore.jl/bin/generate_tl_inputs.jl \ - --positivity-constraint=${params.POSITIVITY_CONSTRAINT} \ - --verbosity=${params.VERBOSITY} \ - --batch-size=${params.BATCH_SIZE} \ - --out-prefix="." \ - permutation-tests ${dataset} ${results} \ - ${limit} \ - --pval-threshold=${params.PVAL_THRESHOLD} \ - --estimator-key=${params.ESTIMATOR_KEY} \ - --orders=${params.PERMUTATION_ORDERS} \ - --rng=${params.RNG} \ - --max-attempts=${params.MAX_PERMUTATION_ATTEMPTS} \ - """ -} - -process GenerateRandomVariantsTestsData { - container "olivierlabayle/tl-core:cvtmle" - publishDir "${params.OUTDIR}", mode: 'symlink' - label "bigmem" - - input: - path variants_to_randomize - path bgenfiles - path results - - output: - path "random_variants_estimands.jls" - - script: - bgen_prefix = longest_prefix(bgenfiles) - """ - TEMPD=\$(mktemp -d) - JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no --sysimage=/TargeneCore.jl/TargeneCoreSysimage.so /TargeneCore.jl/bin/generate_random_variant_estimands.jl \ - ${variants_to_randomize} ${results} ${bgen_prefix} \ - --out=random_variants_estimands.jls \ - --p=${params.N_RANDOM_VARIANTS} \ - --reltol=${params.MAF_MATCHING_RELTOL} \ - --estimator-key=${params.ESTIMATOR_KEY} \ - --pval-threshold=${params.PVAL_THRESHOLD} \ - --rng=${params.RNG} \ - --verbosity=${params.VERBOSITY} - """ -} +include { GeneratePermutationTestsData; GenerateRandomVariantsTestsData} from '../modules/negative_control.nf' workflow PERMUTATION_TEST { // Permutation Tests diff --git a/workflows/pca.nf b/workflows/pca.nf index f4b2a1ff..9e512043 100644 --- a/workflows/pca.nf +++ b/workflows/pca.nf @@ -1,6 +1,5 @@ -include { IIDGenotypes } from '../modules/genotypes.nf' -include { GeneticConfounders } from '../modules/confounders.nf' -include { ExtractTraits } from '../modules/traits.nf' +include { IIDGenotypes; GeneticConfounders } from '../subworkflows/confounders.nf' +include { ExtractTraits } from '../subworkflows/extract_traits.nf' workflow PCA { // Define Parameters diff --git a/workflows/targene.nf b/workflows/targene.nf index 40c790e0..0cf60542 100644 --- a/workflows/targene.nf +++ b/workflows/targene.nf @@ -1,9 +1,8 @@ -include { EstimationInputs } from '../modules/estimation_inputs.nf' -include { IIDGenotypes } from '../modules/genotypes.nf' -include { GeneticConfounders } from '../modules/confounders.nf' -include { ExtractTraits } from '../modules/traits.nf' +include { EstimationInputs } from '../subworkflows/estimation_inputs.nf' +include { IIDGenotypes; GeneticConfounders } from '../subworkflows/confounders.nf' +include { ExtractTraits } from '../subworkflows/extract_traits.nf' include { EstimationWorkflow } from '../subworkflows/estimation.nf' -include { SVPWorkflow } from '../modules/svp.nf' +include { SVPWorkflow } from '../subworkflows/svp.nf' workflow TARGENE { // Define Parameters From bb9cbe2c6f09fe66c2f99037f1a48b8202400771 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Thu, 1 Feb 2024 13:53:08 +0000 Subject: [PATCH 51/65] simplification of workflows --- modules/confounders.nf | 3 +-- modules/estimation.nf | 10 +++------ modules/estimation_inputs.nf | 18 ++++++---------- modules/svp.nf | 12 ++++------- subworkflows/confounders.nf | 3 +-- subworkflows/estimation.nf | 8 -------- subworkflows/estimation_inputs.nf | 19 +++-------------- subworkflows/extract_traits.nf | 3 +-- subworkflows/svp.nf | 13 ++---------- workflows/dataset.nf | 4 ---- workflows/negative_control.nf | 8 -------- workflows/pca.nf | 4 ---- workflows/targene.nf | 34 +------------------------------ 13 files changed, 22 insertions(+), 117 deletions(-) diff --git a/modules/confounders.nf b/modules/confounders.nf index cc34c519..18c62852 100644 --- a/modules/confounders.nf +++ b/modules/confounders.nf @@ -8,7 +8,6 @@ process filterBED{ path qcfile path ld_blocks path traits - val maf_threshold output: path "filtered.*", emit: filtered_bedfiles @@ -20,7 +19,7 @@ process filterBED{ """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no /TargeneCore.jl/bin/prepare_confounders.jl \ - --input $prefix --output filtered.$prefix $qc_file --maf-threshold $maf_threshold \ + --input $prefix --output filtered.$prefix $qc_file --maf-threshold ${params.MAF_THRESHOLD} \ $ld_blocks --traits $traits filter """ } diff --git a/modules/estimation.nf b/modules/estimation.nf index 169c9716..e54c624a 100644 --- a/modules/estimation.nf +++ b/modules/estimation.nf @@ -33,10 +33,6 @@ process TMLE { path data path estimands_file path estimator_file - val keep_ic - val do_svp - val pval_threshold - val save_every output: path "${hdf5out}" @@ -44,8 +40,8 @@ process TMLE { script: basename = "tmle_result." + estimands_file.getName().take(estimands_file.getName().lastIndexOf('.')) hdf5out = basename + ".hdf5" - pval_option = keep_ic == true ? ",${pval_threshold}" : "" - sample_ids = do_svp == true ? ",true" : "" + pval_option = params.KEEP_IC == true ? ",${params.PVAL_THRESHOLD}" : "" + sample_ids = params.SVP == true ? ",true" : "" output_option = "--hdf5-output=${hdf5out}${pval_option}${sample_ids}" """ TEMPD=\$(mktemp -d) @@ -54,7 +50,7 @@ process TMLE { --estimands=$estimands_file \ --estimators=$estimator_file \ $output_option \ - --chunksize=$save_every \ + --chunksize=${params.TMLE_SAVE_EVERY} \ """ } diff --git a/modules/estimation_inputs.nf b/modules/estimation_inputs.nf index dd1ed26d..e3cce0c8 100644 --- a/modules/estimation_inputs.nf +++ b/modules/estimation_inputs.nf @@ -11,9 +11,6 @@ process TMLEInputsFromParamFile { path traits path genetic_confounders path parameter - val batch_size - val call_threshold - val positivity_constraint val command output: @@ -22,18 +19,18 @@ process TMLEInputsFromParamFile { script: bgen_prefix = longest_prefix(bgenfiles) - batchsize = batch_size == 0 ? "" : "--batch-size ${batch_size}" + batch_size = params.BATCH_SIZE == 0 ? "" : "--batch-size ${params.BATCH_SIZE}" """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no --sysimage=/TargeneCore.jl/TargeneCoreSysimage.so /TargeneCore.jl/bin/generate_tl_inputs.jl \ - --positivity-constraint ${positivity_constraint} \ + --positivity-constraint ${params.POSITIVITY_CONSTRAINT} \ $batchsize \ --out-prefix=final \ --verbosity=${params.VERBOSITY} \ $command $parameter \ --traits $traits \ --bgen-prefix $bgen_prefix \ - --call-threshold ${call_threshold} \ + --call-threshold ${params.CALL_THRESHOLD} \ --pcs $genetic_confounders \ """ } @@ -53,9 +50,6 @@ process TMLEInputsFromActors { path extra_covariates path bqtls path trans_actors - val batch_size - val call_threshold - val positivity_constraint output: path "final.data.arrow", emit: dataset @@ -64,14 +58,14 @@ process TMLEInputsFromActors { script: bgen_prefix = longest_prefix(bgenfiles) trans_actors_prefix = longest_prefix(trans_actors) - batch_size = batch_size == 0 ? "" : "--batch-size ${batch_size}" + batch_size = params.BATCH_SIZE == 0 ? "" : "--batch-size ${params.BATCH_SIZE}" extra_confounders = extra_confounders.name != 'NO_EXTRA_CONFOUNDER' ? "--extra-confounders $extra_confounders" : '' extra_treatments = extra_treatments.name != 'NO_EXTRA_TREATMENT' ? "--extra-treatments $extra_treatments" : '' extra_covariates = extra_covariates.name != 'NO_EXTRA_COVARIATE' ? "--extra-covariates $extra_covariates" : '' """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no --sysimage=/TargeneCore.jl/TargeneCoreSysimage.so /TargeneCore.jl/bin/generate_tl_inputs.jl \ - --positivity-constraint ${positivity_constraint} \ + --positivity-constraint ${params.POSITIVITY_CONSTRAINT} \ $batch_size \ --out-prefix=final \ --verbosity=${params.VERBOSITY} \ @@ -82,7 +76,7 @@ process TMLEInputsFromActors { --orders ${params.ORDERS} \ --traits $traits \ --bgen-prefix $bgen_prefix \ - --call-threshold ${call_threshold} \ + --call-threshold ${params.CALL_THRESHOLD} \ --pcs $genetic_confounders \ """ } \ No newline at end of file diff --git a/modules/svp.nf b/modules/svp.nf index d93590da..f2ed0953 100644 --- a/modules/svp.nf +++ b/modules/svp.nf @@ -43,10 +43,6 @@ process SVP { path hdf5_results path GRM_ids path GRM_matrix - val n_estimators - val max_tau - val estimator_key - val verbosity output: path "svp.hdf5" @@ -57,9 +53,9 @@ process SVP { TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --sysimage=/TargetedEstimation.jl/TMLESysimage.so --project=/TargetedEstimation.jl --startup-file=no /TargetedEstimation.jl/tmle.jl svp \ $hdf5_prefix \ - --n-estimators=$n_estimators \ - --max-tau=$max_tau \ - --estimator-key=$estimator_key \ - --verbosity=$verbosity + --n-estimators=${params.NB_SVP_ESTIMATORS} \ + --max-tau=${params.MAX_SVP_THRESHOLD} \ + --estimator-key=${params.ESTIMATOR_KEY} \ + --verbosity=${params.VERBOSITY} """ } diff --git a/subworkflows/confounders.nf b/subworkflows/confounders.nf index 53da1177..109db9b3 100644 --- a/subworkflows/confounders.nf +++ b/subworkflows/confounders.nf @@ -7,10 +7,9 @@ workflow IIDGenotypes{ bed_files qc_file traits - maf_threshold main: - filtered_bedfiles = filterBED(bed_files, qc_file, ld_blocks, traits, maf_threshold) + filtered_bedfiles = filterBED(bed_files, qc_file, ld_blocks, traits) ld_pruned = thinByLD(flashpca_excl_reg, filtered_bedfiles) mergeBEDS(ld_pruned.collect()) SampleQCFilter(mergeBEDS.out.collect()) diff --git a/subworkflows/estimation.nf b/subworkflows/estimation.nf index 1aadfabc..6c2f4494 100644 --- a/subworkflows/estimation.nf +++ b/subworkflows/estimation.nf @@ -6,10 +6,6 @@ workflow EstimationWorkflow { dataset estimands_configs estimators_config - keep_ic - do_svp - pval_threshold - save_every hdf5_output json_output @@ -19,10 +15,6 @@ workflow EstimationWorkflow { dataset, estimands_configs, estimators_config, - keep_ic, - do_svp, - pval_threshold, - save_every ) // Merge results files together MergeOutputs(TMLE.out.collect(), hdf5_output, json_output) diff --git a/subworkflows/estimation_inputs.nf b/subworkflows/estimation_inputs.nf index 01baee44..c4870463 100644 --- a/subworkflows/estimation_inputs.nf +++ b/subworkflows/estimation_inputs.nf @@ -2,7 +2,6 @@ include { TMLEInputsFromActors; TMLEInputsFromParamFile } from '../modules/estim workflow EstimationInputs { take: - study_design bgen_files traits genetic_confounders @@ -12,12 +11,9 @@ workflow EstimationInputs { extra_confounders extra_treatments extra_covariates - batch_size - call_threshold - positivity_constraint main: - if (study_design == "FROM_ACTORS") { + if (params.STUDY_DESIGN == "FROM_ACTORS") { tmle_inputs = TMLEInputsFromActors( bgen_files, traits, @@ -27,32 +23,23 @@ workflow EstimationInputs { extra_covariates, bqtls_file, transactors_files, - batch_size, - call_threshold, - positivity_constraint ) } - else if (study_design == "CUSTOM"){ + else if (params.STUDY_DESIGN == "CUSTOM"){ tmle_inputs = TMLEInputsFromParamFile( bgen_files, traits, genetic_confounders, estimands_file, - batch_size, - call_threshold, - positivity_constraint, "from-param-file" ) } - else if (study_design == "ALLELE_INDEPENDENT"){ + else if (params.STUDY_DESIGN == "ALLELE_INDEPENDENT"){ tmle_inputs = TMLEInputsFromParamFile( bgen_files, traits, genetic_confounders, estimands_file, - batch_size, - call_threshold, - positivity_constraint, "allele-independent" ) } diff --git a/subworkflows/extract_traits.nf b/subworkflows/extract_traits.nf index 2ec59ddc..a425446f 100644 --- a/subworkflows/extract_traits.nf +++ b/subworkflows/extract_traits.nf @@ -3,13 +3,12 @@ include { UKBConv; TraitsFromUKB; UKBFieldsList } from '../modules/extract_trait workflow ExtractTraits { take: traits_dataset - cohort ukb_config ukb_withdrawal_list ukb_encoding_file main: - if (cohort == "UKBB") { + if (params.COHORT == "UKBB") { if (ukb_encoding_file != "NO_UKB_ENCODING_FILE") { UKBFieldsList(ukb_config) decrypted_dataset = UKBConv( diff --git a/subworkflows/svp.nf b/subworkflows/svp.nf index ca29f3a6..9972ac57 100644 --- a/subworkflows/svp.nf +++ b/subworkflows/svp.nf @@ -4,24 +4,15 @@ workflow SVPWorkflow { take: hdf5_result iid_genotypes - n_svp_estimators - max_svp_threshold - svp_estimator_key - grm_n_splits - verbosity main: - grm_parts = Channel.from( 1..grm_n_splits ) - GRMPart(iid_genotypes.collect(), grm_n_splits, grm_parts) + grm_parts = Channel.from( 1..params.GRM_NSPLITS ) + GRMPart(iid_genotypes.collect(), params.GRM_NSPLITS, grm_parts) AggregateGRM(GRMPart.out.collect()) // Sieve estimation SVP( hdf5_result.collect(), AggregateGRM.out.grm_ids, AggregateGRM.out.grm_matrix, - n_svp_estimators, - max_svp_threshold, - svp_estimator_key, - verbosity ) } \ No newline at end of file diff --git a/workflows/dataset.nf b/workflows/dataset.nf index 5724f39f..ad7f3eb8 100644 --- a/workflows/dataset.nf +++ b/workflows/dataset.nf @@ -4,14 +4,12 @@ include { ExtractTraits } from '../subworkflows/extract_traits.nf' workflow MAKE_DATASET { // Traits params - cohort = params.COHORT ukb_encoding_file = params.UKB_ENCODING_FILE ukb_config = Channel.value(file("$params.UKB_CONFIG", checkIfExists: true)) ukb_withdrawal_list = Channel.value(file("$params.UKB_WITHDRAWAL_LIST", checkIfExists: true)) traits_dataset = Channel.value(file("$params.TRAITS_DATASET", checkIfExists: true)) // Confounders params - maf_threshold = params.MAF_THRESHOLD qc_file = Channel.value(file("$params.QC_FILE", checkIfExists: true)) flashpca_excl_reg = Channel.value(file("$params.FLASHPCA_EXCLUSION_REGIONS", checkIfExists: true)) ld_blocks = Channel.value(file("$params.LD_BLOCKS", checkIfExists: true)) @@ -23,7 +21,6 @@ workflow MAKE_DATASET { ExtractTraits( traits_dataset, - cohort, ukb_config, ukb_withdrawal_list, ukb_encoding_file, @@ -36,7 +33,6 @@ workflow MAKE_DATASET { bed_files, qc_file, ExtractTraits.out, - maf_threshold ) // Genetic confounders diff --git a/workflows/negative_control.nf b/workflows/negative_control.nf index 607e8840..8974df2e 100644 --- a/workflows/negative_control.nf +++ b/workflows/negative_control.nf @@ -6,10 +6,6 @@ workflow PERMUTATION_TEST { results_file = Channel.value(file("${params.RESULTS_FILE}")) dataset = Channel.value(file("${params.AGGREGATED_DATASET}")) estimator_config = Channel.value(file("${params.ESTIMATOR_FILE}")) - keep_ic = false - do_svp = false - pval_threshold = params.PVAL_THRESHOLD - save_every = params.TMLE_SAVE_EVERY hdf5_output = params.HDF5_OUTPUT json_output = params.JSON_OUTPUT @@ -21,10 +17,6 @@ workflow PERMUTATION_TEST { GeneratePermutationTestsData.output.dataset, GeneratePermutationTestsData.output.estimands.flatten(), estimator_config, - keep_ic, - do_svp, - pval_threshold, - save_every, hdf5_output, json_output ) diff --git a/workflows/pca.nf b/workflows/pca.nf index 9e512043..6e73e6d8 100644 --- a/workflows/pca.nf +++ b/workflows/pca.nf @@ -3,13 +3,11 @@ include { ExtractTraits } from '../subworkflows/extract_traits.nf' workflow PCA { // Define Parameters - cohort = params.COHORT ukb_encoding_file = params.UKB_ENCODING_FILE ukb_config = Channel.value(file("$params.UKB_CONFIG", checkIfExists: true)) ukb_withdrawal_list = Channel.value(file("$params.UKB_WITHDRAWAL_LIST", checkIfExists: true)) traits_dataset = Channel.value(file("$params.TRAITS_DATASET", checkIfExists: true)) - maf_threshold = params.MAF_THRESHOLD qc_file = Channel.value(file("$params.QC_FILE", checkIfExists: true)) flashpca_excl_reg = Channel.value(file("$params.FLASHPCA_EXCLUSION_REGIONS", checkIfExists: true)) ld_blocks = Channel.value(file("$params.LD_BLOCKS", checkIfExists: true)) @@ -18,7 +16,6 @@ workflow PCA { // Extract Traits ExtractTraits( traits_dataset, - cohort, ukb_config, ukb_withdrawal_list, ukb_encoding_file, @@ -31,7 +28,6 @@ workflow PCA { bed_files, qc_file, ExtractTraits.out, - maf_threshold ) // Genetic confounders diff --git a/workflows/targene.nf b/workflows/targene.nf index 0cf60542..dab288a3 100644 --- a/workflows/targene.nf +++ b/workflows/targene.nf @@ -6,9 +6,6 @@ include { SVPWorkflow } from '../subworkflows/svp.nf' workflow TARGENE { // Define Parameters - verbosity = params.VERBOSITY - - study_design = params.STUDY_DESIGN bgen_files = Channel.fromPath("$params.BGEN_FILES", checkIfExists: true).collect() estimands_file = Channel.value(file("$params.ESTIMANDS_FILE")) bqtls_file = Channel.value(file("$params.BQTLS")) @@ -16,39 +13,24 @@ workflow TARGENE { extra_confounders = Channel.value(file("$params.EXTRA_CONFOUNDERS")) extra_treatments = Channel.value(file("$params.ENVIRONMENTALS")) extra_covariates = Channel.value(file("$params.EXTRA_COVARIATES")) - batch_size = params.BATCH_SIZE - call_threshold = params.CALL_THRESHOLD - positivity_constraint = params.POSITIVITY_CONSTRAINT - cohort = params.COHORT ukb_encoding_file = params.UKB_ENCODING_FILE ukb_config = Channel.value(file("$params.UKB_CONFIG", checkIfExists: true)) ukb_withdrawal_list = Channel.value(file("$params.UKB_WITHDRAWAL_LIST", checkIfExists: true)) traits_dataset = Channel.value(file("$params.TRAITS_DATASET", checkIfExists: true)) - maf_threshold = params.MAF_THRESHOLD qc_file = Channel.value(file("$params.QC_FILE", checkIfExists: true)) flashpca_excl_reg = Channel.value(file("$params.FLASHPCA_EXCLUSION_REGIONS", checkIfExists: true)) ld_blocks = Channel.value(file("$params.LD_BLOCKS", checkIfExists: true)) bed_files = Channel.fromFilePairs("$params.BED_FILES", size: 3, checkIfExists: true){ file -> file.baseName } estimator_config = Channel.value(file("${params.ESTIMATOR_FILE}")) - keep_ic = params.KEEP_IC - pval_threshold = params.PVAL_THRESHOLD - save_every = params.TMLE_SAVE_EVERY hdf5_output = "${params.HDF5_OUTPUT}" json_output = "${params.JSON_OUTPUT}" - do_svp = params.SVP - n_svp_estimators = params.NB_SVP_ESTIMATORS - max_svp_threshold = params.MAX_SVP_THRESHOLD - svp_estimator_key = params.ESTIMATOR_KEY - grm_n_splits = params.GRM_NSPLITS - // Extract Traits ExtractTraits( traits_dataset, - cohort, ukb_config, ukb_withdrawal_list, ukb_encoding_file, @@ -61,7 +43,6 @@ workflow TARGENE { bed_files, qc_file, ExtractTraits.out, - maf_threshold ) // Genetic confounders @@ -69,7 +50,6 @@ workflow TARGENE { // generate main dataset and estimand configuration files EstimationInputs( - study_design, bgen_files, ExtractTraits.out, GeneticConfounders.out, @@ -79,9 +59,6 @@ workflow TARGENE { extra_confounders, extra_treatments, extra_covariates, - batch_size, - call_threshold, - positivity_constraint ) // generate estimates @@ -89,24 +66,15 @@ workflow TARGENE { EstimationInputs.out.aggregated_dataset, EstimationInputs.out.estimands.flatten(), estimator_config, - keep_ic, - do_svp, - pval_threshold, - save_every, hdf5_output, json_output ) // Generate sieve estimates - if (do_svp == true){ + if (params.SVP == true){ sieve_results = SVPWorkflow( EstimationWorkflow.out.hdf5_result, IIDGenotypes.out, - n_svp_estimators, - max_svp_threshold, - svp_estimator_key, - grm_n_splits, - verbosity ) } } \ No newline at end of file From a6a50e88ec77dfa257f4f08537491353bbb5a063 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Thu, 1 Feb 2024 14:12:20 +0000 Subject: [PATCH 52/65] fix typo batch_size --- modules/estimation_inputs.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/estimation_inputs.nf b/modules/estimation_inputs.nf index e3cce0c8..5d263cc8 100644 --- a/modules/estimation_inputs.nf +++ b/modules/estimation_inputs.nf @@ -24,7 +24,7 @@ process TMLEInputsFromParamFile { TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --project=/TargeneCore.jl --startup-file=no --sysimage=/TargeneCore.jl/TargeneCoreSysimage.so /TargeneCore.jl/bin/generate_tl_inputs.jl \ --positivity-constraint ${params.POSITIVITY_CONSTRAINT} \ - $batchsize \ + $batch_size \ --out-prefix=final \ --verbosity=${params.VERBOSITY} \ $command $parameter \ From 44a487fcb4ee837b543160883859e03a1a59cc55 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Thu, 1 Feb 2024 15:27:22 +0000 Subject: [PATCH 53/65] more simplifications --- modules/estimation.nf | 10 ++++------ subworkflows/estimation.nf | 4 +--- workflows/negative_control.nf | 4 ---- workflows/targene.nf | 4 ---- 4 files changed, 5 insertions(+), 17 deletions(-) diff --git a/modules/estimation.nf b/modules/estimation.nf index e54c624a..06f48ada 100644 --- a/modules/estimation.nf +++ b/modules/estimation.nf @@ -5,21 +5,19 @@ process MergeOutputs { input: path tmle_files - val hdf5_output - val json_output output: - path "${hdf5_output}", emit: hdf5_file - path "${json_output}", optional: true, emit: json_file + path "${params.HDF5_OUTPUT}", emit: hdf5_file + path "${params.JSON_OUTPUT}", optional: true, emit: json_file script: - json_option = json_output != "NO_JSON_OUTPUT" ? "--json-output=${json_output}" : "" + json_option = params.JSON_OUTPUT != "NO_JSON_OUTPUT" ? "--json-output=${params.JSON_OUTPUT}" : "" """ TEMPD=\$(mktemp -d) JULIA_DEPOT_PATH=\$TEMPD:/opt julia --sysimage=/TargetedEstimation.jl/TMLESysimage.so --project=/TargetedEstimation.jl --startup-file=no /TargetedEstimation.jl/tmle.jl merge \ tmle_result \ ${json_option} \ - --hdf5-output=${hdf5_output} + --hdf5-output=${params.HDF5_OUTPUT} """ } diff --git a/subworkflows/estimation.nf b/subworkflows/estimation.nf index 6c2f4494..a50a34bb 100644 --- a/subworkflows/estimation.nf +++ b/subworkflows/estimation.nf @@ -6,8 +6,6 @@ workflow EstimationWorkflow { dataset estimands_configs estimators_config - hdf5_output - json_output main: // Run the estimation process for each estimands configuration @@ -17,7 +15,7 @@ workflow EstimationWorkflow { estimators_config, ) // Merge results files together - MergeOutputs(TMLE.out.collect(), hdf5_output, json_output) + MergeOutputs(TMLE.out.collect(), json_output) // Generate Plots GenerateSummaryPlots(MergeOutputs.out.hdf5_file) diff --git a/workflows/negative_control.nf b/workflows/negative_control.nf index 8974df2e..1adf776d 100644 --- a/workflows/negative_control.nf +++ b/workflows/negative_control.nf @@ -6,8 +6,6 @@ workflow PERMUTATION_TEST { results_file = Channel.value(file("${params.RESULTS_FILE}")) dataset = Channel.value(file("${params.AGGREGATED_DATASET}")) estimator_config = Channel.value(file("${params.ESTIMATOR_FILE}")) - hdf5_output = params.HDF5_OUTPUT - json_output = params.JSON_OUTPUT GeneratePermutationTestsData( dataset, @@ -17,8 +15,6 @@ workflow PERMUTATION_TEST { GeneratePermutationTestsData.output.dataset, GeneratePermutationTestsData.output.estimands.flatten(), estimator_config, - hdf5_output, - json_output ) } diff --git a/workflows/targene.nf b/workflows/targene.nf index dab288a3..1bee76ab 100644 --- a/workflows/targene.nf +++ b/workflows/targene.nf @@ -25,8 +25,6 @@ workflow TARGENE { bed_files = Channel.fromFilePairs("$params.BED_FILES", size: 3, checkIfExists: true){ file -> file.baseName } estimator_config = Channel.value(file("${params.ESTIMATOR_FILE}")) - hdf5_output = "${params.HDF5_OUTPUT}" - json_output = "${params.JSON_OUTPUT}" // Extract Traits ExtractTraits( @@ -66,8 +64,6 @@ workflow TARGENE { EstimationInputs.out.aggregated_dataset, EstimationInputs.out.estimands.flatten(), estimator_config, - hdf5_output, - json_output ) // Generate sieve estimates From 4e4784f33417ba99736e64044b134e2f21f03100 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Thu, 1 Feb 2024 15:37:31 +0000 Subject: [PATCH 54/65] fix typoe json output --- subworkflows/estimation.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/estimation.nf b/subworkflows/estimation.nf index a50a34bb..a58dbd91 100644 --- a/subworkflows/estimation.nf +++ b/subworkflows/estimation.nf @@ -15,7 +15,7 @@ workflow EstimationWorkflow { estimators_config, ) // Merge results files together - MergeOutputs(TMLE.out.collect(), json_output) + MergeOutputs(TMLE.out.collect()) // Generate Plots GenerateSummaryPlots(MergeOutputs.out.hdf5_file) From 8222e4029031b1966c1320c633389f8aef3d98d3 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Thu, 1 Feb 2024 17:42:44 +0000 Subject: [PATCH 55/65] start working on docs --- docs/src/index.md | 6 +++--- docs/src/introduction_to_workflows.md | 22 ++++++++++++++++++++++ docs/src/targene/targene.md | 4 ++++ 3 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 docs/src/introduction_to_workflows.md create mode 100644 docs/src/targene/targene.md diff --git a/docs/src/index.md b/docs/src/index.md index 950e6ad7..99e3c9f8 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -21,10 +21,10 @@ The pipeline can roughly be decoupled into three steps. The first, aims at pre-p ## Requirements -The pipeline is tested with: +The pipeline should work with: -- Nextflow: 22.04 -- Singularity: 3.8 +- Nextflow >= 23.10.0 +- Singularity >= 3.8.6 ## Quick start for Eddie users diff --git a/docs/src/introduction_to_workflows.md b/docs/src/introduction_to_workflows.md new file mode 100644 index 00000000..5b996d59 --- /dev/null +++ b/docs/src/introduction_to_workflows.md @@ -0,0 +1,22 @@ +# Workflows + +There are currently 2 main workflows and two secondary workflows within TarGene. Since TarGene uses [Nextflow](https://www.nextflow.io/), all workflows can be run in the same way from the command line: + +```bash +nextflow run https://github.com/TARGENE/targene-pipeline/ -r TAG -entry WORKFLOW_NAME +``` + +where `TAG` is the latest TarGene version, e.g. `v0.9.0` and `WORKFLOW_NAME` is any of the worflows listed below. + +## Main Workflows + +- [The TarGene Workflow](@ref) (`WORKFLOW_NAME: TARGENE`): It is the main workflow for the targeted estimation of genetic effects. +- [The Negative Control Workflows](@ref): These workflow enable the control of the false discovery rate by using the results obtained from a previous TarGene discovery run. There are currently two of them: + - [Permutation Test Workflow](@ref) (`WORKFLOW_NAME: PERMUTATION_TEST`): Performs permutation tests by independently shuffling the individuals in the columns of an aggregated dataset. + - [Randomized Variants Workflow](@ref) (`WORKFLOW_NAME: RANDOMIZATION_TEST`): When there are multiple genetic variants of interest, e.g. in an interaction study, one can replace one of the variant at random by another variant and the effect is expected to be 0 in average. + +## Secondary Workflows + +- [The PCA Workflow](@ref) (`WORKFLOW_NAME: PCA`): This workflow computes principal components. +- [The Make Dataset Workflow](@ref) (`WORKFLOW_NAME: MAKE_DATASET`): This workflow generates an aggregated dataset from traits and genetic data. + diff --git a/docs/src/targene/targene.md b/docs/src/targene/targene.md new file mode 100644 index 00000000..8ac58b87 --- /dev/null +++ b/docs/src/targene/targene.md @@ -0,0 +1,4 @@ +# The TarGene Workflow + +Contrary to a GWAS setting, the main TarGene workflow assumes that a set of genetic variants and/or environmental variables have been pre-identified. + From 835a2a4b4e477eb79c051828d1b94eff254b2a1a Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Fri, 2 Feb 2024 12:28:52 +0100 Subject: [PATCH 56/65] start to work on docs --- docs/make.jl | 33 ++++++----- docs/src/assets/permutation_tests.png | Bin 0 -> 99588 bytes docs/src/introduction_to_workflows.md | 22 ------- docs/src/negative_control.md | 35 ------------ docs/src/negative_control/overview.md | 8 +++ .../src/negative_control/permutation_tests.md | 49 ++++++++++++++++ docs/src/negative_control/randomized_tests.md | 31 ++++++++++ docs/src/nextflow_params.md | 8 +-- docs/src/overview.md | 54 +++++++++++------- docs/src/secondary_workflows/make_dataset.md | 28 +++++++++ docs/src/secondary_workflows/pca.md | 26 +++++++++ .../{ => targene}/confounding_adjustment.md | 0 docs/src/{ => targene}/data_sources.md | 0 docs/src/{ => targene}/miscellaneous.md | 0 docs/src/targene/output.md | 8 +++ .../{ => targene}/runtime_considerations.md | 0 docs/src/{ => targene}/sieve_variance.md | 0 docs/src/{ => targene}/study_designs.md | 0 docs/src/targene/targene.md | 6 ++ docs/src/{ => targene}/tmle.md | 0 main.nf | 2 +- modules/confounders.nf | 2 +- modules/estimation.nf | 2 +- 23 files changed, 217 insertions(+), 97 deletions(-) create mode 100644 docs/src/assets/permutation_tests.png delete mode 100644 docs/src/introduction_to_workflows.md delete mode 100644 docs/src/negative_control.md create mode 100644 docs/src/negative_control/overview.md create mode 100644 docs/src/negative_control/permutation_tests.md create mode 100644 docs/src/negative_control/randomized_tests.md create mode 100644 docs/src/secondary_workflows/make_dataset.md create mode 100644 docs/src/secondary_workflows/pca.md rename docs/src/{ => targene}/confounding_adjustment.md (100%) rename docs/src/{ => targene}/data_sources.md (100%) rename docs/src/{ => targene}/miscellaneous.md (100%) create mode 100644 docs/src/targene/output.md rename docs/src/{ => targene}/runtime_considerations.md (100%) rename docs/src/{ => targene}/sieve_variance.md (100%) rename docs/src/{ => targene}/study_designs.md (100%) rename docs/src/{ => targene}/tmle.md (100%) diff --git a/docs/make.jl b/docs/make.jl index ae67ce92..3d8a8456 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -15,20 +15,27 @@ makedocs(; ), pages=[ "Home" => "index.md", - "User Guide" => [ + "Workflows" => [ "overview.md", - "data_sources.md", - "confounding_adjustment.md", - "study_designs.md", - "tmle.md", - "sieve_variance.md", - "miscellaneous.md", - "negative_control.md" - ], - "Miscellaneous" => [ - "nextflow_params.md", - "runtime_considerations.md" - ], + "TarGene" => [ + joinpath("targene", "targene.md"), + joinpath("targene", "data_sources.md"), + joinpath("targene", "confounding_adjustment.md"), + joinpath("targene", "study_designs.md"), + joinpath("targene", "tmle.md"), + joinpath("targene", "sieve_variance.md"), + joinpath("targene", "miscellaneous.md"), + joinpath("targene", "output.md"), + joinpath("targene", "runtime_considerations.md") + ], + "Negative Control" => [ + joinpath("negative_control", "overview.md"), + joinpath("negative_control", "permutation_tests.md"), + joinpath("negative_control", "randomized_tests.md") + ], + joinpath("secondary_workflows", "pca.md"), + joinpath("secondary_workflows", "make_dataset.md") + ], "Developper Guide" => [ "project_organization.md", "contribution_guide.md" diff --git a/docs/src/assets/permutation_tests.png b/docs/src/assets/permutation_tests.png new file mode 100644 index 0000000000000000000000000000000000000000..162a35e56c21696d0aa867d395a36b95c7040c68 GIT binary patch literal 99588 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
fC)v|8;YnhKcD|)y3VYN{} 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 Date: Fri, 2 Feb 2024 14:40:48 +0100 Subject: [PATCH 57/65] add randomized variant doc --- docs/src/negative_control/randomized_tests.md | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/docs/src/negative_control/randomized_tests.md b/docs/src/negative_control/randomized_tests.md index e6960fa6..04be9ebc 100644 --- a/docs/src/negative_control/randomized_tests.md +++ b/docs/src/negative_control/randomized_tests.md @@ -1,11 +1,9 @@ # The Randomized Variants Workflow -If you are using the `STUDY_DESIGN` = `FROM_ACTORS`, it is likely that you have not chosen the genetic variants at random. Mainly trans-acting variants have been defined because of a likely role in a biological mechanism. If this is the case, replacing a trans-actor by a random variant anywhere on the genome is likely to break the interaction. While unlikely, by chance alone (or lack thereof), one could pick a random trans-actor which is also interacting with any of the bQTLs. In order to account for that it is recommended to instead select a certain number of random variants, denoted by `N_RANDOM_VARIANTS` (default: 10). Furthermore, we enforce two criteria on each of the randomly chosen random variants: +In some interaction studies the variants are chosen based on a priori knowledge, typically they are QTLs. Consider two variants ``V_1`` and ``V_2``, that have been pre-identified to be eQTLs for a given gene's transcript. Then it makes sense to run a phenome-wide association study between these two variants because they potentially interact via the gene's transcript. This can be done via the [TarGene workflow](@ref "The TarGene Workflow") for instance and discoveries can be made. Because these two variants have been carefully chosen, replacing any of them for a random variant whose function is unknown should not result in an interaction. This is the basis of the randomized variants workflow. -- Its minor allele frequency should match that of the original trans-actor up to `MAF_MATCHING_RELTOL` (relative tolerance, default: 0.05). -- It shouldn't lie in a known regulatory region. - -The result of this part of the pipeline is a file named `random_variants_estimands.jls`. To perform the actual tests, you will have to run TarGene again on that using this file with the `STUDY_DESIGN` = `CUSTOM` mode. +!!! note + By chance, one could pick a random variant also interacting with the other QTL. However, on average we should not deviate from the null hypothesis of no association. This can be checked via examination of the QQ plot generated by TarGene. This is addressed by selecting a certain number of random variants (`N_RANDOM_VARIANTS`) instead of 1. ## Example Run Command @@ -13,19 +11,27 @@ The result of this part of the pipeline is a file named `random_variants_estiman nextflow run https://github.com/TARGENE/targene-pipeline/ -r TAG -entry RANDOMIZATION_TEST -profile P -resume ``` -## List Of Workflow Arguments +## Configuration + +### Main Outputs + +The workflow will produce the following output in the output directory (`OUTDIR`, defaults to `results`): an estimand file named "random_variants_estimands.jls". This can be further used by running a classic [TarGene workflow](@ref "The TarGene Workflow") with `STUDY_DESIGN=CUSTOM`. + +### Arguments + +- **`RESULTS_FILE` (required)**: Path to an HDF5 results file generated by a previous TarGene run. +- **`VARIANTS_TO_RANDOMIZE` (required)**: A text file containing the list of variants (one rsid per line) for which random candidates must be proposed. +- **`BGEN_FILES` (required)**: Path to imputed BGEN files from which the variants in `VARIANTS_TO_RANDOMIZE` will be found. + +### Main Options -- **`NB_PCS` (optional, default: 6)**: The number of PCA components to extract. -- **`BED_FILES` (required)**: Path expression to PLINK BED files. -- **`COHORT` (optional: "UKBB")**: Current default for this is UKBB. If set to a value other than UKBB, this will not run UKBB-specific trait extraction. -- **`TRAITS_DATASET` (required)**: Path to a traits dataset. If you are running this for a non-UKBB cohort, your sample IDs must be specified in the first column of this CSV file, with the column name `SAMPLE_ID`. -- **`FLASHPCA_EXCLUSION_REGIONS` (optional, default: data/exclusion_regions_hg19.txt)**: A path to the flashpca special exclusion regions. -- **`MAF_THRESHOLD` (optional, default: 0.01)**: Only variants with that minor allele frequency are considered -- **`LD_BLOCKS` (optional)**: A path to pre-identified linkage disequlibrium blocks to be removed from the BED files. It is good practice to specify `LD_BLOCKS`, as it will remove SNPs correlated with your variants-of-interest before running PCA. +- **`N_RANDOM_VARIANTS` (optional, default: 10)**: The number of random variants to propose for each variant in `VARIANTS_TO_RANDOMIZE`. +- **`MAF_MATCHING_RELTOL` (optional, default: 0.05)**: Each proposed random variant should have the same minor allele frequency as the origin variant, up to a relative threshold. +- **`POSITIVITY_CONSTRAINT` (optional, default: 0.01)**: When the list of estimands is generated or validated. Treatment variables' rarest configuration should have at least that frequency. For example if the treatment variables are two variants with minor allele A and T respectively. The rarest configuration will be (AA, TT) and should have a frequency of at least `POSITIVITY_CONSTRAINT`. +- **`PVAL_THRESHOLD` (optional, default: 0.05)**: Only results with a p-value below this threshold are considered for permutation testing. +- **`ESTIMATOR_KEY` (optional, default: TMLE)**: The p-value for `PVAL_THRESHOLD` is computed using the result from this estimator. -**If the `COHORT` argument is set to `UKBB`**: +### Secondary Options -- **`UKB_CONFIG` (required)**: YAML configuration file describing which traits should be extracted and how the population should be subsetted. -- **`UKB_ENCODING_FILE` (optional)**: If the `TRAITS_DATASET` is encrypted, an encoding file must be provided. -- **`UKB_WITHDRAWAL_LIST` (optional)**: List of participants withdrawn from the study. -- **`QC_FILE` (optional)**: Genotyping quality control file from the UK-Biobank study. +- **`RNG` (optional, default: 123)**: General random seed used to induce permutation. +- **`VERBOSITY` (optional, default: 0)**: Verbosity level of the the Workflow's processes. From c673c0bf522da9c2d71d019043a117a4d155b1a0 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Fri, 2 Feb 2024 15:39:12 +0100 Subject: [PATCH 58/65] update developer guide --- .vscode/ltex.dictionary.en-US.txt | 2 ++ docs/make.jl | 10 +++--- docs/src/assets/make_dataset.png | Bin 0 -> 56821 bytes docs/src/assets/targene_organization.png | Bin 111508 -> 92182 bytes .../assets/targene_workflow_high_level.png | Bin 0 -> 125336 bytes .../contribution_guide.md | 5 ++- .../developper_guide/project_organization.md | 11 ++++++ docs/src/project_organization.md | 16 --------- docs/src/secondary_workflows/make_dataset.md | 2 ++ docs/src/targene/configuration.md | 27 +++++++++++++++ docs/src/targene/output.md | 8 ----- docs/src/targene/overview.md | 32 ++++++++++++++++++ docs/src/targene/targene.md | 10 ------ 13 files changed, 81 insertions(+), 42 deletions(-) create mode 100644 .vscode/ltex.dictionary.en-US.txt create mode 100644 docs/src/assets/make_dataset.png create mode 100644 docs/src/assets/targene_workflow_high_level.png rename docs/src/{ => developper_guide}/contribution_guide.md (85%) create mode 100644 docs/src/developper_guide/project_organization.md delete mode 100644 docs/src/project_organization.md create mode 100644 docs/src/targene/configuration.md delete mode 100644 docs/src/targene/output.md create mode 100644 docs/src/targene/overview.md delete mode 100644 docs/src/targene/targene.md diff --git a/.vscode/ltex.dictionary.en-US.txt b/.vscode/ltex.dictionary.en-US.txt new file mode 100644 index 00000000..6940430d --- /dev/null +++ b/.vscode/ltex.dictionary.en-US.txt @@ -0,0 +1,2 @@ +TarGene +estimands diff --git a/docs/make.jl b/docs/make.jl index 3d8a8456..7b48c77e 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -17,15 +17,15 @@ makedocs(; "Home" => "index.md", "Workflows" => [ "overview.md", - "TarGene" => [ - joinpath("targene", "targene.md"), + "The TarGene Workflow " => [ + joinpath("targene", "overview.md"), joinpath("targene", "data_sources.md"), joinpath("targene", "confounding_adjustment.md"), joinpath("targene", "study_designs.md"), joinpath("targene", "tmle.md"), joinpath("targene", "sieve_variance.md"), joinpath("targene", "miscellaneous.md"), - joinpath("targene", "output.md"), + joinpath("targene", "configuration.md"), joinpath("targene", "runtime_considerations.md") ], "Negative Control" => [ @@ -37,8 +37,8 @@ makedocs(; joinpath("secondary_workflows", "make_dataset.md") ], "Developper Guide" => [ - "project_organization.md", - "contribution_guide.md" + joinpath("developper_guide", "project_organization.md"), + joinpath("developper_guide", "contribution_guide.md") ], "Associated Softwares" => "associated_softwares.md", "Related Publications" => "publications.md" diff --git a/docs/src/assets/make_dataset.png b/docs/src/assets/make_dataset.png new file mode 100644 index 0000000000000000000000000000000000000000..27035f346688ffc4be96962c73b43367487a461f GIT binary patch literal 56821 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

R+nTjFD0-WbA6j0QFBR}(V#TTMNf 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

?FW2^@Wad<`@EUI>gNzBRjFfZpa^%bBSDi~} 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 OpDk_wnz_^M)V}~etwf0c literal 111508 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 diff --git a/docs/src/assets/targene_workflow_high_level.png b/docs/src/assets/targene_workflow_high_level.png new file mode 100644 index 0000000000000000000000000000000000000000..38dd42463e930515cd3646d021bd3dfea5ad58ce GIT binary patch literal 125336 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 ezSA68&!GIi;j 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 -TarGene Organization -
-``` diff --git a/docs/src/secondary_workflows/make_dataset.md b/docs/src/secondary_workflows/make_dataset.md index 193da51f..8b81f2b4 100644 --- a/docs/src/secondary_workflows/make_dataset.md +++ b/docs/src/secondary_workflows/make_dataset.md @@ -2,6 +2,8 @@ This workflow extracts an aggregated dataset containing traits (`TRAITS_DATASET`), genetic confounders (`NB_PCS`) and genetic variants (`VARIANTS_LIST`) in an Arrow tabular format. +![Make Dataset](../assets/make_dataset.png) + ## Example Run Command ```bash diff --git a/docs/src/targene/configuration.md b/docs/src/targene/configuration.md new file mode 100644 index 00000000..aa02a05a --- /dev/null +++ b/docs/src/targene/configuration.md @@ -0,0 +1,27 @@ +# Configuration + +## Main Outputs + +The workflow will produce the following main outputs in the output directory (`OUTDIR`, defaults to `results`): + +- An HDF5 file containing estimation results (`HDF5_OUTPUT`, default: results.hdf5) +- An optional JSON file containing estimation results (`JSON_OUTPUT`) +- A Quantile-Quantile summary plot: QQ.png + +## Arguments + +- **`ESTIMATOR_FILE` (required)**: Estimator name or Julia file containing the description of the Targeted Estimators to use. To be consistent it should match the argument provided to the previous TarGene run. + +## Main Options + +- **`POSITIVITY_CONSTRAINT` (optional, default: 0.01)**: When the list of estimands is generated or validated. Treatment variables' rarest configuration should have at least that frequency. For example if the treatment variables are two variants with minor allele A and T respectively. The rarest configuration will be (AA, TT) and should have a frequency of at least `POSITIVITY_CONSTRAINT`. +- **`PVAL_THRESHOLD` (optional, default: 0.05)**: Only results with a p-value below this threshold are considered for permutation testing. +- **`ESTIMATOR_KEY` (optional, default: TMLE)**: The p-value for `PVAL_THRESHOLD` is computed using the result from this estimator. + +## Secondary Options + +- **`RNG` (optional, default: 123)**: General random seed used to induce permutation. +- **`VERBOSITY` (optional, default: 0)**: Verbosity level of the the Workflow's processes. +- **`BATCH_SIZE` (optional, default: 400)**: The set of estimands to be estimated is batched and the Targeted Learning processes will run in parallel across batches. +- **`TL_SAVE_EVERY` (optional: default: 50)**: During the estimation process, results are appended to the file in chunks to free memory. +- **`KEEP_IC` (optional)**: To save the Influence Curves for each estimate. Depending on the size of your dataset, this can result in massive disk usage. diff --git a/docs/src/targene/output.md b/docs/src/targene/output.md deleted file mode 100644 index 913b6e3c..00000000 --- a/docs/src/targene/output.md +++ /dev/null @@ -1,8 +0,0 @@ -# Outputs - -All outputs are generated in the `$(OUTDIR)` (default: `results`) directory. Here we succintly describe the most important ones: - -- `summary.csv`: is the main output of the pipeline, it contains all summary statistics and information for each estimand of interest. Those are further described [here](https://targene.github.io/TargetedEstimation.jl/stable/tmle_estimation/#Output-file). -- `hdf5files/inf_curves`: contains influence curves in HDF5 format if those were requested (see the `SAVE_IC` Nextflow parameter). -- `tmle_inputs/final.data.csv`: contains the input dataset to all TMLE processes. -- Other sub-directories contain intermediate results that may still be of interest for debugging purposes. diff --git a/docs/src/targene/overview.md b/docs/src/targene/overview.md new file mode 100644 index 00000000..574c32ab --- /dev/null +++ b/docs/src/targene/overview.md @@ -0,0 +1,32 @@ +# The TarGene Workflow + +## Overview + +The main purpose of the TarGene workflow is to estimate a wide variety of genetic effect sizes using the Targeted Learning framework. Contrary to a GWAS setting, this workflow assumes that a set of genetic variants and/or environmental variables have been pre-identified and are provided as an input to the workflow. The workflow can be roughly decomposed into three main steps: + +1. In the first step, all data sources are brought together to build: + + - An aggregated dataset containing all variables in an Arrow tabular format. + - A set of estimands files that contain all the effect sizes to be estimated. + +2. In the second step all effect sizes are estimated via Targeted Learning in a parallel manner across the generated estimands files. Results are then merged into a single file. +3. Finally, an optional Sieve Variance Plateau correction of the variance estimates is performed. + +An overview of the workflow is presented in the following diagram. + +![TarGene Workflow High Level](../assets/targene_workflow_high_level.png) + +## Example Run Command + +```bash +nextflow run https://github.com/TARGENE/targene-pipeline/ -r TAG -entry TARGENE -profile P -resume +``` + +## Content + +- [Setting a data source](@ref) +- [Adjusting for confounders](@ref) +- [Study Designs](@ref) +- [Specifying a Targeted Estimator](@ref) +- [Correcting for population relatedness](@ref) +- [Tweaking additional behaviour](@ref) \ No newline at end of file diff --git a/docs/src/targene/targene.md b/docs/src/targene/targene.md deleted file mode 100644 index c8942b7a..00000000 --- a/docs/src/targene/targene.md +++ /dev/null @@ -1,10 +0,0 @@ -# The TarGene Workflow - -Contrary to a GWAS setting, the main TarGene workflow assumes that a set of genetic variants and/or environmental variables have been pre-identified. - -- [Setting a data source](@ref) -- [Adjusting for confounders](@ref) -- [Study Designs](@ref) -- [Specifying a Targeted Estimator](@ref) -- [Correcting for population relatedness](@ref) -- [Tweaking additional behaviour](@ref) \ No newline at end of file From 96794830498be487b680541de9f42ba127ee4016 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Fri, 2 Feb 2024 18:35:14 +0100 Subject: [PATCH 59/65] more updates --- docs/src/assets/causal_graph.png | Bin 22071 -> 34337 bytes docs/src/targene/data_sources.md | 45 +++++++++++++++++------------- docs/src/targene/overview.md | 9 +----- docs/src/targene/study_designs.md | 44 ++++++++++++----------------- 4 files changed, 45 insertions(+), 53 deletions(-) diff --git a/docs/src/assets/causal_graph.png b/docs/src/assets/causal_graph.png index f36835ec0057235f9e9bfd512df583700f70c21c..37a4658748c2ffc53e62bf3b12b446b94f4aec7a 100644 GIT binary patch literal 34337 zcmeFYg;QML(k={S2o3`TmkjP6+}+(hxQCztf(6&$5Ik6L2p%Lrg1fr~4;mm4oP3Ml zIq!K-eYfiV1(&L+*|Yav)~oyJ?xz=#YAUiAsKlsnaBvv%a#9*_a0pW1qlNqw+&Smr z{{{z#E@CGssU|Ne2~%@*wzhM$f`gNbOwmQs(;UFhF-(jXvxSEghO9#18Q=>;#u4P$ zf@0$#$TYoT(3*m1)GA}C&akQ|dQY*#h-~T4m(tjXR>sWpDZC6H58BVZ{`PbG74Vn; zcP`iND9e+;MTYls$+2Zm;;Dvl`yjVdeRMQa^1^WNgdgFY#MWQCNe`ElyoPi7dH3e+ z8(bgBR%^DI8=JoY+!*AdX=rdbh%St5X_-$>Dd0{RtK_nf;M4~*mB(=9IUL0l(Q!k( zYMvDjxuiTR9y}FES2aRM+rWoQ*5V^|5r8W@iZ9-Eo5~Bb7wvv8kt2p2NK9s)o0U~6 z6rl-g3=^S@D7uN6e(pZ`_fxt+#lU(Ymc_M^<)>$`empBT>$}|TtF_c57NRIKluU&% zK57{O8@;9_ea)^yJ;V(WGkYoO?hI%E^u+Q3T9Aw`FW0vGocqU4?aPrs%
  • Dq@7) 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 -Causal Model - -``` +![Causal Graph](../assets/causal_graph.png) -The following sections describe the available study designs available with TarGene. +Where ``V_1...V_p`` are a set of genetic variants, the ``Y_1...Y_K`` are a set of traits and ``C`` are a set of additional predictors for ``Y`` but not confounding the genetic effects. -## `STUDY_DESIGN` = `CUSTOM` +The following sections describe the available study designs available in TarGene. + +## `CUSTOM` This is the most general setting and should match the needs of any project, however it requires some preliminary work. In this setting, one typically provides a file containing a list of the estimands of interest. If you are interested in only a few estimands, it may be acceptable to write them by hand. Otherwise it is best to generate them using a programming language (for instance using [TMLE.jl](https://targene.github.io/TMLE.jl/stable/)). The path to those estimands is then provided with the `ESTIMANDS_FILE` nextflow parameter. Estimands are specified via a YAML file as follows: @@ -32,9 +30,7 @@ estimands: case: "TC" control: "TT" outcome: ALL - treatment_confounders: - 3:3502414:T:C: [] - 1:238411180:T:C: [] + treatment_confounders: [] - outcome_extra_covariates: [] type: "IATE" treatment_values: @@ -64,15 +60,13 @@ estimands: case: "GG" control: "AG" outcome: ALL - treatment_confounders: - 2:14983:G:A: [] + treatment_confounders: [] - outcome_extra_covariates: [] type: "CM" treatment_values: 2:14983:G:A: "AG" outcome: ALL - treatment_confounders: - 2:14983:G:A: [] + treatment_confounders: [] ``` For each estimand: @@ -83,17 +77,19 @@ For each estimand: - CM: Conditional Mean - `outcome`: The trait of interest. If using the Uk-Biobank datasource it must match the `phenotypes/name` field in the associated `UKB_CONFIG` file. You can also use the wildcard "ALL" to specify that you want to estimate this parameter accross all traits in the dataset. - `treatment_values`: For each treatment variable (genetic-variant / environmental variables), the control/case contrasts. -- `treatment_confounders`: For each treatment variable, a list of confounding variables. If only a single list is provided, then all treatment variables are assumed to share the same confounding variables. Note that principal components will be added to that list automatically and must not be provided here. You can provide an empty list. +- `treatment_confounders`: If each treatment's set of confounding variables is assumed to be the same, it can be a list of these variables. Otherwise, for each treatment variable, a list of confounding variables. Note that principal components will be added to that list automatically and must not be provided here. You can provide an empty list. - `outcome_extra_covariates`: This is optional and correspond to a list of additional covariates for the prediction of the trait. Note that variants must be encoded via an explicit genotype string representation (e.g. "AC"), the order of the alleles in the genotype is not important. -## `STUDY_DESIGN` = `ALLELE_INDEPENDENT` +## `ALLELE_INDEPENDENT` This mode will generate all estimands corresponding to the provided `ESTIMANDS_FILE`. In this case, this file is a plain YAML file as follows: ```yaml -estimands: interactions +orders: [2, 3] +estimands: + - IATE variants: TF1: bQTLs: @@ -117,14 +113,14 @@ extra_confounders: ``` where: - -- `estimands`: The type of generated estimands (only interactions for now) -- `variants`: Two nested levels of variant groups. For each top level group, the cartesian product of variants in each sub group is produced. +- `orders`: If more than 2 treatment variables are provided, interactions can be of order greater than 2. +- `estimands`: The type of generated estimands (only interactions `IATE` for now) +- `variants`: Two nested levels of variant groups. For each top level group, the Cartesian product of variants in each subgroup is produced. - `extra_treatments`: These are added to the treatments combinations. - `outcome_extra_covariates`: Additional covariates predictive of the outcomes - `extra_confounders`: Confounding variables other than Principal Components. -## `STUDY_DESIGN` = `FROM_ACTORS` +## `FROM_ACTORS` In this setting the goal is to infer the interaction effect between multiple variants and potential external factors, interacting together via a specific biological mechanism. Typically, multiple sets of variants are of interest and each set is identified with a specific molecule, contributing to the mechanism. In particular, it is assumed that a set of variants, usually binding quantitative trait loci (bQTLs) play a pivotal role. All interactions of interest are thus defined with respect to that set of genetic variations. Let's Consider the following scenario: we know that a transcription factor binds to molecules `x` and `y` and then differentially binds to specific regions in the genome (`bQTLs`) to regulate downstream genes. We suspect that an alteration of this mechanism is responsible for some diseases. A set of `xQTLs`, associated with the expression of `x` and a set of `yQTLs` associated with the expression of `y` have been identified. Together `xQTLs` and `yQTLs` variants are termed "trans actors". We further suspect that some environmental factors may influence this process. From that scenario, there are many questions that can be asked, for instance : "What is the interaction effects of a bQTL with an environmental factor?". This is a simple pairwise interaction setting and more complex scenarios can be envisaged as described in the following graph. @@ -144,7 +140,3 @@ Let us now turn to the pipeline specification for this parameter plan: - `ORDERS`: A comma separated string that specifies the various interaction orders of interest. All combinations satisfying the positivity constraint will be generated. The order 1 corresponds to the Average Treatment Effect (ATE) for `bQTLs`, any higher order corresponds to the Interaction Average Treatment Effect (IATE) for the various actors. For example, in the previous scenario, assume we provided `ORDERS`=`1,2`. This would generate parameter files for the estimation of all: - ATEs estimands for all bQTLs - IATEs estimands for all (bQTLs, xQTLs), (bQTLs, yQTLs), (bQTLs, Envs) pairs. - -## Parallelization - -Depending on the available resources, you can achieve further speed by batching the estimands. The batch size can be controled via `BATCH_SIZE`(default: 400). From f66c2c5d8baeff78bad344999cd90152283ad0a1 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Mon, 5 Feb 2024 10:43:46 +0100 Subject: [PATCH 60/65] up containers' versions --- docs/src/targene/tmle.md | 24 +++++++++++++++--------- modules/confounders.nf | 6 +++--- modules/dataset.nf | 2 +- modules/estimation.nf | 4 ++-- modules/estimation_inputs.nf | 4 ++-- modules/negative_control.nf | 4 ++-- modules/plot.nf | 2 +- modules/svp.nf | 4 ++-- 8 files changed, 28 insertions(+), 22 deletions(-) diff --git a/docs/src/targene/tmle.md b/docs/src/targene/tmle.md index f88e0510..5b8895bd 100644 --- a/docs/src/targene/tmle.md +++ b/docs/src/targene/tmle.md @@ -2,8 +2,8 @@ TarGene is a flexible procedure that does not impose any constraint on the functional form of the relationship between genetic variants, environmental variables and traits. In practice, we rely on [MLJ](https://alan-turing-institute.github.io/MLJ.jl/dev/) to provide machine learning algorithms. In population genetics studies, there are two learning algorithms we need to specify: -- `E[Y|T, W, C]`: The mean outcome given the treatment, confounders and extra covariates. It is commonly denoted by `Q` in the Targeted Learning litterature. In reality, we will need one specification for continuous outcomes and one specification for binary outcomes. -- `p(T|W)`: The propensity score, which enables the targeting step of the estimation procedure. It is commonly denoted by `G` in the Targeted Learning litterature. +- `E[Y|T, W, C]`: The mean outcome given the treatment, confounders and extra covariates. It is commonly denoted by `Q` in the Targeted Learning literature. In reality, we will need one specification for continuous outcomes and one specification for binary outcomes. +- `p(T|W)`: The propensity score, which enables the targeting step of the estimation procedure. It is commonly denoted by `G` in the Targeted Learning literature. There are two main ways to define targeted estimators, from a predefined configuration or from a custom file. @@ -21,13 +21,13 @@ A set of predefined estimators is readily available and can be accessed by using - superlearning - tuned-xgboost -all using TMLE as the final statistical inference method. While these should cover most use cases, it may be useful to define a custom estimation strategy. This can be achieved by writing a small [Julia](https://julialang.org/) file. +all using TMLE as the meta statistical inference method. While these should cover most use cases, it may be useful to define a custom estimation strategy. This can be achieved by writing a small [Julia](https://julialang.org/) file described below. ## Custom estimators from a file -Writin a [Julia](https://julialang.org/) estimators file is the most flexible way to define an estimation strategy for your study. +Writing a [Julia](https://julialang.org/) estimators file is the most flexible way to define an estimation strategy for your study. -This file should simply define an `ESTIMATORS` [NamedTuple](https://docs.julialang.org/en/v1/base/base/#Core.NamedTuple) variable listing estimators to be used for inference. For example, the following: +This file should simply define a [NamedTuple](https://docs.julialang.org/en/v1/base/base/#Core.NamedTuple) called `ESTIMATORS` and listing estimators to be used for inference. For example, the following: ```julia default_models = TMLE.default_models( @@ -40,16 +40,22 @@ default_models = TMLE.default_models( ) ESTIMATORS = ( - TMLE_weighted = TMLEE(models=default_models, weighted=true), + TMLE_weighted = TMLEE(models=default_models, weighted=true), TMLE_unweighted = TMLEE(models=default_models, weighted=false), - OSE = OSE(models=default_models) + OSE = OSE(models=default_models) ) ``` -defines three estimators: a weighted fluctuation `TMLE` (Targeted Maximum Likelihood Estimator), an unweighted fluctuation `TMLE` and a `OSE` (One Step Estimator). All estimators will learn the nuisance functions `Q` and `G` with the provided defaults: +defines three estimators: + +1. A weighted-fluctuation Targeted Maximum Likelihood Estimator: `TMLE` +2. An unweighted-fluctuation Targeted Maximum Likelihood Estimator: `TMLE` +3. A One-Step Estimator: `OSE` + +All estimators will learn the nuisance functions `Q` and `G` with the provided `models` `NamedTuple`: - `Q_continuous`: A MLJ model used for the estimation of `E[Y|T, W, C]` when the outcome `Y` is continuous. - `Q_binary`: A MLJ model used for the estimation of `E[Y|T, W, C]` when the outcome `Y` is binary. - `G`: A MLJ model used for the estimation of `p(T|W)`. -For full details, visit the [TMLE.jl documentation](https://targene.github.io/TMLE.jl/stable/). +For full details, on available estimators and how to specify them, visit the [TMLE.jl documentation](https://targene.github.io/TMLE.jl/stable/). diff --git a/modules/confounders.nf b/modules/confounders.nf index c62bac33..7f08ac82 100644 --- a/modules/confounders.nf +++ b/modules/confounders.nf @@ -1,6 +1,6 @@ process filterBED{ label 'bigmem' - container "olivierlabayle/tl-core:cvtmle" + container "olivierlabayle/tl-core:0.7" publishDir "$params.OUTDIR/qc_filtered_chromosomes", mode: 'symlink' input: @@ -48,7 +48,7 @@ process thinByLD{ process mergeBEDS{ label 'bigmem' - container "olivierlabayle/tl-core:cvtmle" + container "olivierlabayle/tl-core:0.7" publishDir "$params.OUTDIR/merged_genotypes", mode: 'symlink' input: @@ -98,7 +98,7 @@ process FlashPCA { } process AdaptFlashPCA { - container "olivierlabayle/tl-core:cvtmle" + container "olivierlabayle/tl-core:0.7" publishDir "$params.OUTDIR/covariates/", mode: 'symlink' label 'bigmem' diff --git a/modules/dataset.nf b/modules/dataset.nf index 6d6ae6ff..b1b07dec 100644 --- a/modules/dataset.nf +++ b/modules/dataset.nf @@ -1,7 +1,7 @@ include { longest_prefix } from './utils.nf' process MakeDataset { - container "olivierlabayle/tl-core:cvtmle" + container "olivierlabayle/tl-core:0.7" publishDir "${params.OUTDIR}", mode: 'symlink' label "bigmem" diff --git a/modules/estimation.nf b/modules/estimation.nf index 78db648e..29c9cbac 100644 --- a/modules/estimation.nf +++ b/modules/estimation.nf @@ -1,5 +1,5 @@ process MergeOutputs { - container "olivierlabayle/targeted-estimation:argparse" + container "olivierlabayle/targeted-estimation:0.8" publishDir "$params.OUTDIR", mode: 'symlink' label "bigmem" @@ -22,7 +22,7 @@ process MergeOutputs { } process TMLE { - container "olivierlabayle/targeted-estimation:argparse" + container "olivierlabayle/targeted-estimation:0.8" publishDir "$params.OUTDIR/tmle_outputs/", mode: 'symlink', pattern: "*.hdf5" label "bigmem" label "multithreaded" diff --git a/modules/estimation_inputs.nf b/modules/estimation_inputs.nf index 5d263cc8..01b6a434 100644 --- a/modules/estimation_inputs.nf +++ b/modules/estimation_inputs.nf @@ -1,7 +1,7 @@ include { longest_prefix } from './utils.nf' process TMLEInputsFromParamFile { - container "olivierlabayle/tl-core:cvtmle" + container "olivierlabayle/tl-core:0.7" publishDir "$params.OUTDIR/estimands", mode: 'symlink', pattern: "*.jls" publishDir "$params.OUTDIR", mode: 'symlink', pattern: "*.arrow", saveAs: { filename -> "${params.ARROW_OUTPUT}" } label "bigmem" @@ -36,7 +36,7 @@ process TMLEInputsFromParamFile { } process TMLEInputsFromActors { - container "olivierlabayle/tl-core:cvtmle" + container "olivierlabayle/tl-core:0.7" publishDir "$params.OUTDIR/estimands", mode: 'symlink', pattern: "*.jls" publishDir "$params.OUTDIR", mode: 'symlink', pattern: "*.arrow", saveAs: { filename -> "${params.ARROW_OUTPUT}" } label "bigmem" diff --git a/modules/negative_control.nf b/modules/negative_control.nf index 688abb0b..4b63bdca 100644 --- a/modules/negative_control.nf +++ b/modules/negative_control.nf @@ -2,7 +2,7 @@ include { longest_prefix } from '../modules/utils.nf' process GeneratePermutationTestsData { - container "olivierlabayle/tl-core:cvtmle" + container "olivierlabayle/tl-core:0.7" publishDir "${params.OUTDIR}/permutation_tests", mode: 'symlink', pattern: '*.arrow' publishDir "${params.OUTDIR}/permutation_tests/estimands", mode: 'symlink', pattern: '*.jls' label "bigmem" @@ -35,7 +35,7 @@ process GeneratePermutationTestsData { } process GenerateRandomVariantsTestsData { - container "olivierlabayle/tl-core:cvtmle" + container "olivierlabayle/tl-core:0.7" publishDir "${params.OUTDIR}", mode: 'symlink' label "bigmem" diff --git a/modules/plot.nf b/modules/plot.nf index 954c7c2d..61a7ee7e 100644 --- a/modules/plot.nf +++ b/modules/plot.nf @@ -1,5 +1,5 @@ process GenerateSummaryPlots { - container "olivierlabayle/tl-core:cvtmle" + container "olivierlabayle/tl-core:0.7" publishDir "${params.OUTDIR}", mode: 'symlink' label "bigmem" diff --git a/modules/svp.nf b/modules/svp.nf index f2ed0953..4ae92683 100644 --- a/modules/svp.nf +++ b/modules/svp.nf @@ -1,7 +1,7 @@ include { longest_prefix } from './utils.nf' process GRMPart { - container "olivierlabayle/tl-core:cvtmle" + container "olivierlabayle/tl-core:0.7" label "bigmem" label "multithreaded" @@ -36,7 +36,7 @@ process AggregateGRM { } process SVP { - container "olivierlabayle/targeted-estimation:argparse" + container "olivierlabayle/targeted-estimation:0.8" publishDir "$params.OUTDIR", mode: 'symlink' input: From 0130e663f3738fb4d58e259d3b02ed2ac5c8ed62 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Mon, 5 Feb 2024 11:12:55 +0100 Subject: [PATCH 61/65] add more docs --- docs/src/nextflow_params.md | 2 +- docs/src/targene/configuration.md | 53 +++++++++++++++++++++++++------ docs/src/targene/data_sources.md | 2 +- docs/src/targene/study_designs.md | 1 + docs/src/targene/tmle.md | 2 ++ 5 files changed, 49 insertions(+), 11 deletions(-) diff --git a/docs/src/nextflow_params.md b/docs/src/nextflow_params.md index f8016299..4d2e1574 100644 --- a/docs/src/nextflow_params.md +++ b/docs/src/nextflow_params.md @@ -2,7 +2,7 @@ Here is a list of all the pipeline parameters: -## [Setting a data source](@ref) +## [Setting a Data Source](@ref) - **`COHORT` (required):** Current default for this is UKBB. If set to a value other than UKBB, this will not run UKBB-specific trait extraction. - **`TRAITS_DATASET` (required):** Path to a traits dataset. If you are running this for a non-UKBB cohort, your sample IDs must be specified in the first column of this CSV file, with the column name `SAMPLE_ID`. diff --git a/docs/src/targene/configuration.md b/docs/src/targene/configuration.md index aa02a05a..debdbe25 100644 --- a/docs/src/targene/configuration.md +++ b/docs/src/targene/configuration.md @@ -6,22 +6,57 @@ The workflow will produce the following main outputs in the output directory (`O - An HDF5 file containing estimation results (`HDF5_OUTPUT`, default: results.hdf5) - An optional JSON file containing estimation results (`JSON_OUTPUT`) +- An optional `svp.hdf5` containing Sieve Variance Plateau corrected variance estimates. - A Quantile-Quantile summary plot: QQ.png ## Arguments -- **`ESTIMATOR_FILE` (required)**: Estimator name or Julia file containing the description of the Targeted Estimators to use. To be consistent it should match the argument provided to the previous TarGene run. +- **`ESTIMATOR_FILE`**: Estimator name or Julia file containing the description of the Targeted Estimators to use. To be consistent it should match the argument provided to the previous TarGene run. +- **`BGEN_FILES`**: Path to imputed BGEN files from which the variants in `VARIANTS_LIST` will be extracted. +- **`BED_FILES`**: Path expression to PLINK BED files. +- **`TRAITS_DATASET`**: Path to a traits dataset. If you are running this for a non-UKBB cohort, your sample IDs must be specified in the first column of this CSV file, with the column name `SAMPLE_ID`. ## Main Options -- **`POSITIVITY_CONSTRAINT` (optional, default: 0.01)**: When the list of estimands is generated or validated. Treatment variables' rarest configuration should have at least that frequency. For example if the treatment variables are two variants with minor allele A and T respectively. The rarest configuration will be (AA, TT) and should have a frequency of at least `POSITIVITY_CONSTRAINT`. -- **`PVAL_THRESHOLD` (optional, default: 0.05)**: Only results with a p-value below this threshold are considered for permutation testing. -- **`ESTIMATOR_KEY` (optional, default: TMLE)**: The p-value for `PVAL_THRESHOLD` is computed using the result from this estimator. +- **`STUDY_DESIGN` (default: CUSTOM)**: How genetic variants and effect sizes are specified. See [the study design section](@ref "Study Designs"). +- **`COHORT` (default: "UKBB")**: Current default for this is UKBB. If set to a value other than UKBB, this will not run UKBB-specific trait extraction. +- **`POSITIVITY_CONSTRAINT` (default: 0.01)**: When the list of estimands is generated or validated. Treatment variables' rarest configuration should have at least that frequency. For example if the treatment variables are two variants with minor allele A and T respectively. The rarest configuration will be (AA, TT) and should have a frequency of at least `POSITIVITY_CONSTRAINT`. +- **`NB_PCS` (default: 6)**: The number of PCA components to extract. +- **`SVP` (default: false)**: Whether Sieve Variance Plateau correction should be performed. +- **`FLASHPCA_EXCLUSION_REGIONS` (default: data/exclusion_regions_hg19.txt)**: A path to the flashpca special exclusion regions. +- **`MAF_THRESHOLD` (default: 0.01)**: Only variants with that minor allele frequency are considered +- **`LD_BLOCKS`**: A path to pre-identified linkage disequilibrium blocks to be removed from the BED files. It is good practice to specify `LD_BLOCKS`, as it will remove SNPs correlated with your variants-of-interest before running PCA. +- **`PVAL_THRESHOLD` (default: 0.05)**: Only results with a p-value below this threshold are considered for Sieve Plateau Variance correction. +- **`ESTIMATOR_KEY` (default: TMLE)**: The p-value for `PVAL_THRESHOLD` is computed using the result from this estimator. + +### If `COHORT=UKBB` (default) + +- **`UKB_CONFIG` (default: data/ukbconfig.yaml)**: YAML configuration file describing which traits should be extracted and how the population should be subsetted. +- **`UKB_ENCODING_FILE`**: If the `TRAITS_DATASET` is encrypted, an encoding file must be provided. +- **`UKB_WITHDRAWAL_LIST`**: List of participants withdrawn from the study. +- **`QC_FILE`**: Genotyping quality control file from the UK-Biobank study. + +### If `STUDY_DESIGN=CUSTOM` (default) + +- **`ESTIMANDS_FILE`**: YAML configuration file describing the effect sizes of interest, see the [custom study design section](@ref "`CUSTOM`") + +### If `STUDY_DESIGN=ALLELE_INDEPENDENT` + +- **`ESTIMANDS_FILE`**: YAML configuration file describing the effect sizes of interest, see the [allele independent section](@ref "`ALLELE_INDEPENDENT`"). + +### If `STUDY_DESIGN=FROM_ACTORS` + +- **`BQTLS`**: A CSV file containing binding quantitative trait loci (bQTLs). If multiple transcription factors (TFs) are included in a single run, you must include a column called `TF`, which specifies the TF associated with each bQTL. +- **`TRANS_ACTORS`**: A prefix to CSV files containing quantitative trait loci potentially interacting with the previous bqtls. If multiple transcription factors (TFs) are included in a single run, you must include a column called `TF`, which specifies the TF associated with each transactor. +- **`EXTRA_CONFOUNDERS` (optional, default: nothing)**: Path to additional confounders file, one per line, no header. +- **`EXTRA_COVARIATES` (optional, default: nothing)**: Path to additional covariates file, one per line, no header. +- **`ENVIRONMENTALS` (optional, default: nothing)**: Path to additional environmental treatments file, one per line, no header. +- **`ORDERS` (optional, default: "1,2")**: Comma separated list describing the order of desired interaction estimands, 1 for the ATE (no interaction), 2 for pairwise interactions etc... e.g. "1,2" ## Secondary Options -- **`RNG` (optional, default: 123)**: General random seed used to induce permutation. -- **`VERBOSITY` (optional, default: 0)**: Verbosity level of the the Workflow's processes. -- **`BATCH_SIZE` (optional, default: 400)**: The set of estimands to be estimated is batched and the Targeted Learning processes will run in parallel across batches. -- **`TL_SAVE_EVERY` (optional: default: 50)**: During the estimation process, results are appended to the file in chunks to free memory. -- **`KEEP_IC` (optional)**: To save the Influence Curves for each estimate. Depending on the size of your dataset, this can result in massive disk usage. +- **`RNG` (default: 123)**: General random seed used to induce permutation. +- **`VERBOSITY` (default: 0)**: Verbosity level of the the Workflow's processes. +- **`BATCH_SIZE` (default: 400)**: The set of estimands to be estimated is batched and the Targeted Learning processes will run in parallel across batches. +- **`TL_SAVE_EVERY` (default: 50)**: During the estimation process, results are appended to the file in chunks to free memory. +- **`KEEP_IC` (default: SVP)**: To save the Influence Curves for each estimate. Depending on the size of your dataset, this can result in massive disk usage. diff --git a/docs/src/targene/data_sources.md b/docs/src/targene/data_sources.md index 95c3dfff..74fe65f8 100644 --- a/docs/src/targene/data_sources.md +++ b/docs/src/targene/data_sources.md @@ -1,4 +1,4 @@ -# Setting a data source +# Setting a Data Source The dataset is the main ingredient manipulated by TarGene. Population Genetics datasets are typically split into a variety of files and formats. The following section describes these formats and how to input them to a TarGene run. diff --git a/docs/src/targene/study_designs.md b/docs/src/targene/study_designs.md index 0dbffb3b..7404a8b2 100644 --- a/docs/src/targene/study_designs.md +++ b/docs/src/targene/study_designs.md @@ -113,6 +113,7 @@ extra_confounders: ``` where: + - `orders`: If more than 2 treatment variables are provided, interactions can be of order greater than 2. - `estimands`: The type of generated estimands (only interactions `IATE` for now) - `variants`: Two nested levels of variant groups. For each top level group, the Cartesian product of variants in each subgroup is produced. diff --git a/docs/src/targene/tmle.md b/docs/src/targene/tmle.md index 5b8895bd..deab01c8 100644 --- a/docs/src/targene/tmle.md +++ b/docs/src/targene/tmle.md @@ -58,4 +58,6 @@ All estimators will learn the nuisance functions `Q` and `G` with the provided ` - `Q_binary`: A MLJ model used for the estimation of `E[Y|T, W, C]` when the outcome `Y` is binary. - `G`: A MLJ model used for the estimation of `p(T|W)`. +For the list of available models and resampling strategies, checkout the [TargetedEstimation documentation](https://targene.github.io/TargetedEstimation.jl/stable/models/). + For full details, on available estimators and how to specify them, visit the [TMLE.jl documentation](https://targene.github.io/TMLE.jl/stable/). From 7ed1c7f681bc1ec0ed981c95d0f59b271f30826a Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Mon, 5 Feb 2024 11:25:12 +0100 Subject: [PATCH 62/65] rename datadir to assets dir --- docs/src/nextflow_params.md | 10 +----- docs/src/secondary_workflows/make_dataset.md | 2 +- docs/src/secondary_workflows/pca.md | 2 +- docs/src/targene/configuration.md | 32 ++++++++++++-------- docs/src/targene/confounding_adjustment.md | 2 +- main.nf | 16 +++++----- test/configs/base.config | 6 ++-- test/configs/custom_from_actors.config | 6 ++-- test/configs/dataset.config | 2 +- test/configs/ukb.config | 10 +++--- test/configs/ukb_allele_independent.config | 2 +- test/configs/ukb_custom.config | 2 +- test/configs/ukb_from_actors.config | 6 ++-- test/custom_from_actors.jl | 2 +- test/ukb_from_actors.jl | 2 +- test/utils.jl | 2 +- 16 files changed, 51 insertions(+), 53 deletions(-) diff --git a/docs/src/nextflow_params.md b/docs/src/nextflow_params.md index 4d2e1574..00e533fd 100644 --- a/docs/src/nextflow_params.md +++ b/docs/src/nextflow_params.md @@ -16,7 +16,7 @@ Here is a list of all the pipeline parameters: ## [Adjusting for confounders](@ref) - `LD_BLOCKS` (optional): A path to pre-identified linkage disequlibrium blocks around the variants that will be queried for causal effect estimation. Those will be removed from the data. It is good practice to specify `LD_BLOCKS`, as it will remove SNPs correlated with your variants-of-interest before running PCA. -- `FLASHPCA_EXCLUSION_REGIONS` (optional, default: data/exclusion_regions_hg19.txt): A path to the flashpca special exclusion regions. +- `FLASHPCA_EXCLUSION_REGIONS` (optional, default: assets/exclusion_regions_hg19.txt): A path to the flashpca special exclusion regions. - `MAF_THRESHOLD` (optional, default: 0.01): Only variants with that minor allele frequency are considered - `NB_PCS` (optional, default: 6): The number of PCA components to extract. @@ -47,14 +47,6 @@ If `STUDY_DESIGN`=`FROM_ACTORS`: - `POSITIVITY_CONSTRAINT` (optional, default: 0.01): Treatment variables rarest configuration should have at least that frequency. - `KEEP_IC` (optional, default: false): For all parameters with an p-value below `PVAL_THRESHOLD`, the influence curve is saved. -## [Correcting for population relatedness](@ref) - -- `SVP` (optional, default: false): To perform Sieve Variance Correction. -- `GRM_NSPLITS` (optional, default: 100): To fasten GRM computation, it is typically split in batches. -- `NB_SVP_ESTIMATORS` (optional, default: 100): Number of sieve variance estimates per curve. Setting this value to 0 results in skipping sieve variance correction. -- `MAX_SVP_THRESHOLD` (optional, default: 0.9): Variance estimates are computed for tau ranging from 0 to MAX_SVP_THRESHOLD -- `PVAL_THRESHOLD` (optional, default: 0.05): To save computation time and disk, only parameters with a p-value below this threshold are considered for sieve variance correction. -- `ESTIMATOR_KEY` (optional, default: "TMLE"): The estimator to use for Sieve Variance Plateau correction. ## [Tweaking additional behaviour](@ref) diff --git a/docs/src/secondary_workflows/make_dataset.md b/docs/src/secondary_workflows/make_dataset.md index 8b81f2b4..fa689c05 100644 --- a/docs/src/secondary_workflows/make_dataset.md +++ b/docs/src/secondary_workflows/make_dataset.md @@ -18,7 +18,7 @@ nextflow run https://github.com/TARGENE/targene-pipeline/ -r TAG -entry MAKE_DAT - **`BED_FILES` (required)**: Path expression to PLINK BED files. - **`COHORT` (optional: "UKBB")**: Current default for this is UKBB. If set to a value other than UKBB, this will not run UKBB-specific trait extraction. - **`TRAITS_DATASET` (required)**: Path to a traits dataset. If you are running this for a non-UKBB cohort, your sample IDs must be specified in the first column of this CSV file, with the column name `SAMPLE_ID`. -- **`FLASHPCA_EXCLUSION_REGIONS` (optional, default: data/exclusion_regions_hg19.txt)**: A path to the flashpca special exclusion regions. +- **`FLASHPCA_EXCLUSION_REGIONS` (optional, default: assets/exclusion_regions_hg19.txt)**: A path to the flashpca special exclusion regions. - **`MAF_THRESHOLD` (optional, default: 0.01)**: Only variants with that minor allele frequency are considered - **`LD_BLOCKS` (optional)**: A path to pre-identified linkage disequlibrium blocks to be removed from the BED files. It is good practice to specify `LD_BLOCKS`, as it will remove SNPs correlated with your variants-of-interest before running PCA. diff --git a/docs/src/secondary_workflows/pca.md b/docs/src/secondary_workflows/pca.md index 9f328da6..8dd2eade 100644 --- a/docs/src/secondary_workflows/pca.md +++ b/docs/src/secondary_workflows/pca.md @@ -14,7 +14,7 @@ nextflow run https://github.com/TARGENE/targene-pipeline/ -r TAG -entry PCA -pro - **`BED_FILES` (required)**: Path expression to PLINK BED files. - **`COHORT` (optional: "UKBB")**: Current default for this is UKBB. If set to a value other than UKBB, this will not run UKBB-specific trait extraction. - **`TRAITS_DATASET` (required)**: Path to a traits dataset. If you are running this for a non-UKBB cohort, your sample IDs must be specified in the first column of this CSV file, with the column name `SAMPLE_ID`. -- **`FLASHPCA_EXCLUSION_REGIONS` (optional, default: data/exclusion_regions_hg19.txt)**: A path to the flashpca special exclusion regions. +- **`FLASHPCA_EXCLUSION_REGIONS` (optional, default: assets/exclusion_regions_hg19.txt)**: A path to the flashpca special exclusion regions. - **`MAF_THRESHOLD` (optional, default: 0.01)**: Only variants with that minor allele frequency are considered - **`LD_BLOCKS` (optional)**: A path to pre-identified linkage disequlibrium blocks to be removed from the BED files. It is good practice to specify `LD_BLOCKS`, as it will remove SNPs correlated with your variants-of-interest before running PCA. diff --git a/docs/src/targene/configuration.md b/docs/src/targene/configuration.md index debdbe25..24f4ec7e 100644 --- a/docs/src/targene/configuration.md +++ b/docs/src/targene/configuration.md @@ -23,15 +23,13 @@ The workflow will produce the following main outputs in the output directory (`O - **`POSITIVITY_CONSTRAINT` (default: 0.01)**: When the list of estimands is generated or validated. Treatment variables' rarest configuration should have at least that frequency. For example if the treatment variables are two variants with minor allele A and T respectively. The rarest configuration will be (AA, TT) and should have a frequency of at least `POSITIVITY_CONSTRAINT`. - **`NB_PCS` (default: 6)**: The number of PCA components to extract. - **`SVP` (default: false)**: Whether Sieve Variance Plateau correction should be performed. -- **`FLASHPCA_EXCLUSION_REGIONS` (default: data/exclusion_regions_hg19.txt)**: A path to the flashpca special exclusion regions. +- **`FLASHPCA_EXCLUSION_REGIONS` (default: assets/exclusion_regions_hg19.txt)**: A path to the flashpca special exclusion regions. - **`MAF_THRESHOLD` (default: 0.01)**: Only variants with that minor allele frequency are considered - **`LD_BLOCKS`**: A path to pre-identified linkage disequilibrium blocks to be removed from the BED files. It is good practice to specify `LD_BLOCKS`, as it will remove SNPs correlated with your variants-of-interest before running PCA. -- **`PVAL_THRESHOLD` (default: 0.05)**: Only results with a p-value below this threshold are considered for Sieve Plateau Variance correction. -- **`ESTIMATOR_KEY` (default: TMLE)**: The p-value for `PVAL_THRESHOLD` is computed using the result from this estimator. ### If `COHORT=UKBB` (default) -- **`UKB_CONFIG` (default: data/ukbconfig.yaml)**: YAML configuration file describing which traits should be extracted and how the population should be subsetted. +- **`UKB_CONFIG` (default: assets/ukbconfig.yaml)**: YAML configuration file describing which traits should be extracted and how the population should be subsetted. - **`UKB_ENCODING_FILE`**: If the `TRAITS_DATASET` is encrypted, an encoding file must be provided. - **`UKB_WITHDRAWAL_LIST`**: List of participants withdrawn from the study. - **`QC_FILE`**: Genotyping quality control file from the UK-Biobank study. @@ -48,15 +46,23 @@ The workflow will produce the following main outputs in the output directory (`O - **`BQTLS`**: A CSV file containing binding quantitative trait loci (bQTLs). If multiple transcription factors (TFs) are included in a single run, you must include a column called `TF`, which specifies the TF associated with each bQTL. - **`TRANS_ACTORS`**: A prefix to CSV files containing quantitative trait loci potentially interacting with the previous bqtls. If multiple transcription factors (TFs) are included in a single run, you must include a column called `TF`, which specifies the TF associated with each transactor. -- **`EXTRA_CONFOUNDERS` (optional, default: nothing)**: Path to additional confounders file, one per line, no header. -- **`EXTRA_COVARIATES` (optional, default: nothing)**: Path to additional covariates file, one per line, no header. -- **`ENVIRONMENTALS` (optional, default: nothing)**: Path to additional environmental treatments file, one per line, no header. -- **`ORDERS` (optional, default: "1,2")**: Comma separated list describing the order of desired interaction estimands, 1 for the ATE (no interaction), 2 for pairwise interactions etc... e.g. "1,2" +- **`EXTRA_CONFOUNDERS`, default: nothing**: Path to additional confounders file, one per line, no header. +- **`EXTRA_COVARIATES`, default: nothing**: Path to additional covariates file, one per line, no header. +- **`ENVIRONMENTALS`, default: nothing**: Path to additional environmental treatments file, one per line, no header. +- **`ORDERS`, default: "1,2"**: Comma separated list describing the order of desired interaction estimands, 1 for the ATE (no interaction), 2 for pairwise interactions etc... e.g. "1,2" + +### If `SVP=true` + +- **`GRM_NSPLITS`, default: 100**: To fasten GRM computation, it is typically split in batches. +- **`NB_SVP_ESTIMATORS`, default: 100**: Number of sieve variance estimates per curve. Setting this value to 0 results in skipping sieve variance correction. +- **`MAX_SVP_THRESHOLD`, default: 0.9**: Variance estimates are computed for tau ranging from 0 to MAX_SVP_THRESHOLD +- **`PVAL_THRESHOLD`, default: 0.05**: Only results with a p-value below this threshold are considered for Sieve Plateau Variance correction. +- **`ESTIMATOR_KEY`, default: TMLE**: The p-value for `PVAL_THRESHOLD` is computed using the result from this estimator. ## Secondary Options -- **`RNG` (default: 123)**: General random seed used to induce permutation. -- **`VERBOSITY` (default: 0)**: Verbosity level of the the Workflow's processes. -- **`BATCH_SIZE` (default: 400)**: The set of estimands to be estimated is batched and the Targeted Learning processes will run in parallel across batches. -- **`TL_SAVE_EVERY` (default: 50)**: During the estimation process, results are appended to the file in chunks to free memory. -- **`KEEP_IC` (default: SVP)**: To save the Influence Curves for each estimate. Depending on the size of your dataset, this can result in massive disk usage. +- **`RNG`, default: 123**: General random seed used to induce permutation. +- **`VERBOSITY`, default: 0**: Verbosity level of the the Workflow's processes. +- **`BATCH_SIZE`, default: 400**: The set of estimands to be estimated is batched and the Targeted Learning processes will run in parallel across batches. +- **`TL_SAVE_EVERY`, default: 50**: During the estimation process, results are appended to the file in chunks to free memory. +- **`KEEP_IC`, default: SVP**: To save the Influence Curves for each estimate. Depending on the size of your dataset, this can result in massive disk usage. diff --git a/docs/src/targene/confounding_adjustment.md b/docs/src/targene/confounding_adjustment.md index d0c1c964..5d40e417 100644 --- a/docs/src/targene/confounding_adjustment.md +++ b/docs/src/targene/confounding_adjustment.md @@ -3,6 +3,6 @@ To account for potential confounding effect due to population stratification, we extract principal components from the genetic data using [flashpca](https://github.com/gabraham/flashpca). We follow the recommended procedure for this tool which implies some preprocessing and filtering. The associated arguments are as follows: - `LD_BLOCKS` (optional): A path to pre-identified linkage desequlibrium blocks around the variants that will be queried for causal effect estimation. Those LD blocks will be removed from the data. -- `FLASHPCA_EXCLUSION_REGIONS` (required, default: [data/exclusion_regions_hg19.txt](https://github.com/TARGENE/targene-pipeline/data/exclusion_regions_hg19.txt)): A path to the flashpca special exclusion regions which is provided in [their repository](https://github.com/gabraham/flashpca/blob/master/exclusion_regions_hg19.txt). +- `FLASHPCA_EXCLUSION_REGIONS` (required, default: [assets/exclusion_regions_hg19.txt](https://github.com/TARGENE/targene-pipeline/assets/exclusion_regions_hg19.txt)): A path to the flashpca special exclusion regions which is provided in [their repository](https://github.com/gabraham/flashpca/blob/master/exclusion_regions_hg19.txt). - `MAF_THRESHOLD` (optional, default: 0.01): Only variants with that minor allele frequency are used to compute principal components. - `NB_PCS` (optional, default: 6): The number of PCA components to extract. diff --git a/main.nf b/main.nf index 23178ea8..59dd8ad0 100644 --- a/main.nf +++ b/main.nf @@ -10,15 +10,15 @@ params.CALL_THRESHOLD = 0.9 params.POSITIVITY_CONSTRAINT = 0.01 params.MAF_THRESHOLD = 0.01 params.COHORT = "UKBB" -params.UKB_CONFIG = "${projectDir}/data/ukbconfig.yaml" -params.UKB_WITHDRAWAL_LIST = "${projectDir}/data/NO_WITHDRAWAL_LIST" +params.UKB_CONFIG = "${projectDir}/assets/ukbconfig.yaml" +params.UKB_WITHDRAWAL_LIST = "${projectDir}/assets/NO_WITHDRAWAL_LIST" params.OUTDIR = "${launchDir}/results" // Confounding adjustment by PCA params.NB_PCS = 6 -params.QC_FILE = "${projectDir}/data/NO_QC_FILE" -params.LD_BLOCKS = "${projectDir}/data/NO_LD_BLOCKS" -params.FLASHPCA_EXCLUSION_REGIONS = "${projectDir}/data/exclusion_regions_hg19.txt" +params.QC_FILE = "${projectDir}/assets/NO_QC_FILE" +params.LD_BLOCKS = "${projectDir}/assets/NO_LD_BLOCKS" +params.FLASHPCA_EXCLUSION_REGIONS = "${projectDir}/assets/exclusion_regions_hg19.txt" // Estimands Generation params.BATCH_SIZE = 400 @@ -28,9 +28,9 @@ params.STUDY_DESIGN = "CUSTOM" params.ESTIMANDS_FILE = "NO_ESTIMANDS_FILE" // FROM_ACTORS -params.EXTRA_CONFOUNDERS = "${projectDir}/data/NO_EXTRA_CONFOUNDER" -params.EXTRA_COVARIATES = "${projectDir}/data/NO_EXTRA_COVARIATE" -params.ENVIRONMENTALS = "${projectDir}/data/NO_EXTRA_TREATMENT" +params.EXTRA_CONFOUNDERS = "${projectDir}/assets/NO_EXTRA_CONFOUNDER" +params.EXTRA_COVARIATES = "${projectDir}/assets/NO_EXTRA_COVARIATE" +params.ENVIRONMENTALS = "${projectDir}/assets/NO_EXTRA_TREATMENT" params.ORDERS = "1,2" // SVP Parameters diff --git a/test/configs/base.config b/test/configs/base.config index 220275e8..4af95711 100644 --- a/test/configs/base.config +++ b/test/configs/base.config @@ -1,5 +1,5 @@ params { - BED_FILES = "test/data/unphased_bed/ukb_chr{1,2,3}.{bed,bim,fam}" - BGEN_FILES = "test/data/unphased_bgen/ukb_chr{1,2,3}.{bgen,bgen.bgi,sample}" - ESTIMATOR_FILE = "test/data/estimator.jl" + BED_FILES = "test/assets/unphased_bed/ukb_chr{1,2,3}.{bed,bim,fam}" + BGEN_FILES = "test/assets/unphased_bgen/ukb_chr{1,2,3}.{bgen,bgen.bgi,sample}" + ESTIMATOR_FILE = "test/assets/estimator.jl" } \ No newline at end of file diff --git a/test/configs/custom_from_actors.config b/test/configs/custom_from_actors.config index 1288bcbd..df8ac445 100644 --- a/test/configs/custom_from_actors.config +++ b/test/configs/custom_from_actors.config @@ -2,12 +2,12 @@ includeConfig 'base.config' params { STUDY_DESIGN = "FROM_ACTORS" - TRAITS_DATASET = "test/data/traits.csv" + TRAITS_DATASET = "test/assets/traits.csv" COHORT = "CUSTOM" SVP = true NB_SVP_ESTIMATORS = 10 PVAL_THRESHOLD = 1 - BQTLS = "test/data/actors/bqtls_multiple_TFs.csv" - TRANS_ACTORS = "test/data/actors/eqtls_multiple_TFs.csv" + BQTLS = "test/assets/actors/bqtls_multiple_TFs.csv" + TRANS_ACTORS = "test/assets/actors/eqtls_multiple_TFs.csv" GRM_NSPLITS = 10 } diff --git a/test/configs/dataset.config b/test/configs/dataset.config index c9d7256e..5cb81ba9 100644 --- a/test/configs/dataset.config +++ b/test/configs/dataset.config @@ -1,5 +1,5 @@ includeConfig 'ukb.config' params { - VARIANTS_LIST = "test/data/variants_list.txt" + VARIANTS_LIST = "test/assets/variants_list.txt" } \ No newline at end of file diff --git a/test/configs/ukb.config b/test/configs/ukb.config index 17a218ed..41f6acfd 100644 --- a/test/configs/ukb.config +++ b/test/configs/ukb.config @@ -2,9 +2,9 @@ includeConfig 'base.config' params { COHORT = "UKBB" - TRAITS_DATASET = "test/data/dataset.csv" - QC_FILE = "test/data/qc_file.csv" - LD_BLOCKS = "test/data/ld_blocks.txt" - UKB_WITHDRAWAL_LIST = "test/data/withdrawal_list.txt" - UKB_CONFIG = "test/data/ukbconfig_small.yaml" + TRAITS_DATASET = "test/assets/dataset.csv" + QC_FILE = "test/assets/qc_file.csv" + LD_BLOCKS = "test/assets/ld_blocks.txt" + UKB_WITHDRAWAL_LIST = "test/assets/withdrawal_list.txt" + UKB_CONFIG = "test/assets/ukbconfig_small.yaml" } \ No newline at end of file diff --git a/test/configs/ukb_allele_independent.config b/test/configs/ukb_allele_independent.config index 90f1ee18..6dac0fce 100644 --- a/test/configs/ukb_allele_independent.config +++ b/test/configs/ukb_allele_independent.config @@ -2,5 +2,5 @@ includeConfig 'ukb.config' params { STUDY_DESIGN = "ALLELE_INDEPENDENT" - ESTIMANDS_FILE = "test/data/interactions_allele_independent.yaml" + ESTIMANDS_FILE = "test/assets/interactions_allele_independent.yaml" } diff --git a/test/configs/ukb_custom.config b/test/configs/ukb_custom.config index fac20b0d..b72d15c6 100644 --- a/test/configs/ukb_custom.config +++ b/test/configs/ukb_custom.config @@ -2,6 +2,6 @@ includeConfig 'ukb.config' params { STUDY_DESIGN = "CUSTOM" - ESTIMANDS_FILE = "test/data/parameters/parameters.yaml" + ESTIMANDS_FILE = "test/assets/parameters/parameters.yaml" POSITIVITY_CONSTRAINT = 0.0 } diff --git a/test/configs/ukb_from_actors.config b/test/configs/ukb_from_actors.config index 7ca8c2ef..0cd540d3 100644 --- a/test/configs/ukb_from_actors.config +++ b/test/configs/ukb_from_actors.config @@ -4,10 +4,10 @@ params { STUDY_DESIGN = "FROM_ACTORS" JSON_OUTPUT = "results.json" PVAL_THRESHOLD = 1 - BQTLS = "test/data/actors/bqtls.csv" - TRANS_ACTORS = "test/data/actors/eqtls.csv" + BQTLS = "test/assets/actors/bqtls.csv" + TRANS_ACTORS = "test/assets/actors/eqtls.csv" MAX_PERMUTATION_TESTS = 100 MAF_MATCHING_RELTOL = 0.9 N_RANDOM_VARIANTS = 5 - VARIANTS_TO_RANDOMIZE = "test/data/variants_list.txt" + VARIANTS_TO_RANDOMIZE = "test/assets/variants_list.txt" } diff --git a/test/custom_from_actors.jl b/test/custom_from_actors.jl index 5ca1ec11..23658aa9 100644 --- a/test/custom_from_actors.jl +++ b/test/custom_from_actors.jl @@ -50,7 +50,7 @@ include("utils.jl") @test length(n_chr_files) == 4*3 ##Β Checking parameter files correspond to either bQTL only or bQTL/eQTL - bQTLs = Symbol.(CSV.read(joinpath("test", "data", "actors", "bqtls.csv"), DataFrame).ID) + bQTLs = Symbol.(CSV.read(joinpath("test", "assets", "actors", "bqtls.csv"), DataFrame).ID) estimands_tf1 = deserialize(joinpath("results", "estimands", "final.TF1.estimands_1.jls")) estimands_tf2 = deserialize(joinpath("results", "estimands", "final.TF2.estimands_1.jls")) diff --git a/test/ukb_from_actors.jl b/test/ukb_from_actors.jl index baeb08b4..25798a39 100644 --- a/test/ukb_from_actors.jl +++ b/test/ukb_from_actors.jl @@ -41,7 +41,7 @@ include("utils.jl") check_fails_are_extremely_rare_traits(failed_results.TMLE, dataset; ncases=3) ##Β Checking parameter files correspond to either bQTL only or bQTL/eQTL - bQTLs = Symbol.(CSV.read(joinpath("test", "data", "actors", "bqtls.csv"), DataFrame).ID) + bQTLs = Symbol.(CSV.read(joinpath("test", "assets", "actors", "bqtls.csv"), DataFrame).ID) config_1 = deserialize(joinpath("results", "estimands", "final.estimands_1.jls")) @test length(config_1.estimands) == 400 diff --git a/test/utils.jl b/test/utils.jl index ac64ca63..c8ffb95b 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -58,5 +58,5 @@ function write_custom_configuration() treatment_confounders = [] ) ]) - TMLE.write_yaml(joinpath("test", "data", "parameters", "parameters.yaml"), config) + TMLE.write_yaml(joinpath("test", "assets", "parameters", "parameters.yaml"), config) end \ No newline at end of file From c23ebec5feeac1c1d0ca80e0db2bfe3a5f903da9 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Mon, 5 Feb 2024 11:25:42 +0100 Subject: [PATCH 63/65] rename test data dir to assets dir --- test/{data => assets}/actors/bqtls.csv | 0 test/{data => assets}/actors/bqtls_multiple_TFs.csv | 0 test/{data => assets}/actors/eqtls.csv | 0 test/{data => assets}/actors/eqtls_multiple_TFs.csv | 0 test/{data => assets}/dataset.csv | 0 test/{data => assets}/estimator.jl | 0 test/{data => assets}/exclusion_regions_hg19.txt | 0 .../interactions_allele_independent.yaml | 0 test/{data => assets}/ld_blocks.txt | 0 test/{data => assets}/parameters/parameters.yaml | 0 test/{data => assets}/phased_bed/ukb_chr1.bed | 0 test/{data => assets}/phased_bed/ukb_chr1.bim | 0 test/{data => assets}/phased_bed/ukb_chr1.fam | 0 test/{data => assets}/phased_bed/ukb_chr2.bed | Bin test/{data => assets}/phased_bed/ukb_chr2.bim | 0 test/{data => assets}/phased_bed/ukb_chr2.fam | 0 test/{data => assets}/phased_bed/ukb_chr3.bed | 0 test/{data => assets}/phased_bed/ukb_chr3.bim | 0 test/{data => assets}/phased_bed/ukb_chr3.fam | 0 test/{data => assets}/phased_bgen/ukb_chr1.bgen | Bin test/{data => assets}/phased_bgen/ukb_chr1.bgen.bgi | Bin test/{data => assets}/phased_bgen/ukb_chr1.sample | 0 test/{data => assets}/phased_bgen/ukb_chr2.bgen | Bin test/{data => assets}/phased_bgen/ukb_chr2.bgen.bgi | Bin test/{data => assets}/phased_bgen/ukb_chr2.sample | 0 test/{data => assets}/phased_bgen/ukb_chr3.bgen | Bin test/{data => assets}/phased_bgen/ukb_chr3.bgen.bgi | Bin test/{data => assets}/phased_bgen/ukb_chr3.sample | 0 test/{data => assets}/qc_file.csv | 0 test/{data => assets}/traits.csv | 0 test/{data => assets}/ukbconfig.yaml | 0 test/{data => assets}/ukbconfig_small.yaml | 0 test/{data => assets}/unphased_bed/ukb_chr1.bed | 0 test/{data => assets}/unphased_bed/ukb_chr1.bim | 0 test/{data => assets}/unphased_bed/ukb_chr1.fam | 0 test/{data => assets}/unphased_bed/ukb_chr2.bed | Bin test/{data => assets}/unphased_bed/ukb_chr2.bim | 0 test/{data => assets}/unphased_bed/ukb_chr2.fam | 0 test/{data => assets}/unphased_bed/ukb_chr3.bed | 0 test/{data => assets}/unphased_bed/ukb_chr3.bim | 0 test/{data => assets}/unphased_bed/ukb_chr3.fam | 0 test/{data => assets}/unphased_bgen/ukb_chr1.bgen | Bin .../unphased_bgen/ukb_chr1.bgen.bgi | Bin test/{data => assets}/unphased_bgen/ukb_chr1.sample | 0 test/{data => assets}/unphased_bgen/ukb_chr2.bgen | Bin .../unphased_bgen/ukb_chr2.bgen.bgi | Bin test/{data => assets}/unphased_bgen/ukb_chr2.sample | 0 test/{data => assets}/unphased_bgen/ukb_chr3.bgen | Bin .../unphased_bgen/ukb_chr3.bgen.bgi | Bin test/{data => assets}/unphased_bgen/ukb_chr3.sample | 0 test/{data => assets}/variants_list.txt | 0 test/{data => assets}/withdrawal_list.txt | 0 52 files changed, 0 insertions(+), 0 deletions(-) rename test/{data => assets}/actors/bqtls.csv (100%) rename test/{data => assets}/actors/bqtls_multiple_TFs.csv (100%) rename test/{data => assets}/actors/eqtls.csv (100%) rename test/{data => assets}/actors/eqtls_multiple_TFs.csv (100%) rename test/{data => assets}/dataset.csv (100%) rename test/{data => assets}/estimator.jl (100%) rename test/{data => assets}/exclusion_regions_hg19.txt (100%) rename test/{data => assets}/interactions_allele_independent.yaml (100%) rename test/{data => assets}/ld_blocks.txt (100%) rename test/{data => assets}/parameters/parameters.yaml (100%) rename test/{data => assets}/phased_bed/ukb_chr1.bed (100%) rename test/{data => assets}/phased_bed/ukb_chr1.bim (100%) rename test/{data => assets}/phased_bed/ukb_chr1.fam (100%) rename test/{data => assets}/phased_bed/ukb_chr2.bed (100%) rename test/{data => assets}/phased_bed/ukb_chr2.bim (100%) rename test/{data => assets}/phased_bed/ukb_chr2.fam (100%) rename test/{data => assets}/phased_bed/ukb_chr3.bed (100%) rename test/{data => assets}/phased_bed/ukb_chr3.bim (100%) rename test/{data => assets}/phased_bed/ukb_chr3.fam (100%) rename test/{data => assets}/phased_bgen/ukb_chr1.bgen (100%) rename test/{data => assets}/phased_bgen/ukb_chr1.bgen.bgi (100%) rename test/{data => assets}/phased_bgen/ukb_chr1.sample (100%) rename test/{data => assets}/phased_bgen/ukb_chr2.bgen (100%) rename test/{data => assets}/phased_bgen/ukb_chr2.bgen.bgi (100%) rename test/{data => assets}/phased_bgen/ukb_chr2.sample (100%) rename test/{data => assets}/phased_bgen/ukb_chr3.bgen (100%) rename test/{data => assets}/phased_bgen/ukb_chr3.bgen.bgi (100%) rename test/{data => assets}/phased_bgen/ukb_chr3.sample (100%) rename test/{data => assets}/qc_file.csv (100%) rename test/{data => assets}/traits.csv (100%) rename test/{data => assets}/ukbconfig.yaml (100%) rename test/{data => assets}/ukbconfig_small.yaml (100%) rename test/{data => assets}/unphased_bed/ukb_chr1.bed (100%) rename test/{data => assets}/unphased_bed/ukb_chr1.bim (100%) rename test/{data => assets}/unphased_bed/ukb_chr1.fam (100%) rename test/{data => assets}/unphased_bed/ukb_chr2.bed (100%) rename test/{data => assets}/unphased_bed/ukb_chr2.bim (100%) rename test/{data => assets}/unphased_bed/ukb_chr2.fam (100%) rename test/{data => assets}/unphased_bed/ukb_chr3.bed (100%) rename test/{data => assets}/unphased_bed/ukb_chr3.bim (100%) rename test/{data => assets}/unphased_bed/ukb_chr3.fam (100%) rename test/{data => assets}/unphased_bgen/ukb_chr1.bgen (100%) rename test/{data => assets}/unphased_bgen/ukb_chr1.bgen.bgi (100%) rename test/{data => assets}/unphased_bgen/ukb_chr1.sample (100%) rename test/{data => assets}/unphased_bgen/ukb_chr2.bgen (100%) rename test/{data => assets}/unphased_bgen/ukb_chr2.bgen.bgi (100%) rename test/{data => assets}/unphased_bgen/ukb_chr2.sample (100%) rename test/{data => assets}/unphased_bgen/ukb_chr3.bgen (100%) rename test/{data => assets}/unphased_bgen/ukb_chr3.bgen.bgi (100%) rename test/{data => assets}/unphased_bgen/ukb_chr3.sample (100%) rename test/{data => assets}/variants_list.txt (100%) rename test/{data => assets}/withdrawal_list.txt (100%) diff --git a/test/data/actors/bqtls.csv b/test/assets/actors/bqtls.csv similarity index 100% rename from test/data/actors/bqtls.csv rename to test/assets/actors/bqtls.csv diff --git a/test/data/actors/bqtls_multiple_TFs.csv b/test/assets/actors/bqtls_multiple_TFs.csv similarity index 100% rename from test/data/actors/bqtls_multiple_TFs.csv rename to test/assets/actors/bqtls_multiple_TFs.csv diff --git a/test/data/actors/eqtls.csv b/test/assets/actors/eqtls.csv similarity index 100% rename from test/data/actors/eqtls.csv rename to test/assets/actors/eqtls.csv diff --git a/test/data/actors/eqtls_multiple_TFs.csv b/test/assets/actors/eqtls_multiple_TFs.csv similarity index 100% rename from test/data/actors/eqtls_multiple_TFs.csv rename to test/assets/actors/eqtls_multiple_TFs.csv diff --git a/test/data/dataset.csv b/test/assets/dataset.csv similarity index 100% rename from test/data/dataset.csv rename to test/assets/dataset.csv diff --git a/test/data/estimator.jl b/test/assets/estimator.jl similarity index 100% rename from test/data/estimator.jl rename to test/assets/estimator.jl diff --git a/test/data/exclusion_regions_hg19.txt b/test/assets/exclusion_regions_hg19.txt similarity index 100% rename from test/data/exclusion_regions_hg19.txt rename to test/assets/exclusion_regions_hg19.txt diff --git a/test/data/interactions_allele_independent.yaml b/test/assets/interactions_allele_independent.yaml similarity index 100% rename from test/data/interactions_allele_independent.yaml rename to test/assets/interactions_allele_independent.yaml diff --git a/test/data/ld_blocks.txt b/test/assets/ld_blocks.txt similarity index 100% rename from test/data/ld_blocks.txt rename to test/assets/ld_blocks.txt diff --git a/test/data/parameters/parameters.yaml b/test/assets/parameters/parameters.yaml similarity index 100% rename from test/data/parameters/parameters.yaml rename to test/assets/parameters/parameters.yaml diff --git a/test/data/phased_bed/ukb_chr1.bed b/test/assets/phased_bed/ukb_chr1.bed similarity index 100% rename from test/data/phased_bed/ukb_chr1.bed rename to test/assets/phased_bed/ukb_chr1.bed diff --git a/test/data/phased_bed/ukb_chr1.bim b/test/assets/phased_bed/ukb_chr1.bim similarity index 100% rename from test/data/phased_bed/ukb_chr1.bim rename to test/assets/phased_bed/ukb_chr1.bim diff --git a/test/data/phased_bed/ukb_chr1.fam b/test/assets/phased_bed/ukb_chr1.fam similarity index 100% rename from test/data/phased_bed/ukb_chr1.fam rename to test/assets/phased_bed/ukb_chr1.fam diff --git a/test/data/phased_bed/ukb_chr2.bed b/test/assets/phased_bed/ukb_chr2.bed similarity index 100% rename from test/data/phased_bed/ukb_chr2.bed rename to test/assets/phased_bed/ukb_chr2.bed diff --git a/test/data/phased_bed/ukb_chr2.bim b/test/assets/phased_bed/ukb_chr2.bim similarity index 100% rename from test/data/phased_bed/ukb_chr2.bim rename to test/assets/phased_bed/ukb_chr2.bim diff --git a/test/data/phased_bed/ukb_chr2.fam b/test/assets/phased_bed/ukb_chr2.fam similarity index 100% rename from test/data/phased_bed/ukb_chr2.fam rename to test/assets/phased_bed/ukb_chr2.fam diff --git a/test/data/phased_bed/ukb_chr3.bed b/test/assets/phased_bed/ukb_chr3.bed similarity index 100% rename from test/data/phased_bed/ukb_chr3.bed rename to test/assets/phased_bed/ukb_chr3.bed diff --git a/test/data/phased_bed/ukb_chr3.bim b/test/assets/phased_bed/ukb_chr3.bim similarity index 100% rename from test/data/phased_bed/ukb_chr3.bim rename to test/assets/phased_bed/ukb_chr3.bim diff --git a/test/data/phased_bed/ukb_chr3.fam b/test/assets/phased_bed/ukb_chr3.fam similarity index 100% rename from test/data/phased_bed/ukb_chr3.fam rename to test/assets/phased_bed/ukb_chr3.fam diff --git a/test/data/phased_bgen/ukb_chr1.bgen b/test/assets/phased_bgen/ukb_chr1.bgen similarity index 100% rename from test/data/phased_bgen/ukb_chr1.bgen rename to test/assets/phased_bgen/ukb_chr1.bgen diff --git a/test/data/phased_bgen/ukb_chr1.bgen.bgi b/test/assets/phased_bgen/ukb_chr1.bgen.bgi similarity index 100% rename from test/data/phased_bgen/ukb_chr1.bgen.bgi rename to test/assets/phased_bgen/ukb_chr1.bgen.bgi diff --git a/test/data/phased_bgen/ukb_chr1.sample b/test/assets/phased_bgen/ukb_chr1.sample similarity index 100% rename from test/data/phased_bgen/ukb_chr1.sample rename to test/assets/phased_bgen/ukb_chr1.sample diff --git a/test/data/phased_bgen/ukb_chr2.bgen b/test/assets/phased_bgen/ukb_chr2.bgen similarity index 100% rename from test/data/phased_bgen/ukb_chr2.bgen rename to test/assets/phased_bgen/ukb_chr2.bgen diff --git a/test/data/phased_bgen/ukb_chr2.bgen.bgi b/test/assets/phased_bgen/ukb_chr2.bgen.bgi similarity index 100% rename from test/data/phased_bgen/ukb_chr2.bgen.bgi rename to test/assets/phased_bgen/ukb_chr2.bgen.bgi diff --git a/test/data/phased_bgen/ukb_chr2.sample b/test/assets/phased_bgen/ukb_chr2.sample similarity index 100% rename from test/data/phased_bgen/ukb_chr2.sample rename to test/assets/phased_bgen/ukb_chr2.sample diff --git a/test/data/phased_bgen/ukb_chr3.bgen b/test/assets/phased_bgen/ukb_chr3.bgen similarity index 100% rename from test/data/phased_bgen/ukb_chr3.bgen rename to test/assets/phased_bgen/ukb_chr3.bgen diff --git a/test/data/phased_bgen/ukb_chr3.bgen.bgi b/test/assets/phased_bgen/ukb_chr3.bgen.bgi similarity index 100% rename from test/data/phased_bgen/ukb_chr3.bgen.bgi rename to test/assets/phased_bgen/ukb_chr3.bgen.bgi diff --git a/test/data/phased_bgen/ukb_chr3.sample b/test/assets/phased_bgen/ukb_chr3.sample similarity index 100% rename from test/data/phased_bgen/ukb_chr3.sample rename to test/assets/phased_bgen/ukb_chr3.sample diff --git a/test/data/qc_file.csv b/test/assets/qc_file.csv similarity index 100% rename from test/data/qc_file.csv rename to test/assets/qc_file.csv diff --git a/test/data/traits.csv b/test/assets/traits.csv similarity index 100% rename from test/data/traits.csv rename to test/assets/traits.csv diff --git a/test/data/ukbconfig.yaml b/test/assets/ukbconfig.yaml similarity index 100% rename from test/data/ukbconfig.yaml rename to test/assets/ukbconfig.yaml diff --git a/test/data/ukbconfig_small.yaml b/test/assets/ukbconfig_small.yaml similarity index 100% rename from test/data/ukbconfig_small.yaml rename to test/assets/ukbconfig_small.yaml diff --git a/test/data/unphased_bed/ukb_chr1.bed b/test/assets/unphased_bed/ukb_chr1.bed similarity index 100% rename from test/data/unphased_bed/ukb_chr1.bed rename to test/assets/unphased_bed/ukb_chr1.bed diff --git a/test/data/unphased_bed/ukb_chr1.bim b/test/assets/unphased_bed/ukb_chr1.bim similarity index 100% rename from test/data/unphased_bed/ukb_chr1.bim rename to test/assets/unphased_bed/ukb_chr1.bim diff --git a/test/data/unphased_bed/ukb_chr1.fam b/test/assets/unphased_bed/ukb_chr1.fam similarity index 100% rename from test/data/unphased_bed/ukb_chr1.fam rename to test/assets/unphased_bed/ukb_chr1.fam diff --git a/test/data/unphased_bed/ukb_chr2.bed b/test/assets/unphased_bed/ukb_chr2.bed similarity index 100% rename from test/data/unphased_bed/ukb_chr2.bed rename to test/assets/unphased_bed/ukb_chr2.bed diff --git a/test/data/unphased_bed/ukb_chr2.bim b/test/assets/unphased_bed/ukb_chr2.bim similarity index 100% rename from test/data/unphased_bed/ukb_chr2.bim rename to test/assets/unphased_bed/ukb_chr2.bim diff --git a/test/data/unphased_bed/ukb_chr2.fam b/test/assets/unphased_bed/ukb_chr2.fam similarity index 100% rename from test/data/unphased_bed/ukb_chr2.fam rename to test/assets/unphased_bed/ukb_chr2.fam diff --git a/test/data/unphased_bed/ukb_chr3.bed b/test/assets/unphased_bed/ukb_chr3.bed similarity index 100% rename from test/data/unphased_bed/ukb_chr3.bed rename to test/assets/unphased_bed/ukb_chr3.bed diff --git a/test/data/unphased_bed/ukb_chr3.bim b/test/assets/unphased_bed/ukb_chr3.bim similarity index 100% rename from test/data/unphased_bed/ukb_chr3.bim rename to test/assets/unphased_bed/ukb_chr3.bim diff --git a/test/data/unphased_bed/ukb_chr3.fam b/test/assets/unphased_bed/ukb_chr3.fam similarity index 100% rename from test/data/unphased_bed/ukb_chr3.fam rename to test/assets/unphased_bed/ukb_chr3.fam diff --git a/test/data/unphased_bgen/ukb_chr1.bgen b/test/assets/unphased_bgen/ukb_chr1.bgen similarity index 100% rename from test/data/unphased_bgen/ukb_chr1.bgen rename to test/assets/unphased_bgen/ukb_chr1.bgen diff --git a/test/data/unphased_bgen/ukb_chr1.bgen.bgi b/test/assets/unphased_bgen/ukb_chr1.bgen.bgi similarity index 100% rename from test/data/unphased_bgen/ukb_chr1.bgen.bgi rename to test/assets/unphased_bgen/ukb_chr1.bgen.bgi diff --git a/test/data/unphased_bgen/ukb_chr1.sample b/test/assets/unphased_bgen/ukb_chr1.sample similarity index 100% rename from test/data/unphased_bgen/ukb_chr1.sample rename to test/assets/unphased_bgen/ukb_chr1.sample diff --git a/test/data/unphased_bgen/ukb_chr2.bgen b/test/assets/unphased_bgen/ukb_chr2.bgen similarity index 100% rename from test/data/unphased_bgen/ukb_chr2.bgen rename to test/assets/unphased_bgen/ukb_chr2.bgen diff --git a/test/data/unphased_bgen/ukb_chr2.bgen.bgi b/test/assets/unphased_bgen/ukb_chr2.bgen.bgi similarity index 100% rename from test/data/unphased_bgen/ukb_chr2.bgen.bgi rename to test/assets/unphased_bgen/ukb_chr2.bgen.bgi diff --git a/test/data/unphased_bgen/ukb_chr2.sample b/test/assets/unphased_bgen/ukb_chr2.sample similarity index 100% rename from test/data/unphased_bgen/ukb_chr2.sample rename to test/assets/unphased_bgen/ukb_chr2.sample diff --git a/test/data/unphased_bgen/ukb_chr3.bgen b/test/assets/unphased_bgen/ukb_chr3.bgen similarity index 100% rename from test/data/unphased_bgen/ukb_chr3.bgen rename to test/assets/unphased_bgen/ukb_chr3.bgen diff --git a/test/data/unphased_bgen/ukb_chr3.bgen.bgi b/test/assets/unphased_bgen/ukb_chr3.bgen.bgi similarity index 100% rename from test/data/unphased_bgen/ukb_chr3.bgen.bgi rename to test/assets/unphased_bgen/ukb_chr3.bgen.bgi diff --git a/test/data/unphased_bgen/ukb_chr3.sample b/test/assets/unphased_bgen/ukb_chr3.sample similarity index 100% rename from test/data/unphased_bgen/ukb_chr3.sample rename to test/assets/unphased_bgen/ukb_chr3.sample diff --git a/test/data/variants_list.txt b/test/assets/variants_list.txt similarity index 100% rename from test/data/variants_list.txt rename to test/assets/variants_list.txt diff --git a/test/data/withdrawal_list.txt b/test/assets/withdrawal_list.txt similarity index 100% rename from test/data/withdrawal_list.txt rename to test/assets/withdrawal_list.txt From bd50938a8430c21ab728559184a94dc15bf389d8 Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Mon, 5 Feb 2024 11:26:08 +0100 Subject: [PATCH 64/65] rename conf datadir to assets dir --- {data => assets}/NO_EXTRA_CONFOUNDER | 0 {data => assets}/NO_EXTRA_COVARIATE | 0 {data => assets}/NO_EXTRA_TREATMENT | 0 {data => assets}/NO_LD_BLOCKS | 0 {data => assets}/NO_QC_FILE | 0 {data => assets}/NO_WITHDRAWAL_LIST | 0 {data => assets}/exclusion_regions_hg19.txt | 0 {data => assets}/exclusion_regions_hg38.txt | 0 {data => assets}/ukbconfig.yaml | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename {data => assets}/NO_EXTRA_CONFOUNDER (100%) rename {data => assets}/NO_EXTRA_COVARIATE (100%) rename {data => assets}/NO_EXTRA_TREATMENT (100%) rename {data => assets}/NO_LD_BLOCKS (100%) rename {data => assets}/NO_QC_FILE (100%) rename {data => assets}/NO_WITHDRAWAL_LIST (100%) rename {data => assets}/exclusion_regions_hg19.txt (100%) rename {data => assets}/exclusion_regions_hg38.txt (100%) rename {data => assets}/ukbconfig.yaml (100%) diff --git a/data/NO_EXTRA_CONFOUNDER b/assets/NO_EXTRA_CONFOUNDER similarity index 100% rename from data/NO_EXTRA_CONFOUNDER rename to assets/NO_EXTRA_CONFOUNDER diff --git a/data/NO_EXTRA_COVARIATE b/assets/NO_EXTRA_COVARIATE similarity index 100% rename from data/NO_EXTRA_COVARIATE rename to assets/NO_EXTRA_COVARIATE diff --git a/data/NO_EXTRA_TREATMENT b/assets/NO_EXTRA_TREATMENT similarity index 100% rename from data/NO_EXTRA_TREATMENT rename to assets/NO_EXTRA_TREATMENT diff --git a/data/NO_LD_BLOCKS b/assets/NO_LD_BLOCKS similarity index 100% rename from data/NO_LD_BLOCKS rename to assets/NO_LD_BLOCKS diff --git a/data/NO_QC_FILE b/assets/NO_QC_FILE similarity index 100% rename from data/NO_QC_FILE rename to assets/NO_QC_FILE diff --git a/data/NO_WITHDRAWAL_LIST b/assets/NO_WITHDRAWAL_LIST similarity index 100% rename from data/NO_WITHDRAWAL_LIST rename to assets/NO_WITHDRAWAL_LIST diff --git a/data/exclusion_regions_hg19.txt b/assets/exclusion_regions_hg19.txt similarity index 100% rename from data/exclusion_regions_hg19.txt rename to assets/exclusion_regions_hg19.txt diff --git a/data/exclusion_regions_hg38.txt b/assets/exclusion_regions_hg38.txt similarity index 100% rename from data/exclusion_regions_hg38.txt rename to assets/exclusion_regions_hg38.txt diff --git a/data/ukbconfig.yaml b/assets/ukbconfig.yaml similarity index 100% rename from data/ukbconfig.yaml rename to assets/ukbconfig.yaml From e262c2fe9de52c8205bfe82d38d129233aec48bc Mon Sep 17 00:00:00 2001 From: Olivier Labayle Date: Mon, 5 Feb 2024 11:43:31 +0100 Subject: [PATCH 65/65] config docs --- docs/src/nextflow_params.md | 64 ------------------------------------- docs/src/overview.md | 45 ++++++++++++-------------- 2 files changed, 21 insertions(+), 88 deletions(-) delete mode 100644 docs/src/nextflow_params.md diff --git a/docs/src/nextflow_params.md b/docs/src/nextflow_params.md deleted file mode 100644 index 00e533fd..00000000 --- a/docs/src/nextflow_params.md +++ /dev/null @@ -1,64 +0,0 @@ -# Index of the pipeline parameters - -Here is a list of all the pipeline parameters: - -## [Setting a Data Source](@ref) - -- **`COHORT` (required):** Current default for this is UKBB. If set to a value other than UKBB, this will not run UKBB-specific trait extraction. -- **`TRAITS_DATASET` (required):** Path to a traits dataset. If you are running this for a non-UKBB cohort, your sample IDs must be specified in the first column of this CSV file, with the column name `SAMPLE_ID`. -- **`BED_FILES` (required)**: Path expression to PLINK BED files. -- **`BGEN_FILES` (required)**: Path expression to imputed BGEN files. -- **`UKB_CONFIG` (required for COHORT=UKBB)**: - **`UKB_CONFIG` (required)**: YAML configuration file describing which traits should be extracted and how the population should be subsetted. -- `UKB_ENCODING_FILE` (optional): If the `TRAITS_DATASET` is encrypted, an encoding file must be provided. -- `UKB_WITHDRAWAL_LIST` (optional): List of participants withdrawn from the study. -- `QC_FILE` (optional): Genotyping quality control file from the UK-Biobank study. - -## [Adjusting for confounders](@ref) - -- `LD_BLOCKS` (optional): A path to pre-identified linkage disequlibrium blocks around the variants that will be queried for causal effect estimation. Those will be removed from the data. It is good practice to specify `LD_BLOCKS`, as it will remove SNPs correlated with your variants-of-interest before running PCA. -- `FLASHPCA_EXCLUSION_REGIONS` (optional, default: assets/exclusion_regions_hg19.txt): A path to the flashpca special exclusion regions. -- `MAF_THRESHOLD` (optional, default: 0.01): Only variants with that minor allele frequency are considered -- `NB_PCS` (optional, default: 6): The number of PCA components to extract. - -## [Study Designs](@ref) - -- **`STUDY_DESIGN`** (required, default: "FROM\_PARAM\_FILE"): One of "FROM\_PARAM\_FILE", "FROM\_ACTORS". - -If `STUDY_DESIGN`=`CUSTOM`: - -- `ESTIMANDS_FILE` (required): Path expression to the estimands file. - -If `STUDY_DESIGN`=`ALLELE_INDEPENDENT`: - -- `ESTIMANDS_FILE` (required): YAML configuration file. - -If `STUDY_DESIGN`=`FROM_ACTORS`: - -- **`BQTLS` (required)**: A CSV file containing binding quantitative trait loci (bQTLs). If multiple transcription factors (TFs) are included in a single run, you must include a column called `TF`, which specifies the TF associated with each bQTL. -- **`TRANS_ACTORS` (required)**: A prefix to CSV files containing quantitative trait loci potentially interacting with the previous bqtls. If multiple transcription factors (TFs) are included in a single run, you must include a column called `TF`, which specifies the TF associated with each transactor. -- `EXTRA_CONFOUNDERS` (optional, default: nothing): Path to additional confounders file, one per line, no header. -- `EXTRA_COVARIATES` (optional, default: nothing): Path to additional covariates file, one per line, no header. -- `ENVIRONMENTALS` (optional, default: nothing): Path to additional environmental treatments file, one per line, no header. -- `ORDERS` (optional, default: "1,2"): Comma separated list describing the order of desired interaction estimands, 1 for the ATE (no interaction), 2 for pairwise interactions etc... e.g. "1,2" - -## [Specifying a Targeted Estimator](@ref) - -- **`ESTIMATOR_FILE` (required)**: Julia configuration file describing the nuisance function learning algorithms. -- `POSITIVITY_CONSTRAINT` (optional, default: 0.01): Treatment variables rarest configuration should have at least that frequency. -- `KEEP_IC` (optional, default: false): For all parameters with an p-value below `PVAL_THRESHOLD`, the influence curve is saved. - - -## [Tweaking additional behaviour](@ref) - -- `CALL_THRESHOLD` (optional, default: 0.9): For putative causal variants (listed in the parameter files described in the [Study Designs](@ref) section). If a individual's allele's probability is greater than the threshold, then it is called, otherwise it is considered missing. -- `BATCH_SIZE` (optional, default: 400): The set of parameters to be estimated is batched and the TMLE processes will run in parallel across batches on your platform. -- `OUTDIR` (optional, default: "results"): Output directory -- `RNG` (optional, default: 123): General random seed used where appropriate. - -## Running negative control checks - -- `MAX_PERMUTATION_TESTS` (optional, default: null): Arbitrarily limits the number of permutation tests performed. -- `ESTIMATOR_KEY` (optional, default: "TMLE"): The estimator from `ESTIMATOR_FILE` to use to asses significance. -- `PERMUTATION_ORDERS` (optional, default: "1"): A comma separating string defining the permutation test orders to be performed. -- `MAF_MATCHING_RELTOL`(optional, default:0.05): Random variants are chosen with a similar MAF matched with the given relative tolerance. -- `N_RANDOM_VARIANTS`(optional, default: 10): For each hit, that many variants are randomly picked. diff --git a/docs/src/overview.md b/docs/src/overview.md index 716e2562..7d79e960 100644 --- a/docs/src/overview.md +++ b/docs/src/overview.md @@ -1,19 +1,5 @@ # Overview -There are currently 2 main workflows and two secondary workflows within TarGene. - -## Main Workflows - -- [The TarGene Workflow](@ref) (`WORKFLOW_NAME: TARGENE`): It is the main workflow for the targeted estimation of genetic effects. -- [The Negative Control Workflows](@ref "Negative Control Overview"): These workflow enable the control of the false discovery rate by using the results obtained from a previous TarGene discovery run. There are currently two of them: - - [The Permutation Test Workflow](@ref) (`WORKFLOW_NAME: PERMUTATION_TEST`): Performs permutation tests by independently shuffling the individuals in the columns of an aggregated dataset. - - [The Randomized Variants Workflow](@ref) (`WORKFLOW_NAME: RANDOMIZATION_TEST`): When there are multiple genetic variants of interest, e.g. in an interaction study, one can replace one of the variant at random by another variant and the effect is expected to be 0 in average. - -## Secondary Workflows - -- [The PCA Workflow](@ref) (`WORKFLOW_NAME: PCA`): This workflow computes principal components. -- [The Make Dataset Workflow](@ref) (`WORKFLOW_NAME: MAKE_DATASET`): This workflow generates an aggregated dataset from traits and genetic data. - ## Running the Workflows Since TarGene uses [Nextflow](https://www.nextflow.io/), all workflows can be run in the same way from the command line: @@ -22,26 +8,37 @@ Since TarGene uses [Nextflow](https://www.nextflow.io/), all workflows can be ru nextflow run https://github.com/TARGENE/targene-pipeline/ -r TAG -entry WORKFLOW_NAME -profile P -resume ``` -where `TAG` is the latest TarGene version, e.g. `v0.9.0` and `WORKFLOW_NAME` is any of the worflows listed below. +where: + +- `TAG` is the latest TarGene version, e.g. `v0.9.0` +- `WORKFLOW_NAME` is any of the [TarGene workflows](@ref "Project Configuration") +- `P` is a [Nextflow profile](https://www.nextflow.io/docs/latest/config.html) describing your run environment (see [Environment Configuration](@ref)). -Additional Nextflow arguments can be found in their documentation, for example: +Additional Nextflow command line arguments can be found in their documentation, for example: - `-resume`: Tells Nextflow to try to resume the pipeline if an error occurred during the execution (if you forgot to specify a parameter for instance) -- `-with-trace` and `-with-report` will generate additional report files. +- `-with-trace` and `-with-report` will generate additional report files. ## Workflows Configurations -There are mainly two parts to configuring a workflow run. The first part describes the execution and environment and the second part describes your actual project. +There are mainly two parts to configuring a workflow run. The first part describes the execution and environment and the second part describes your actual project. When running the `nextflow run` command, Nextflow will look for a `nextflow.config` configuration file in your current directory. If you are new to Nextflow, we suggest you use this file to setup both the environment and project configurations. As your project grows you may want to benefit from splitting this file in more [modular components](https://www.nextflow.io/docs/latest/config.html#configuration). ### Environment Configuration -This is typically done only once for each platform by defining a [Nextflow profile](https://www.nextflow.io/docs/latest/config.html) and all your projects will benefit the same profile. -- The `-profile P` option is described below and implicit, is the -All arguments are optional but encouraged. Here `-r vX` describes the version to be used and should be provided for reproducibility purposes, e.g. `-r v0.3.7`. If left unspecified, the latest development version will be used. The `-resume` option and the existence of a `nextflow.config` file, the content of which is also described here: +It is likely that you will run TarGene on a HPC platform, in particular the [Executors](https://www.nextflow.io/docs/latest/executor.html) and [Singularity](https://www.nextflow.io/docs/latest/container.html#singularity) configurations are required. Since Nextflow is so widespread, it is probable that such a configuration file is already available from your HPC administrators. Since this configuration only describes de computing platform and not your project, it is often described as a [Profile](https://www.nextflow.io/docs/latest/config.html#config-profiles). If your HPC uses the SGE executor, the `-profile eddie` may work with no, or minor adjustment (it can also serve as a template for other executors [see file](https://github.com/TARGENE/targene-pipeline/blob/main/conf/eddie.config)). -1. It is likely that you will run TarGene on a HPC platform, in particular the [Executors](https://www.nextflow.io/docs/latest/executor.html) and [Singularity](https://www.nextflow.io/docs/latest/container.html#singularity) configurations are required. Since Nextflow is so widespread, it is probable that such a configuration file is already available from your HPC administrators. Since this configuration only describes de computing platform and not your project, it is often described as a [Profile](https://www.nextflow.io/docs/latest/config.html#config-profiles). If your HPC uses the SGE executor, the `-profile eddie` may work with no, or minor adjustment (it can also serve as a template for other executors [see file](https://github.com/TARGENE/targene-pipeline/blob/main/conf/eddie.config)). +### Project Configuration -2. You need to provide the configuration details associated with your project, this is usually done in a `nextflow.config` file living at the root of your project's directory. The configuration parameters are described in the following sections: +These are the configuration details associated with your project, this is usually done in a `nextflow.config` file living at the root of your project's directory. The configuration parameters are specific to each workflow and described in the following sections. There are currently two main workflows and two secondary workflows within TarGene. +#### Main Workflows -A list of all TarGene's parameters is available in the [Index of the pipeline parameters](@ref). \ No newline at end of file +- [The TarGene Workflow](@ref) (`WORKFLOW_NAME: TARGENE`): It is the main workflow for the targeted estimation of genetic effects. +- [The Negative Control Workflows](@ref "Negative Control Overview"): These workflows enable the control of the false discovery rate by using the results obtained from a previous TarGene discovery run. There are currently two of them: + - [The Permutation Test Workflow](@ref) (`WORKFLOW_NAME: PERMUTATION_TEST`): Performs permutation tests by independently shuffling the individuals in the columns of an aggregated dataset. + - [The Randomized Variants Workflow](@ref) (`WORKFLOW_NAME: RANDOMIZATION_TEST`): When there are multiple genetic variants of interest, e.g. in an interaction study, one can replace one of the variant at random by another variant and the effect is expected to be 0 in average. + +#### Secondary Workflows + +- [The PCA Workflow](@ref) (`WORKFLOW_NAME: PCA`): This workflow computes principal components. +- [The Make Dataset Workflow](@ref) (`WORKFLOW_NAME: MAKE_DATASET`): This workflow generates an aggregated dataset from traits and genetic data.