mJ-Net Core / Penumbra — FE3 Encoder
2D + time CNN · admission 4D CT perfusion · IEEE BHI 2026
Read this first
These weights are released as a feature extractor, not as a segmenter. They are the FE3 encoder from the paper, where the 256-D bottleneck descriptor gave the clearest separation between salvageable and non-salvageable penumbra of any feature family tested.
As a segmentation model it is weak — penumbra Dice 0.30, core Dice 0.05 on the held-out test set. If you want a core/penumbra segmentation, use the nnU-Net weights instead (Dice 0.71 / 0.30 on the same 33 patients).
If you use these weights, please cite two papers. Ours, for the weights and the feature read-out — Md Sazidur Rahman, Kjersti Engan, Kathinka Dæhli Kurz and Mahdieh Khanmohammadi, Bi-temporal Image-driven Acute Stroke Evolution Analysis, IEEE-EMBS International Conference on Biomedical and Health Informatics (BHI), 2026. arXiv:2602.07535 — and Tomasetti et al. (ACM-BCB '20) for the architecture itself, which is not ours. BibTeX for both in Citation and Original architecture below.
A PyTorch port of mJ-Net, applied to admission 4D CT perfusion. The network consumes a 16×16 spatial patch across all 40 timepoints, collapses the temporal axis, and predicts a 4-class label for that patch.
| Task | 4-class segmentation, background / brain / penumbra / core |
| Input | 16×16×40 patch of a preprocessed CTP volume |
| Framework | PyTorch, 5-fold ensemble, 0.98 M parameters |
| Feature read-out | 256-D encoder bottleneck (this is the point) |
| Trained on | 116 cases, Stavanger University Hospital (SUH) |
| Size | 19.5 MB for all 5 folds |
On the linked dataset. Trained on the SUH cohort only. The linked ISLES'24 dataset is where the model was applied, not trained or scored.
Quick start
pip install torch SimpleITK numpy huggingface_hub
hf download yokko123/ctp-core-penumbra-mjnet --local-dir ./mjnet
python mjnet/predict.py \
--input CASE_ctp.nii.gz \
--output CASE_seg.nii.gz \
--weights mjnet/folds
--input takes either a 4-D CTP NIfTI with 40 timepoints, or a directory of 40
3-D frames named CASE_0000.nii.gz … CASE_0039.nii.gz. Omit --weights and the
script fetches them from the Hub itself. --stride trades speed for smoothness
(default 4); --folds 0 runs a single fold.
For the 256-D FE3 descriptor — the actual contribution — use
02_features/fe3_mjnet/extract_features.py
from the code repository. It pools the bottleneck over 16×16 patches inside each
labelled region, which predict.py does not reproduce.
Input contract
The model expects exactly the preprocessing it was trained on and will not behave sensibly on raw CTP:
- 4D CTP motion-corrected by rigidly registering every frame to the first,
- temporally resampled to a uniform 1 fps, giving 40 frames,
- rigidly registered to the admission NCCT and resampled onto that grid,
- skull-stripped (SynthStrip),
- windowed to [0, 100] HU and rescaled to an 8-bit grey range,
- divided by 255 at inference time (
predict.pydoes this step for you).
The full chain is stage 01 of the code repository.
Labels
| Value | Class |
|---|---|
| 0 | background |
| 1 | brain |
| 2 | penumbra |
| 3 | core |
Results
Held-out test set, 33 cases — the same patients the nnU-Net was tested on:
| Class | Dice |
|---|---|
| penumbra | 0.30 ± 0.23 |
| core | 0.05 ± 0.06 |
| lesion (core ∪ penumbra) | 0.24 ± 0.20 |
Core segmentation is effectively unusable, and penumbra is well below the nnU-Net. We report it anyway because the paper's claim does not rest on it: the FE3 result is about the structure of the encoder's feature space, which these numbers say nothing about. Connected-component postprocessing moved penumbra to 0.32 and left core unchanged, so none is applied by default.
Architecture
| Input | (1, 40, 16, 16) — one channel, 40 timepoints, 16×16 patch |
| Variant | standard mJ-Net (longJ=False, v2=False) |
| Normalisation | BatchNorm after every conv |
| Dropout | 0.2 at all designated locations |
| Parameters | 978,351 |
| Encoder bottleneck | 256-D after spatial mean pooling |
Trained with AdamW, lr 1·10⁻³ on a cosine schedule to 1·10⁻⁶, weight decay 10⁻², batch size 32, patches drawn at stride 4 with lesion-containing patches oversampled 6×, and early stopping on the validation metric.
The five folds stopped at epochs 23, 17, 9, 26 and 13 — early stopping fired well before the epoch budget in every fold. The numbers above were computed from exactly these checkpoints.
Each folds/fold_N.pt holds only the weights plus the architecture description
needed to rebuild the model; optimizer and scheduler state were stripped, taking
the release from 59 MB to 19.5 MB.
Role in the paper
These are the FE3 weights in:
Bi-temporal Image-driven Acute Stroke Evolution Analysis Md Sazidur Rahman, Kjersti Engan, Kathinka Dæhli Kurz, Mahdieh Khanmohammadi IEEE-EMBS International Conference on Biomedical and Health Informatics (BHI), 2026 arXiv:2602.07535
Admission CTP is registered to follow-up DWI and the two label sets are intersected into six outcome-aware ROI classes. Each region is described by four feature families; FE3 is this network's encoder bottleneck. It produced the strongest separation between penumbra that was salvaged and penumbra that went on to infarct.
Training data
A retrospective Stavanger University Hospital (SUH) cohort: patients scanned between January 2014 and August 2020 with admission CTP and follow-up MRI, 149 in total, split 116 for development and 33 held out.
The cohort is not public and is not distributed with these weights.
Citation
@inproceedings{rahman2026bitemporal,
title = {Bi-temporal Image-driven Acute Stroke Evolution Analysis},
author = {Rahman, Md Sazidur and Engan, Kjersti and
Kurz, Kathinka D{\ae}hli and Khanmohammadi, Mahdieh},
booktitle = {2026 IEEE-EMBS International Conference on Biomedical and Health Informatics (BHI)},
year = {2026},
eprint = {2602.07535},
archivePrefix= {arXiv},
primaryClass = {cs.CV},
note = {In press}
}
Original architecture
mJ-Net is not our architecture. It was introduced by Tomasetti et al. at the Biomedical Data Analysis Laboratory, University of Stavanger:
CNN Based Segmentation of Infarcted Regions in Acute Cerebral Stroke Patients From Computed Tomography Perfusion Imaging Luca Tomasetti, Kjersti Engan, Mahdieh Khanmohammadi, Kathinka Dæhli Kurz Proceedings of the 11th ACM International Conference on Bioinformatics, Computational Biology and Health Informatics (ACM-BCB '20), 2020, pp. 1–8. doi:10.1145/3388440.3412470 · arXiv:2104.03002
@inproceedings{tomasetti2020cnn,
title = {CNN Based Segmentation of Infarcted Regions in Acute Cerebral
Stroke Patients From Computed Tomography Perfusion Imaging},
author = {Tomasetti, Luca and Engan, Kjersti and
Khanmohammadi, Mahdieh and Kurz, Kathinka D{\ae}hli},
booktitle = {Proceedings of the 11th ACM International Conference on
Bioinformatics, Computational Biology and Health Informatics},
series = {ACM-BCB '20},
publisher = {ACM},
year = {2020},
pages = {1--8},
doi = {10.1145/3388440.3412470}
}
If you use these weights, cite that paper for the architecture and ours for the bi-temporal analysis they were trained for.
The same group later extended the design to a true 4D convolution in CT Perfusion is All We Need: 4D CNN Segmentation of Penumbra and Core (Tomasetti, Engan, Høllesli, Kurz, Khanmohammadi; IEEE Access 11:138936–138953, 2023, doi:10.1109/ACCESS.2023.3336590), released as 4D-mJ-Net. These weights are the earlier 2D+time mJ-Net, not the 4D variant.
What is ours: an independent PyTorch port of the TensorFlow reference — a
layer-for-layer match, documented in arch_mJNet.py — retrained from scratch on
the SUH cohort for 4-class core/penumbra segmentation, and the FE3 feature
read-out built on its encoder.