ImmuVis is a masked autoencoder for multiplex imaging data. It combines a marker-agnostic encoder, a hyperkernel-based multiplex encoder, and a channel-aware decoder to reconstruct masked multiplex images.
Preferred setup:
uv syncThis installs the project dependencies from pyproject.toml and the lockfile.
Alternative editable install:
pip install -e .After installation you can run commands with uv run ... or with the Python environment created by your editable install.
The model is a masked autoencoder for multiplex microscopy-style inputs where each sample contains several channels corresponding to biological markers.
The architecture has three main parts:
- A marker-agnostic encoder that processes each channel independently with a shared backbone.
- A hyperkernel module that transforms the channels into a shared pan-marker representation, with a consequtive pan-marker encoder.
- A marker-agnostic decoder that learns reconstructs each masked channel.
The default architecture is defined in train_masked_config.yaml and can be customized through the encoder and decoder sections.
The encoder is configured with:
ma_layers_blocksandma_embedding_dimsfor the marker-agnostic stage.pm_layers_blocksandpm_embedding_dimsfor the pan-marker stage.hyperkernel, which defines the channel-conditioned projection (kernel_size,stride,padding,use_bias).encoder_type, which can be a string registry name such asconvnext,resnet,swin, orvit, or a dict withtypeandmodule_parameters.
The decoder uses:
decoded_embed_dimfor the hidden decoder width.num_blocksfor the number of decoder blocks.hyperkernelfor channel-aware decoding.num_outputs, which defaults to2and determines the number of output values per pixel and channel.block_type, which defaults toconvnextand can be changed through the registry system.
The model predicts two values per output pixel and channel:
mi, interpreted as the reconstructed mean after a sigmoid.logvar, interpreted as the predicted uncertainty and clamped during training for stability.
The dataset loader expects a split-by-panel directory structure like the following:
.
└── data
├── test
│ ├── dataset1
│ │ └── imgs
│ ├── dataset2
│ │ └── imgs
│ └── dataset3
│ └── imgs
└── train
├── dataset1
│ └── imgs
├── dataset2
│ └── imgs
└── dataset3
└── imgs
train and test are the data splits, and each dataset... directory is a panel. Store the image files for each panel in the corresponding imgs directory.
The loader supports:
.tifffiles throughtifffile.npyfiles throughnumpy
The file extension is controlled by data_config.file_extension in the training config.
Then update configs/all_panels_config.yaml:
- Set
paths.trainandpaths.testto the full paths of your split directories. - List the panel subdirectories you want to use under
datasets. - For each panel, provide the ordered marker names under
markers; these must match the consecutive image channels in the corresponding files. - Use
clip_limitswhen you want panel-specific clipping during scaling. - Use
marker_statswhen you want per-dataset normalization statistics loaded from CSV.
The dataset loader validates that:
pathscontains the requested split name.datasetsexists and contains the panel subdirectories.markerscontains the channel names for every listed panel.
The tokenizer config in configs/all_markers_tokenizer.yaml must include all marker names used by the panel config.
The main training config is train_masked_config.yaml. It is split into these groups:
encoderanddecoder: architecture configuration forMultiplexAutoencoder.panel_config: path toconfigs/all_panels_config.yamlor an inline panel config dict.tokenizer_config: path toconfigs/all_markers_tokenizer.yamlor an inline tokenizer config dict.input_image_size: final spatial size after preprocessing and transforms.data_config: preprocessing, denoising, scaling, normalization, file extension, and kwargs.device,lr,final_lr,weight_decay,epochs,gradient_accumulation_steps, andfrac_warmup_steps: optimizer and schedule settings.min_channels_frac,fully_masked_channels_max_frac,spatial_masking_ratio, andmask_patch_size: masking strategy during training and validation.checkpoints_dir,from_checkpoint, andsave_checkpoint_freq: checkpoint handling.comet_project,comet_workspace,comet_api_key,tags, andrun_name: Comet.ml experiment metadata.
Training uses Comet.ml logging. Create a free account at https://www.comet.com and set the following fields in train_masked_config.yaml:
comet_projectcomet_workspacecomet_api_key
Run training with:
uv run python train_masked_model.py train_masked_config.yamlor, if you used the editable install:
python3 train_masked_model.py train_masked_config.yamlDuring training the script:
- builds the model from the encoder/decoder config,
- loads the panel and tokenizer config,
- applies channel masking and spatial masking,
- optimizes with AdamW and a warmup plus cosine schedule,
- logs metrics and validation reconstructions to Comet.ml,
- saves periodic checkpoints and the latest checkpoint.
The default checkpoint directory is checkpoints. The model writes:
- periodic checkpoints every
save_checkpoint_freqepochs, last_checkpoint-<run_name>.pthafter each epoch,final_model-<run_name>.pthafter training finishes.
To resume training, set from_checkpoint to a checkpoint path or to last.
Use MultiplexAutoencoder.load_from_checkpoint(...) to restore a saved model. If the checkpoint includes model_config, the model can be rebuilt directly from the checkpoint contents.
- The repo uses registry-based architecture resolution, so new encoder or block types can be added without changing the training script.
- If you change marker ordering in the panel config, update the tokenizer and any downstream analysis to match.
