diff --git a/.github/workflows/publish-to-dafni.yaml b/.github/workflows/publish-to-dafni.yaml index 424a0fe6..051655de 100644 --- a/.github/workflows/publish-to-dafni.yaml +++ b/.github/workflows/publish-to-dafni.yaml @@ -18,8 +18,9 @@ jobs: - name: Get release version id: get_release run: | - export VERSION=$(curl -sSL https://api.github.com/repos/CITCOM-project/CausalTestingFramework/releases/latest | jq -r '.tag_name' | head -c 2) - echo "::set-output name=version::$VERSION" + # Extract the version without the 'v' prefix using regex + export VERSION=$(curl -sSL https://api.github.com/repos/CITCOM-project/CausalTestingFramework/releases/latest | jq -r '.tag_name' | sed -E 's/^v?([0-9]+(\.[0-9]+)?).*/\1/') + echo "version=$VERSION" >> $GITHUB_OUTPUT build_and_upload: name: Docker Build @@ -38,17 +39,28 @@ jobs: with: python-version: '3.10' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install causal-testing-framework -e .[dev] + python -m pip install dafni-cli + + - name: Check if unit tests are passing first + id: tests + uses: ./.github/workflows/ci-tests.yml + - name: Build the container + if: success() && steps.tests.outcome == 'success' run: | docker build -t ctf:${{ env.VERSION }} -f ./dafni/Dockerfile . docker save ctf:${{ env.VERSION }} | gzip > ctf-dafni-${{ env.VERSION }}.tar.gz - - name: Install DAFNI-CLI and log in + + - name: Log into DAFNI run: | - python -m pip install dafni-cli dafni login - name: Upload to DAFNI run: | - dafni upload model ./dafni/model_definition.yaml ctf-dafni-${{ env.VERSION }}.tar.gz --version-message "Causal Testing Framework ${{ env.VERSION }}. Uploaded via Github Actions." --parent-id ${{ env.DAFNI_PARENT_ID }} -y - dafni logout + dafni upload model ./dafni/model_definition.yaml ctf-dafni-${{ env.VERSION }}.tar.gz --version-message "Causal Testing Framework v${{ env.VERSION }}. Uploaded via Github Actions." --parent-id ${{ env.DAFNI_PARENT_ID }} -y + dafni logout \ No newline at end of file diff --git a/dafni/Dockerfile b/dafni/Dockerfile index 8969ad3f..2330a9df 100644 --- a/dafni/Dockerfile +++ b/dafni/Dockerfile @@ -1,5 +1,5 @@ # Define the Python version neded for CTF -FROM python:3.10-slim +FROM python:3.12-slim ## Prevents Python from writing pyc files ENV PYTHONDONTWRITEBYTECODE=1 @@ -8,26 +8,22 @@ ENV PYTHONDONTWRITEBYTECODE=1 ## from crashing without emitting any logs due to buffering ENV PYTHONUNBUFFERED=1 -#Label maintainer +# Label maintainer LABEL maintainer="Dr. Farhad Allian - The University of Sheffield" # Create a folder for the source code/outputs RUN mkdir -p ./causal_testing RUN mkdir -p ./data/outputs -# Copy the source code and test files from build into the container -COPY --chown=nobody ../causal_testing ./causal_testing -COPY --chown=nobody ./dafni/main_dafni.py ./ +# Copy the source code from local root and test files from build into the container +COPY --chown=nobody ./causal_testing ./causal_testing COPY --chown=nobody ./dafni/data/inputs ./data/inputs # Install core dependencies using PyPi RUN pip install causal-testing-framework --no-cache-dir -#For local testing purposes -ENV VARIABLES_PATH=./data/inputs/variables.json \ - CAUSAL_TESTS=./data/inputs/causal_tests.json \ - DATA_PATH=./data/inputs/runtime_data.csv \ - DAG_PATH=./data/inputs/dag.dot +# Set the PYTHONPATH environment variable to include the /src directory +ENV PYTHONPATH="/causal_testing:${PYTHONPATH}" # Define the entrypoint/commands -CMD python main_dafni.py --variables_path $VARIABLES_PATH --dag_path $DAG_PATH --data_path $DATA_PATH --tests_path $CAUSAL_TESTS +CMD python -m causal_testing --dag_path $DAG_PATH --data_path $DATA_PATH --test_config $TESTS_PATH --output $OUTPUT \ No newline at end of file diff --git a/dafni/README.md b/dafni/README.md index 29833d61..47f0b186 100644 --- a/dafni/README.md +++ b/dafni/README.md @@ -5,25 +5,29 @@ to upload the framework onto [DAFNI](https://www.dafni.ac.uk). - It is **not** recommended to install the causal testing framework using Docker, and should only be installed using [PyPI](https://pypi.org/project/causal-testing-framework/). -### Folders +### Directory Hierarchy - `data` contains two sub-folders (the structure is important for DAFNI). - `inputs` is a folder that contains the input files that are (separately) uploaded to DAFNI. - `causal_tests.json` is a JSON file that contains the causal tests. - - `variables.json` is a JSON file that contains the variables and constraints to be used. - - `dag.dot` is a dot file that contains the directed acyclc graph (dag) file. - - `runtime_data.csv` is a csv file that contains the runtime data. + - `dag.dot` is a dot file that contains the directed acyclic graph (dag). In this file, Causal Variables are defined as + node metadata attributes as key-value pairs using the following syntax: + `node [datatype="int", typestring="input"]`. The `datatype` key specifies the datatype of the causal variable + as a string (e.g. `"int"`, `"str"`) and the `typestring` key specifies its typestring, which is also a string + representing the variable type (e.g. `"input"` or `"output"`). + - `runtime_data.csv` is the `.csv` file that contains the runtime data. - `outputs` is a folder where the `causal_tests_results.json` output file is created. ### Docker files -- `main_dafni.py` is the entry-point to the causal testing framework that is used by Docker. - `model_definition.yaml` is the model metadata that is required to be uploaded to DAFNI. -- `.env` is an example of a configuration file containing the environment variables. This is only required - if using `docker-compose` to build the image. -- `Dockerfile` is the main blueprint that builds the image. -- `.dockerignore` tells the Dockerfile which files to not include in the image. +- `Dockerfile` is the main blueprint that builds the image. The main command calls the `causal_testing` module, + with specified paths for the DAG, input runtime data, test configurations, and the output filename as defined above. + This command is identical to that referenced in the main [README.md](../README.md) file. - `docker-compose.yaml` is another method of building the image and running the container in one line. Note: the `.env` file that contains the environment variables for `main_dafni.py` is only used here. +- `.dockerignore` tells the Dockerfile which files to not include in the image. +- `.env` is an example of a configuration file containing the environment variables. This is only required + if using `docker-compose` to build the image. diff --git a/dafni/data/inputs/causal_tests.json b/dafni/data/inputs/causal_tests.json index 6c78c57f..539dd927 100644 --- a/dafni/data/inputs/causal_tests.json +++ b/dafni/data/inputs/causal_tests.json @@ -1,58 +1,11 @@ { "tests": [ - { - "name": "max_doses _||_ cum_vaccinations", - "estimator": "LinearRegressionEstimator", - "estimate_type": "coefficient", - "effect": "direct", - "mutations": [ - "max_doses" - ], - "expected_effect": { - "cum_vaccinations": "NoEffect" - }, - "formula": "cum_vaccinations ~ max_doses", - "alpha": 0.05, - "skip": false - }, - { - "name": "max_doses _||_ cum_vaccinated", - "estimator": "LinearRegressionEstimator", - "estimate_type": "coefficient", - "effect": "direct", - "mutations": [ - "max_doses" - ], - "expected_effect": { - "cum_vaccinated": "NoEffect" - }, - "formula": "cum_vaccinated ~ max_doses", - "alpha": 0.05, - "skip": false - }, - { - "name": "max_doses _||_ cum_infections", - "estimator": "LinearRegressionEstimator", - "estimate_type": "coefficient", - "effect": "direct", - "mutations": [ - "max_doses" - ], - "expected_effect": { - "cum_infections": "NoEffect" - }, - "formula": "cum_infections ~ max_doses", - "alpha": 0.05, - "skip": false - }, { "name": "vaccine --> cum_vaccinations", "estimator": "LinearRegressionEstimator", "estimate_type": "coefficient", "effect": "direct", - "mutations": [ - "vaccine" - ], + "treatment_variable": "vaccine", "expected_effect": { "cum_vaccinations": "SomeEffect" }, @@ -64,9 +17,7 @@ "estimator": "LinearRegressionEstimator", "estimate_type": "coefficient", "effect": "direct", - "mutations": [ - "vaccine" - ], + "treatment_variable": "vaccine", "expected_effect": { "cum_vaccinated": "SomeEffect" }, @@ -78,9 +29,7 @@ "estimator": "LinearRegressionEstimator", "estimate_type": "coefficient", "effect": "direct", - "mutations": [ - "vaccine" - ], + "treatment_variable": "vaccine", "expected_effect": { "cum_infections": "SomeEffect" }, @@ -92,9 +41,7 @@ "estimator": "LinearRegressionEstimator", "estimate_type": "coefficient", "effect": "direct", - "mutations": [ - "cum_vaccinations" - ], + "treatment_variable": "cum_vaccinations", "expected_effect": { "cum_vaccinated": "NoEffect" }, @@ -107,9 +54,7 @@ "estimator": "LinearRegressionEstimator", "estimate_type": "coefficient", "effect": "direct", - "mutations": [ - "cum_vaccinations" - ], + "treatment_variable": "cum_vaccinations", "expected_effect": { "cum_infections": "NoEffect" }, @@ -122,9 +67,7 @@ "estimator": "LinearRegressionEstimator", "estimate_type": "coefficient", "effect": "direct", - "mutations": [ - "cum_vaccinated" - ], + "treatment_variable": "cum_vaccinated", "expected_effect": { "cum_infections": "NoEffect" }, diff --git a/dafni/data/inputs/dag.dot b/dafni/data/inputs/dag.dot index 43628817..67b9007b 100644 --- a/dafni/data/inputs/dag.dot +++ b/dafni/data/inputs/dag.dot @@ -1,7 +1,12 @@ digraph CausalDAG { rankdir=LR; - "vaccine" -> "cum_vaccinations"; - "vaccine" -> "cum_vaccinated"; - "vaccine" -> "cum_infections"; - "max_doses"; + vaccine [datatype="int", typestring="input"]; + cum_vaccinations [datatype="int", typestring="output"]; + cum_vaccinated [datatype="int", typestring="output"]; + cum_infections [datatype="int", typestring="output"]; + max_doses [datatype="int", typestring="output"]; + vaccine -> cum_vaccinations; + vaccine -> cum_vaccinated; + vaccine -> cum_infections; + max_doses; } \ No newline at end of file diff --git a/dafni/data/inputs/variables.json b/dafni/data/inputs/variables.json deleted file mode 100644 index 8e4a1add..00000000 --- a/dafni/data/inputs/variables.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "variables": [ - { - "name": "pop_size", - "datatype": "int", - "typestring": "Input", - "constraint": 50000 - }, - { - "name": "pop_infected", - "datatype": "int", - "typestring": "Input", - "constraint": 1000 - }, - { - "name": "n_days", - "datatype": "int", - "typestring": "Input", - "constraint": 50 - }, - { - "name": "vaccine", - "datatype": "int", - "typestring": "Input" - }, - { - "name": "cum_infections", - "datatype": "int", - "typestring": "Output" - }, - { - "name": "cum_vaccinations", - "datatype": "int", - "typestring": "Output" - }, - { - "name": "cum_vaccinated", - "datatype": "int", - "typestring": "Output" - }, - { - "name": "max_doses", - "datatype": "int", - "typestring": "Output" - } - ] -} \ No newline at end of file diff --git a/dafni/data/outputs/causal_tests_results.json b/dafni/data/outputs/causal_tests_results.json index f5e503aa..00dcbc6c 100644 --- a/dafni/data/outputs/causal_tests_results.json +++ b/dafni/data/outputs/causal_tests_results.json @@ -1,215 +1,176 @@ [ - { - "name": "max_doses _||_ cum_vaccinations", - "estimate_type": "coefficient", - "effect": "direct", - "mutations": [ - "max_doses" - ], - "expected_effect": { - "cum_vaccinations": "NoEffect" - }, - "formula": "cum_vaccinations ~ max_doses", - "alpha": 0.05, - "skip": false, - "failed": true, - "result": { - "treatment": "max_doses", - "outcome": "cum_vaccinations", - "adjustment_set": [], - "effect_measure": "coefficient", - "effect_estimate": 252628.1066666667, - "ci_low": 252271.33332001517, - "ci_high": 252984.8800133182 - } - }, - { - "name": "max_doses _||_ cum_vaccinated", - "estimate_type": "coefficient", - "effect": "direct", - "mutations": [ - "max_doses" - ], - "expected_effect": { - "cum_vaccinated": "NoEffect" - }, - "formula": "cum_vaccinated ~ max_doses", - "alpha": 0.05, - "skip": false, - "failed": true, - "result": { - "treatment": "max_doses", - "outcome": "cum_vaccinated", - "adjustment_set": [], - "effect_measure": "coefficient", - "effect_estimate": 213111.93333333335, - "ci_low": 212755.15056812647, - "ci_high": 213468.71609854023 - } - }, - { - "name": "max_doses _||_ cum_infections", - "estimate_type": "coefficient", - "effect": "direct", - "mutations": [ - "max_doses" - ], - "expected_effect": { - "cum_infections": "NoEffect" - }, - "formula": "cum_infections ~ max_doses", - "alpha": 0.05, - "skip": false, - "failed": true, - "result": { - "treatment": "max_doses", - "outcome": "cum_infections", - "adjustment_set": [], - "effect_measure": "coefficient", - "effect_estimate": 2666.3066666666664, - "ci_low": 2619.972040648758, - "ci_high": 2712.6412926845746 - } - }, { "name": "vaccine --> cum_vaccinations", "estimate_type": "coefficient", "effect": "direct", - "mutations": [ - "vaccine" - ], + "treatment_variable": "vaccine", "expected_effect": { "cum_vaccinations": "SomeEffect" }, "formula": "cum_vaccinations ~ vaccine", + "alpha": 0.05, "skip": false, - "failed": false, + "passed": true, "result": { "treatment": "vaccine", "outcome": "cum_vaccinations", "adjustment_set": [], "effect_measure": "coefficient", - "effect_estimate": 315785.1333333332, - "ci_low": 315339.1666500188, - "ci_high": 316231.1000166476 + "effect_estimate": { + "vaccine": 315785.1333333332 + }, + "ci_low": [ + 315339.1666500188 + ], + "ci_high": [ + 316231.1000166476 + ] } }, { "name": "vaccine --> cum_vaccinated", "estimate_type": "coefficient", "effect": "direct", - "mutations": [ - "vaccine" - ], + "treatment_variable": "vaccine", "expected_effect": { "cum_vaccinated": "SomeEffect" }, "formula": "cum_vaccinated ~ vaccine", + "alpha": 0.05, "skip": false, - "failed": false, + "passed": true, "result": { "treatment": "vaccine", "outcome": "cum_vaccinated", "adjustment_set": [], "effect_measure": "coefficient", - "effect_estimate": 266389.91666666657, - "ci_low": 265943.93821015797, - "ci_high": 266835.89512317517 + "effect_estimate": { + "vaccine": 266389.91666666657 + }, + "ci_low": [ + 265943.93821015797 + ], + "ci_high": [ + 266835.89512317517 + ] } }, { "name": "vaccine --> cum_infections", "estimate_type": "coefficient", "effect": "direct", - "mutations": [ - "vaccine" - ], + "treatment_variable": "vaccine", "expected_effect": { "cum_infections": "SomeEffect" }, "formula": "cum_infections ~ vaccine", + "alpha": 0.05, "skip": false, - "failed": false, + "passed": true, "result": { "treatment": "vaccine", "outcome": "cum_infections", "adjustment_set": [], "effect_measure": "coefficient", - "effect_estimate": 3332.883333333332, - "ci_low": 3274.9650508109467, - "ci_high": 3390.801615855717 + "effect_estimate": { + "vaccine": 3332.883333333332 + }, + "ci_low": [ + 3274.9650508109467 + ], + "ci_high": [ + 3390.801615855717 + ] } }, { "name": "cum_vaccinations _||_ cum_vaccinated | ['vaccine']", "estimate_type": "coefficient", "effect": "direct", - "mutations": [ - "cum_vaccinations" - ], + "treatment_variable": "cum_vaccinations", "expected_effect": { "cum_vaccinated": "NoEffect" }, "formula": "cum_vaccinated ~ cum_vaccinations + vaccine", "alpha": 0.05, "skip": false, - "failed": true, + "passed": false, "result": { "treatment": "cum_vaccinations", "outcome": "cum_vaccinated", - "adjustment_set": [], + "adjustment_set": [ + "vaccine" + ], "effect_measure": "coefficient", - "effect_estimate": 0.9998656401531605, - "ci_low": 0.9929245394499968, - "ci_high": 1.0068067408563242 + "effect_estimate": { + "cum_vaccinations": 0.9998656401531605 + }, + "ci_low": [ + 0.9929245394499968 + ], + "ci_high": [ + 1.0068067408563242 + ] } }, { "name": "cum_vaccinations _||_ cum_infections | ['vaccine']", "estimate_type": "coefficient", "effect": "direct", - "mutations": [ - "cum_vaccinations" - ], + "treatment_variable": "cum_vaccinations", "expected_effect": { "cum_infections": "NoEffect" }, "formula": "cum_infections ~ cum_vaccinations + vaccine", "alpha": 0.05, "skip": false, - "failed": false, + "passed": true, "result": { "treatment": "cum_vaccinations", "outcome": "cum_infections", - "adjustment_set": [], + "adjustment_set": [ + "vaccine" + ], "effect_measure": "coefficient", - "effect_estimate": -0.006416682407515084, - "ci_low": -0.05663010083886572, - "ci_high": 0.043796736023835554 + "effect_estimate": { + "cum_vaccinations": -0.006416682407515084 + }, + "ci_low": [ + -0.05663010083886572 + ], + "ci_high": [ + 0.043796736023835554 + ] } }, { "name": "cum_vaccinated _||_ cum_infections | ['vaccine']", "estimate_type": "coefficient", "effect": "direct", - "mutations": [ - "cum_vaccinated" - ], + "treatment_variable": "cum_vaccinated", "expected_effect": { "cum_infections": "NoEffect" }, "formula": "cum_infections ~ cum_vaccinated + vaccine", "alpha": 0.05, "skip": false, - "failed": false, + "passed": true, "result": { "treatment": "cum_vaccinated", "outcome": "cum_infections", - "adjustment_set": [], + "adjustment_set": [ + "vaccine" + ], "effect_measure": "coefficient", - "effect_estimate": -0.006176900588291234, - "ci_low": -0.05639349612119588, - "ci_high": 0.04403969494461341 + "effect_estimate": { + "cum_vaccinated": -0.006176900588291234 + }, + "ci_low": [ + -0.05639349612119588 + ], + "ci_high": [ + 0.04403969494461341 + ] } } -] +] \ No newline at end of file diff --git a/dafni/docker-compose.yaml b/dafni/docker-compose.yaml index 9a38d1c4..bc18197b 100644 --- a/dafni/docker-compose.yaml +++ b/dafni/docker-compose.yaml @@ -1,10 +1,9 @@ -version: '3' services: causal-testing-framework: build: context: ../ - dockerfile: ./dafni/Dockerfile + dockerfile: dafni/Dockerfile env_file: - .env volumes: - - .:/usr/src/app + - .:/usr/src/ diff --git a/dafni/main_dafni.py b/dafni/main_dafni.py index a3d8f5c6..e69de29b 100644 --- a/dafni/main_dafni.py +++ b/dafni/main_dafni.py @@ -1,211 +0,0 @@ -""" - -Entrypoint script to run the causal testing framework on DAFNI - -""" - -from pathlib import Path -import argparse -import json -import pandas as pd -from causal_testing.specification.scenario import Scenario -from causal_testing.specification.variable import Input, Output -from causal_testing.testing.causal_effect import Positive, Negative, NoEffect, SomeEffect -from causal_testing.estimation.linear_regression_estimator import LinearRegressionEstimator -from causal_testing.estimation.logistic_regression_estimator import LogisticRegressionEstimator -from causal_testing.json_front.json_class import JsonUtility - - -class ValidationError(Exception): - """ - Custom class to capture validation errors in this script - """ - - -def get_args(test_args=None) -> argparse.Namespace: - """ - Function to parse arguments from the user using the CLI - :param test_args: None - :returns: - - argparse.Namespace - A Namsespace consisting of the arguments to this script - """ - parser = argparse.ArgumentParser(description="A script for running the CTF on DAFNI.") - parser.add_argument("-d", "--data_path", required=True, help="Path to the input runtime data (.csv)", nargs="+") - parser.add_argument( - "-t", "--tests_path", required=True, help="Input configuration file path " "containing the causal tests (.json)" - ) - parser.add_argument( - "-v", - "--variables_path", - required=True, - help="Input configuration file path " "containing the predefined variables (.json)", - ) - parser.add_argument( - "-D", - "--dag_path", - required=True, - help="Input configuration file path containing a valid DAG (.dot). " - "Note: this must be supplied if the --tests argument isn't provided.", - ) - parser.add_argument( - "-i", "--ignore_cycles", action="store_true", help="Whether to ignore cycles in the DAG.", default=False - ) - parser.add_argument( - "-f", default=False, help="(Optional) Failure flag to step the framework from running if a test has failed." - ) - parser.add_argument("-o", "--output_path", required=False, help="Path to the output directory.") - parser.add_argument( - "-w", - default=False, - help="(Optional) Specify to overwrite any existing output files. " - "This can lead to the loss of existing outputs if not careful", - ) - args = parser.parse_args(test_args) - - # Convert these to Path objects for main() - - args.variables_path = Path(args.variables_path) - - args.tests_path = Path(args.tests_path) - - if args.dag_path is not None: - args.dag_path = Path(args.dag_path) - - if args.output_path is None: - args.output_path = "./data/outputs/causal_tests_results.json" - - Path(args.output_path).parent.mkdir(exist_ok=True) - - else: - args.output_path = Path(args.output_path) - - args.output_path.parent.mkdir(exist_ok=True) - - return args - - -def read_variables(variables_path: Path) -> FileNotFoundError | dict: - """ - Function to read the variables.json file specified by the user - :param variables_path: A Path object of the user-specified file path - :returns: - - dict - A valid dictionary consisting of the causal tests - """ - if not variables_path.exists() or variables_path.is_dir(): - print(f"JSON file not found at the specified location: {variables_path}") - - raise FileNotFoundError - - with variables_path.open("r") as file: - inputs = json.load(file) - - return inputs - - -def validate_variables(data_dict: dict) -> tuple: - """ - Function to validate the variables defined in the causal tests - :param data_dict: A dictionary consisting of the pre-defined variables for the causal tests - :returns: - - Tuple containing the inputs, outputs and constraints to pass into the modelling scenario - """ - if data_dict["variables"]: - variables = data_dict["variables"] - - inputs = [ - Input(variable["name"], eval(variable["datatype"])) - for variable in variables - if variable["typestring"] == "Input" - ] - - outputs = [ - Output(variable["name"], eval(variable["datatype"])) - for variable in variables - if variable["typestring"] == "Output" - ] - - constraints = set() - - else: - raise ValidationError("Cannot find the variables defined by the causal tests.") - - return inputs, outputs, constraints - - -def main(): - """ - Main entrypoint of the script: - """ - args = get_args() - - try: - # Step 0: Read in the runtime dataset(s) - - data_frame = pd.concat([pd.read_csv(d) for d in args.data_path]) - - # Step 1: Read in the JSON input/output variables and parse io arguments - - variables_dict = read_variables(args.variables_path) - - inputs, outputs, constraints = validate_variables(variables_dict) - - # Step 2: Set up the modeling scenario and estimator - - modelling_scenario = Scenario(variables=inputs + outputs, constraints=constraints) - - modelling_scenario.setup_treatment_variables() - - estimators = { - "LinearRegressionEstimator": LinearRegressionEstimator, - "LogisticRegressionEstimator": LogisticRegressionEstimator, - } - - # Step 3: Define the expected variables - - expected_outcome_effects = { - "Positive": Positive(), - "Negative": Negative(), - "NoEffect": NoEffect(), - "SomeEffect": SomeEffect(), - } - - # Step 4: Call the JSONUtility class to perform the causal tests - - json_utility = JsonUtility(args.output_path, output_overwrite=True) - - # Step 5: Set the path to the data.csv, dag.dot and causal_tests.json file - json_utility.set_paths(args.tests_path, args.dag_path, args.data_path) - - # Step 6: Sets up all the necessary parts of the json_class needed to execute tests - json_utility.setup(scenario=modelling_scenario, data=data_frame, ignore_cycles=args.ignore_cycles) - - # Step 7: Run the causal tests - test_outcomes = json_utility.run_json_tests( - effects=expected_outcome_effects, mutates={}, estimators=estimators, f_flag=args.f - ) - - # Step 8: Update, print and save the final outputs - - for test in test_outcomes: - test.pop("estimator") - - test["result"] = test["result"].to_dict(json=True) - - test["result"].pop("treatment_value") - - test["result"].pop("control_value") - - with open(args.output_path, "w", encoding="utf-8") as f: - print(json.dumps(test_outcomes, indent=2), file=f) - - print(json.dumps(test_outcomes, indent=2)) - - except ValidationError as ve: - print(f"Cannot validate the specified input configurations: {ve}") - - else: - print(f"Execution successful. " f"Output file saved at {Path(args.output_path).parent.resolve()}") - - -if __name__ == "__main__": - main() diff --git a/dafni/model_definition.yaml b/dafni/model_definition.yaml index 901e2570..a9e2e2ce 100644 --- a/dafni/model_definition.yaml +++ b/dafni/model_definition.yaml @@ -1,5 +1,5 @@ # Model definition file to run the causal testing framework on DAFNI -# https://docs.secure.dafni.rl.ac.uk/docs/how-to/how-to-write-a-model-definition-file +# https://docs.secure.dafni.rl.ac.uk/docs/How%20to/how-to-write-a-model-definition-file kind: M api_version: v1beta3 @@ -20,6 +20,9 @@ metadata: contact_point_email: farhad.allian@sheffield.ac.uk source_code: https://github.com/CITCOM-project/CausalTestingFramework licence: https://github.com/CITCOM-project/CausalTestingFramework?tab=MIT-1-ov-file#readme + rights: If you use our model, please use the following instructions to cite our work - The paper citation should be the Causal Testing Framework paper, and the software citation should contain the specific Figshare DOI of the version used in your work. + project_name: CITCOM + funding: The Causal Testing Framework is supported by the UK's Engineering and Physical Sciences Research Council (EPSRC), with the project name CITCOM - "Causal Inference for Testing of Computational Models" under the grant EP/T030526/1. spec: @@ -49,17 +52,9 @@ spec: path: inputs/ required: true - - name: Variables - description: > - A .JSON file containing the input variables to be used - default: - - 02e755c8-952b-461a-a914-4f4ffbe2edf1 - path: inputs/ - required: true - outputs: - datasets: - - name: causal_test_results.json - type: json - description: > - A JSON file containing the output causal test results. \ No newline at end of file + datasets: + - name: causal_test_results.json + type: json + description: > + A JSON file containing the output causal test results. \ No newline at end of file