Skip to content

Commit 3ddb581

Browse files
Rename package pyAMICA to pamica
1 parent 79d1fa7 commit 3ddb581

181 files changed

Lines changed: 615 additions & 615 deletions

File tree

Some content is hidden

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

.context/decisions/0001-torch-backend-natural-gradient-em.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ The default PyTorch backend (`torch_impl/amica_torch.py`, and the experimental
1111
reparameterized tensors" (`softmax`/`exp`/`sigmoid` on `alpha`, `beta`, `rho`), driven by
1212
autograd. AMICA is fundamentally an EM / natural-gradient fixed-point iteration with
1313
closed-form sufficient-statistic updates; the Fortran reference (`amica17.f90`) and the legacy
14-
NumPy `pyAMICA.py` implement it that way. The reframing follows a different optimization
14+
NumPy `pamica.py` implement it that way. The reframing follows a different optimization
1515
trajectory and converges to a different fixed point, which is the primary cause of the poor
1616
component correlation with Fortran (~0.46-0.9 vs target >0.95). It also blocks scaling: the
1717
autograd path materializes all-sample intermediates and retains the graph, so peak memory grows
@@ -23,7 +23,7 @@ binary is the definition of done for this project.
2323
Rewrite the PyTorch backend as a direct, vectorized port of the NumPy/Fortran natural-gradient
2424
(and Newton) update rules. Parameterize `W` directly (no `pinv(A.T).T` per forward), broadcast
2525
the E-step over `(model, mix, source, block)` instead of Python loops, accumulate sufficient
26-
statistics block-wise, and drop Adam/autograd for the parameter updates. The NumPy `pyAMICA.py`
26+
statistics block-wise, and drop Adam/autograd for the parameter updates. The NumPy `pamica.py`
2727
`_get_block_updates` / `_update_parameters` are the reference spec; validation runs in float64.
2828

2929
## Consequences
@@ -60,7 +60,7 @@ partition matching is tracked in #27, adaptive-PDF in #26.
6060

6161
- Fortran LL normalization: `amica17.f90:1866` (`LL = LLtmp2 / (num_samples*nw)`).
6262
- Fortran per-source mixture reduction: `amica17.f90:1313-1360`.
63-
- NumPy reference updates: `pyAMICA.py:505-730` (block updates, natural-gradient + Newton).
63+
- NumPy reference updates: `pamica.py:505-730` (block updates, natural-gradient + Newton).
6464
- Bug catalog and perf/memory analysis: `.context/research.md` (2026-07-02 design review).
6565

6666
## Addendum (2026-07-04, issue #32)

.context/decisions/0002-adaptive-pdf-families.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ sub-Gaussian cosh+, and `pdftype=1` = the extended-Infomax adaptive switcher (Fo
2424
sub-Gaussian (code 4) cosh densities by kurtosis sign on the `kurt_start`/`num_kurt`/
2525
`kurt_int` schedule. `rho` is frozen for every non-GG family (`amica15.f90:3682`), and the
2626
single-component families 1/4 require `n_mix=1`. The ground-truth `amica15.f90`/
27-
`amica15_header.f90` are copied into `pyAMICA/`.
27+
`amica15_header.f90` are copied into `pamica/`.
2828

2929
## Consequences
3030

@@ -51,7 +51,7 @@ single-component families 1/4 require `n_mix=1`. The ground-truth `amica15.f90`/
5151

5252
## Receipts
5353

54-
- `pyAMICA/amica15.f90` select-cases at :1277 (likelihood) / :1449 (score); `dorho=.false.`
54+
- `pamica/amica15.f90` select-cases at :1277 (likelihood) / :1449 (score); `dorho=.false.`
5555
at :3682; `do_choose_pdfs` at :594; the `m2sum`/`m4sum` moment buffers are allocated/zeroed
5656
(:590-591) but never accumulated, confirming the dynamic switch is dead code in the binary.
5757
- The extended-Infomax intent comes from the upstream AMICA MATLAB wrapper `runamica15.m`
@@ -63,6 +63,6 @@ single-component families 1/4 require `n_mix=1`. The ground-truth `amica15.f90`/
6363
```
6464
and defaults `pdftype=0; kurt_start=3; num_kurt=5; kurt_int=1;`. The super/sub-Gaussian
6565
scores `y +/- tanh(y)` (amica15 codes 1/4) are the classic extended-Infomax nonlinearities.
66-
- `pyAMICA/torch_impl/amica_torch_ng.py`: `_log_pdf_and_deriv`, `_score`, `_choose_pdfs`.
67-
- `pyAMICA/tests/torch_tests/test_ng_pdf_families.py` (formula parity + real-data + opt-in
66+
- `pamica/torch_impl/amica_torch_ng.py`: `_log_pdf_and_deriv`, `_score`, `_choose_pdfs`.
67+
- `pamica/tests/torch_tests/test_ng_pdf_families.py` (formula parity + real-data + opt-in
6868
binary integration behind `AMICA_RUN_FORTRAN=1`).

.context/decisions/0003-best-iterate-safeguard.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ changes across iterations and per-iteration LLs are not comparable.
7070

7171
## Receipts
7272

73-
- `pyAMICA/torch_impl/amica_torch_ng.py` (`keep_best`, `_snapshot_params`/
73+
- `pamica/torch_impl/amica_torch_ng.py` (`keep_best`, `_snapshot_params`/
7474
`_restore_params`, `final_ll_`, `_KEEP_BEST_TOL`).
75-
- `pyAMICA/tests/torch_tests/test_ng_backend.py::test_keep_best_*`.
75+
- `pamica/tests/torch_tests/test_ng_backend.py::test_keep_best_*`.
7676
- `.context/issue-51/ensemble_ll.py` (Fortran-vs-NG LL ensemble, real data).
77-
- Fortran schedule: `pyAMICA/amica15.f90:1038-1058` (anneal-on-decrease).
77+
- Fortran schedule: `pamica/amica15.f90:1038-1058` (anneal-on-decrease).

.context/ideas.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# pyAMICA Design Ideas
1+
# pamica Design Ideas
22

33
High-level PyTorch design decisions and library options for the AMICA port.
44

.context/issue-136/matlab_viz_verification.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ MATLAB cannot run in CI, so this is recorded rather than automated.
3737
`pop_topohistplot.m` and `pop_modPMI.m` carry explicit **GPL-2.0-or-later** headers
3838
(Copyright Ozgur Baklan, SCCN, INC, UCSD). `modprobplot.m`, `minfojp.m`, `LLt2v.m`,
3939
`smooth_amica_prob.m` carry no header but sit inside that GPL plugin, so they are
40-
conservatively GPL too. pyAMICA is BSD-3-Clause, which is why Phase 2's PMI was a
40+
conservatively GPL too. pamica is BSD-3-Clause, which is why Phase 2's PMI was a
4141
clean-room reimplementation.
4242

4343
**Posture: run-and-observe only. No `.m` implementation source was read at any point.**
@@ -77,10 +77,10 @@ Notes on the two correlation-rather-than-equality rows:
7777

7878
Side-by-side renders on the same data are committed here:
7979

80-
- `cmp_modprob.png` — MATLAB `modprobplot` vs `pyAMICA.viz.plot_model_probability`
80+
- `cmp_modprob.png` — MATLAB `modprobplot` vs `pamica.viz.plot_model_probability`
8181
(1 s smoothing). Same two stacked panels, same switching times (~1.4, 3.4, 6.5, 9.3,
8282
12.5, 15.7 s), same log-likelihood trace and range (-105 to -125), seconds axis.
83-
- `cmp_pmi.png` — MATLAB `pop_modPMI` vs `pyAMICA.viz.plot_pmi_heatmap`, rendered on
83+
- `cmp_pmi.png` — MATLAB `pop_modPMI` vs `pamica.viz.plot_pmi_heatmap`, rendered on
8484
**identical signals** (MATLAB's own `EEG.icaact`) so the comparison isolates the
8585
estimator and the ordering. Both show the same dependent-subspace cluster near the
8686
centre with the same radiating cross pattern, at the same MI scale.
@@ -193,7 +193,7 @@ algorithm (ours greedy nearest-neighbour chain vs MATLAB's iterative cost minimi
193193
must agree, since exact-equality dispatch sends them down different branches).
194194

195195
4. **postAmicaUtility's own `loadmodout15.m` is broken on R2025b** (`Unmatched ']'`,
196-
line 120). pyAMICA's bundled copy works. `addpath` `pyAMICA/sample_data` LAST so ours
196+
line 120). pamica's bundled copy works. `addpath` `pamica/sample_data` LAST so ours
197197
shadows theirs, or the model never loads and every plot fails with a misleading
198198
"No AMICA solution found".
199199
5. **`pop_topohistplot` is broken upstream** (`Unrecognized function or variable
@@ -216,7 +216,7 @@ git clone --depth 1 https://github.com/sccn/postAmicaUtility.git # GPL: run,
216216
git clone --depth 1 https://github.com/bigdelys/pre_ICA_cleaning.git # Apache-2.0: getMIR.m
217217
```
218218

219-
Then: `addpath(genpath(eeglab)); addpath(postAmicaUtility); addpath(pyAMICA/sample_data)`
219+
Then: `addpath(genpath(eeglab)); addpath(postAmicaUtility); addpath(pamica/sample_data)`
220220
(last, per trap 4); `eeglab nogui`; `pop_loadset` + `pop_loadmodout(EEG, <amicaout dir>)`;
221221
`modprobplot(EEG, 1:num_models, smooth_sec, [])` returns `[v2plot, llt2plot]` — the exact
222222
series it draws — and `pop_modPMI(EEG, 'models2plot', 1, 'order', true)` writes

.context/issue-144-parity-data-adequacy/bundled_sample_newton0.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
HERE = Path(__file__).resolve().parent
3030
REPO = HERE.parents[1]
3131
sys.path.insert(0, str(REPO))
32-
from pyAMICA import AMICA # noqa: E402
33-
from pyAMICA.torch_impl.utils import load_eeglab_data # noqa: E402
32+
from pamica import AMICA # noqa: E402
33+
from pamica.torch_impl.utils import load_eeglab_data # noqa: E402
3434

3535

3636
def xcorr(Wa, Wb):
@@ -62,9 +62,9 @@ def amari_distance(Wa, Wb):
6262
def run_fortran(data_dim, max_iter, seed, work_dir):
6363
work_dir.mkdir(parents=True, exist_ok=True)
6464
shutil.copy(
65-
REPO / "pyAMICA/sample_data/eeglab_data.fdt", work_dir / "eeglab_data.fdt"
65+
REPO / "pamica/sample_data/eeglab_data.fdt", work_dir / "eeglab_data.fdt"
6666
)
67-
template = (REPO / "pyAMICA/sample_data/input.param").read_text().splitlines()
67+
template = (REPO / "pamica/sample_data/input.param").read_text().splitlines()
6868
lines = []
6969
for line in template:
7070
if line.startswith("files"):
@@ -81,7 +81,7 @@ def run_fortran(data_dim, max_iter, seed, work_dir):
8181
(work_dir / "fortran_output").mkdir(exist_ok=True)
8282

8383
result = subprocess.run(
84-
[str(REPO / "pyAMICA/sample_data/amica15mac"), "input.param"],
84+
[str(REPO / "pamica/sample_data/amica15mac"), "input.param"],
8585
cwd=work_dir,
8686
capture_output=True,
8787
text=True,
@@ -116,13 +116,13 @@ def main():
116116
)
117117
seeds = list(range(301, 301 + n_seeds))
118118

119-
with open(REPO / "pyAMICA/sample_data/sample_params.json") as f:
119+
with open(REPO / "pamica/sample_data/sample_params.json") as f:
120120
params = json.load(f)
121121
data_dim = params["data_dim"]
122122
field_dim = params["field_dim"][0]
123123

124124
data = load_eeglab_data(
125-
str(REPO / "pyAMICA/sample_data/eeglab_data.fdt"),
125+
str(REPO / "pamica/sample_data/eeglab_data.fdt"),
126126
data_dim=data_dim,
127127
field_dim=field_dim,
128128
dtype=np.float32,

.context/issue-144-parity-data-adequacy/run_5seed_newton0.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
# the NEXT seed's Fortran starts immediately -- CPU and GPU work overlap
1111
# since they don't compete for the same resource.
1212
set -e
13-
cd ~/pyAMICA-issue144
13+
cd ~/pamica-issue144
1414
NPY=benchmarks/data/ds002718_sub-002_eeg70_full.npy
1515
SCRIPTS=.context/issue-144-parity-data-adequacy
1616

.context/issue-144-parity-data-adequacy/run_fortran_only.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515

1616
HERE = Path(__file__).resolve().parent
1717
REPO = HERE.parents[1]
18-
BIN = REPO / "pyAMICA/sample_data/amica15_linux"
19-
INPUT_PARAM = REPO / "pyAMICA/sample_data/input.param"
18+
BIN = REPO / "pamica/sample_data/amica15_linux"
19+
INPUT_PARAM = REPO / "pamica/sample_data/input.param"
2020

2121

2222
def write_fdt(data: np.ndarray, path: Path) -> None:

.context/issue-144-parity-data-adequacy/run_ng_only.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
HERE = Path(__file__).resolve().parent
1515
REPO = HERE.parents[1]
1616
sys.path.insert(0, str(REPO))
17-
from pyAMICA.torch_impl import AMICATorchNG # noqa: E402
17+
from pamica.torch_impl import AMICATorchNG # noqa: E402
1818

1919

2020
def xcorr(Wa, Wb):

.context/issue-144-parity-data-adequacy/test_ds002718_32ch.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@
2525
HERE = Path(__file__).resolve().parent
2626
REPO = HERE.parents[1]
2727
sys.path.insert(0, str(REPO))
28-
from pyAMICA.torch_impl import AMICATorchNG # noqa: E402
28+
from pamica.torch_impl import AMICATorchNG # noqa: E402
2929

30-
BIN = REPO / "pyAMICA/sample_data/amica15mac"
31-
INPUT_PARAM = REPO / "pyAMICA/sample_data/input.param"
30+
BIN = REPO / "pamica/sample_data/amica15mac"
31+
INPUT_PARAM = REPO / "pamica/sample_data/input.param"
3232

3333

3434
def xcorr(Wa, Wb):

0 commit comments

Comments
 (0)