Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
283 changes: 197 additions & 86 deletions causal_testing/estimation/ipcw_estimator.py

Large diffs are not rendered by default.

77 changes: 0 additions & 77 deletions causal_testing/specification/capabilities.py
Copy link
Contributor

@f-allian f-allian Sep 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@f-allian, is the codecov just failing on this because the codebase has got slightly bigger? It says I have 100% coverage of the patch, so that's all I can think of, but adding in extra code with 100% coverage should be fine right?

@jmafoster1 Looks like the coverage is failing because you've deleted causal_testing/specification/capabilities.py. Do you know if this was intentional? If so, recommitting it should fix it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this was intentional. It is no longer required as the new functionality requires timesteps to be specified explicitly, which is what I wrote capabilities.py to handle implicitly.

This file was deleted.

23 changes: 7 additions & 16 deletions causal_testing/testing/causal_test_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import logging
from typing import Any
import numpy as np

from causal_testing.specification.variable import Variable
from causal_testing.testing.causal_test_outcome import CausalTestOutcome
Expand Down Expand Up @@ -81,21 +80,13 @@ def _return_causal_test_results(self, estimator) -> CausalTestResult:
if not hasattr(estimator, f"estimate_{self.estimate_type}"):
raise AttributeError(f"{estimator.__class__} has no {self.estimate_type} method.")
estimate_effect = getattr(estimator, f"estimate_{self.estimate_type}")
try:
effect, confidence_intervals = estimate_effect(**self.estimate_params)
return CausalTestResult(
estimator=estimator,
test_value=TestValue(self.estimate_type, effect),
effect_modifier_configuration=self.effect_modifier_configuration,
confidence_intervals=confidence_intervals,
)
except np.linalg.LinAlgError:
return CausalTestResult(
estimator=estimator,
test_value=TestValue(self.estimate_type, None),
effect_modifier_configuration=self.effect_modifier_configuration,
confidence_intervals=None,
)
effect, confidence_intervals = estimate_effect(**self.estimate_params)
return CausalTestResult(
estimator=estimator,
test_value=TestValue(self.estimate_type, effect),
effect_modifier_configuration=self.effect_modifier_configuration,
confidence_intervals=confidence_intervals,
)

def __str__(self):
treatment_config = {self.treatment_variable.name: self.treatment_value}
Expand Down
1 change: 0 additions & 1 deletion tests/estimation_tests/test_cubic_spline_estimator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import matplotlib.pyplot as plt
from causal_testing.specification.variable import Input
from causal_testing.utils.validation import CausalValidator
from causal_testing.specification.capabilities import TreatmentSequence

from causal_testing.estimation.cubic_spline_estimator import CubicSplineRegressionEstimator
from causal_testing.estimation.linear_regression_estimator import LinearRegressionEstimator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import matplotlib.pyplot as plt
from causal_testing.specification.variable import Input
from causal_testing.utils.validation import CausalValidator
from causal_testing.specification.capabilities import TreatmentSequence

from causal_testing.estimation.instrumental_variable_estimator import InstrumentalVariableEstimator

Expand Down
59 changes: 51 additions & 8 deletions tests/estimation_tests/test_ipcw_estimator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import matplotlib.pyplot as plt
from causal_testing.specification.variable import Input
from causal_testing.utils.validation import CausalValidator
from causal_testing.specification.capabilities import TreatmentSequence

from causal_testing.estimation.ipcw_estimator import IPCWEstimator

Expand All @@ -16,8 +15,8 @@ class TestIPCWEstimator(unittest.TestCase):

def test_estimate_hazard_ratio(self):
timesteps_per_intervention = 1
control_strategy = TreatmentSequence(timesteps_per_intervention, [("t", 0), ("t", 0), ("t", 0)])
treatment_strategy = TreatmentSequence(timesteps_per_intervention, [("t", 1), ("t", 1), ("t", 1)])
control_strategy = [[t, "t", 0] for t in range(1, 4, timesteps_per_intervention)]
treatment_strategy = [[t, "t", 1] for t in range(1, 4, timesteps_per_intervention)]
outcome = "outcome"
fit_bl_switch_formula = "xo_t_do ~ time"
df = pd.read_csv("tests/resources/data/temporal_data.csv")
Expand All @@ -34,12 +33,12 @@ def test_estimate_hazard_ratio(self):
eligibility=None,
)
estimate, intervals = estimation_model.estimate_hazard_ratio()
self.assertEqual(estimate["trtrand"], 1.0)
self.assertEqual(round(estimate["trtrand"], 3), 1.936)

def test_invalid_treatment_strategies(self):
timesteps_per_intervention = 1
control_strategy = TreatmentSequence(timesteps_per_intervention, [("t", 0), ("t", 0), ("t", 0)])
treatment_strategy = TreatmentSequence(timesteps_per_intervention, [("t", 1), ("t", 1), ("t", 1)])
control_strategy = [[t, "t", 0] for t in range(1, 4, timesteps_per_intervention)]
treatment_strategy = [[t, "t", 1] for t in range(1, 4, timesteps_per_intervention)]
outcome = "outcome"
fit_bl_switch_formula = "xo_t_do ~ time"
df = pd.read_csv("tests/resources/data/temporal_data.csv")
Expand All @@ -60,8 +59,8 @@ def test_invalid_treatment_strategies(self):

def test_invalid_fault_t_do(self):
timesteps_per_intervention = 1
control_strategy = TreatmentSequence(timesteps_per_intervention, [("t", 0), ("t", 0), ("t", 0)])
treatment_strategy = TreatmentSequence(timesteps_per_intervention, [("t", 1), ("t", 1), ("t", 1)])
control_strategy = [[t, "t", 0] for t in range(1, 4, timesteps_per_intervention)]
treatment_strategy = [[t, "t", 1] for t in range(1, 4, timesteps_per_intervention)]
outcome = "outcome"
fit_bl_switch_formula = "xo_t_do ~ time"
df = pd.read_csv("tests/resources/data/temporal_data.csv")
Expand All @@ -80,3 +79,47 @@ def test_invalid_fault_t_do(self):
estimation_model.df["fault_t_do"] = 0
with self.assertRaises(ValueError):
estimate, intervals = estimation_model.estimate_hazard_ratio()

def test_no_individual_began_control_strategy(self):
timesteps_per_intervention = 1
control_strategy = [[t, "t", 0] for t in range(1, 4, timesteps_per_intervention)]
treatment_strategy = [[t, "t", 1] for t in range(1, 4, timesteps_per_intervention)]
outcome = "outcome"
fit_bl_switch_formula = "xo_t_do ~ time"
df = pd.read_csv("tests/resources/data/temporal_data.csv")
df["t"] = 1
df["ok"] = df["outcome"] == 1
with self.assertRaises(ValueError):
estimation_model = IPCWEstimator(
df,
timesteps_per_intervention,
control_strategy,
treatment_strategy,
outcome,
"ok",
fit_bl_switch_formula=fit_bl_switch_formula,
fit_bltd_switch_formula=fit_bl_switch_formula,
eligibility=None,
)

def test_no_individual_began_treatment_strategy(self):
timesteps_per_intervention = 1
control_strategy = [[t, "t", 0] for t in range(1, 4, timesteps_per_intervention)]
treatment_strategy = [[t, "t", 1] for t in range(1, 4, timesteps_per_intervention)]
outcome = "outcome"
fit_bl_switch_formula = "xo_t_do ~ time"
df = pd.read_csv("tests/resources/data/temporal_data.csv")
df["t"] = 0
df["ok"] = df["outcome"] == 1
with self.assertRaises(ValueError):
estimation_model = IPCWEstimator(
df,
timesteps_per_intervention,
control_strategy,
treatment_strategy,
outcome,
"ok",
fit_bl_switch_formula=fit_bl_switch_formula,
fit_bltd_switch_formula=fit_bl_switch_formula,
eligibility=None,
)
1 change: 0 additions & 1 deletion tests/estimation_tests/test_linear_regression_estimator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import matplotlib.pyplot as plt
from causal_testing.specification.variable import Input
from causal_testing.utils.validation import CausalValidator
from causal_testing.specification.capabilities import TreatmentSequence

from causal_testing.estimation.linear_regression_estimator import LinearRegressionEstimator
from causal_testing.estimation.genetic_programming_regression_fitter import reciprocal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import matplotlib.pyplot as plt
from causal_testing.specification.variable import Input
from causal_testing.utils.validation import CausalValidator
from causal_testing.specification.capabilities import TreatmentSequence
from causal_testing.estimation.logistic_regression_estimator import LogisticRegressionEstimator


Expand Down
36 changes: 0 additions & 36 deletions tests/specification_tests/test_capabilities.py

This file was deleted.

14 changes: 7 additions & 7 deletions tests/testing_tests/test_causal_test_adequacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
from causal_testing.specification.variable import Input, Output, Meta
from causal_testing.specification.scenario import Scenario
from causal_testing.specification.causal_specification import CausalSpecification
from causal_testing.specification.capabilities import TreatmentSequence
from causal_testing.testing.causal_test_adequacy import DataAdequacy


Expand Down Expand Up @@ -112,8 +111,8 @@ def test_data_adequacy_cateogorical(self):

def test_data_adequacy_group_by(self):
timesteps_per_intervention = 1
control_strategy = TreatmentSequence(timesteps_per_intervention, [("t", 0), ("t", 0), ("t", 0)])
treatment_strategy = TreatmentSequence(timesteps_per_intervention, [("t", 1), ("t", 1), ("t", 1)])
control_strategy = [[t, "t", 0] for t in range(1, 4, timesteps_per_intervention)]
treatment_strategy = [[t, "t", 1] for t in range(1, 4, timesteps_per_intervention)]
outcome = "outcome"
fit_bl_switch_formula = "xo_t_do ~ time"
df = pd.read_csv("tests/resources/data/temporal_data.csv")
Expand Down Expand Up @@ -145,11 +144,12 @@ def test_data_adequacy_group_by(self):
causal_test_result = causal_test_case.execute_test(estimation_model, None)
adequacy_metric = DataAdequacy(causal_test_case, estimation_model, group_by="id")
adequacy_metric.measure_adequacy()
causal_test_result.adequacy = adequacy_metric
print(causal_test_result.adequacy.to_dict())
adequacy_dict = adequacy_metric.to_dict()
self.assertEqual(round(adequacy_dict["kurtosis"]["trtrand"], 3), -0.336)
adequacy_dict.pop("kurtosis")
self.assertEqual(
causal_test_result.adequacy.to_dict(),
{"kurtosis": {"trtrand": 0.0}, "bootstrap_size": 100, "passing": 0, "successful": 95},
adequacy_dict,
{"bootstrap_size": 100, "passing": 28, "successful": 95},
)

def test_dag_adequacy_dependent(self):
Expand Down
Loading