Skip to content

Commit 82ac98c

Browse files
committed
Merge branch 'main' of github.com:CITCOM-project/CausalTestingFramework into metamorphic_testing
2 parents 4e4ca19 + 6764fb3 commit 82ac98c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+2367
-1196
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
name: Bug report
3+
about: Create a report to help us improve
4+
title: ''
5+
labels: ''
6+
assignees: ''
7+
8+
---
9+
10+
**Describe the bug**
11+
A clear and concise description of what the bug is.
12+
13+
**To Reproduce**
14+
Steps to reproduce the behavior:
15+
1. Go to '...'
16+
2. Click on '....'
17+
3. Scroll down to '....'
18+
4. See error
19+
20+
**Expected behavior**
21+
A clear and concise description of what you expected to happen.
22+
23+
**Screenshots**
24+
If applicable, add screenshots to help explain your problem.
25+
26+
**Desktop (please complete the following information):**
27+
- OS: [e.g. iOS]
28+
- Browser [e.g. chrome, safari]
29+
- Version [e.g. 22]
30+
31+
**Smartphone (please complete the following information):**
32+
- Device: [e.g. iPhone6]
33+
- OS: [e.g. iOS8.1]
34+
- Browser [e.g. stock browser, safari]
35+
- Version [e.g. 22]
36+
37+
**Additional context**
38+
Add any other context about the problem here.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
name: Feature request
3+
about: Suggest an idea for this project
4+
title: ''
5+
labels: ''
6+
assignees: ''
7+
8+
---
9+
10+
**Is your feature request related to a problem? Please describe.**
11+
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12+
13+
**Describe the solution you'd like**
14+
A clear and concise description of what you want to happen.
15+
16+
**Describe alternatives you've considered**
17+
A clear and concise description of any alternative solutions or features you've considered.
18+
19+
**Additional context**
20+
Add any other context or screenshots about the feature request here.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Publish python PyPI
2+
3+
on:
4+
push:
5+
tags:
6+
- v*
7+
8+
jobs:
9+
build-release:
10+
name: Build and publish PyPI
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v3
14+
with:
15+
fetch-depth: 0
16+
- name: Set up Python
17+
uses: actions/setup-python@v3
18+
with:
19+
python-version: 3.9
20+
- name: Installing package
21+
run: |
22+
pip3 install .
23+
pip3 install .[pypi]
24+
pip3 install build
25+
pip3 install setuptools --upgrade
26+
pip3 install setuptools_scm
27+
- name: Build Package
28+
run: |
29+
python -m build --no-isolation
30+
- name: Publish package to PyPI
31+
uses: pypa/gh-action-pypi-publish@release/v1
32+
with:
33+
password: ${{ secrets.PYPI_API_TOKEN }}

.pylintrc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ disable=raw-checker-failed,
152152
useless-suppression,
153153
deprecated-pragma,
154154
use-symbolic-message-instead,
155+
logging-fstring-interpolation,
156+
import-error,
155157

156158
# Enable the message, report, category or checker with the given id(s). You can
157159
# either give multiple identifier separated by comma (,) or put this option
@@ -239,7 +241,9 @@ good-names=i,
239241
j,
240242
k,
241243
ex,
244+
df,
242245
Run,
246+
z3,
243247
_
244248

245249
# Good variable names regexes, separated by a comma. If names match any regex,

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Here are some explanations for the causal inference terminology used above.
3131

3232
## Installation
3333

34-
To use the causal testing framework, clone the repository, `cd` into the root directory, and run `pip install -e .`. More detailled installation instructions can be found in the [online documentation](https://causal-testing-framework.readthedocs.io/en/latest/installation.html).
34+
See the readthedocs site for installation instructions](https://causal-testing-framework.readthedocs.io/en/latest/installation.html).
3535

3636
## Usage
3737

causal_testing/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
"""
2+
This is the CausalTestingFramework Module
3+
It contains 5 subpackages:
4+
data_collection
5+
generation
6+
json_front
7+
specification
8+
testing
9+
"""
10+
111
import logging
212

313
logger = logging.getLogger(__name__)

causal_testing/data_collection/data_collector.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
"""This module contains the DataCollector abstract class, as well as its concrete extensions: ExperimentalDataCollector
2+
and ObservationalDataCollector"""
3+
14
import logging
25
from abc import ABC, abstractmethod
6+
from enum import Enum
37

48
import pandas as pd
59
import z3
@@ -34,11 +38,15 @@ def filter_valid_data(self, data: pd.DataFrame, check_pos: bool = True) -> pd.Da
3438
"""
3539

3640
# Check positivity
37-
scenario_variables = set(self.scenario.variables)
41+
scenario_variables = set(self.scenario.variables) - {x.name for x in self.scenario.hidden_variables()}
3842

39-
if check_pos and not scenario_variables.issubset(data.columns):
43+
if check_pos and not (scenario_variables - {x.name for x in self.scenario.hidden_variables()}).issubset(
44+
set(data.columns)
45+
):
4046
missing_variables = scenario_variables - set(data.columns)
41-
raise IndexError(f"Positivity violation: missing data for variables {missing_variables}.")
47+
raise IndexError(
48+
f"Missing columns: missing data for variables {missing_variables}. Should they be marked as hidden?"
49+
)
4250

4351
# For each row, does it satisfy the constraints?
4452
solver = z3.Solver()
@@ -53,6 +61,7 @@ def filter_valid_data(self, data: pd.DataFrame, check_pos: bool = True) -> pd.Da
5361
self.scenario.variables[var].z3
5462
== self.scenario.variables[var].z3_val(self.scenario.variables[var].z3, row[var])
5563
for var in self.scenario.variables
64+
if var in row
5665
]
5766
for c in model:
5867
solver.assert_and_track(c, f"model: {c}")
@@ -72,10 +81,7 @@ def filter_valid_data(self, data: pd.DataFrame, check_pos: bool = True) -> pd.Da
7281
size_diff = len(data) - len(satisfying_data)
7382
if size_diff > 0:
7483
logger.warning(
75-
"Discarded %s/%s values due to constraint violations.\n" "For example%s",
76-
size_diff,
77-
len(data),
78-
unsat_core,
84+
f"Discarded {size_diff}/{len(data)} values due to constraint violations.\n For example {unsat_core}",
7985
)
8086
return satisfying_data
8187

@@ -123,23 +129,27 @@ def run_system_with_input_configuration(self, input_configuration: dict) -> pd.D
123129

124130

125131
class ObservationalDataCollector(DataCollector):
126-
"""A data collector that extracts data that is relevant to the specified scenario from a csv of execution data."""
132+
"""A data collector that extracts data that is relevant to the specified scenario from a dataframe of execution
133+
data."""
127134

128-
def __init__(self, scenario: Scenario, csv_path: str):
135+
def __init__(self, scenario: Scenario, data: pd.DataFrame):
129136
super().__init__(scenario)
130-
self.csv_path = csv_path
137+
self.data = data
131138

132139
def collect_data(self, **kwargs) -> pd.DataFrame:
133-
"""Read a csv containing execution data for the system-under-test into a pandas dataframe and filter to remove
140+
"""Read a pandas dataframe and filter to remove
134141
any data which is invalid for the scenario-under-test.
135142
136143
Data is invalid if it does not meet the constraints outlined in the scenario-under-test (Scenario).
137144
138145
:return: A pandas dataframe containing execution data that is valid for the scenario-under-test.
139146
"""
140147

141-
execution_data_df = pd.read_csv(self.csv_path, **kwargs)
148+
execution_data_df = self.data
142149
for meta in self.scenario.metas():
143150
meta.populate(execution_data_df)
144151
scenario_execution_data_df = self.filter_valid_data(execution_data_df)
152+
for var_name, var in self.scenario.variables.items():
153+
if issubclass(var.datatype, Enum):
154+
scenario_execution_data_df[var_name] = [var.datatype(x) for x in scenario_execution_data_df[var_name]]
145155
return scenario_execution_data_df

0 commit comments

Comments
 (0)