@@ -56,6 +56,8 @@ class InterruptedTimeSeries(BaseExperiment):
5656 treatment_time : Union[int, float, pd.Timestamp]
5757 The time when treatment occurred, should be in reference to the data index.
5858 Must match the index type (DatetimeIndex requires pd.Timestamp).
59+ **INCLUSIVE**: Observations at exactly ``treatment_time`` are included in the
60+ post-intervention period (uses ``>=`` comparison).
5961 formula : str
6062 A statistical model formula using patsy syntax (e.g., "y ~ 1 + t + C(month)").
6163 model : Union[PyMCModel, RegressorMixin], optional
@@ -65,33 +67,11 @@ class InterruptedTimeSeries(BaseExperiment):
6567 The time when treatment ended, enabling three-period analysis. Must be
6668 greater than ``treatment_time`` and within the data range. If None (default),
6769 the analysis assumes a permanent intervention (two-period design).
70+ **INCLUSIVE**: Observations at exactly ``treatment_end_time`` are included in the
71+ post-intervention period (uses ``>=`` comparison).
6872 **kwargs : dict
6973 Additional keyword arguments passed to the model.
7074
71- Attributes
72- ----------
73- When ``treatment_end_time`` is provided, the following additional attributes
74- are available:
75-
76- data_intervention : pd.DataFrame
77- Data from the intervention period (between ``treatment_time`` and
78- ``treatment_end_time``).
79- data_post_intervention : pd.DataFrame
80- Data from the post-intervention period (after ``treatment_end_time``).
81- intervention_pred : az.InferenceData or np.ndarray
82- Counterfactual predictions for the intervention period (PyMC: InferenceData,
83- sklearn: numpy array).
84- post_intervention_pred : az.InferenceData or np.ndarray
85- Counterfactual predictions for the post-intervention period.
86- intervention_impact : xr.DataArray
87- Causal impact during the intervention period.
88- post_intervention_impact : xr.DataArray
89- Causal impact during the post-intervention period.
90- intervention_impact_cumulative : xr.DataArray
91- Cumulative causal impact during the intervention period.
92- post_intervention_impact_cumulative : xr.DataArray
93- Cumulative causal impact during the post-intervention period.
94-
9575 Examples
9676 --------
9777 **Two-period design (permanent intervention):**
@@ -172,6 +152,9 @@ def __init__(
172152 # set experiment type - usually done in subclasses
173153 self .expt_type = "Pre-Post Fit"
174154 # split data in to pre and post intervention
155+ # NOTE: treatment_time is INCLUSIVE (>=) in post-period
156+ # Pre-period: index < treatment_time (exclusive)
157+ # Post-period: index >= treatment_time (inclusive)
175158 self .datapre = data [data .index < self .treatment_time ]
176159 self .datapost = data [data .index >= self .treatment_time ]
177160
@@ -379,11 +362,13 @@ def input_validation(
379362 )
380363 # Validate treatment_end_time > treatment_time
381364 # Type check: we've already validated both match the index type, so they're compatible
365+ # NOTE: Both treatment_time and treatment_end_time are INCLUSIVE (>=) in their respective periods
382366 if treatment_end_time <= treatment_time : # type: ignore[operator]
383367 raise ValueError (
384368 f"treatment_end_time ({ treatment_end_time } ) must be greater than treatment_time ({ treatment_time } )"
385369 )
386370 # Validate treatment_end_time is within data range
371+ # NOTE: treatment_end_time is INCLUSIVE, so it can equal data.index.max()
387372 if treatment_end_time > data .index .max (): # type: ignore[operator]
388373 raise ValueError (
389374 f"treatment_end_time ({ treatment_end_time } ) is beyond the data range (max: { data .index .max ()} )"
@@ -398,8 +383,15 @@ def _split_post_period(self) -> None:
398383 Key insight: intervention_pred and post_intervention_pred are slices of post_pred,
399384 not new computations. The model makes one continuous forecast (post_pred), which is
400385 then sliced into two periods for analysis.
386+
387+ NOTE: treatment_end_time is INCLUSIVE (>=) in post-intervention period.
388+ - Intervention period: treatment_time <= index < treatment_end_time
389+ - Post-intervention period: index >= treatment_end_time (inclusive)
401390 """
402391 # 1. Create boolean masks based on treatment_end_time
392+ # NOTE: treatment_end_time is INCLUSIVE (>=) in post-intervention period
393+ # Intervention period: index < treatment_end_time (exclusive)
394+ # Post-intervention period: index >= treatment_end_time (inclusive)
403395 during_mask = self .datapost .index < self .treatment_end_time
404396 post_mask = self .datapost .index >= self .treatment_end_time
405397
0 commit comments