xai4tsc 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. xai4tsc-1.0.0/LICENSE +21 -0
  2. xai4tsc-1.0.0/PKG-INFO +280 -0
  3. xai4tsc-1.0.0/README.md +244 -0
  4. xai4tsc-1.0.0/pyproject.toml +134 -0
  5. xai4tsc-1.0.0/src/xai4tsc/__init__.py +124 -0
  6. xai4tsc-1.0.0/src/xai4tsc/data/__init__.py +43 -0
  7. xai4tsc-1.0.0/src/xai4tsc/data/base.py +678 -0
  8. xai4tsc-1.0.0/src/xai4tsc/data/data_loaders.py +146 -0
  9. xai4tsc-1.0.0/src/xai4tsc/data/datasets.py +765 -0
  10. xai4tsc-1.0.0/src/xai4tsc/evaluation/__init__.py +31 -0
  11. xai4tsc-1.0.0/src/xai4tsc/evaluation/base.py +344 -0
  12. xai4tsc-1.0.0/src/xai4tsc/evaluation/evaluate.py +180 -0
  13. xai4tsc-1.0.0/src/xai4tsc/evaluation/frequency_evaluate.py +333 -0
  14. xai4tsc-1.0.0/src/xai4tsc/evaluation/timefrequency_auc.py +248 -0
  15. xai4tsc-1.0.0/src/xai4tsc/evaluation/timefrequency_perturbation.py +112 -0
  16. xai4tsc-1.0.0/src/xai4tsc/models/__init__.py +41 -0
  17. xai4tsc-1.0.0/src/xai4tsc/models/base.py +639 -0
  18. xai4tsc-1.0.0/src/xai4tsc/models/models.py +883 -0
  19. xai4tsc-1.0.0/src/xai4tsc/utils/__init__.py +45 -0
  20. xai4tsc-1.0.0/src/xai4tsc/utils/animation.py +194 -0
  21. xai4tsc-1.0.0/src/xai4tsc/utils/defaults.py +36 -0
  22. xai4tsc-1.0.0/src/xai4tsc/utils/fourier_transforms.py +443 -0
  23. xai4tsc-1.0.0/src/xai4tsc/utils/perturbation.py +148 -0
  24. xai4tsc-1.0.0/src/xai4tsc/utils/plot.py +599 -0
  25. xai4tsc-1.0.0/src/xai4tsc/utils/utils.py +153 -0
  26. xai4tsc-1.0.0/src/xai4tsc/xai/__init__.py +52 -0
  27. xai4tsc-1.0.0/src/xai4tsc/xai/_types.py +106 -0
  28. xai4tsc-1.0.0/src/xai4tsc/xai/base.py +238 -0
  29. xai4tsc-1.0.0/src/xai4tsc/xai/explain.py +446 -0
  30. xai4tsc-1.0.0/src/xai4tsc/xai/explanation_domains.py +130 -0
  31. xai4tsc-1.0.0/src/xai4tsc/xai/feature_attribution.py +520 -0
  32. xai4tsc-1.0.0/src/xai4tsc/xai/freqrise.py +240 -0
  33. xai4tsc-1.0.0/src/xai4tsc/xai/random_baseline.py +109 -0
  34. xai4tsc-1.0.0/src/xai4tsc/xai/wrappers.py +92 -0
xai4tsc-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 TimeXAI Junior Research Group
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
xai4tsc-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,280 @@
1
+ Metadata-Version: 2.4
2
+ Name: xai4tsc
3
+ Version: 1.0.0
4
+ Summary: An evaluation framework for eXplainable AI (XAI) methods applied to Time Series Classification (TSC).
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Keywords: xai,explainable-ai,interpretability,time-series,time-series-classification,captum,quantus,pytorch
8
+ Author: TimeXAI Research Group
9
+ Maintainer: Louis Peter
10
+ Maintainer-email: Louis.Peter@kite.thm.de
11
+ Requires-Python: >=3.12,<3.14
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
+ Classifier: Typing :: Typed
20
+ Requires-Dist: cachetools (>=6.1.0,<7.0.0)
21
+ Requires-Dist: captum (>=0.8.0,<0.9.0)
22
+ Requires-Dist: matplotlib (>=3.10.5,<4.0.0)
23
+ Requires-Dist: protobuf (==3.20.3)
24
+ Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
25
+ Requires-Dist: quantus[torch] (>=0.6.0,<0.7.0)
26
+ Requires-Dist: scikit-learn (>=1.6)
27
+ Requires-Dist: shap (>=0.48.0,<0.49.0)
28
+ Requires-Dist: sktime (>=0.40.1,<0.41.0)
29
+ Project-URL: Bug Tracker, https://github.com/TimeXAIgroup/XAI4TSC/issues
30
+ Project-URL: Changelog, https://github.com/TimeXAIgroup/XAI4TSC/releases
31
+ Project-URL: Documentation, https://timexaigroup.github.io/XAI4TSC/
32
+ Project-URL: Homepage, https://github.com/TimeXAIgroup/XAI4TSC
33
+ Project-URL: Repository, https://github.com/TimeXAIgroup/XAI4TSC
34
+ Description-Content-Type: text/markdown
35
+
36
+ # XAI4TSC
37
+
38
+ An evaluation framework for eXplainable AI (XAI) methods applied to Time Series Classification
39
+ (TSC), developed by the TimeXAI Research Group.
40
+
41
+ XAI4TSC has two independent use cases:
42
+
43
+ - **Standalone experiment runner** — clone the repo, write a YAML config, run experiments from
44
+ the command line.
45
+ - **Importable Python package** — `pip install -e .` and use the public API in your own code,
46
+ notebooks, or scripts.
47
+
48
+ ---
49
+
50
+ ## Installation
51
+
52
+ ### Standalone (experiment runner)
53
+
54
+ We use Poetry for package management inside a Conda environment:
55
+
56
+ 1. Install the Conda environment from `environment.yml`:
57
+ ```bash
58
+ conda env create # environment.yml is picked up automatically
59
+ ```
60
+ 2. Activate the environment:
61
+ ```bash
62
+ conda activate xai4tsc
63
+ ```
64
+ 3. Create a local virtual environment:
65
+ ```bash
66
+ python -m venv .venv
67
+ ```
68
+ 4. Activate the local environment:
69
+ ```bash
70
+ source .venv/bin/activate
71
+ ```
72
+ 5. Confirm setup — check which `python` and `poetry` your shell uses:
73
+ ```bash
74
+ which python # should point to the local venv
75
+ which poetry # should point to the conda environment
76
+ ```
77
+ 6. Install dependencies with Poetry:
78
+ ```bash
79
+ poetry install # use --dry-run to preview safely
80
+ ```
81
+
82
+ ### Package only
83
+
84
+ ```bash
85
+ pip install xai4tsc
86
+ ```
87
+
88
+ Or, for a local/editable install from a clone:
89
+
90
+ ```bash
91
+ pip install -e PATH/TO/REPOSITORY
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Project layout
97
+
98
+ ```
99
+ xai4tsc/
100
+ ├── experiment_runner/ # Standalone CLI — owns all config and orchestration logic
101
+ │ ├── main.py # Entry point: python -m experiment_runner.main --conf ...
102
+ │ ├── config.py # Config loading, validation, defaults
103
+ │ ├── cache.py # Runner-level split caching helpers
104
+ │ ├── explain.py # Runner adapter for xai4tsc.xai
105
+ │ ├── evaluate.py # Runner adapter for xai4tsc.evaluation
106
+ │ ├── log_setup.py # Logging setup for the standalone runner
107
+ │ └── configs/
108
+ │ ├── master.yaml # Annotated reference — all available options and defaults
109
+ │ ├── example.yaml # Go-to demo: synthetic data, time-domain explainers + metrics
110
+ │ ├── example_frequency.yaml # Frequency / time-frequency showcase (FreqRISE, freq metrics)
111
+ │ ├── ucr_benchmark.yaml # Full UCR sweep (LeNet + Integrated Gradients + Complexity)
112
+ │ └── uea_benchmark.yaml # Full UEA sweep (skips OOM-risky datasets)
113
+
114
+ ├── src/xai4tsc/ # Importable package
115
+ │ ├── data/
116
+ │ │ ├── datasets.py # UcrUeaDataset, LocalDataset, SyntheticDataset
117
+ │ │ └── ... # base classes, data loaders
118
+ │ ├── models/ # ModelBase, built-in models, registry
119
+ │ ├── xai/ # Explainer ABC, generate_explanation(), built-in explainers
120
+ │ ├── evaluation/ # evaluate(), Quantus metric registry
121
+ │ └── utils/ # Shared utilities (dict_to_args, merge_dicts, rescale_array, plot)
122
+
123
+ └── tests/
124
+ ├── conftest.py # Session-scoped fixtures (GunPoint download, split, model)
125
+ ├── fixtures/
126
+ │ └── test_config.yaml # Minimal runner config for integration tests
127
+ ├── unit/ # Fast, no-I/O tests (@pytest.mark.unit)
128
+ └── integration/ # Full pipeline tests (@pytest.mark.integration)
129
+ ```
130
+
131
+ ---
132
+
133
+ ## Running an experiment
134
+
135
+ Run the runner as a module from the repository root:
136
+
137
+ ```bash
138
+ python -m experiment_runner.main --conf experiment_runner/configs/example.yaml
139
+ python -m experiment_runner.main --conf experiment_runner/configs/example.yaml --debug
140
+ ```
141
+
142
+ Four ready-to-run configs ship under `experiment_runner/configs/`:
143
+
144
+ - `example.yaml` — the go-to demo (and the default when `--conf` is omitted):
145
+ the synthetic `freq_shapes` dataset, two models, and time-domain explainers
146
+ and metrics. Needs no download.
147
+ - `example_frequency.yaml` — the same dataset explained with FreqRISE in the
148
+ frequency and time-frequency domains, scored with the frequency metrics.
149
+ - `ucr_benchmark.yaml` / `uea_benchmark.yaml` — full-archive sweeps with a
150
+ minimal model/explainer/metric stack.
151
+
152
+ Edit or copy any of them to configure datasets, models, explainers, and metrics.
153
+ `master.yaml` contains annotated documentation for every available option.
154
+
155
+ ---
156
+
157
+ ## Testing
158
+
159
+ The test suite uses two pytest markers to separate fast unit tests from slow
160
+ integration tests that require a live dataset and a training run.
161
+
162
+ ```bash
163
+ # Unit tests only — fast, no I/O, no training
164
+ pytest -m unit
165
+
166
+ # Integration tests only — downloads GunPoint on first run, trains a model
167
+ pytest -m integration
168
+
169
+ # Full suite
170
+ pytest
171
+ ```
172
+
173
+ GunPoint is downloaded automatically on the first integration run and cached in
174
+ `tests/cache/` (override with the `XAI4TSC_TEST_CACHE` environment variable).
175
+
176
+ ---
177
+
178
+ ## Using xai4tsc as a package
179
+
180
+ ```python
181
+ import xai4tsc
182
+ from xai4tsc.data import load_dataset, LocalDataset
183
+ from xai4tsc.models.models import load_model
184
+ from xai4tsc.xai.explain import generate_explanation
185
+ from xai4tsc.evaluation.evaluate import evaluate
186
+
187
+ # ── Load data (UCR download or local numpy files) ─────────────────────────────
188
+ ds = load_dataset("GunPoint") # UcrUeaDataset — downloads on first use
189
+ # ds = LocalDataset("/path/to/data", name="MyDataset") # local data.npy + labels.json
190
+
191
+ splits, encoder = ds.split(
192
+ train_split=0.8, val_split=0.1, random_state=42, encode="label"
193
+ )
194
+ train_data, train_labels, _ = splits[0]
195
+ test_data, test_labels, _ = splits[1]
196
+
197
+ # ── Train a model ─────────────────────────────────────────────────────────────
198
+ model = load_model(
199
+ {"model": "FCN", "init_params": {"in_channels": 1, "num_classes": 2}},
200
+ device="cpu",
201
+ )
202
+ model.train_model(
203
+ train_data, train_labels,
204
+ hyperparams={"epochs": 50, "batchsize": 32, "loss_func": "CrossEntropy",
205
+ "optimizer": "adam", "learn_rate": 0.001, "patience": 10},
206
+ save_path="results", # best checkpoint + training plots land here
207
+ )
208
+
209
+ # ── Generate explanations ─────────────────────────────────────────────────────
210
+ exp = generate_explanation(
211
+ method="integrated_gradients",
212
+ model=model,
213
+ data=test_data,
214
+ labels=test_labels,
215
+ encoder=encoder,
216
+ indices=[0, 1, 2],
217
+ device="cpu",
218
+ )
219
+ # exp.exp_values — numpy array, same shape as test_data[[0, 1, 2]]
220
+
221
+ # ── Evaluate ──────────────────────────────────────────────────────────────────
222
+ score = evaluate(
223
+ model=model,
224
+ metric="Complexity",
225
+ explanation=exp,
226
+ data=test_data[exp.indices],
227
+ labels=test_labels[exp.indices],
228
+ metric_class_params={"normalise": True, "abs": True, "disable_warnings": True},
229
+ device="cpu",
230
+ )
231
+
232
+ # ── Register a custom explainer ───────────────────────────────────────────────
233
+ from captum.attr import Saliency
234
+ from xai4tsc import GradientExplainer, register_explainer
235
+
236
+ class SaliencyExplainer(GradientExplainer):
237
+ def _get_captum_attribution(self, model):
238
+ return Saliency(model)
239
+
240
+ register_explainer("saliency", SaliencyExplainer)
241
+ exp2 = generate_explanation(
242
+ "saliency", model=model, data=test_data,
243
+ labels=test_labels, encoder=encoder, indices=[0], device="cpu",
244
+ )
245
+ ```
246
+
247
+ ---
248
+
249
+ ## Built on
250
+
251
+ - **Computational backends:** PyTorch, scikit-learn
252
+ - **Explanation backend:** Captum
253
+ - **Evaluation backend:** Quantus
254
+
255
+ ---
256
+
257
+ ## Contributing
258
+
259
+ Contributions are welcome. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the
260
+ development setup, code style and quality gate, testing conventions, and the
261
+ pattern for adding a new model, explainer, or metric. By participating you agree
262
+ to the [Code of Conduct](CODE_OF_CONDUCT.md). The project is released under the
263
+ [MIT License](LICENSE).
264
+
265
+ ---
266
+
267
+ ## Disclaimer
268
+
269
+ XAI4TSC bundles **clean-room re-implementations** of models, explainers, and
270
+ metrics from the research literature, alongside thin wrappers around third-party
271
+ libraries (Captum, Quantus). These implementations have **not** been verified by
272
+ the original authors and may differ from the source papers or reference code in
273
+ ways that affect results.
274
+
275
+ Evaluation scores are an empirical, sometimes contested, proxy for explanation
276
+ quality — treat them as guidance, not ground truth. When using XAI4TSC for
277
+ research, cite the original papers, state which implementation you used, and,
278
+ where possible, validate against a reference implementation. See the
279
+ [full disclaimer](docs/source/disclaimer.md) in the documentation for details.
280
+
@@ -0,0 +1,244 @@
1
+ # XAI4TSC
2
+
3
+ An evaluation framework for eXplainable AI (XAI) methods applied to Time Series Classification
4
+ (TSC), developed by the TimeXAI Research Group.
5
+
6
+ XAI4TSC has two independent use cases:
7
+
8
+ - **Standalone experiment runner** — clone the repo, write a YAML config, run experiments from
9
+ the command line.
10
+ - **Importable Python package** — `pip install -e .` and use the public API in your own code,
11
+ notebooks, or scripts.
12
+
13
+ ---
14
+
15
+ ## Installation
16
+
17
+ ### Standalone (experiment runner)
18
+
19
+ We use Poetry for package management inside a Conda environment:
20
+
21
+ 1. Install the Conda environment from `environment.yml`:
22
+ ```bash
23
+ conda env create # environment.yml is picked up automatically
24
+ ```
25
+ 2. Activate the environment:
26
+ ```bash
27
+ conda activate xai4tsc
28
+ ```
29
+ 3. Create a local virtual environment:
30
+ ```bash
31
+ python -m venv .venv
32
+ ```
33
+ 4. Activate the local environment:
34
+ ```bash
35
+ source .venv/bin/activate
36
+ ```
37
+ 5. Confirm setup — check which `python` and `poetry` your shell uses:
38
+ ```bash
39
+ which python # should point to the local venv
40
+ which poetry # should point to the conda environment
41
+ ```
42
+ 6. Install dependencies with Poetry:
43
+ ```bash
44
+ poetry install # use --dry-run to preview safely
45
+ ```
46
+
47
+ ### Package only
48
+
49
+ ```bash
50
+ pip install xai4tsc
51
+ ```
52
+
53
+ Or, for a local/editable install from a clone:
54
+
55
+ ```bash
56
+ pip install -e PATH/TO/REPOSITORY
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Project layout
62
+
63
+ ```
64
+ xai4tsc/
65
+ ├── experiment_runner/ # Standalone CLI — owns all config and orchestration logic
66
+ │ ├── main.py # Entry point: python -m experiment_runner.main --conf ...
67
+ │ ├── config.py # Config loading, validation, defaults
68
+ │ ├── cache.py # Runner-level split caching helpers
69
+ │ ├── explain.py # Runner adapter for xai4tsc.xai
70
+ │ ├── evaluate.py # Runner adapter for xai4tsc.evaluation
71
+ │ ├── log_setup.py # Logging setup for the standalone runner
72
+ │ └── configs/
73
+ │ ├── master.yaml # Annotated reference — all available options and defaults
74
+ │ ├── example.yaml # Go-to demo: synthetic data, time-domain explainers + metrics
75
+ │ ├── example_frequency.yaml # Frequency / time-frequency showcase (FreqRISE, freq metrics)
76
+ │ ├── ucr_benchmark.yaml # Full UCR sweep (LeNet + Integrated Gradients + Complexity)
77
+ │ └── uea_benchmark.yaml # Full UEA sweep (skips OOM-risky datasets)
78
+
79
+ ├── src/xai4tsc/ # Importable package
80
+ │ ├── data/
81
+ │ │ ├── datasets.py # UcrUeaDataset, LocalDataset, SyntheticDataset
82
+ │ │ └── ... # base classes, data loaders
83
+ │ ├── models/ # ModelBase, built-in models, registry
84
+ │ ├── xai/ # Explainer ABC, generate_explanation(), built-in explainers
85
+ │ ├── evaluation/ # evaluate(), Quantus metric registry
86
+ │ └── utils/ # Shared utilities (dict_to_args, merge_dicts, rescale_array, plot)
87
+
88
+ └── tests/
89
+ ├── conftest.py # Session-scoped fixtures (GunPoint download, split, model)
90
+ ├── fixtures/
91
+ │ └── test_config.yaml # Minimal runner config for integration tests
92
+ ├── unit/ # Fast, no-I/O tests (@pytest.mark.unit)
93
+ └── integration/ # Full pipeline tests (@pytest.mark.integration)
94
+ ```
95
+
96
+ ---
97
+
98
+ ## Running an experiment
99
+
100
+ Run the runner as a module from the repository root:
101
+
102
+ ```bash
103
+ python -m experiment_runner.main --conf experiment_runner/configs/example.yaml
104
+ python -m experiment_runner.main --conf experiment_runner/configs/example.yaml --debug
105
+ ```
106
+
107
+ Four ready-to-run configs ship under `experiment_runner/configs/`:
108
+
109
+ - `example.yaml` — the go-to demo (and the default when `--conf` is omitted):
110
+ the synthetic `freq_shapes` dataset, two models, and time-domain explainers
111
+ and metrics. Needs no download.
112
+ - `example_frequency.yaml` — the same dataset explained with FreqRISE in the
113
+ frequency and time-frequency domains, scored with the frequency metrics.
114
+ - `ucr_benchmark.yaml` / `uea_benchmark.yaml` — full-archive sweeps with a
115
+ minimal model/explainer/metric stack.
116
+
117
+ Edit or copy any of them to configure datasets, models, explainers, and metrics.
118
+ `master.yaml` contains annotated documentation for every available option.
119
+
120
+ ---
121
+
122
+ ## Testing
123
+
124
+ The test suite uses two pytest markers to separate fast unit tests from slow
125
+ integration tests that require a live dataset and a training run.
126
+
127
+ ```bash
128
+ # Unit tests only — fast, no I/O, no training
129
+ pytest -m unit
130
+
131
+ # Integration tests only — downloads GunPoint on first run, trains a model
132
+ pytest -m integration
133
+
134
+ # Full suite
135
+ pytest
136
+ ```
137
+
138
+ GunPoint is downloaded automatically on the first integration run and cached in
139
+ `tests/cache/` (override with the `XAI4TSC_TEST_CACHE` environment variable).
140
+
141
+ ---
142
+
143
+ ## Using xai4tsc as a package
144
+
145
+ ```python
146
+ import xai4tsc
147
+ from xai4tsc.data import load_dataset, LocalDataset
148
+ from xai4tsc.models.models import load_model
149
+ from xai4tsc.xai.explain import generate_explanation
150
+ from xai4tsc.evaluation.evaluate import evaluate
151
+
152
+ # ── Load data (UCR download or local numpy files) ─────────────────────────────
153
+ ds = load_dataset("GunPoint") # UcrUeaDataset — downloads on first use
154
+ # ds = LocalDataset("/path/to/data", name="MyDataset") # local data.npy + labels.json
155
+
156
+ splits, encoder = ds.split(
157
+ train_split=0.8, val_split=0.1, random_state=42, encode="label"
158
+ )
159
+ train_data, train_labels, _ = splits[0]
160
+ test_data, test_labels, _ = splits[1]
161
+
162
+ # ── Train a model ─────────────────────────────────────────────────────────────
163
+ model = load_model(
164
+ {"model": "FCN", "init_params": {"in_channels": 1, "num_classes": 2}},
165
+ device="cpu",
166
+ )
167
+ model.train_model(
168
+ train_data, train_labels,
169
+ hyperparams={"epochs": 50, "batchsize": 32, "loss_func": "CrossEntropy",
170
+ "optimizer": "adam", "learn_rate": 0.001, "patience": 10},
171
+ save_path="results", # best checkpoint + training plots land here
172
+ )
173
+
174
+ # ── Generate explanations ─────────────────────────────────────────────────────
175
+ exp = generate_explanation(
176
+ method="integrated_gradients",
177
+ model=model,
178
+ data=test_data,
179
+ labels=test_labels,
180
+ encoder=encoder,
181
+ indices=[0, 1, 2],
182
+ device="cpu",
183
+ )
184
+ # exp.exp_values — numpy array, same shape as test_data[[0, 1, 2]]
185
+
186
+ # ── Evaluate ──────────────────────────────────────────────────────────────────
187
+ score = evaluate(
188
+ model=model,
189
+ metric="Complexity",
190
+ explanation=exp,
191
+ data=test_data[exp.indices],
192
+ labels=test_labels[exp.indices],
193
+ metric_class_params={"normalise": True, "abs": True, "disable_warnings": True},
194
+ device="cpu",
195
+ )
196
+
197
+ # ── Register a custom explainer ───────────────────────────────────────────────
198
+ from captum.attr import Saliency
199
+ from xai4tsc import GradientExplainer, register_explainer
200
+
201
+ class SaliencyExplainer(GradientExplainer):
202
+ def _get_captum_attribution(self, model):
203
+ return Saliency(model)
204
+
205
+ register_explainer("saliency", SaliencyExplainer)
206
+ exp2 = generate_explanation(
207
+ "saliency", model=model, data=test_data,
208
+ labels=test_labels, encoder=encoder, indices=[0], device="cpu",
209
+ )
210
+ ```
211
+
212
+ ---
213
+
214
+ ## Built on
215
+
216
+ - **Computational backends:** PyTorch, scikit-learn
217
+ - **Explanation backend:** Captum
218
+ - **Evaluation backend:** Quantus
219
+
220
+ ---
221
+
222
+ ## Contributing
223
+
224
+ Contributions are welcome. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the
225
+ development setup, code style and quality gate, testing conventions, and the
226
+ pattern for adding a new model, explainer, or metric. By participating you agree
227
+ to the [Code of Conduct](CODE_OF_CONDUCT.md). The project is released under the
228
+ [MIT License](LICENSE).
229
+
230
+ ---
231
+
232
+ ## Disclaimer
233
+
234
+ XAI4TSC bundles **clean-room re-implementations** of models, explainers, and
235
+ metrics from the research literature, alongside thin wrappers around third-party
236
+ libraries (Captum, Quantus). These implementations have **not** been verified by
237
+ the original authors and may differ from the source papers or reference code in
238
+ ways that affect results.
239
+
240
+ Evaluation scores are an empirical, sometimes contested, proxy for explanation
241
+ quality — treat them as guidance, not ground truth. When using XAI4TSC for
242
+ research, cite the original papers, state which implementation you used, and,
243
+ where possible, validate against a reference implementation. See the
244
+ [full disclaimer](docs/source/disclaimer.md) in the documentation for details.
@@ -0,0 +1,134 @@
1
+ [project]
2
+ name = "xai4tsc"
3
+ version = "1.0.0"
4
+ description = "An evaluation framework for eXplainable AI (XAI) methods applied to Time Series Classification (TSC)."
5
+ authors = [
6
+ {name = "TimeXAI Research Group"}
7
+ ]
8
+ maintainers = [
9
+ {name = "Louis Peter", email = "Louis.Peter@kite.thm.de"}
10
+ ]
11
+ license = "MIT"
12
+ readme = "README.md"
13
+ requires-python = ">=3.12,<3.14"
14
+ keywords = [
15
+ "xai",
16
+ "explainable-ai",
17
+ "interpretability",
18
+ "time-series",
19
+ "time-series-classification",
20
+ "captum",
21
+ "quantus",
22
+ "pytorch",
23
+ ]
24
+ # The MIT license classifier is intentionally omitted: the SPDX `license`
25
+ # field above already declares it (PEP 639), and mixing the two is discouraged.
26
+ classifiers = [
27
+ "Development Status :: 5 - Production/Stable",
28
+ "Intended Audience :: Science/Research",
29
+ "Operating System :: OS Independent",
30
+ "Programming Language :: Python :: 3",
31
+ "Programming Language :: Python :: 3.12",
32
+ "Programming Language :: Python :: 3.13",
33
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
34
+ "Typing :: Typed",
35
+ ]
36
+ dependencies = [
37
+ "sktime (>=0.40.1,<0.41.0)",
38
+ "pyyaml (>=6.0.2,<7.0.0)",
39
+ "shap (>=0.48.0,<0.49.0)",
40
+ "captum (>=0.8.0,<0.9.0)",
41
+ "cachetools (>=6.1.0,<7.0.0)",
42
+ "matplotlib (>=3.10.5,<4.0.0)",
43
+ "protobuf (==3.20.3)",
44
+ "quantus[torch] (>=0.6.0,<0.7.0)",
45
+ "scikit-learn (>=1.6)"
46
+ ]
47
+
48
+ [project.urls]
49
+ Homepage = "https://github.com/TimeXAIgroup/XAI4TSC"
50
+ Repository = "https://github.com/TimeXAIgroup/XAI4TSC"
51
+ Documentation = "https://timexaigroup.github.io/XAI4TSC/"
52
+ "Bug Tracker" = "https://github.com/TimeXAIgroup/XAI4TSC/issues"
53
+ Changelog = "https://github.com/TimeXAIgroup/XAI4TSC/releases"
54
+
55
+ [build-system]
56
+ requires = ["poetry-core>=2.0.0,<3.0.0"]
57
+ build-backend = "poetry.core.masonry.api"
58
+
59
+ [tool.poetry.group.dev.dependencies]
60
+ ruff = "^0.15.14"
61
+ pytest = "^9.0.3"
62
+ pytest-cov = "^7.0"
63
+
64
+
65
+
66
+ [tool.poetry.group.docs.dependencies]
67
+ sphinx = "^9.1.0"
68
+ sphinx-autoapi = "^3.8.0"
69
+ sphinx-rtd-theme = "^3.1.0"
70
+ myst-parser = "^5.1.0"
71
+
72
+ [tool.pytest.ini_options]
73
+ testpaths = ["tests"]
74
+ addopts = "-v"
75
+ markers = [
76
+ "unit: fast tests with no I/O or training — run constantly during development",
77
+ "integration: full pipeline tests with real data and training — run explicitly",
78
+ ]
79
+
80
+ # Coverage is opt-in: pass --cov on the command line so the default fast
81
+ # `pytest -m unit` run stays free of measurement overhead. See CLAUDE.md.
82
+ [tool.coverage.run]
83
+ source = ["src/xai4tsc", "experiment_runner"]
84
+ branch = true # also track which if/else branches are taken, not just lines
85
+
86
+ [tool.coverage.report]
87
+ show_missing = true
88
+ exclude_lines = [
89
+ "pragma: no cover",
90
+ "if TYPE_CHECKING:",
91
+ "raise NotImplementedError",
92
+ "if __name__ == .__main__.:",
93
+ "@(abc\\.)?abstractmethod",
94
+ ]
95
+
96
+ [tool.ruff]
97
+ # Source folders, specified to ease detection and support GitHub workflow.
98
+ src = ["src", "experiment_runner"]
99
+ preview = false
100
+ indent-width = 4
101
+ # 88 is the ruff/Black default; it keeps two files readable side by side on a
102
+ # typical screen. Set explicitly so the limit is visible and intentional.
103
+ line-length = 88
104
+ lint.select = [
105
+ "E", # pycodestyle errors
106
+ "W", # pycodestyle warnings
107
+ "F", # pyflakes (real bugs: unused/undefined names)
108
+ "I", # isort import sorting
109
+ "UP", # pyupgrade (modern syntax)
110
+ "B", # flake8-bugbear (likely bugs)
111
+ "SIM", # flake8-simplify
112
+ "RUF", # ruff-specific rules
113
+ "D", # pydocstyle (numpy convention, see below)
114
+ "N", # pep8-naming
115
+ "ANN", # flake8-annotations (typed public API)
116
+ ]
117
+ lint.extend-select = [
118
+ "D213", # enforce summary on second docstring line (counterpart of ignored D212)
119
+ "D417", # keep undocumented-param despite numpy convention
120
+ ]
121
+ lint.ignore = [
122
+ "D203", # using D211: no blank line before class docstring
123
+ "D212", # using D213: summary on second docstring line
124
+ ### specific rules
125
+ "D100",
126
+ "D104",
127
+ ]
128
+ lint.pydocstyle.convention = "numpy"
129
+
130
+ [tool.ruff.lint.per-file-ignores]
131
+ "tests/**" = [
132
+ "ANN", # test functions need no type annotations
133
+ "D103", # test names are self-documenting; no docstrings required
134
+ ]