heterodecomp 0.1.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 (51) hide show
  1. heterodecomp-0.1.0/MANIFEST.in +1 -0
  2. heterodecomp-0.1.0/PKG-INFO +156 -0
  3. heterodecomp-0.1.0/README.md +133 -0
  4. heterodecomp-0.1.0/examples/01_perpca.py +40 -0
  5. heterodecomp-0.1.0/examples/02_hmf.py +45 -0
  6. heterodecomp-0.1.0/examples/03_jive.py +36 -0
  7. heterodecomp-0.1.0/examples/04_robust_jive.py +38 -0
  8. heterodecomp-0.1.0/examples/05_rajive.py +44 -0
  9. heterodecomp-0.1.0/examples/06_slide.py +43 -0
  10. heterodecomp-0.1.0/examples/07_pertucker.py +43 -0
  11. heterodecomp-0.1.0/examples/08_percdl.py +43 -0
  12. heterodecomp-0.1.0/examples/09_robust_pca.py +42 -0
  13. heterodecomp-0.1.0/examples/10_real_bold_no_ground_truth.py +38 -0
  14. heterodecomp-0.1.0/examples/README.md +60 -0
  15. heterodecomp-0.1.0/examples/_common.py +71 -0
  16. heterodecomp-0.1.0/heterodecomp/__init__.py +27 -0
  17. heterodecomp-0.1.0/heterodecomp/_engine/__init__.py +3 -0
  18. heterodecomp-0.1.0/heterodecomp/_engine/metrics.py +169 -0
  19. heterodecomp-0.1.0/heterodecomp/_engine/models/__init__.py +47 -0
  20. heterodecomp-0.1.0/heterodecomp/_engine/models/base.py +66 -0
  21. heterodecomp-0.1.0/heterodecomp/_engine/models/hmf_adapter.py +54 -0
  22. heterodecomp-0.1.0/heterodecomp/_engine/models/jive_adapter.py +121 -0
  23. heterodecomp-0.1.0/heterodecomp/_engine/models/percdl_adapter.py +66 -0
  24. heterodecomp-0.1.0/heterodecomp/_engine/models/perpca_adapter.py +65 -0
  25. heterodecomp-0.1.0/heterodecomp/_engine/models/pertucker_adapter.py +61 -0
  26. heterodecomp-0.1.0/heterodecomp/_engine/models/robust_pca_adapter.py +44 -0
  27. heterodecomp-0.1.0/heterodecomp/_engine/models/slide_adapter.py +113 -0
  28. heterodecomp-0.1.0/heterodecomp/_engine/models/utils.py +88 -0
  29. heterodecomp-0.1.0/heterodecomp/_engine/progress.py +118 -0
  30. heterodecomp-0.1.0/heterodecomp/_engine/types.py +32 -0
  31. heterodecomp-0.1.0/heterodecomp/_engine/vendor/__init__.py +7 -0
  32. heterodecomp-0.1.0/heterodecomp/_engine/vendor/hmf.py +529 -0
  33. heterodecomp-0.1.0/heterodecomp/_engine/vendor/percdl.py +239 -0
  34. heterodecomp-0.1.0/heterodecomp/_engine/vendor/perpca.py +162 -0
  35. heterodecomp-0.1.0/heterodecomp/_engine/vendor/pertucker.py +265 -0
  36. heterodecomp-0.1.0/heterodecomp/_engine/vendor/rajive.py +487 -0
  37. heterodecomp-0.1.0/heterodecomp/_engine/vendor/slide.py +460 -0
  38. heterodecomp-0.1.0/heterodecomp/core.py +734 -0
  39. heterodecomp-0.1.0/heterodecomp/p300.py +231 -0
  40. heterodecomp-0.1.0/heterodecomp.egg-info/PKG-INFO +156 -0
  41. heterodecomp-0.1.0/heterodecomp.egg-info/SOURCES.txt +49 -0
  42. heterodecomp-0.1.0/heterodecomp.egg-info/dependency_links.txt +1 -0
  43. heterodecomp-0.1.0/heterodecomp.egg-info/requires.txt +14 -0
  44. heterodecomp-0.1.0/heterodecomp.egg-info/top_level.txt +1 -0
  45. heterodecomp-0.1.0/pyproject.toml +32 -0
  46. heterodecomp-0.1.0/setup.cfg +4 -0
  47. heterodecomp-0.1.0/tests/test_algorithms.py +69 -0
  48. heterodecomp-0.1.0/tests/test_core.py +96 -0
  49. heterodecomp-0.1.0/tests/test_fixtures.py +71 -0
  50. heterodecomp-0.1.0/tests/test_p300.py +68 -0
  51. heterodecomp-0.1.0/tests/test_progress.py +36 -0
@@ -0,0 +1 @@
1
+ recursive-include examples *.py *.md
@@ -0,0 +1,156 @@
1
+ Metadata-Version: 2.4
2
+ Name: heterodecomp
3
+ Version: 0.1.0
4
+ Summary: Shared and individual pattern decomposition for heterogeneous data
5
+ Classifier: Development Status :: 3 - Alpha
6
+ Classifier: Intended Audience :: Science/Research
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ Requires-Dist: numpy>=1.23
12
+ Requires-Dist: openpyxl>=3.1
13
+ Requires-Dist: pandas>=1.5
14
+ Requires-Dist: pillow>=9
15
+ Requires-Dist: scipy>=1.9
16
+ Requires-Dist: tensorly>=0.8
17
+ Requires-Dist: torch>=2.0
18
+ Provides-Extra: eeg
19
+ Requires-Dist: mne>=1.6; extra == "eeg"
20
+ Provides-Extra: test
21
+ Requires-Dist: build>=1; extra == "test"
22
+ Requires-Dist: twine>=5; extra == "test"
23
+
24
+ # HeteroDecomp
25
+
26
+ HeteroDecomp separates repeated data items into shared, individual-specific, and
27
+ residual patterns. It accepts time-series tables (BOLD, EEG, and similar
28
+ signals), general matrices (including symmetric FC matrices), and common image
29
+ formats.
30
+
31
+ ## Install for development
32
+
33
+ ```bash
34
+ python -m pip install -e .
35
+ ```
36
+
37
+ Install the optional EEG reader for MNE FIF files:
38
+
39
+ ```bash
40
+ python -m pip install -e ".[eeg]"
41
+ ```
42
+
43
+ ## Basic API
44
+
45
+ ```python
46
+ from heterodecomp import decompose
47
+
48
+ result = decompose(
49
+ r"D:\data\bold",
50
+ kind="timeseries",
51
+ algorithm="perpca",
52
+ shared_rank=5,
53
+ individual_rank=2,
54
+ params={"epochs": 200, "lr": 0.01},
55
+ )
56
+
57
+ print(result.summary_metrics)
58
+ print(result.output_dir)
59
+ ```
60
+
61
+ Before fitting, HeteroDecomp prints detected shapes, headers, index columns, missing
62
+ values, constant columns, symmetry, and a recommended truncation length when
63
+ time series differ in duration. Use explicit `header=` and `index=` arguments
64
+ to override conservative automatic detection.
65
+
66
+ By default, outputs are saved beside the input directory in separate `shared`,
67
+ `individual`, `reconstruction`, and `residual` folders. Per-item metrics,
68
+ summary metrics, the data audit, and model metadata are saved with them.
69
+
70
+ ## Functional-connectivity matrices
71
+
72
+ ```python
73
+ result = decompose(
74
+ r"D:\data\fc",
75
+ kind="matrix",
76
+ algorithm="perpca",
77
+ shared_rank=10,
78
+ individual_rank=3,
79
+ output_format="xlsx",
80
+ )
81
+ ```
82
+
83
+ If every input is square and symmetric within tolerance, every saved shared and
84
+ individual FC component is explicitly symmetrized and keeps its detected row
85
+ and column labels.
86
+
87
+ ## Images
88
+
89
+ ```python
90
+ result = decompose(
91
+ r"D:\data\frames",
92
+ kind="image",
93
+ algorithm="perpca",
94
+ shared_rank=5,
95
+ individual_rank=20,
96
+ image_format="png",
97
+ )
98
+ ```
99
+
100
+ PNG previews are accompanied by `exact_components.npz`, which preserves signed
101
+ individual and residual arrays without visualization clipping.
102
+
103
+ ## Simulated ground truth
104
+
105
+ ```python
106
+ from heterodecomp import evaluate_ground_truth
107
+
108
+ metrics = evaluate_ground_truth(
109
+ result,
110
+ r"D:\data\shared_signal",
111
+ r"D:\data\individual_signal",
112
+ )
113
+ ```
114
+
115
+ Ground-truth recovery metrics are kept separate from real-data metrics so that
116
+ recovery claims cannot accidentally be made for empirical datasets.
117
+
118
+ ## P300 validation
119
+
120
+ ```python
121
+ from heterodecomp import prepare_p300, validate_p300
122
+
123
+ prepared = prepare_p300(r"D:\data\P300")
124
+ validation = validate_p300(prepared, shared_rank=5, individual_rank=2)
125
+ print(validation.pearson_r, validation.permutation_p)
126
+ ```
127
+
128
+ P300 validation matches the recovered shared spatial basis to the group target
129
+ topography, applies a maximum-component channel-label permutation test, and
130
+ reports target/non-target projection effects and peak latency.
131
+
132
+ ## Algorithms
133
+
134
+ `perpca`, `hmf`, `jive`, `robust_jive`, `rajive`, `slide`, `pertucker`,
135
+ `percdl`, and `robust_pca` share one interface. Algorithm-specific settings are
136
+ passed through `params`; see each adapter in `heterodecomp/_engine/models` for the
137
+ accepted options.
138
+
139
+ All algorithms print interpretable quality metrics approximately every 1% of
140
+ the configured iterations (`epochs=300` prints every 3 iterations), including
141
+ explained variance, reconstruction correlation, residual energy, and—where
142
+ available—shared/individual energy allocation. Internal optimizer losses are
143
+ not printed. Runs shorter than 100 iterations print every iteration. Pass
144
+ `params={"progress": False}` to disable progress. RaJIVE has no epoch loop, so
145
+ it reports the equivalent block and decomposition stages instead.
146
+
147
+ Complete runnable examples for every algorithm are in
148
+ [`examples/README.md`](examples/README.md).
149
+
150
+ ## Test
151
+
152
+ ```bash
153
+ python -m unittest discover -s tests -v
154
+ python -m build
155
+ python -m twine check dist/*
156
+ ```
@@ -0,0 +1,133 @@
1
+ # HeteroDecomp
2
+
3
+ HeteroDecomp separates repeated data items into shared, individual-specific, and
4
+ residual patterns. It accepts time-series tables (BOLD, EEG, and similar
5
+ signals), general matrices (including symmetric FC matrices), and common image
6
+ formats.
7
+
8
+ ## Install for development
9
+
10
+ ```bash
11
+ python -m pip install -e .
12
+ ```
13
+
14
+ Install the optional EEG reader for MNE FIF files:
15
+
16
+ ```bash
17
+ python -m pip install -e ".[eeg]"
18
+ ```
19
+
20
+ ## Basic API
21
+
22
+ ```python
23
+ from heterodecomp import decompose
24
+
25
+ result = decompose(
26
+ r"D:\data\bold",
27
+ kind="timeseries",
28
+ algorithm="perpca",
29
+ shared_rank=5,
30
+ individual_rank=2,
31
+ params={"epochs": 200, "lr": 0.01},
32
+ )
33
+
34
+ print(result.summary_metrics)
35
+ print(result.output_dir)
36
+ ```
37
+
38
+ Before fitting, HeteroDecomp prints detected shapes, headers, index columns, missing
39
+ values, constant columns, symmetry, and a recommended truncation length when
40
+ time series differ in duration. Use explicit `header=` and `index=` arguments
41
+ to override conservative automatic detection.
42
+
43
+ By default, outputs are saved beside the input directory in separate `shared`,
44
+ `individual`, `reconstruction`, and `residual` folders. Per-item metrics,
45
+ summary metrics, the data audit, and model metadata are saved with them.
46
+
47
+ ## Functional-connectivity matrices
48
+
49
+ ```python
50
+ result = decompose(
51
+ r"D:\data\fc",
52
+ kind="matrix",
53
+ algorithm="perpca",
54
+ shared_rank=10,
55
+ individual_rank=3,
56
+ output_format="xlsx",
57
+ )
58
+ ```
59
+
60
+ If every input is square and symmetric within tolerance, every saved shared and
61
+ individual FC component is explicitly symmetrized and keeps its detected row
62
+ and column labels.
63
+
64
+ ## Images
65
+
66
+ ```python
67
+ result = decompose(
68
+ r"D:\data\frames",
69
+ kind="image",
70
+ algorithm="perpca",
71
+ shared_rank=5,
72
+ individual_rank=20,
73
+ image_format="png",
74
+ )
75
+ ```
76
+
77
+ PNG previews are accompanied by `exact_components.npz`, which preserves signed
78
+ individual and residual arrays without visualization clipping.
79
+
80
+ ## Simulated ground truth
81
+
82
+ ```python
83
+ from heterodecomp import evaluate_ground_truth
84
+
85
+ metrics = evaluate_ground_truth(
86
+ result,
87
+ r"D:\data\shared_signal",
88
+ r"D:\data\individual_signal",
89
+ )
90
+ ```
91
+
92
+ Ground-truth recovery metrics are kept separate from real-data metrics so that
93
+ recovery claims cannot accidentally be made for empirical datasets.
94
+
95
+ ## P300 validation
96
+
97
+ ```python
98
+ from heterodecomp import prepare_p300, validate_p300
99
+
100
+ prepared = prepare_p300(r"D:\data\P300")
101
+ validation = validate_p300(prepared, shared_rank=5, individual_rank=2)
102
+ print(validation.pearson_r, validation.permutation_p)
103
+ ```
104
+
105
+ P300 validation matches the recovered shared spatial basis to the group target
106
+ topography, applies a maximum-component channel-label permutation test, and
107
+ reports target/non-target projection effects and peak latency.
108
+
109
+ ## Algorithms
110
+
111
+ `perpca`, `hmf`, `jive`, `robust_jive`, `rajive`, `slide`, `pertucker`,
112
+ `percdl`, and `robust_pca` share one interface. Algorithm-specific settings are
113
+ passed through `params`; see each adapter in `heterodecomp/_engine/models` for the
114
+ accepted options.
115
+
116
+ All algorithms print interpretable quality metrics approximately every 1% of
117
+ the configured iterations (`epochs=300` prints every 3 iterations), including
118
+ explained variance, reconstruction correlation, residual energy, and—where
119
+ available—shared/individual energy allocation. Internal optimizer losses are
120
+ not printed. Runs shorter than 100 iterations print every iteration. Pass
121
+ `params={"progress": False}` to disable progress. RaJIVE has no epoch loop, so
122
+ it reports the equivalent block and decomposition stages instead.
123
+
124
+ Complete runnable examples for every algorithm are in
125
+ [`examples/README.md`](examples/README.md).
126
+
127
+ ## Test
128
+
129
+ ```bash
130
+ python -m unittest discover -s tests -v
131
+ python -m build
132
+ python -m twine check dist/*
133
+ ```
@@ -0,0 +1,40 @@
1
+ """Detailed PerPCA example for BOLD time-series matrices.
2
+
3
+ PerPCA is the recommended default when the goal is an explicit shared feature
4
+ subspace plus an orthogonal subject-specific subspace.
5
+ """
6
+
7
+ from pathlib import Path
8
+
9
+ from _common import run_example
10
+
11
+
12
+ DATA_ROOT = Path("YOUR_DATA_ROOT")
13
+ DATA_DIR = DATA_ROOT / "BOLD" / "full_signal"
14
+ TRUE_SHARED_DIR = DATA_ROOT / "BOLD" / "shared_signal"
15
+ TRUE_INDIVIDUAL_DIR = DATA_ROOT / "BOLD" / "individual_signal"
16
+ OUTPUT_DIR = Path(__file__).resolve().parents[1] / "example_outputs" / "perpca"
17
+
18
+ PARAMS = {
19
+ "epochs": 200, # Number of distributed covariance-gradient iterations.
20
+ "lr": 0.01, # Initial manifold-gradient step size.
21
+ "progress": True, # Print interpretable quality metrics every ~1%.
22
+ }
23
+
24
+
25
+ if __name__ == "__main__":
26
+ run_example(
27
+ algorithm="perpca",
28
+ params=PARAMS,
29
+ data_dir=DATA_DIR,
30
+ data_kind="timeseries",
31
+ pattern="*.csv",
32
+ max_items=10, # Use None for every subject.
33
+ shared_rank=3,
34
+ individual_rank=3,
35
+ target_length=150,
36
+ scaling="zscore",
37
+ output_dir=OUTPUT_DIR,
38
+ true_shared_dir=TRUE_SHARED_DIR, # Set both truth paths to None for real data.
39
+ true_individual_dir=TRUE_INDIVIDUAL_DIR,
40
+ )
@@ -0,0 +1,45 @@
1
+ """Detailed HMF example for shared/individual BOLD decomposition.
2
+
3
+ HMF uses separate global and local matrix factors and is useful when accurate
4
+ reconstruction is more important than strict projection-only components.
5
+ """
6
+
7
+ from pathlib import Path
8
+
9
+ from _common import run_example
10
+
11
+
12
+ DATA_ROOT = Path("YOUR_DATA_ROOT")
13
+ DATA_DIR = DATA_ROOT / "BOLD" / "full_signal"
14
+ TRUE_SHARED_DIR = DATA_ROOT / "BOLD" / "shared_signal"
15
+ TRUE_INDIVIDUAL_DIR = DATA_ROOT / "BOLD" / "individual_signal"
16
+ OUTPUT_DIR = Path(__file__).resolve().parents[1] / "example_outputs" / "hmf"
17
+
18
+ PARAMS = {
19
+ "epochs": 100,
20
+ "lr": 0.001,
21
+ "beta": 0.1, # Coupling strength for the shared factors.
22
+ "wd": 0.0, # Optimizer weight decay.
23
+ "optim": "SGD", # The vendored implementation also accepts Adam.
24
+ "epsilon": 0.0, # Set above zero to enable convergence stopping.
25
+ "device": "cpu", # Change to "cuda" when a compatible GPU is available.
26
+ "progress": True,
27
+ }
28
+
29
+
30
+ if __name__ == "__main__":
31
+ run_example(
32
+ algorithm="hmf",
33
+ params=PARAMS,
34
+ data_dir=DATA_DIR,
35
+ data_kind="timeseries",
36
+ pattern="*.csv",
37
+ max_items=10,
38
+ shared_rank=3,
39
+ individual_rank=3,
40
+ target_length=150,
41
+ scaling="zscore",
42
+ output_dir=OUTPUT_DIR,
43
+ true_shared_dir=TRUE_SHARED_DIR,
44
+ true_individual_dir=TRUE_INDIVIDUAL_DIR,
45
+ )
@@ -0,0 +1,36 @@
1
+ """Detailed JIVE example for joint and individual variation."""
2
+
3
+ from pathlib import Path
4
+
5
+ from _common import run_example
6
+
7
+
8
+ DATA_ROOT = Path("YOUR_DATA_ROOT")
9
+ DATA_DIR = DATA_ROOT / "BOLD" / "full_signal"
10
+ TRUE_SHARED_DIR = DATA_ROOT / "BOLD" / "shared_signal"
11
+ TRUE_INDIVIDUAL_DIR = DATA_ROOT / "BOLD" / "individual_signal"
12
+ OUTPUT_DIR = Path(__file__).resolve().parents[1] / "example_outputs" / "jive"
13
+
14
+ PARAMS = {
15
+ "epochs": 100, # Alternating joint/individual update iterations.
16
+ "device": "cpu",
17
+ "progress": True,
18
+ }
19
+
20
+
21
+ if __name__ == "__main__":
22
+ run_example(
23
+ algorithm="jive",
24
+ params=PARAMS,
25
+ data_dir=DATA_DIR,
26
+ data_kind="timeseries",
27
+ pattern="*.csv",
28
+ max_items=10,
29
+ shared_rank=3,
30
+ individual_rank=3,
31
+ target_length=150,
32
+ scaling="zscore",
33
+ output_dir=OUTPUT_DIR,
34
+ true_shared_dir=TRUE_SHARED_DIR,
35
+ true_individual_dir=TRUE_INDIVIDUAL_DIR,
36
+ )
@@ -0,0 +1,38 @@
1
+ """Detailed RobustJIVE example with an explicit sparse-error component."""
2
+
3
+ from pathlib import Path
4
+
5
+ from _common import run_example
6
+
7
+
8
+ DATA_ROOT = Path("YOUR_DATA_ROOT")
9
+ DATA_DIR = DATA_ROOT / "BOLD" / "full_signal"
10
+ TRUE_SHARED_DIR = DATA_ROOT / "BOLD" / "shared_signal"
11
+ TRUE_INDIVIDUAL_DIR = DATA_ROOT / "BOLD" / "individual_signal"
12
+ OUTPUT_DIR = Path(__file__).resolve().parents[1] / "example_outputs" / "robust_jive"
13
+
14
+ PARAMS = {
15
+ "epochs": 100,
16
+ "mu": 10.0, # Augmented-Lagrangian penalty.
17
+ "lbd": 0.01, # Sparse-error regularization strength.
18
+ "device": "cpu",
19
+ "progress": True,
20
+ }
21
+
22
+
23
+ if __name__ == "__main__":
24
+ run_example(
25
+ algorithm="robust_jive",
26
+ params=PARAMS,
27
+ data_dir=DATA_DIR,
28
+ data_kind="timeseries",
29
+ pattern="*.csv",
30
+ max_items=10,
31
+ shared_rank=3,
32
+ individual_rank=3,
33
+ target_length=150,
34
+ scaling="zscore",
35
+ output_dir=OUTPUT_DIR,
36
+ true_shared_dir=TRUE_SHARED_DIR,
37
+ true_individual_dir=TRUE_INDIVIDUAL_DIR,
38
+ )
@@ -0,0 +1,44 @@
1
+ """Detailed angle-based robust JIVE (RaJIVE) example.
2
+
3
+ RaJIVE estimates joint structure using resampled Wedin and random-direction
4
+ bounds. Its sampling controls trade runtime for rank-selection stability.
5
+ """
6
+
7
+ from pathlib import Path
8
+
9
+ from _common import run_example
10
+
11
+
12
+ DATA_ROOT = Path("YOUR_DATA_ROOT")
13
+ DATA_DIR = DATA_ROOT / "BOLD" / "full_signal"
14
+ TRUE_SHARED_DIR = DATA_ROOT / "BOLD" / "shared_signal"
15
+ TRUE_INDIVIDUAL_DIR = DATA_ROOT / "BOLD" / "individual_signal"
16
+ OUTPUT_DIR = Path(__file__).resolve().parents[1] / "example_outputs" / "rajive"
17
+
18
+ PARAMS = {
19
+ "n_wedin_samples": 100,
20
+ "n_rand_dir_samples": 100,
21
+ "joint_rank": 3, # Set to None only when automatic selection is desired.
22
+ "robust_niter": 100,
23
+ "robust_tol": 1e-5,
24
+ "use_hmf_variant": False,
25
+ "progress": True,
26
+ }
27
+
28
+
29
+ if __name__ == "__main__":
30
+ run_example(
31
+ algorithm="rajive",
32
+ params=PARAMS,
33
+ data_dir=DATA_DIR,
34
+ data_kind="timeseries",
35
+ pattern="*.csv",
36
+ max_items=10,
37
+ shared_rank=3,
38
+ individual_rank=3,
39
+ target_length=150,
40
+ scaling="zscore",
41
+ output_dir=OUTPUT_DIR,
42
+ true_shared_dir=TRUE_SHARED_DIR,
43
+ true_individual_dir=TRUE_INDIVIDUAL_DIR,
44
+ )
@@ -0,0 +1,43 @@
1
+ """Detailed SLIDE example with a fixed shared/individual structure.
2
+
3
+ The default avoids expensive bi-cross-validation and constructs a structure
4
+ from the requested ranks. Enable ``use_bcv`` for data-driven structure search.
5
+ """
6
+
7
+ from pathlib import Path
8
+
9
+ from _common import run_example
10
+
11
+
12
+ DATA_ROOT = Path("YOUR_DATA_ROOT")
13
+ DATA_DIR = DATA_ROOT / "BOLD" / "full_signal"
14
+ TRUE_SHARED_DIR = DATA_ROOT / "BOLD" / "shared_signal"
15
+ TRUE_INDIVIDUAL_DIR = DATA_ROOT / "BOLD" / "individual_signal"
16
+ OUTPUT_DIR = Path(__file__).resolve().parents[1] / "example_outputs" / "slide"
17
+
18
+ PARAMS = {
19
+ "use_bcv": False,
20
+ "center": True,
21
+ "k_max": 1000,
22
+ "eps": 1e-6,
23
+ "progress": True,
24
+ # BCV-only controls: n_lambda, lambda_min, n_fold, p_fold, ratio_max.
25
+ }
26
+
27
+
28
+ if __name__ == "__main__":
29
+ run_example(
30
+ algorithm="slide",
31
+ params=PARAMS,
32
+ data_dir=DATA_DIR,
33
+ data_kind="timeseries",
34
+ pattern="*.csv",
35
+ max_items=10,
36
+ shared_rank=3,
37
+ individual_rank=3,
38
+ target_length=150,
39
+ scaling="zscore",
40
+ output_dir=OUTPUT_DIR,
41
+ true_shared_dir=TRUE_SHARED_DIR,
42
+ true_individual_dir=TRUE_INDIVIDUAL_DIR,
43
+ )
@@ -0,0 +1,43 @@
1
+ """Detailed Personalized Tucker decomposition example.
2
+
3
+ Each 2-D input is represented as a small tensor internally. This method is most
4
+ useful when multilinear row and column structure is scientifically meaningful.
5
+ """
6
+
7
+ from pathlib import Path
8
+
9
+ from _common import run_example
10
+
11
+
12
+ DATA_ROOT = Path("YOUR_DATA_ROOT")
13
+ DATA_DIR = DATA_ROOT / "BOLD" / "full_signal"
14
+ TRUE_SHARED_DIR = DATA_ROOT / "BOLD" / "shared_signal"
15
+ TRUE_INDIVIDUAL_DIR = DATA_ROOT / "BOLD" / "individual_signal"
16
+ OUTPUT_DIR = Path(__file__).resolve().parents[1] / "example_outputs" / "pertucker"
17
+
18
+ PARAMS = {
19
+ "max_itr": 100,
20
+ "tol": 1e-8,
21
+ "rho": 0.0, # Optional local-factor regularization.
22
+ "init_method": "random", # Supported by the vendored PerTucker solver.
23
+ "orthogonal": True,
24
+ "progress": True,
25
+ }
26
+
27
+
28
+ if __name__ == "__main__":
29
+ run_example(
30
+ algorithm="pertucker",
31
+ params=PARAMS,
32
+ data_dir=DATA_DIR,
33
+ data_kind="timeseries",
34
+ pattern="*.csv",
35
+ max_items=10,
36
+ shared_rank=3,
37
+ individual_rank=3,
38
+ target_length=150,
39
+ scaling="zscore",
40
+ output_dir=OUTPUT_DIR,
41
+ true_shared_dir=TRUE_SHARED_DIR,
42
+ true_individual_dir=TRUE_INDIVIDUAL_DIR,
43
+ )
@@ -0,0 +1,43 @@
1
+ """Detailed personalized convolutional dictionary learning example.
2
+
3
+ PerCDL is specialized for one-dimensional time series. Each feature/ROI is
4
+ treated as a signal; it should not be the first choice for FC matrices/images.
5
+ """
6
+
7
+ from pathlib import Path
8
+
9
+ from _common import run_example
10
+
11
+
12
+ DATA_ROOT = Path("YOUR_DATA_ROOT")
13
+ DATA_DIR = DATA_ROOT / "BOLD" / "full_signal"
14
+ TRUE_SHARED_DIR = DATA_ROOT / "BOLD" / "shared_signal"
15
+ TRUE_INDIVIDUAL_DIR = DATA_ROOT / "BOLD" / "individual_signal"
16
+ OUTPUT_DIR = Path(__file__).resolve().parents[1] / "example_outputs" / "percdl"
17
+
18
+ PARAMS = {
19
+ "n_steps": 100,
20
+ "n_atoms": 3,
21
+ "atom_length": 24, # Must be shorter than the aligned time series.
22
+ "step_size": 1e-3,
23
+ "sparsity": 0.05,
24
+ "progress": True,
25
+ }
26
+
27
+
28
+ if __name__ == "__main__":
29
+ run_example(
30
+ algorithm="percdl",
31
+ params=PARAMS,
32
+ data_dir=DATA_DIR,
33
+ data_kind="timeseries",
34
+ pattern="*.csv",
35
+ max_items=10,
36
+ shared_rank=3,
37
+ individual_rank=3,
38
+ target_length=150,
39
+ scaling="zscore",
40
+ output_dir=OUTPUT_DIR,
41
+ true_shared_dir=TRUE_SHARED_DIR,
42
+ true_individual_dir=TRUE_INDIVIDUAL_DIR,
43
+ )
@@ -0,0 +1,42 @@
1
+ """Detailed robust PCA baseline example.
2
+
3
+ The adapter fits low-rank plus sparse structure per item, defines the group mean
4
+ low-rank matrix as shared, and treats deviations from it as individual-specific.
5
+ """
6
+
7
+ from pathlib import Path
8
+
9
+ from _common import run_example
10
+
11
+
12
+ DATA_ROOT = Path("YOUR_DATA_ROOT")
13
+ DATA_DIR = DATA_ROOT / "BOLD" / "full_signal"
14
+ TRUE_SHARED_DIR = DATA_ROOT / "BOLD" / "shared_signal"
15
+ TRUE_INDIVIDUAL_DIR = DATA_ROOT / "BOLD" / "individual_signal"
16
+ OUTPUT_DIR = Path(__file__).resolve().parents[1] / "example_outputs" / "robust_pca"
17
+
18
+ PARAMS = {
19
+ "outer_epochs": 100,
20
+ "lbd_s_outer": 0.02, # Sparse-component shrinkage.
21
+ "rho": 0.95, # Continuation factor used by the robust solver.
22
+ "device": "cpu",
23
+ "progress": True,
24
+ }
25
+
26
+
27
+ if __name__ == "__main__":
28
+ run_example(
29
+ algorithm="robust_pca",
30
+ params=PARAMS,
31
+ data_dir=DATA_DIR,
32
+ data_kind="timeseries",
33
+ pattern="*.csv",
34
+ max_items=10,
35
+ shared_rank=3,
36
+ individual_rank=3,
37
+ target_length=150,
38
+ scaling="zscore",
39
+ output_dir=OUTPUT_DIR,
40
+ true_shared_dir=TRUE_SHARED_DIR,
41
+ true_individual_dir=TRUE_INDIVIDUAL_DIR,
42
+ )